15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/renderer/external_extension.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/render_messages.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/search_provider.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/renderer/render_view.h"
127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebDocument.h"
137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebFrame.h"
147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebView.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "v8/include/v8.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using WebKit::WebFrame;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using WebKit::WebView;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderView;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions_v8 {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char* const kSearchProviderApi =
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "var external;"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "if (!external)"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  external = {};"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "external.AddSearchProvider = function(name) {"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  native function NativeAddSearchProvider();"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  NativeAddSearchProvider(name);"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "};"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "external.IsSearchProviderInstalled = function(name) {"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  native function NativeIsSearchProviderInstalled();"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  return NativeIsSearchProviderInstalled(name);"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "};";
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* const kExternalExtensionName = "v8/External";
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExternalExtensionWrapper : public v8::Extension {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExternalExtensionWrapper();
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allows v8's javascript code to call the native functions defined
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in this class for window.external.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      v8::Handle<v8::String> name) OVERRIDE;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helper function to find the RenderView. May return NULL.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static RenderView* GetRenderView();
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Implementation of window.external.AddSearchProvider.
517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static void AddSearchProvider(
527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      const v8::FunctionCallbackInfo<v8::Value>& args);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Implementation of window.external.IsSearchProviderInstalled.
557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static void IsSearchProviderInstalled(
567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      const v8::FunctionCallbackInfo<v8::Value>& args);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ExternalExtensionWrapper);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExternalExtensionWrapper::ExternalExtensionWrapper()
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : v8::Extension(
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kExternalExtensionName,
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kSearchProviderApi) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)v8::Handle<v8::FunctionTemplate> ExternalExtensionWrapper::GetNativeFunction(
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Handle<v8::String> name) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (name->Equals(v8::String::New("NativeAddSearchProvider")))
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return v8::FunctionTemplate::New(AddSearchProvider);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (name->Equals(v8::String::New("NativeIsSearchProviderInstalled")))
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return v8::FunctionTemplate::New(IsSearchProviderInstalled);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return v8::Handle<v8::FunctionTemplate>();
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RenderView* ExternalExtensionWrapper::GetRenderView() {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebFrame* webframe = WebFrame::frameForCurrentContext();
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(webframe) << "There should be an active frame since we just got "
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "a native function called.";
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!webframe) return NULL;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebView* webview = webframe->view();
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!webview) return NULL;  // can happen during closing
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return RenderView::FromWebView(webview);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void ExternalExtensionWrapper::AddSearchProvider(
947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const v8::FunctionCallbackInfo<v8::Value>& args) {
957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!args.Length()) return;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name = std::string(*v8::String::Utf8Value(args[0]));
987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!name.length()) return;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RenderView* render_view = GetRenderView();
1017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!render_view) return;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL osd_url(name);
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!osd_url.is_empty() && osd_url.is_valid()) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_view->Send(new ChromeViewHostMsg_PageHasOSDD(
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        render_view->GetRoutingID(), render_view->GetPageId(), osd_url,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        search_provider::EXPLICIT_PROVIDER));
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void ExternalExtensionWrapper::IsSearchProviderInstalled(
1137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const v8::FunctionCallbackInfo<v8::Value>& args) {
1147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!args.Length()) return;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::String::Utf8Value utf8name(args[0]);
1167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!utf8name.length()) return;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name = std::string(*utf8name);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RenderView* render_view = GetRenderView();
1207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!render_view) return;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebFrame* webframe = WebFrame::frameForCurrentContext();
1237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!webframe) return;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  search_provider::InstallState install = search_provider::DENIED;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL inquiry_url = GURL(name);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!inquiry_url.is_empty()) {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_view->Send(new ChromeViewHostMsg_GetSearchProviderInstallState(
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          render_view->GetRoutingID(),
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          webframe->document().url(),
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          inquiry_url,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &install));
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (install == search_provider::DENIED) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // FIXME: throw access denied exception.
1377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    v8::ThrowException(v8::Exception::Error(v8::String::Empty()));
1387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  args.GetReturnValue().Set(static_cast<int32_t>(install));
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)v8::Extension* ExternalExtension::Get() {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ExternalExtensionWrapper();
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions_v8
148