11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved. 21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Use of this source code is governed by a BSD-style license that can be 31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// found in the LICENSE file. 41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/renderer/guest_view/guest_view_container.h" 61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/renderer/browser_plugin_delegate.h" 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/renderer/render_frame.h" 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/renderer/render_view.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/common/extension_messages.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/common/guest_view/guest_view_constants.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "third_party/WebKit/public/web/WebLocalFrame.h" 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h" 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "third_party/WebKit/public/web/WebView.h" 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace { 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitypedef std::pair<int, int> GuestViewID; 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitypedef std::map<GuestViewID, extensions::GuestViewContainer*> 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GuestViewContainerMap; 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistatic base::LazyInstance<GuestViewContainerMap> g_guest_view_container_map = 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LAZY_INSTANCE_INITIALIZER; 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace extensions { 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciGuestViewContainer::GuestViewContainer( 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::RenderFrame* render_frame, 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& mime_type) 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : content::BrowserPluginDelegate(render_frame, mime_type), 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::RenderFrameObserver(render_frame), 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mime_type_(mime_type), 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci element_instance_id_(guestview::kInstanceIDNone), 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci render_view_routing_id_(render_frame->GetRenderView()->GetRoutingID()), 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci attached_(false), 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci attach_pending_(false), 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci isolate_(NULL) { 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciGuestViewContainer::~GuestViewContainer() { 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (element_instance_id_ != guestview::kInstanceIDNone) { 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci g_guest_view_container_map.Get().erase( 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GuestViewID(render_view_routing_id_, element_instance_id_)); 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciGuestViewContainer* GuestViewContainer::FromID(int render_view_routing_id, 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int element_instance_id) { 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GuestViewContainerMap* guest_view_containers = 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci g_guest_view_container_map.Pointer(); 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GuestViewContainerMap::iterator it = guest_view_containers->find( 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GuestViewID(render_view_routing_id, element_instance_id)); 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return it == guest_view_containers->end() ? NULL : it->second; 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid GuestViewContainer::AttachGuest(int element_instance_id, 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int guest_instance_id, 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<base::DictionaryValue> params, 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci v8::Handle<v8::Function> callback, 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci v8::Isolate* isolate) { 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // GuestViewContainer supports reattachment (i.e. attached_ == true) but not 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // while a current attach process is pending. 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (attach_pending_) 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Step 1, send the attach params to chrome/. 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci render_frame()->Send(new ExtensionHostMsg_AttachGuest(render_view_routing_id_, 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci element_instance_id, 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci guest_instance_id, 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *params)); 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Step 2, attach plugin through content/. 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci render_frame()->AttachGuest(element_instance_id); 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback_.reset(callback); 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci isolate_ = isolate; 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci attach_pending_ = true; 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid GuestViewContainer::SetElementInstanceID(int element_instance_id) { 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GuestViewID guest_view_id(render_view_routing_id_, element_instance_id); 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_EQ(element_instance_id_, guestview::kInstanceIDNone); 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(g_guest_view_container_map.Get().find(guest_view_id) == 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci g_guest_view_container_map.Get().end()); 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci element_instance_id_ = element_instance_id; 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci g_guest_view_container_map.Get().insert(std::make_pair(guest_view_id, this)); 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid GuestViewContainer::DidFinishLoading() { 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (mime_type_.empty()) 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_NE(element_instance_id_, guestview::kInstanceIDNone); 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci render_frame()->Send(new ExtensionHostMsg_CreateMimeHandlerViewGuest( 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci routing_id(), html_string_, mime_type_, element_instance_id_)); 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid GuestViewContainer::DidReceiveData(const char* data, int data_length) { 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::string value(data, data_length); 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci html_string_ += value; 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid GuestViewContainer::OnDestruct() { 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // GuestViewContainer's lifetime is managed by BrowserPlugin so don't let 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // RenderFrameObserver self-destruct here. 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool GuestViewContainer::OnMessageReceived(const IPC::Message& message) { 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!ShouldHandleMessage(message)) 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_NE(element_instance_id_, guestview::kInstanceIDNone); 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int element_instance_id = guestview::kInstanceIDNone; 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PickleIterator iter(message); 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool success = iter.ReadInt(&element_instance_id); 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(success); 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (element_instance_id != element_instance_id_) 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool handled = true; 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_BEGIN_MESSAGE_MAP(GuestViewContainer, message) 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_MESSAGE_HANDLER(ExtensionMsg_CreateMimeHandlerViewGuestACK, 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OnCreateMimeHandlerViewGuestACK) 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_MESSAGE_HANDLER(ExtensionMsg_GuestAttached, OnGuestAttached) 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_MESSAGE_UNHANDLED(handled = false) 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_END_MESSAGE_MAP() 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return handled; 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid GuestViewContainer::OnCreateMimeHandlerViewGuestACK( 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int element_instance_id) { 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_NE(element_instance_id_, guestview::kInstanceIDNone); 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_EQ(element_instance_id_, element_instance_id); 1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(!mime_type_.empty()); 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci render_frame()->AttachGuest(element_instance_id); 1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid GuestViewContainer::OnGuestAttached(int element_instance_id, 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int guest_routing_id) { 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci attached_ = true; 1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci attach_pending_ = false; 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If we don't have a callback then there's nothing more to do. 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (callback_.IsEmpty()) 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::RenderView* guest_proxy_render_view = 1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::RenderView::FromRoutingID(guest_routing_id); 1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(fsamuel): Should we be reporting an error to JavaScript or DCHECKing? 1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!guest_proxy_render_view) 1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci v8::HandleScope handle_scope(isolate_); 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci v8::Handle<v8::Function> callback = callback_.NewHandle(isolate_); 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci v8::Handle<v8::Context> context = callback->CreationContext(); 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (context.IsEmpty()) 1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci blink::WebFrame* frame = guest_proxy_render_view->GetWebView()->mainFrame(); 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci v8::Local<v8::Value> window = frame->mainWorldScriptContext()->Global(); 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const int argc = 1; 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci v8::Handle<v8::Value> argv[argc] = { window }; 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci v8::Context::Scope context_scope(context); 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci blink::WebScopedMicrotaskSuppression suppression; 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Call the AttachGuest API's callback with the guest proxy as the first 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // parameter. 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback->Call(context->Global(), argc, argv); 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback_.reset(); 1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool GuestViewContainer::ShouldHandleMessage(const IPC::Message& message) { 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci switch (message.type()) { 1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case ExtensionMsg_CreateMimeHandlerViewGuestACK::ID: 1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case ExtensionMsg_GuestAttached::ID: 1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return true; 1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci default: 1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace extensions 187