Home | History | Annotate | Download | only in renderer
      1 // Copyright (c) 2012 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 "chrome/renderer/external_extension.h"
      6 
      7 #include "chrome/common/render_messages.h"
      8 #include "chrome/common/search_provider.h"
      9 #include "content/public/renderer/render_view.h"
     10 #include "third_party/WebKit/public/web/WebDocument.h"
     11 #include "third_party/WebKit/public/web/WebLocalFrame.h"
     12 #include "third_party/WebKit/public/web/WebView.h"
     13 #include "v8/include/v8.h"
     14 
     15 using blink::WebLocalFrame;
     16 using blink::WebView;
     17 using content::RenderView;
     18 
     19 namespace extensions_v8 {
     20 
     21 namespace {
     22 
     23 const char* const kSearchProviderApi =
     24     "var external;"
     25     "if (!external)"
     26     "  external = {};"
     27     "external.AddSearchProvider = function(name) {"
     28     "  native function NativeAddSearchProvider();"
     29     "  NativeAddSearchProvider(name);"
     30     "};"
     31     "external.IsSearchProviderInstalled = function(name) {"
     32     "  native function NativeIsSearchProviderInstalled();"
     33     "  return NativeIsSearchProviderInstalled(name);"
     34     "};";
     35 
     36 const char kExternalExtensionName[] = "v8/External";
     37 
     38 }  // namespace
     39 
     40 class ExternalExtensionWrapper : public v8::Extension {
     41  public:
     42   ExternalExtensionWrapper();
     43 
     44   // Allows v8's javascript code to call the native functions defined
     45   // in this class for window.external.
     46   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
     47       v8::Isolate* isolate,
     48       v8::Handle<v8::String> name) OVERRIDE;
     49 
     50   // Helper function to find the RenderView. May return NULL.
     51   static RenderView* GetRenderView();
     52 
     53   // Implementation of window.external.AddSearchProvider.
     54   static void AddSearchProvider(
     55       const v8::FunctionCallbackInfo<v8::Value>& args);
     56 
     57   // Implementation of window.external.IsSearchProviderInstalled.
     58   static void IsSearchProviderInstalled(
     59       const v8::FunctionCallbackInfo<v8::Value>& args);
     60 
     61  private:
     62   DISALLOW_COPY_AND_ASSIGN(ExternalExtensionWrapper);
     63 };
     64 
     65 ExternalExtensionWrapper::ExternalExtensionWrapper()
     66     : v8::Extension(kExternalExtensionName, kSearchProviderApi) {
     67 }
     68 
     69 v8::Handle<v8::FunctionTemplate>
     70 ExternalExtensionWrapper::GetNativeFunctionTemplate(
     71     v8::Isolate* isolate,
     72     v8::Handle<v8::String> name) {
     73   if (name->Equals(v8::String::NewFromUtf8(isolate, "NativeAddSearchProvider")))
     74     return v8::FunctionTemplate::New(isolate, AddSearchProvider);
     75 
     76   if (name->Equals(v8::String::NewFromUtf8(
     77           isolate, "NativeIsSearchProviderInstalled"))) {
     78     return v8::FunctionTemplate::New(isolate, IsSearchProviderInstalled);
     79   }
     80 
     81   return v8::Handle<v8::FunctionTemplate>();
     82 }
     83 
     84 // static
     85 RenderView* ExternalExtensionWrapper::GetRenderView() {
     86   WebLocalFrame* webframe = WebLocalFrame::frameForCurrentContext();
     87   DCHECK(webframe) << "There should be an active frame since we just got "
     88       "a native function called.";
     89   if (!webframe)
     90     return NULL;
     91 
     92   WebView* webview = webframe->view();
     93   if (!webview)
     94     return NULL;  // can happen during closing
     95 
     96   return RenderView::FromWebView(webview);
     97 }
     98 
     99 // static
    100 void ExternalExtensionWrapper::AddSearchProvider(
    101     const v8::FunctionCallbackInfo<v8::Value>& args) {
    102   if (!args.Length() || !args[0]->IsString())
    103     return;
    104 
    105   std::string osdd_string(*v8::String::Utf8Value(args[0]));
    106   if (osdd_string.empty())
    107     return;
    108 
    109   RenderView* render_view = GetRenderView();
    110   if (!render_view)
    111     return;
    112 
    113   WebLocalFrame* webframe = WebLocalFrame::frameForCurrentContext();
    114   if (!webframe)
    115     return;
    116 
    117   GURL osdd_url(osdd_string);
    118   if (!osdd_url.is_empty() && osdd_url.is_valid()) {
    119     render_view->Send(new ChromeViewHostMsg_PageHasOSDD(
    120         render_view->GetRoutingID(), webframe->document().url(), osdd_url,
    121         search_provider::EXPLICIT_PROVIDER));
    122   }
    123 }
    124 
    125 // static
    126 void ExternalExtensionWrapper::IsSearchProviderInstalled(
    127     const v8::FunctionCallbackInfo<v8::Value>& args) {
    128   if (!args.Length() || !args[0]->IsString())
    129     return;
    130 
    131   v8::String::Utf8Value utf8name(args[0]);
    132   if (!utf8name.length())
    133     return;
    134 
    135   std::string name(*utf8name);
    136   RenderView* render_view = GetRenderView();
    137   if (!render_view)
    138     return;
    139 
    140   WebLocalFrame* webframe = WebLocalFrame::frameForCurrentContext();
    141   if (!webframe)
    142     return;
    143 
    144   search_provider::InstallState install = search_provider::DENIED;
    145   GURL inquiry_url = GURL(name);
    146   if (!inquiry_url.is_empty()) {
    147       render_view->Send(new ChromeViewHostMsg_GetSearchProviderInstallState(
    148           render_view->GetRoutingID(),
    149           webframe->document().url(),
    150           inquiry_url,
    151           &install));
    152   }
    153 
    154   if (install == search_provider::DENIED) {
    155     // FIXME: throw access denied exception.
    156     v8::Isolate* isolate = args.GetIsolate();
    157     isolate->ThrowException(v8::Exception::Error(v8::String::Empty(isolate)));
    158     return;
    159   }
    160   args.GetReturnValue().Set(static_cast<int32_t>(install));
    161 }
    162 
    163 v8::Extension* ExternalExtension::Get() {
    164   return new ExternalExtensionWrapper();
    165 }
    166 
    167 }  // namespace extensions_v8
    168