| Index: extensions/renderer/guest_view/guest_view_internal_custom_bindings.cc | 
| 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 a4b08d2e53d770904c095a0b6cafa1af6b428a2f..653cf2d64a2f8b1a0fe55458e80818637ce1f80d 100644 | 
| --- a/extensions/renderer/guest_view/guest_view_internal_custom_bindings.cc | 
| +++ b/extensions/renderer/guest_view/guest_view_internal_custom_bindings.cc | 
| @@ -7,15 +7,21 @@ | 
| #include <string> | 
|  | 
| #include "base/bind.h" | 
| +#include "base/command_line.h" | 
| #include "components/guest_view/common/guest_view_constants.h" | 
| #include "components/guest_view/renderer/guest_view_request.h" | 
| #include "content/public/child/v8_value_converter.h" | 
| +#include "content/public/common/content_switches.h" | 
| +#include "content/public/renderer/render_frame.h" | 
| #include "content/public/renderer/render_view.h" | 
| #include "extensions/common/extension.h" | 
| #include "extensions/common/extension_messages.h" | 
| +#include "extensions/common/guest_view/extensions_guest_view_messages.h" | 
| #include "extensions/renderer/guest_view/extensions_guest_view_container.h" | 
| +#include "extensions/renderer/guest_view/extensions_guest_view_request.h" | 
| #include "extensions/renderer/script_context.h" | 
| #include "third_party/WebKit/public/web/WebFrame.h" | 
| +#include "third_party/WebKit/public/web/WebLocalFrame.h" | 
| #include "third_party/WebKit/public/web/WebScopedUserGesture.h" | 
| #include "third_party/WebKit/public/web/WebView.h" | 
| #include "v8/include/v8.h" | 
| @@ -24,6 +30,21 @@ using content::V8ValueConverter; | 
|  | 
| namespace extensions { | 
|  | 
| +namespace { | 
| + | 
| +content::RenderFrame* GetRenderFrame(v8::Handle<v8::Value> value) { | 
| +  v8::Local<v8::Context> context = | 
| +      v8::Local<v8::Object>::Cast(value)->CreationContext(); | 
| +  if (context.IsEmpty()) | 
| +    return nullptr; | 
| +  blink::WebLocalFrame* frame = blink::WebLocalFrame::frameForContext(context); | 
| +  if (!frame) | 
| +    return nullptr; | 
| +  return content::RenderFrame::FromWebFrame(frame); | 
| +} | 
| + | 
| +}  // namespace | 
| + | 
| GuestViewInternalCustomBindings::GuestViewInternalCustomBindings( | 
| ScriptContext* context) | 
| : ObjectBackedNativeHandler(context) { | 
| @@ -49,6 +70,13 @@ GuestViewInternalCustomBindings::GuestViewInternalCustomBindings( | 
| "RunWithGesture", | 
| base::Bind(&GuestViewInternalCustomBindings::RunWithGesture, | 
| base::Unretained(this))); | 
| +  RouteFunction("AttachIframeGuest", | 
| +                base::Bind(&GuestViewInternalCustomBindings::AttachIframeGuest, | 
| +                           base::Unretained(this))); | 
| +  // TODO(lazyboy): There must be a better way to query command line from JS. | 
| +  RouteFunction("IsSitePerProcess", | 
| +                base::Bind(&GuestViewInternalCustomBindings::IsSitePerProcess, | 
| +                           base::Unretained(this))); | 
| } | 
|  | 
| void GuestViewInternalCustomBindings::AttachGuest( | 
| @@ -211,4 +239,88 @@ void GuestViewInternalCustomBindings::RunWithGesture( | 
| context()->CallFunction(v8::Local<v8::Function>::Cast(args[0]), 0, &no_args); | 
| } | 
|  | 
| +void GuestViewInternalCustomBindings::AttachIframeGuest( | 
| +    const v8::FunctionCallbackInfo<v8::Value>& args) { | 
| +  // Allow for an optional callback parameter. | 
| +  const int num_required_params = 4; | 
| +  CHECK(args.Length() >= num_required_params && | 
| +        args.Length() <= (num_required_params + 1)); | 
| +  // Element Instance ID. | 
| +  CHECK(args[0]->IsInt32()); | 
| +  // Guest Instance ID. | 
| +  CHECK(args[1]->IsInt32()); | 
| +  // Attach Parameters. | 
| +  CHECK(args[2]->IsObject()); | 
| +  // <iframe>.contentWindow. | 
| +  CHECK(args[3]->IsObject()); | 
| +  // Optional Callback Function. | 
| +  CHECK(args.Length() <= num_required_params || | 
| +        args[num_required_params]->IsFunction()); | 
| +  LOG(WARNING) << "has_callback: " | 
| +               << (args.Length() >= (num_required_params + 1)); | 
| + | 
| +  int element_instance_id = args[0]->Int32Value(); | 
| +  int guest_instance_id = args[1]->Int32Value(); | 
| +  LOG(WARNING) << "guest_instance_id: " << guest_instance_id | 
| +               << ", element_instance_id: " << element_instance_id; | 
| + | 
| +  scoped_ptr<base::DictionaryValue> params; | 
| +  { | 
| +    scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create()); | 
| +    scoped_ptr<base::Value> params_as_value( | 
| +        converter->FromV8Value(args[2], context()->v8_context())); | 
| +    CHECK(params_as_value->IsType(base::Value::TYPE_DICTIONARY)); | 
| +    params.reset( | 
| +        static_cast<base::DictionaryValue*>(params_as_value.release())); | 
| +  } | 
| + | 
| +  // Add flag to |params| to indicate that the element size is specified in | 
| +  // logical units. | 
| +  params->SetBoolean(guest_view::kElementSizeIsLogical, true); | 
| + | 
| +  content::RenderFrame* render_frame = GetRenderFrame(args[3]); | 
| +  blink::WebLocalFrame* frame = render_frame->GetWebFrame(); | 
| + | 
| +  // Parent must exist. | 
| +  blink::WebFrame* parent_frame = frame->parent(); | 
| +  DCHECK(parent_frame); | 
| +  DCHECK(parent_frame->isWebLocalFrame()); | 
| + | 
| +  content::RenderFrame* embedder_parent_frame = | 
| +      content::RenderFrame::FromWebFrame(parent_frame); | 
| + | 
| +  // Create a GuestViewContainer if it does not exist. | 
| +  // An element instance ID uniquely identifies a ExtensionsGuestViewContainer | 
| +  // within a RenderView. | 
| +  auto* guest_view_container = static_cast<ExtensionsGuestViewContainer*>( | 
| +      guest_view::GuestViewContainer::FromID(element_instance_id)); | 
| +  // This is the first time we hear about the |element_instance_id|. | 
| +  DCHECK(!guest_view_container); | 
| +  // TODO(lazyboy): Leaked, make this render_frame observer and destruct. | 
| +  guest_view_container = | 
| +      new extensions::ExtensionsGuestViewContainer(embedder_parent_frame); | 
| +  guest_view_container->SetElementInstanceID(element_instance_id); | 
| + | 
| +  linked_ptr<guest_view::GuestViewRequest> request( | 
| +      new GuestViewAttachIframeRequest( | 
| +          guest_view_container, render_frame->GetRoutingID(), guest_instance_id, | 
| +          params.Pass(), args.Length() == (num_required_params + 1) | 
| +                             ? args[num_required_params].As<v8::Function>() | 
| +                             : v8::Local<v8::Function>(), | 
| +      args.GetIsolate())); | 
| +  guest_view_container->IssueRequest(request); | 
| + | 
| +  args.GetReturnValue().Set(v8::Boolean::New(context()->isolate(), true)); | 
| + | 
| +  LOG(WARNING) << "AttachLocalFrameToGuest complete"; | 
| +} | 
| + | 
| +void GuestViewInternalCustomBindings::IsSitePerProcess( | 
| +    const v8::FunctionCallbackInfo<v8::Value>& args) { | 
| +  bool is_site_per_process = base::CommandLine::ForCurrentProcess()->HasSwitch( | 
| +      switches::kSitePerProcess); | 
| +  args.GetReturnValue().Set( | 
| +      v8::Boolean::New(context()->isolate(), is_site_per_process)); | 
| +} | 
| + | 
| }  // namespace extensions | 
|  |