diff options
author | fsamuel <fsamuel@chromium.org> | 2015-05-08 10:27:17 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-05-08 17:27:37 +0000 |
commit | 7427a2fea91dcd0331628297cc08a33eb1765ad2 (patch) | |
tree | fc7d42eacd945ef071d3cf52ccfe05e3250c0d13 /extensions/renderer/guest_view | |
parent | 5d8094a323492b3cb1439e6c69fc0851f330757a (diff) | |
download | chromium_src-7427a2fea91dcd0331628297cc08a33eb1765ad2.zip chromium_src-7427a2fea91dcd0331628297cc08a33eb1765ad2.tar.gz chromium_src-7427a2fea91dcd0331628297cc08a33eb1765ad2.tar.bz2 |
Decouple GuestViewContainer from Extensions
This CL does the following:
1. It moves ExtensionsGuestViewContainer::Request/AttachRequest/DetachRequest to guest_view_request.*
2. It moves the queuing functionality for attach/detach to guest_view_container.*
3. It removes extensions dependencies in guest_view_container
A subsequent patch will move extensions/this to components.
BUG=444869
Review URL: https://codereview.chromium.org/1118243003
Cr-Commit-Position: refs/heads/master@{#328974}
Diffstat (limited to 'extensions/renderer/guest_view')
9 files changed, 377 insertions, 321 deletions
diff --git a/extensions/renderer/guest_view/extensions_guest_view_container.cc b/extensions/renderer/guest_view/extensions_guest_view_container.cc index 5b43598..358f800 100644 --- a/extensions/renderer/guest_view/extensions_guest_view_container.cc +++ b/extensions/renderer/guest_view/extensions_guest_view_container.cc @@ -4,157 +4,21 @@ #include "extensions/renderer/guest_view/extensions_guest_view_container.h" -#include "components/guest_view/common/guest_view_constants.h" -#include "components/guest_view/common/guest_view_messages.h" #include "content/public/renderer/render_frame.h" -#include "content/public/renderer/render_view.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::map<int, extensions::ExtensionsGuestViewContainer*> - ExtensionsGuestViewContainerMap; -static base::LazyInstance<ExtensionsGuestViewContainerMap> - g_guest_view_container_map = LAZY_INSTANCE_INITIALIZER; -} // namespace +#include "ui/gfx/geometry/size.h" namespace extensions { -ExtensionsGuestViewContainer::Request::Request(GuestViewContainer* container, - v8::Local<v8::Function> callback, - v8::Isolate* isolate) - : container_(container), callback_(isolate, callback), isolate_(isolate) { -} - -ExtensionsGuestViewContainer::Request::~Request() { -} - -bool ExtensionsGuestViewContainer::Request::HasCallback() const { - return !callback_.IsEmpty(); -} - -v8::Local<v8::Function> ExtensionsGuestViewContainer::Request::GetCallback() - const { - return v8::Local<v8::Function>::New(isolate_, callback_); -} - -void ExtensionsGuestViewContainer::Request::ExecuteCallbackIfAvailable( - int argc, - scoped_ptr<v8::Local<v8::Value>[]> argv) { - if (!HasCallback()) - return; - - v8::HandleScope handle_scope(isolate()); - v8::Local<v8::Function> callback = GetCallback(); - v8::Local<v8::Context> context = callback->CreationContext(); - if (context.IsEmpty()) - return; - - 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.get()); -} - -ExtensionsGuestViewContainer::AttachRequest::AttachRequest( - GuestViewContainer* container, - int guest_instance_id, - scoped_ptr<base::DictionaryValue> params, - v8::Local<v8::Function> callback, - v8::Isolate* isolate) - : Request(container, callback, isolate), - guest_instance_id_(guest_instance_id), - params_(params.Pass()) { -} - -ExtensionsGuestViewContainer::AttachRequest::~AttachRequest() { -} - -void ExtensionsGuestViewContainer::AttachRequest::PerformRequest() { - if (!container()->render_frame()) - return; - - // Step 1, send the attach params to extensions/. - container()->render_frame()->Send( - new GuestViewHostMsg_AttachGuest(container()->element_instance_id(), - guest_instance_id_, - *params_)); - - // Step 2, attach plugin through content/. - container()->render_frame()->AttachGuest(container()->element_instance_id()); -} - -void ExtensionsGuestViewContainer::AttachRequest::HandleResponse( - const IPC::Message& message) { - GuestViewMsg_GuestAttached::Param param; - if (!GuestViewMsg_GuestAttached::Read(&message, ¶m)) - return; - - content::RenderView* guest_proxy_render_view = - content::RenderView::FromRoutingID(get<1>(param)); - // TODO(fsamuel): Should we be reporting an error to JavaScript or DCHECKing? - if (!guest_proxy_render_view) - return; - - v8::HandleScope handle_scope(isolate()); - blink::WebFrame* frame = guest_proxy_render_view->GetWebView()->mainFrame(); - v8::Local<v8::Value> window = frame->mainWorldScriptContext()->Global(); - - const int argc = 1; - scoped_ptr<v8::Local<v8::Value>[]> argv(new v8::Local<v8::Value>[argc]); - argv[0] = window; - - ExecuteCallbackIfAvailable(argc, argv.Pass()); -} - -ExtensionsGuestViewContainer::DetachRequest::DetachRequest( - GuestViewContainer* container, - v8::Local<v8::Function> callback, - v8::Isolate* isolate) - : Request(container, callback, isolate) { -} - -ExtensionsGuestViewContainer::DetachRequest::~DetachRequest() { -} - -void ExtensionsGuestViewContainer::DetachRequest::PerformRequest() { - if (!container()->render_frame()) - return; - - container()->render_frame()->DetachGuest(container()->element_instance_id()); -} - -void ExtensionsGuestViewContainer::DetachRequest::HandleResponse( - const IPC::Message& message) { - ExecuteCallbackIfAvailable(0 /* argc */, nullptr); -} - ExtensionsGuestViewContainer::ExtensionsGuestViewContainer( content::RenderFrame* render_frame) : GuestViewContainer(render_frame), - ready_(false), destruction_isolate_(nullptr), element_resize_isolate_(nullptr), weak_ptr_factory_(this) { } ExtensionsGuestViewContainer::~ExtensionsGuestViewContainer() { - if (element_instance_id() != guest_view::kInstanceIDNone) - g_guest_view_container_map.Get().erase(element_instance_id()); - - if (pending_response_.get()) - pending_response_->ExecuteCallbackIfAvailable(0 /* argc */, nullptr); - - while (pending_requests_.size() > 0) { - linked_ptr<Request> pending_request = pending_requests_.front(); - pending_requests_.pop_front(); - // Call the JavaScript callbacks with no arguments which implies an error. - pending_request->ExecuteCallbackIfAvailable(0 /* argc */, nullptr); - } - // Call the destruction callback, if one is registered. if (!destruction_callback_.IsEmpty()) { v8::HandleScope handle_scope(destruction_isolate_); @@ -171,19 +35,6 @@ ExtensionsGuestViewContainer::~ExtensionsGuestViewContainer() { } } -ExtensionsGuestViewContainer* ExtensionsGuestViewContainer::FromID( - int element_instance_id) { - ExtensionsGuestViewContainerMap* guest_view_containers = - g_guest_view_container_map.Pointer(); - auto it = guest_view_containers->find(element_instance_id); - return it == guest_view_containers->end() ? nullptr : it->second; -} - -void ExtensionsGuestViewContainer::IssueRequest(linked_ptr<Request> request) { - EnqueueRequest(request); - PerformPendingRequest(); -} - void ExtensionsGuestViewContainer::RegisterDestructionCallback( v8::Local<v8::Function> callback, v8::Isolate* isolate) { @@ -210,36 +61,6 @@ void ExtensionsGuestViewContainer::DidResizeElement(const gfx::Size& old_size, weak_ptr_factory_.GetWeakPtr(), old_size, new_size)); } -bool ExtensionsGuestViewContainer::OnMessageReceived( - const IPC::Message& message) { - OnHandleCallback(message); - return true; -} - -void ExtensionsGuestViewContainer::SetElementInstanceID( - int element_instance_id) { - GuestViewContainer::SetElementInstanceID(element_instance_id); - - DCHECK(g_guest_view_container_map.Get().find(element_instance_id) == - g_guest_view_container_map.Get().end()); - g_guest_view_container_map.Get().insert( - std::make_pair(element_instance_id, this)); -} - -void ExtensionsGuestViewContainer::Ready() { - ready_ = true; - CHECK(!pending_response_.get()); - PerformPendingRequest(); -} - -void ExtensionsGuestViewContainer::OnHandleCallback( - const IPC::Message& message) { - // Handle the callback for the current request with a pending response. - HandlePendingResponseCallback(message); - // Perform the subsequent attach request if one exists. - PerformPendingRequest(); -} - void ExtensionsGuestViewContainer::CallElementResizeCallback( const gfx::Size& old_size, const gfx::Size& new_size) { @@ -263,25 +84,4 @@ void ExtensionsGuestViewContainer::CallElementResizeCallback( callback->Call(context->Global(), argc, argv); } -void ExtensionsGuestViewContainer::EnqueueRequest(linked_ptr<Request> request) { - pending_requests_.push_back(request); -} - -void ExtensionsGuestViewContainer::PerformPendingRequest() { - if (!ready_ || pending_requests_.empty() || pending_response_.get()) - return; - - linked_ptr<Request> pending_request = pending_requests_.front(); - pending_requests_.pop_front(); - pending_request->PerformRequest(); - pending_response_ = pending_request; -} - -void ExtensionsGuestViewContainer::HandlePendingResponseCallback( - const IPC::Message& message) { - CHECK(pending_response_.get()); - linked_ptr<Request> pending_response(pending_response_.release()); - pending_response->HandleResponse(message); -} - } // namespace extensions diff --git a/extensions/renderer/guest_view/extensions_guest_view_container.h b/extensions/renderer/guest_view/extensions_guest_view_container.h index f1a6622..0a29daf 100644 --- a/extensions/renderer/guest_view/extensions_guest_view_container.h +++ b/extensions/renderer/guest_view/extensions_guest_view_container.h @@ -7,9 +7,6 @@ #include <queue> -#include "base/memory/linked_ptr.h" -#include "base/memory/scoped_ptr.h" -#include "base/values.h" #include "extensions/renderer/guest_view/guest_view_container.h" #include "v8/include/v8.h" @@ -21,97 +18,21 @@ namespace extensions { class ExtensionsGuestViewContainer : public GuestViewContainer { public: - - class Request { - public: - Request(GuestViewContainer* container, - v8::Local<v8::Function> callback, - v8::Isolate* isolate); - virtual ~Request(); - - virtual void PerformRequest() = 0; - virtual void HandleResponse(const IPC::Message& message) = 0; - - void ExecuteCallbackIfAvailable(int argc, - scoped_ptr<v8::Local<v8::Value>[]> argv); - - GuestViewContainer* container() const { return container_; } - - bool HasCallback() const; - - v8::Local<v8::Function> GetCallback() const; - - v8::Isolate* isolate() const { return isolate_; } - - private: - GuestViewContainer* container_; - v8::Global<v8::Function> callback_; - v8::Isolate* const isolate_; - }; - - // This class represents an AttachGuest request from Javascript. It includes - // the input parameters and the callback function. The Attach operation may - // not execute immediately, if the container is not ready or if there are - // other attach operations in flight. - class AttachRequest : public Request { - public: - AttachRequest(GuestViewContainer* container, - int guest_instance_id, - scoped_ptr<base::DictionaryValue> params, - v8::Local<v8::Function> callback, - v8::Isolate* isolate); - ~AttachRequest() override; - - void PerformRequest() override; - void HandleResponse(const IPC::Message& message) override; - - private: - const int guest_instance_id_; - scoped_ptr<base::DictionaryValue> params_; - }; - - class DetachRequest : public Request { - public: - DetachRequest(GuestViewContainer* container, - v8::Local<v8::Function> callback, - v8::Isolate* isolate); - ~DetachRequest() override; - - void PerformRequest() override; - void HandleResponse(const IPC::Message& message) override; - }; - explicit ExtensionsGuestViewContainer(content::RenderFrame* render_frame); ~ExtensionsGuestViewContainer() override; - static ExtensionsGuestViewContainer* FromID(int element_instance_id); - - void IssueRequest(linked_ptr<Request> request); void RegisterDestructionCallback(v8::Local<v8::Function> callback, v8::Isolate* isolate); void RegisterElementResizeCallback(v8::Local<v8::Function> callback, v8::Isolate* isolate); // BrowserPluginDelegate implementation. - bool OnMessageReceived(const IPC::Message& message) override; - void SetElementInstanceID(int element_instance_id) override; - void Ready() override; void DidResizeElement(const gfx::Size& old_size, const gfx::Size& new_size) override; private: - void OnHandleCallback(const IPC::Message& message); - void CallElementResizeCallback(const gfx::Size& old_size, const gfx::Size& new_size); - void EnqueueRequest(linked_ptr<Request> request); - void PerformPendingRequest(); - void HandlePendingResponseCallback(const IPC::Message& message); - - bool ready_; - - std::deque<linked_ptr<Request> > pending_requests_; - linked_ptr<Request> pending_response_; v8::Global<v8::Function> destruction_callback_; v8::Isolate* destruction_isolate_; diff --git a/extensions/renderer/guest_view/guest_view_container.cc b/extensions/renderer/guest_view/guest_view_container.cc index be6316d..d09fa00 100644 --- a/extensions/renderer/guest_view/guest_view_container.cc +++ b/extensions/renderer/guest_view/guest_view_container.cc @@ -10,6 +10,15 @@ #include "content/public/renderer/render_frame_observer.h" #include "content/public/renderer/render_view.h" #include "extensions/common/guest_view/extensions_guest_view_messages.h" +#include "extensions/renderer/guest_view/guest_view_request.h" + +namespace { + +using GuestViewContainerMap = std::map<int, extensions::GuestViewContainer*>; +static base::LazyInstance<GuestViewContainerMap> g_guest_view_container_map = + LAZY_INSTANCE_INITIALIZER; + +} // namespace namespace extensions { @@ -40,17 +49,33 @@ void GuestViewContainer::RenderFrameLifetimeObserver::OnDestruct() { GuestViewContainer::GuestViewContainer(content::RenderFrame* render_frame) : element_instance_id_(guest_view::kInstanceIDNone), - render_frame_(render_frame) { + render_frame_(render_frame), + ready_(false) { render_frame_lifetime_observer_.reset( new RenderFrameLifetimeObserver(this, render_frame_)); } -GuestViewContainer::~GuestViewContainer() {} +GuestViewContainer::~GuestViewContainer() { + if (element_instance_id() != guest_view::kInstanceIDNone) + g_guest_view_container_map.Get().erase(element_instance_id()); + + if (pending_response_.get()) + pending_response_->ExecuteCallbackIfAvailable(0 /* argc */, nullptr); + + while (pending_requests_.size() > 0) { + linked_ptr<GuestViewRequest> pending_request = pending_requests_.front(); + pending_requests_.pop_front(); + // Call the JavaScript callbacks with no arguments which implies an error. + pending_request->ExecuteCallbackIfAvailable(0 /* argc */, nullptr); + } +} // static. -bool GuestViewContainer::HandlesMessage(const IPC::Message& msg) { - return (IPC_MESSAGE_CLASS(msg) == GuestViewMsgStart) || - (IPC_MESSAGE_CLASS(msg) == ExtensionsGuestViewMsgStart); +GuestViewContainer* GuestViewContainer::FromID(int element_instance_id) { + GuestViewContainerMap* guest_view_containers = + g_guest_view_container_map.Pointer(); + auto it = guest_view_containers->find(element_instance_id); + return it == guest_view_containers->end() ? nullptr : it->second; } void GuestViewContainer::RenderFrameDestroyed() { @@ -58,9 +83,68 @@ void GuestViewContainer::RenderFrameDestroyed() { render_frame_ = nullptr; } +void GuestViewContainer::IssueRequest(linked_ptr<GuestViewRequest> request) { + EnqueueRequest(request); + PerformPendingRequest(); +} + +void GuestViewContainer::EnqueueRequest(linked_ptr<GuestViewRequest> request) { + pending_requests_.push_back(request); +} + +void GuestViewContainer::PerformPendingRequest() { + if (!ready_ || pending_requests_.empty() || pending_response_.get()) + return; + + linked_ptr<GuestViewRequest> pending_request = pending_requests_.front(); + pending_requests_.pop_front(); + pending_request->PerformRequest(); + pending_response_ = pending_request; +} + +void GuestViewContainer::HandlePendingResponseCallback( + const IPC::Message& message) { + CHECK(pending_response_.get()); + linked_ptr<GuestViewRequest> pending_response(pending_response_.release()); + pending_response->HandleResponse(message); +} + +void GuestViewContainer::OnHandleCallback(const IPC::Message& message) { + // Handle the callback for the current request with a pending response. + HandlePendingResponseCallback(message); + // Perform the subsequent request if one exists. + PerformPendingRequest(); +} + +bool GuestViewContainer::OnMessage(const IPC::Message& message) { + return false; +} + +bool GuestViewContainer::OnMessageReceived(const IPC::Message& message) { + if (OnMessage(message)) + return true; + + OnHandleCallback(message); + return true; +} + +void GuestViewContainer::Ready() { + ready_ = true; + CHECK(!pending_response_.get()); + PerformPendingRequest(); + + // Give the derived type an opportunity to perform some actions when the + // container acquires a geometry. + OnReady(); +} + void GuestViewContainer::SetElementInstanceID(int element_instance_id) { DCHECK_EQ(element_instance_id_, guest_view::kInstanceIDNone); element_instance_id_ = element_instance_id; + + DCHECK(!g_guest_view_container_map.Get().count(element_instance_id)); + g_guest_view_container_map.Get().insert( + std::make_pair(element_instance_id, this)); } } // namespace extensions diff --git a/extensions/renderer/guest_view/guest_view_container.h b/extensions/renderer/guest_view/guest_view_container.h index 42ec6e14..8855dd7 100644 --- a/extensions/renderer/guest_view/guest_view_container.h +++ b/extensions/renderer/guest_view/guest_view_container.h @@ -5,37 +5,66 @@ #ifndef EXTENSIONS_RENDERER_GUEST_VIEW_GUEST_VIEW_CONTAINER_H_ #define EXTENSIONS_RENDERER_GUEST_VIEW_GUEST_VIEW_CONTAINER_H_ +#include "base/memory/linked_ptr.h" #include "base/memory/scoped_ptr.h" #include "content/public/renderer/browser_plugin_delegate.h" #include "ipc/ipc_message.h" namespace extensions { +class GuestViewRequest; + class GuestViewContainer : public content::BrowserPluginDelegate { public: explicit GuestViewContainer(content::RenderFrame* render_frame); ~GuestViewContainer() override; - // Queries whether GuestViewContainer is interested in the |message|. - static bool HandlesMessage(const IPC::Message& message); - - void RenderFrameDestroyed(); + static GuestViewContainer* FromID(int element_instance_id); - // BrowserPluginDelegate implementation. - void SetElementInstanceID(int element_instance_id) override; + // IssueRequest queues up a |request| until the container is ready and + // the browser process has responded to the last request if it's still + // pending. + void IssueRequest(linked_ptr<GuestViewRequest> request); int element_instance_id() const { return element_instance_id_; } content::RenderFrame* render_frame() const { return render_frame_; } + // Called when the embedding RenderFrame is destroyed. virtual void OnRenderFrameDestroyed() {} + // Called to respond to IPCs from the browser process that have not been + // handled by GuestViewContainer. + virtual bool OnMessage(const IPC::Message& message); + + // Called to perform actions when a GuestViewContainer gets a geometry. + virtual void OnReady() {} + private: class RenderFrameLifetimeObserver; + friend class RenderFrameLifetimeObserver; + + void RenderFrameDestroyed(); + + void EnqueueRequest(linked_ptr<GuestViewRequest> request); + void PerformPendingRequest(); + void HandlePendingResponseCallback(const IPC::Message& message); + + void OnHandleCallback(const IPC::Message& message); + + // BrowserPluginDelegate implementation. + bool OnMessageReceived(const IPC::Message& message) final; + void Ready() final; + void SetElementInstanceID(int element_instance_id) final; int element_instance_id_; content::RenderFrame* render_frame_; scoped_ptr<RenderFrameLifetimeObserver> render_frame_lifetime_observer_; + bool ready_; + + std::deque<linked_ptr<GuestViewRequest> > pending_requests_; + linked_ptr<GuestViewRequest> pending_response_; + DISALLOW_COPY_AND_ASSIGN(GuestViewContainer); }; diff --git a/extensions/renderer/guest_view/guest_view_internal_custom_bindings.cc b/extensions/renderer/guest_view/guest_view_internal_custom_bindings.cc index 9f8d952..902465f 100644 --- a/extensions/renderer/guest_view/guest_view_internal_custom_bindings.cc +++ b/extensions/renderer/guest_view/guest_view_internal_custom_bindings.cc @@ -13,6 +13,7 @@ #include "extensions/common/extension.h" #include "extensions/common/extension_messages.h" #include "extensions/renderer/guest_view/extensions_guest_view_container.h" +#include "extensions/renderer/guest_view/guest_view_request.h" #include "extensions/renderer/script_context.h" #include "third_party/WebKit/public/web/WebFrame.h" #include "third_party/WebKit/public/web/WebScopedUserGesture.h" @@ -64,9 +65,8 @@ void GuestViewInternalCustomBindings::AttachGuest( CHECK(args.Length() < 4 || args[3]->IsFunction()); int element_instance_id = args[0]->Int32Value(); - // An element instance ID uniquely identifies a ExtensionsGuestViewContainer. - ExtensionsGuestViewContainer* guest_view_container = - ExtensionsGuestViewContainer::FromID(element_instance_id); + // An element instance ID uniquely identifies a GuestViewContainer. + auto guest_view_container = GuestViewContainer::FromID(element_instance_id); // TODO(fsamuel): Should we be reporting an error if the element instance ID // is invalid? @@ -89,8 +89,8 @@ void GuestViewInternalCustomBindings::AttachGuest( // logical units. params->SetBoolean(guest_view::kElementSizeIsLogical, true); - linked_ptr<ExtensionsGuestViewContainer::Request> request( - new ExtensionsGuestViewContainer::AttachRequest( + linked_ptr<GuestViewRequest> request( + new GuestViewAttachRequest( guest_view_container, guest_instance_id, params.Pass(), args.Length() == 4 ? args[3].As<v8::Function>() : v8::Local<v8::Function>(), @@ -110,17 +110,16 @@ void GuestViewInternalCustomBindings::DetachGuest( CHECK(args.Length() < 2 || args[1]->IsFunction()); int element_instance_id = args[0]->Int32Value(); - // An element instance ID uniquely identifies a ExtensionsGuestViewContainer. - ExtensionsGuestViewContainer* guest_view_container = - ExtensionsGuestViewContainer::FromID(element_instance_id); + // An element instance ID uniquely identifies a GuestViewContainer. + auto guest_view_container = GuestViewContainer::FromID(element_instance_id); // TODO(fsamuel): Should we be reporting an error if the element instance ID // is invalid? if (!guest_view_container) return; - linked_ptr<ExtensionsGuestViewContainer::Request> request( - new ExtensionsGuestViewContainer::DetachRequest( + linked_ptr<GuestViewRequest> request( + new GuestViewDetachRequest( guest_view_container, args.Length() == 2 ? args[1].As<v8::Function>() : v8::Local<v8::Function>(), args.GetIsolate())); @@ -166,8 +165,8 @@ void GuestViewInternalCustomBindings::RegisterDestructionCallback( int element_instance_id = args[0]->Int32Value(); // An element instance ID uniquely identifies a ExtensionsGuestViewContainer // within a RenderView. - ExtensionsGuestViewContainer* guest_view_container = - ExtensionsGuestViewContainer::FromID(element_instance_id); + auto guest_view_container = static_cast<ExtensionsGuestViewContainer*>( + GuestViewContainer::FromID(element_instance_id)); if (!guest_view_container) return; @@ -189,8 +188,8 @@ void GuestViewInternalCustomBindings::RegisterElementResizeCallback( int element_instance_id = args[0]->Int32Value(); // An element instance ID uniquely identifies a ExtensionsGuestViewContainer // within a RenderView. - ExtensionsGuestViewContainer* guest_view_container = - ExtensionsGuestViewContainer::FromID(element_instance_id); + auto guest_view_container = static_cast<ExtensionsGuestViewContainer*>( + GuestViewContainer::FromID(element_instance_id)); if (!guest_view_container) return; diff --git a/extensions/renderer/guest_view/guest_view_request.cc b/extensions/renderer/guest_view/guest_view_request.cc new file mode 100644 index 0000000..78251d9 --- /dev/null +++ b/extensions/renderer/guest_view/guest_view_request.cc @@ -0,0 +1,123 @@ +// Copyright 2015 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 "extensions/renderer/guest_view/guest_view_request.h" + +#include "components/guest_view/common/guest_view_messages.h" +#include "content/public/renderer/render_frame.h" +#include "content/public/renderer/render_view.h" +#include "extensions/renderer/guest_view/guest_view_container.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 extensions { + +GuestViewRequest::GuestViewRequest(GuestViewContainer* container, + v8::Local<v8::Function> callback, + v8::Isolate* isolate) + : container_(container), + callback_(isolate, callback), + isolate_(isolate) { +} + +GuestViewRequest::~GuestViewRequest() { +} + +void GuestViewRequest::ExecuteCallbackIfAvailable( + int argc, + scoped_ptr<v8::Local<v8::Value>[]> argv) { + if (callback_.IsEmpty()) + return; + + v8::HandleScope handle_scope(isolate()); + v8::Local<v8::Function> callback = + v8::Local<v8::Function>::New(isolate_, callback_); + v8::Local<v8::Context> context = callback->CreationContext(); + if (context.IsEmpty()) + return; + + v8::Context::Scope context_scope(context); + blink::WebScopedMicrotaskSuppression suppression; + + callback->Call(context->Global(), argc, argv.get()); +} + +GuestViewAttachRequest::GuestViewAttachRequest( + GuestViewContainer* container, + int guest_instance_id, + scoped_ptr<base::DictionaryValue> params, + v8::Local<v8::Function> callback, + v8::Isolate* isolate) + : GuestViewRequest(container, callback, isolate), + guest_instance_id_(guest_instance_id), + params_(params.Pass()) { +} + +GuestViewAttachRequest::~GuestViewAttachRequest() { +} + +void GuestViewAttachRequest::PerformRequest() { + if (!container()->render_frame()) + return; + + // Step 1, send the attach params to extensions/. + container()->render_frame()->Send( + new GuestViewHostMsg_AttachGuest(container()->element_instance_id(), + guest_instance_id_, + *params_)); + + // Step 2, attach plugin through content/. + container()->render_frame()->AttachGuest(container()->element_instance_id()); +} + +void GuestViewAttachRequest::HandleResponse(const IPC::Message& message) { + // TODO(fsamuel): Rename this message so that it's apparent that this is a + // response to GuestViewHostMsg_AttachGuest. Perhaps + // GuestViewMsg_AttachGuest_ACK? + GuestViewMsg_GuestAttached::Param param; + if (!GuestViewMsg_GuestAttached::Read(&message, ¶m)) + return; + + content::RenderView* guest_proxy_render_view = + content::RenderView::FromRoutingID(get<1>(param)); + // TODO(fsamuel): Should we be reporting an error to JavaScript or DCHECKing? + if (!guest_proxy_render_view) + return; + + v8::HandleScope handle_scope(isolate()); + blink::WebFrame* frame = guest_proxy_render_view->GetWebView()->mainFrame(); + v8::Local<v8::Value> window = frame->mainWorldScriptContext()->Global(); + + const int argc = 1; + scoped_ptr<v8::Local<v8::Value>[]> argv(new v8::Local<v8::Value>[argc]); + argv[0] = window; + + // Call the AttachGuest API's callback with the guest proxy as the first + // parameter. + ExecuteCallbackIfAvailable(argc, argv.Pass()); +} + +GuestViewDetachRequest::GuestViewDetachRequest( + GuestViewContainer* container, + v8::Local<v8::Function> callback, + v8::Isolate* isolate) + : GuestViewRequest(container, callback, isolate) { +} + +GuestViewDetachRequest::~GuestViewDetachRequest() { +} + +void GuestViewDetachRequest::PerformRequest() { + if (!container()->render_frame()) + return; + + container()->render_frame()->DetachGuest(container()->element_instance_id()); +} + +void GuestViewDetachRequest::HandleResponse(const IPC::Message& message) { + ExecuteCallbackIfAvailable(0 /* argc */, nullptr); +} + +} // namespace extensions diff --git a/extensions/renderer/guest_view/guest_view_request.h b/extensions/renderer/guest_view/guest_view_request.h new file mode 100644 index 0000000..dbb7343 --- /dev/null +++ b/extensions/renderer/guest_view/guest_view_request.h @@ -0,0 +1,97 @@ +// Copyright 2015 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. + +#ifndef EXTENSIONS_RENDERER_GUEST_VIEW_EXTENSIONS_GUEST_VIEW_REQUEST_H_ +#define EXTENSIONS_RENDERER_GUEST_VIEW_EXTENSIONS_GUEST_VIEW_REQUEST_H_ + +#include "ipc/ipc_message.h" +#include "v8/include/v8.h" + +namespace extensions { + +class GuestViewContainer; + +// A GuestViewRequest is the base class for an asynchronous operation performed +// on a GuestView or GuestViewContainer from JavaScript. This operation may be +// queued until the container is ready to be operated upon (it has geometry). +// A GuestViewRequest may or may not have a callback back into JavaScript. +// Typically, performing a request involves sending an IPC to the browser +// process in PerformRequest. Handling a response involves receiving a related +// IPC from the browser process in HandleResponse. +class GuestViewRequest { + public: + GuestViewRequest(GuestViewContainer* container, + v8::Local<v8::Function> callback, + v8::Isolate* isolate); + virtual ~GuestViewRequest(); + + // Performs the associated request. + virtual void PerformRequest() = 0; + + // Called by GuestViewContainer when the browser process has responded to the + // request initiated by PerformRequest. + virtual void HandleResponse(const IPC::Message& message) = 0; + + // Called to call the callback associated with this request if one is + // available. + // Note: the callback may be called even if a response has not been heard from + // the browser process if the GuestViewContainer is being torn down. + void ExecuteCallbackIfAvailable(int argc, + scoped_ptr<v8::Local<v8::Value>[]> argv); + + GuestViewContainer* container() const { return container_; } + + v8::Isolate* isolate() const { return isolate_; } + + private: + GuestViewContainer* const container_; + v8::Global<v8::Function> callback_; + v8::Isolate* const isolate_; + + DISALLOW_COPY_AND_ASSIGN(GuestViewRequest); +}; + +// This class represents an AttachGuest request from Javascript. It includes +// the input parameters and the callback function. The Attach operation may +// not execute immediately, if the container is not ready or if there are +// other GuestViewRequests in flight. +class GuestViewAttachRequest : public GuestViewRequest { + public: + GuestViewAttachRequest(GuestViewContainer* container, + int guest_instance_id, + scoped_ptr<base::DictionaryValue> params, + v8::Local<v8::Function> callback, + v8::Isolate* isolate); + ~GuestViewAttachRequest() override; + + void PerformRequest() override; + void HandleResponse(const IPC::Message& message) override; + + private: + const int guest_instance_id_; + scoped_ptr<base::DictionaryValue> params_; + + DISALLOW_COPY_AND_ASSIGN(GuestViewAttachRequest); +}; + +// This class represents a DetachGuest request from Javascript. The Detach +// operation may not execute immediately, if the container is not ready or if +// there are other GuestViewRequests in flight. +class GuestViewDetachRequest : public GuestViewRequest { + public: + GuestViewDetachRequest(GuestViewContainer* container, + v8::Local<v8::Function> callback, + v8::Isolate* isolate); + ~GuestViewDetachRequest() override; + + void PerformRequest() override; + void HandleResponse(const IPC::Message& message) override; + + private: + DISALLOW_COPY_AND_ASSIGN(GuestViewDetachRequest); +}; + +} // namespace extensions + +#endif // EXTENSIONS_RENDERER_GUEST_VIEW_EXTENSIONS_GUEST_VIEW_CONTAINER_H_ diff --git a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.cc b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.cc index 67add24..812f381 100644 --- a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.cc +++ b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.cc @@ -129,7 +129,7 @@ MimeHandlerViewContainer::FromRenderFrame(content::RenderFrame* render_frame) { it->second.end()); } -void MimeHandlerViewContainer::Ready() { +void MimeHandlerViewContainer::OnReady() { if (!render_frame()) return; @@ -148,6 +148,20 @@ void MimeHandlerViewContainer::Ready() { loader_->loadAsynchronously(request, this); } +bool MimeHandlerViewContainer::OnMessage(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(MimeHandlerViewContainer, message) + IPC_MESSAGE_HANDLER(ExtensionsGuestViewMsg_CreateMimeHandlerViewGuestACK, + OnCreateMimeHandlerViewGuestACK) + IPC_MESSAGE_HANDLER( + ExtensionsGuestViewMsg_MimeHandlerViewGuestOnLoadCompleted, + OnMimeHandlerViewGuestOnLoadCompleted) + IPC_MESSAGE_HANDLER(GuestViewMsg_GuestAttached, OnGuestAttached) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + void MimeHandlerViewContainer::DidFinishLoading() { DCHECK(!is_embedded_); CreateMimeHandlerViewGuest(); @@ -162,19 +176,6 @@ void MimeHandlerViewContainer::DidReceiveData(const char* data, view_id_ += std::string(data, data_length); } -bool MimeHandlerViewContainer::OnMessageReceived(const IPC::Message& message) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(MimeHandlerViewContainer, message) - IPC_MESSAGE_HANDLER(ExtensionsGuestViewMsg_CreateMimeHandlerViewGuestACK, - OnCreateMimeHandlerViewGuestACK) - IPC_MESSAGE_HANDLER( - ExtensionsGuestViewMsg_MimeHandlerViewGuestOnLoadCompleted, - OnMimeHandlerViewGuestOnLoadCompleted) - IPC_MESSAGE_HANDLER(GuestViewMsg_GuestAttached, OnGuestAttached) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; -} void MimeHandlerViewContainer::DidResizeElement(const gfx::Size& old_size, const gfx::Size& new_size) { diff --git a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h index b08f1c9..00f0211 100644 --- a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h +++ b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h @@ -46,13 +46,15 @@ class MimeHandlerViewContainer : public GuestViewContainer, static std::vector<MimeHandlerViewContainer*> FromRenderFrame( content::RenderFrame* render_frame); + // GuestViewContainer implementation. + bool OnMessage(const IPC::Message& message) override; + void OnReady() override; + // BrowserPluginDelegate implementation. - void Ready() override; void DidFinishLoading() override; void DidReceiveData(const char* data, int data_length) override; void DidResizeElement(const gfx::Size& old_size, const gfx::Size& new_size) override; - bool OnMessageReceived(const IPC::Message& message) override; v8::Local<v8::Object> V8ScriptableObject(v8::Isolate*) override; // WebURLLoaderClient overrides. |