diff options
Diffstat (limited to 'components/guest_view')
-rw-r--r-- | components/guest_view/browser/BUILD.gn (renamed from components/guest_view/BUILD.gn) | 12 | ||||
-rw-r--r-- | components/guest_view/common/BUILD.gn | 15 | ||||
-rw-r--r-- | components/guest_view/renderer/BUILD.gn | 17 | ||||
-rw-r--r-- | components/guest_view/renderer/DEPS | 6 | ||||
-rw-r--r-- | components/guest_view/renderer/OWNERS | 3 | ||||
-rw-r--r-- | components/guest_view/renderer/guest_view_container.cc | 149 | ||||
-rw-r--r-- | components/guest_view/renderer/guest_view_container.h | 73 | ||||
-rw-r--r-- | components/guest_view/renderer/guest_view_request.cc | 123 | ||||
-rw-r--r-- | components/guest_view/renderer/guest_view_request.h | 97 |
9 files changed, 487 insertions, 8 deletions
diff --git a/components/guest_view/BUILD.gn b/components/guest_view/browser/BUILD.gn index 0beda18..7bc221f 100644 --- a/components/guest_view/BUILD.gn +++ b/components/guest_view/browser/BUILD.gn @@ -2,8 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -static_library("guest_view") { - output_name = "guest_view" +static_library("browser") { + output_name = "guest_view_browser" sources = [ "//components/guest_view/browser/guest_view.h", "//components/guest_view/browser/guest_view_base.cc", @@ -17,15 +17,11 @@ static_library("guest_view") { "//components/guest_view/browser/guest_view_manager_factory.h", "//components/guest_view/browser/guest_view_message_filter.cc", "//components/guest_view/browser/guest_view_message_filter.h", - "//components/guest_view/common/guest_view_constants.cc", - "//components/guest_view/common/guest_view_constants.h", - "//components/guest_view/common/guest_view_message_generator.cc", - "//components/guest_view/common/guest_view_message_generator.h", - "//components/guest_view/common/guest_view_messages.h", ] deps = [ "//base", + "//components/guest_view/common", "//content/public/browser", "//content/public/common", "//third_party/WebKit/public:blink", @@ -40,7 +36,7 @@ static_library("test_support") { ] deps = [ - ":guest_view", + ":browser", "//content/test:test_support", ] } diff --git a/components/guest_view/common/BUILD.gn b/components/guest_view/common/BUILD.gn new file mode 100644 index 0000000..9916d95a --- /dev/null +++ b/components/guest_view/common/BUILD.gn @@ -0,0 +1,15 @@ +static_library("common") { + output_name = "guest_view_common" + sources = [ + "guest_view_constants.cc", + "guest_view_constants.h", + "guest_view_message_generator.cc", + "guest_view_message_generator.h", + "guest_view_messages.h", + ] + + deps = [ + "//base", + "//ipc", + ] +} diff --git a/components/guest_view/renderer/BUILD.gn b/components/guest_view/renderer/BUILD.gn new file mode 100644 index 0000000..200070b --- /dev/null +++ b/components/guest_view/renderer/BUILD.gn @@ -0,0 +1,17 @@ +static_library("renderer") { + sources = [ + "guest_view_container.cc", + "guest_view_container.h", + "guest_view_request.cc", + "guest_view_request.h" + ] + + deps = [ + "//base", + "//components/guest_view/common", + "//content/public/renderer", + "//ipc", + "//third_party/WebKit/public:blink", + "//v8", + ] +} diff --git a/components/guest_view/renderer/DEPS b/components/guest_view/renderer/DEPS new file mode 100644 index 0000000..2f9ba27 --- /dev/null +++ b/components/guest_view/renderer/DEPS @@ -0,0 +1,6 @@ +include_rules = [ + "+content/public/renderer", + "+ipc", + "+third_party/WebKit/public", + "+v8/include/v8.h", +] diff --git a/components/guest_view/renderer/OWNERS b/components/guest_view/renderer/OWNERS new file mode 100644 index 0000000..f9575e8 --- /dev/null +++ b/components/guest_view/renderer/OWNERS @@ -0,0 +1,3 @@ +fsamuel@chromium.org +lazyboy@chromium.org +hanxi@chromium.org diff --git a/components/guest_view/renderer/guest_view_container.cc b/components/guest_view/renderer/guest_view_container.cc new file mode 100644 index 0000000..1c13456 --- /dev/null +++ b/components/guest_view/renderer/guest_view_container.cc @@ -0,0 +1,149 @@ +// Copyright 2014 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 "components/guest_view/renderer/guest_view_container.h" + +#include "components/guest_view/common/guest_view_constants.h" +#include "components/guest_view/common/guest_view_messages.h" +#include "components/guest_view/renderer/guest_view_request.h" +#include "content/public/renderer/render_frame.h" +#include "content/public/renderer/render_frame_observer.h" +#include "content/public/renderer/render_view.h" + +namespace { + +using GuestViewContainerMap = std::map<int, guest_view::GuestViewContainer*>; +static base::LazyInstance<GuestViewContainerMap> g_guest_view_container_map = + LAZY_INSTANCE_INITIALIZER; + +} // namespace + +namespace guest_view { + +class GuestViewContainer::RenderFrameLifetimeObserver + : public content::RenderFrameObserver { + public: + RenderFrameLifetimeObserver(GuestViewContainer* container, + content::RenderFrame* render_frame); + + // content::RenderFrameObserver overrides. + void OnDestruct() override; + + private: + GuestViewContainer* container_; + + DISALLOW_COPY_AND_ASSIGN(RenderFrameLifetimeObserver); +}; + +GuestViewContainer::RenderFrameLifetimeObserver::RenderFrameLifetimeObserver( + GuestViewContainer* container, + content::RenderFrame* render_frame) + : content::RenderFrameObserver(render_frame), + container_(container) {} + +void GuestViewContainer::RenderFrameLifetimeObserver::OnDestruct() { + container_->RenderFrameDestroyed(); +} + +GuestViewContainer::GuestViewContainer(content::RenderFrame* render_frame) + : element_instance_id_(guest_view::kInstanceIDNone), + render_frame_(render_frame), + ready_(false) { + render_frame_lifetime_observer_.reset( + new RenderFrameLifetimeObserver(this, render_frame_)); +} + +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. +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() { + OnRenderFrameDestroyed(); + 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 guest_view diff --git a/components/guest_view/renderer/guest_view_container.h b/components/guest_view/renderer/guest_view_container.h new file mode 100644 index 0000000..19175b9c --- /dev/null +++ b/components/guest_view/renderer/guest_view_container.h @@ -0,0 +1,73 @@ +// Copyright 2014 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 COMPONENTS_GUEST_VIEW_RENDERER_GUEST_VIEW_CONTAINER_H_ +#define COMPONENTS_GUEST_VIEW_RENDERER_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 guest_view { + +class GuestViewRequest; + +class GuestViewContainer : public content::BrowserPluginDelegate { + public: + explicit GuestViewContainer(content::RenderFrame* render_frame); + ~GuestViewContainer() override; + + static GuestViewContainer* FromID(int element_instance_id); + + // 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); +}; + +} // namespace guest_view + +#endif // COMPONENTS_GUEST_VIEW_RENDERER_GUEST_VIEW_CONTAINER_H_ diff --git a/components/guest_view/renderer/guest_view_request.cc b/components/guest_view/renderer/guest_view_request.cc new file mode 100644 index 0000000..902429c --- /dev/null +++ b/components/guest_view/renderer/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 "components/guest_view/renderer/guest_view_request.h" + +#include "components/guest_view/common/guest_view_messages.h" +#include "components/guest_view/renderer/guest_view_container.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 guest_view { + +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 guest_view/. + 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 guest_view diff --git a/components/guest_view/renderer/guest_view_request.h b/components/guest_view/renderer/guest_view_request.h new file mode 100644 index 0000000..222c7dd --- /dev/null +++ b/components/guest_view/renderer/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 COMPONENTS_GUEST_VIEW_RENDERER_GUEST_VIEW_REQUEST_H_ +#define COMPONENTS_GUEST_VIEW_RENDERER_GUEST_VIEW_REQUEST_H_ + +#include "ipc/ipc_message.h" +#include "v8/include/v8.h" + +namespace guest_view { + +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 guest_view + +#endif // COMPONENTS_GUEST_VIEW_RENDERER_GUEST_VIEW_CONTAINER_H_ |