Home | History | Annotate | Download | only in renderer
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "extensions/renderer/runtime_custom_bindings.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/memory/scoped_ptr.h"
      9 #include "base/values.h"
     10 #include "content/public/renderer/render_view.h"
     11 #include "content/public/renderer/v8_value_converter.h"
     12 #include "extensions/common/extension.h"
     13 #include "extensions/common/extension_messages.h"
     14 #include "extensions/common/features/feature.h"
     15 #include "extensions/common/features/feature_provider.h"
     16 #include "extensions/common/manifest.h"
     17 #include "extensions/renderer/api_activity_logger.h"
     18 #include "extensions/renderer/extension_helper.h"
     19 #include "extensions/renderer/script_context.h"
     20 #include "third_party/WebKit/public/web/WebDocument.h"
     21 #include "third_party/WebKit/public/web/WebFrame.h"
     22 #include "third_party/WebKit/public/web/WebView.h"
     23 
     24 using content::V8ValueConverter;
     25 
     26 namespace extensions {
     27 
     28 RuntimeCustomBindings::RuntimeCustomBindings(ScriptContext* context)
     29     : ObjectBackedNativeHandler(context) {
     30   RouteFunction(
     31       "GetManifest",
     32       base::Bind(&RuntimeCustomBindings::GetManifest, base::Unretained(this)));
     33   RouteFunction("OpenChannelToExtension",
     34                 base::Bind(&RuntimeCustomBindings::OpenChannelToExtension,
     35                            base::Unretained(this)));
     36   RouteFunction("OpenChannelToNativeApp",
     37                 base::Bind(&RuntimeCustomBindings::OpenChannelToNativeApp,
     38                            base::Unretained(this)));
     39   RouteFunction("GetExtensionViews",
     40                 base::Bind(&RuntimeCustomBindings::GetExtensionViews,
     41                            base::Unretained(this)));
     42 }
     43 
     44 RuntimeCustomBindings::~RuntimeCustomBindings() {
     45 }
     46 
     47 void RuntimeCustomBindings::OpenChannelToExtension(
     48     const v8::FunctionCallbackInfo<v8::Value>& args) {
     49   // Get the current RenderView so that we can send a routed IPC message from
     50   // the correct source.
     51   content::RenderView* renderview = context()->GetRenderView();
     52   if (!renderview)
     53     return;
     54 
     55   // The Javascript code should validate/fill the arguments.
     56   CHECK_EQ(args.Length(), 3);
     57   CHECK(args[0]->IsString() && args[1]->IsString() && args[2]->IsBoolean());
     58 
     59   ExtensionMsg_ExternalConnectionInfo info;
     60 
     61   // For messaging APIs, hosted apps should be considered a web page so hide
     62   // its extension ID.
     63   const Extension* extension = context()->extension();
     64   if (extension && !extension->is_hosted_app())
     65     info.source_id = extension->id();
     66 
     67   info.target_id = *v8::String::Utf8Value(args[0]->ToString());
     68   info.source_url = context()->GetURL();
     69   std::string channel_name = *v8::String::Utf8Value(args[1]->ToString());
     70   bool include_tls_channel_id =
     71       args.Length() > 2 ? args[2]->BooleanValue() : false;
     72   int port_id = -1;
     73   renderview->Send(
     74       new ExtensionHostMsg_OpenChannelToExtension(renderview->GetRoutingID(),
     75                                                   info,
     76                                                   channel_name,
     77                                                   include_tls_channel_id,
     78                                                   &port_id));
     79   args.GetReturnValue().Set(static_cast<int32_t>(port_id));
     80 }
     81 
     82 void RuntimeCustomBindings::OpenChannelToNativeApp(
     83     const v8::FunctionCallbackInfo<v8::Value>& args) {
     84   // Verify that the extension has permission to use native messaging.
     85   Feature::Availability availability =
     86       FeatureProvider::GetPermissionFeatures()
     87           ->GetFeature("nativeMessaging")
     88           ->IsAvailableToContext(context()->extension(),
     89                                  context()->context_type(),
     90                                  context()->GetURL());
     91   if (!availability.is_available())
     92     return;
     93 
     94   // Get the current RenderView so that we can send a routed IPC message from
     95   // the correct source.
     96   content::RenderView* renderview = context()->GetRenderView();
     97   if (!renderview)
     98     return;
     99 
    100   // The Javascript code should validate/fill the arguments.
    101   CHECK(args.Length() >= 2 && args[0]->IsString() && args[1]->IsString());
    102 
    103   std::string extension_id = *v8::String::Utf8Value(args[0]->ToString());
    104   std::string native_app_name = *v8::String::Utf8Value(args[1]->ToString());
    105 
    106   int port_id = -1;
    107   renderview->Send(new ExtensionHostMsg_OpenChannelToNativeApp(
    108       renderview->GetRoutingID(), extension_id, native_app_name, &port_id));
    109   args.GetReturnValue().Set(static_cast<int32_t>(port_id));
    110 }
    111 
    112 void RuntimeCustomBindings::GetManifest(
    113     const v8::FunctionCallbackInfo<v8::Value>& args) {
    114   CHECK(context()->extension());
    115 
    116   scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
    117   args.GetReturnValue().Set(converter->ToV8Value(
    118       context()->extension()->manifest()->value(), context()->v8_context()));
    119 }
    120 
    121 void RuntimeCustomBindings::GetExtensionViews(
    122     const v8::FunctionCallbackInfo<v8::Value>& args) {
    123   if (args.Length() != 2)
    124     return;
    125 
    126   if (!args[0]->IsInt32() || !args[1]->IsString())
    127     return;
    128 
    129   // |browser_window_id| == extension_misc::kUnknownWindowId means getting
    130   // all views for the current extension.
    131   int browser_window_id = args[0]->Int32Value();
    132 
    133   std::string view_type_string = *v8::String::Utf8Value(args[1]->ToString());
    134   StringToUpperASCII(&view_type_string);
    135   // |view_type| == VIEW_TYPE_INVALID means getting any type of
    136   // views.
    137   ViewType view_type = VIEW_TYPE_INVALID;
    138   if (view_type_string == kViewTypeBackgroundPage) {
    139     view_type = VIEW_TYPE_EXTENSION_BACKGROUND_PAGE;
    140   } else if (view_type_string == kViewTypeInfobar) {
    141     view_type = VIEW_TYPE_EXTENSION_INFOBAR;
    142   } else if (view_type_string == kViewTypeTabContents) {
    143     view_type = VIEW_TYPE_TAB_CONTENTS;
    144   } else if (view_type_string == kViewTypePopup) {
    145     view_type = VIEW_TYPE_EXTENSION_POPUP;
    146   } else if (view_type_string == kViewTypeExtensionDialog) {
    147     view_type = VIEW_TYPE_EXTENSION_DIALOG;
    148   } else if (view_type_string == kViewTypeAppWindow) {
    149     view_type = VIEW_TYPE_APP_WINDOW;
    150   } else if (view_type_string == kViewTypeLauncherPage) {
    151     view_type = VIEW_TYPE_LAUNCHER_PAGE;
    152   } else if (view_type_string == kViewTypePanel) {
    153     view_type = VIEW_TYPE_PANEL;
    154   } else if (view_type_string != kViewTypeAll) {
    155     return;
    156   }
    157 
    158   std::string extension_id = context()->GetExtensionID();
    159   if (extension_id.empty())
    160     return;
    161 
    162   std::vector<content::RenderView*> views = ExtensionHelper::GetExtensionViews(
    163       extension_id, browser_window_id, view_type);
    164   v8::Local<v8::Array> v8_views = v8::Array::New(args.GetIsolate());
    165   int v8_index = 0;
    166   for (size_t i = 0; i < views.size(); ++i) {
    167     v8::Local<v8::Context> context =
    168         views[i]->GetWebView()->mainFrame()->mainWorldScriptContext();
    169     if (!context.IsEmpty()) {
    170       v8::Local<v8::Value> window = context->Global();
    171       DCHECK(!window.IsEmpty());
    172       v8_views->Set(v8::Integer::New(args.GetIsolate(), v8_index++), window);
    173     }
    174   }
    175 
    176   args.GetReturnValue().Set(v8_views);
    177 }
    178 
    179 }  // namespace extensions
    180