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