1 // Copyright 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 "content/renderer/web_ui_extension.h" 6 7 #include "base/memory/scoped_ptr.h" 8 #include "base/values.h" 9 #include "content/common/view_messages.h" 10 #include "content/public/common/bindings_policy.h" 11 #include "content/public/common/url_constants.h" 12 #include "content/public/renderer/render_thread.h" 13 #include "content/public/renderer/render_view.h" 14 #include "content/public/renderer/v8_value_converter.h" 15 #include "content/renderer/web_ui_extension_data.h" 16 #include "gin/arguments.h" 17 #include "gin/function_template.h" 18 #include "third_party/WebKit/public/web/WebDocument.h" 19 #include "third_party/WebKit/public/web/WebKit.h" 20 #include "third_party/WebKit/public/web/WebLocalFrame.h" 21 #include "third_party/WebKit/public/web/WebView.h" 22 #include "url/gurl.h" 23 #include "v8/include/v8.h" 24 25 namespace content { 26 27 namespace { 28 29 bool ShouldRespondToRequest( 30 blink::WebFrame** frame_ptr, 31 RenderView** render_view_ptr) { 32 blink::WebFrame* frame = blink::WebLocalFrame::frameForCurrentContext(); 33 if (!frame || !frame->view()) 34 return false; 35 36 RenderView* render_view = RenderView::FromWebView(frame->view()); 37 if (!render_view) 38 return false; 39 40 GURL frame_url = frame->document().url(); 41 42 bool webui_enabled = 43 (render_view->GetEnabledBindings() & BINDINGS_POLICY_WEB_UI) && 44 (frame_url.SchemeIs(kChromeUIScheme) || 45 frame_url.SchemeIs(url::kDataScheme)); 46 47 if (!webui_enabled) 48 return false; 49 50 *frame_ptr = frame; 51 *render_view_ptr = render_view; 52 return true; 53 } 54 55 } // namespace 56 57 // Exposes two methods: 58 // - chrome.send: Used to send messages to the browser. Requires the message 59 // name as the first argument and can have an optional second argument that 60 // should be an array. 61 // - chrome.getVariableValue: Returns value for the input variable name if such 62 // a value was set by the browser. Else will return an empty string. 63 void WebUIExtension::Install(blink::WebFrame* frame) { 64 v8::Isolate* isolate = blink::mainThreadIsolate(); 65 v8::HandleScope handle_scope(isolate); 66 v8::Handle<v8::Context> context = frame->mainWorldScriptContext(); 67 if (context.IsEmpty()) 68 return; 69 70 v8::Context::Scope context_scope(context); 71 72 v8::Handle<v8::Object> global = context->Global(); 73 v8::Handle<v8::Object> chrome = 74 global->Get(gin::StringToV8(isolate, "chrome"))->ToObject(); 75 if (chrome.IsEmpty()) { 76 chrome = v8::Object::New(isolate); 77 global->Set(gin::StringToSymbol(isolate, "chrome"), chrome); 78 } 79 chrome->Set(gin::StringToSymbol(isolate, "send"), 80 gin::CreateFunctionTemplate( 81 isolate, base::Bind(&WebUIExtension::Send))->GetFunction()); 82 chrome->Set(gin::StringToSymbol(isolate, "getVariableValue"), 83 gin::CreateFunctionTemplate( 84 isolate, base::Bind(&WebUIExtension::GetVariableValue)) 85 ->GetFunction()); 86 } 87 88 // static 89 void WebUIExtension::Send(gin::Arguments* args) { 90 blink::WebFrame* frame; 91 RenderView* render_view; 92 if (!ShouldRespondToRequest(&frame, &render_view)) 93 return; 94 95 std::string message; 96 if (!args->GetNext(&message)) { 97 args->ThrowError(); 98 return; 99 } 100 101 // If they've provided an optional message parameter, convert that into a 102 // Value to send to the browser process. 103 scoped_ptr<base::ListValue> content; 104 if (args->PeekNext().IsEmpty() || args->PeekNext()->IsUndefined()) { 105 content.reset(new base::ListValue()); 106 } else { 107 v8::Handle<v8::Object> obj; 108 if (!args->GetNext(&obj)) { 109 args->ThrowError(); 110 return; 111 } 112 113 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create()); 114 115 base::Value* value = 116 converter->FromV8Value(obj, frame->mainWorldScriptContext()); 117 base::ListValue* list = NULL; 118 value->GetAsList(&list); 119 DCHECK(list); 120 content.reset(list); 121 } 122 123 // Send the message up to the browser. 124 render_view->Send(new ViewHostMsg_WebUISend(render_view->GetRoutingID(), 125 frame->document().url(), 126 message, 127 *content)); 128 } 129 130 // static 131 std::string WebUIExtension::GetVariableValue(const std::string& name) { 132 blink::WebFrame* frame; 133 RenderView* render_view; 134 if (!ShouldRespondToRequest(&frame, &render_view)) 135 return std::string(); 136 137 return WebUIExtensionData::Get(render_view)->GetValue(name); 138 } 139 140 } // namespace content 141