blob: 6c05d14378b03c0f958cb10a41c57b0c3498db6b [file] [log] [blame]
[email protected]940ed1d2012-11-27 21:03:211// 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
dchengcedca5612016-04-09 01:40:157#include <memory>
dcheng0232f572016-05-27 17:47:448#include <utility>
dchengcedca5612016-04-09 01:40:159
[email protected]940ed1d2012-11-27 21:03:2110#include "base/values.h"
Lukasz Anforowicz02923102017-10-09 18:11:3711#include "content/common/frame_messages.h"
[email protected]940ed1d2012-11-27 21:03:2112#include "content/public/common/bindings_policy.h"
13#include "content/public/common/url_constants.h"
donndbd8a6612015-12-02 02:39:5814#include "content/public/renderer/chrome_object_extensions_utils.h"
sammc7f6c6a02017-01-30 00:53:5115#include "content/public/renderer/render_frame.h"
[email protected]940ed1d2012-11-27 21:03:2116#include "content/public/renderer/render_thread.h"
17#include "content/public/renderer/render_view.h"
John Abd-El-Malek312a30bb2017-10-23 19:51:5218#include "content/public/renderer/v8_value_converter.h"
[email protected]940ed1d2012-11-27 21:03:2119#include "content/renderer/web_ui_extension_data.h"
[email protected]f5c9f0882014-02-16 22:19:3220#include "gin/arguments.h"
21#include "gin/function_template.h"
Blink Reformata30d4232018-04-07 15:31:0622#include "third_party/blink/public/web/blink.h"
23#include "third_party/blink/public/web/web_document.h"
24#include "third_party/blink/public/web/web_local_frame.h"
Blink Reformata30d4232018-04-07 15:31:0625#include "third_party/blink/public/web/web_view.h"
[email protected]707e1c42013-07-09 21:18:5826#include "url/gurl.h"
[email protected]940ed1d2012-11-27 21:03:2127#include "v8/include/v8.h"
28
29namespace content {
30
[email protected]f5c9f0882014-02-16 22:19:3231namespace {
[email protected]940ed1d2012-11-27 21:03:2132
lukaszadf18ba762017-06-09 22:24:3033bool ShouldRespondToRequest(blink::WebLocalFrame** frame_ptr,
Lukasz Anforowicz02923102017-10-09 18:11:3734 RenderFrame** render_frame_ptr) {
lukaszadf18ba762017-06-09 22:24:3035 blink::WebLocalFrame* frame = blink::WebLocalFrame::FrameForCurrentContext();
Blink Reformat1c4d759e2017-04-09 16:34:5436 if (!frame || !frame->View())
[email protected]940ed1d2012-11-27 21:03:2137 return false;
38
Blink Reformat1c4d759e2017-04-09 16:34:5439 GURL frame_url = frame->GetDocument().Url();
[email protected]940ed1d2012-11-27 21:03:2140
sammc7f6c6a02017-01-30 00:53:5141 RenderFrame* render_frame = RenderFrame::FromWebFrame(frame);
42 if (!render_frame)
43 return false;
44
[email protected]940ed1d2012-11-27 21:03:2145 bool webui_enabled =
sammc7f6c6a02017-01-30 00:53:5146 (render_frame->GetEnabledBindings() & BINDINGS_POLICY_WEB_UI) &&
[email protected]2d9748b22014-02-11 00:17:2947 (frame_url.SchemeIs(kChromeUIScheme) ||
[email protected]cca6f392014-05-28 21:32:2648 frame_url.SchemeIs(url::kDataScheme));
[email protected]940ed1d2012-11-27 21:03:2149
50 if (!webui_enabled)
51 return false;
52
53 *frame_ptr = frame;
Lukasz Anforowicz02923102017-10-09 18:11:3754 *render_frame_ptr = render_frame;
[email protected]940ed1d2012-11-27 21:03:2155 return true;
56}
57
[email protected]f5c9f0882014-02-16 22:19:3258} // namespace
59
60// Exposes two methods:
61// - chrome.send: Used to send messages to the browser. Requires the message
62// name as the first argument and can have an optional second argument that
63// should be an array.
64// - chrome.getVariableValue: Returns value for the input variable name if such
65// a value was set by the browser. Else will return an empty string.
lukaszadf18ba762017-06-09 22:24:3066void WebUIExtension::Install(blink::WebLocalFrame* frame) {
Blink Reformat1c4d759e2017-04-09 16:34:5467 v8::Isolate* isolate = blink::MainThreadIsolate();
[email protected]f5c9f0882014-02-16 22:19:3268 v8::HandleScope handle_scope(isolate);
Blink Reformat1c4d759e2017-04-09 16:34:5469 v8::Local<v8::Context> context = frame->MainWorldScriptContext();
[email protected]f5c9f0882014-02-16 22:19:3270 if (context.IsEmpty())
71 return;
72
73 v8::Context::Scope context_scope(context);
74
deepak.s750d68f2015-04-30 07:32:4175 v8::Local<v8::Object> chrome = GetOrCreateChromeObject(isolate,
kolczyke1b79c752014-10-01 10:06:5676 context->Global());
Andreas Haas3bf2a0e2018-09-21 09:56:4477 chrome->Set(
78 gin::StringToSymbol(isolate, "send"),
79 gin::CreateFunctionTemplate(isolate, base::Bind(&WebUIExtension::Send))
80 ->GetFunction(context)
81 .ToLocalChecked());
[email protected]f5c9f0882014-02-16 22:19:3282 chrome->Set(gin::StringToSymbol(isolate, "getVariableValue"),
83 gin::CreateFunctionTemplate(
84 isolate, base::Bind(&WebUIExtension::GetVariableValue))
Andreas Haas3bf2a0e2018-09-21 09:56:4485 ->GetFunction(context)
86 .ToLocalChecked());
[email protected]f5c9f0882014-02-16 22:19:3287}
88
[email protected]940ed1d2012-11-27 21:03:2189// static
[email protected]f5c9f0882014-02-16 22:19:3290void WebUIExtension::Send(gin::Arguments* args) {
lukaszadf18ba762017-06-09 22:24:3091 blink::WebLocalFrame* frame;
Lukasz Anforowicz02923102017-10-09 18:11:3792 RenderFrame* render_frame;
93 if (!ShouldRespondToRequest(&frame, &render_frame))
[email protected]187a3532013-06-13 20:25:0194 return;
[email protected]940ed1d2012-11-27 21:03:2195
[email protected]f5c9f0882014-02-16 22:19:3296 std::string message;
97 if (!args->GetNext(&message)) {
98 args->ThrowError();
[email protected]187a3532013-06-13 20:25:0199 return;
[email protected]f5c9f0882014-02-16 22:19:32100 }
[email protected]940ed1d2012-11-27 21:03:21101
102 // If they've provided an optional message parameter, convert that into a
103 // Value to send to the browser process.
dchengcedca5612016-04-09 01:40:15104 std::unique_ptr<base::ListValue> content;
[email protected]f5c9f0882014-02-16 22:19:32105 if (args->PeekNext().IsEmpty() || args->PeekNext()->IsUndefined()) {
[email protected]85ecd7e2013-12-23 21:58:45106 content.reset(new base::ListValue());
[email protected]940ed1d2012-11-27 21:03:21107 } else {
deepak.s750d68f2015-04-30 07:32:41108 v8::Local<v8::Object> obj;
[email protected]f5c9f0882014-02-16 22:19:32109 if (!args->GetNext(&obj)) {
110 args->ThrowError();
[email protected]187a3532013-06-13 20:25:01111 return;
[email protected]f5c9f0882014-02-16 22:19:32112 }
[email protected]940ed1d2012-11-27 21:03:21113
rdevlin.cronin694c6052017-06-13 22:07:35114 content = base::ListValue::From(V8ValueConverter::Create()->FromV8Value(
115 obj, frame->MainWorldScriptContext()));
dcheng0232f572016-05-27 17:47:44116 DCHECK(content);
Rob Wu90585e652017-12-26 17:09:25117 // The conversion of |obj| could have triggered arbitrary JavaScript code,
118 // so check that the frame is still valid to avoid dereferencing a stale
119 // pointer.
120 if (frame != blink::WebLocalFrame::FrameForCurrentContext()) {
121 NOTREACHED();
122 return;
123 }
[email protected]940ed1d2012-11-27 21:03:21124 }
125
126 // Send the message up to the browser.
Lukasz Anforowicz02923102017-10-09 18:11:37127 render_frame->Send(new FrameHostMsg_WebUISend(render_frame->GetRoutingID(),
Lukasz Anforowicz02923102017-10-09 18:11:37128 message, *content));
[email protected]940ed1d2012-11-27 21:03:21129}
130
131// static
[email protected]f5c9f0882014-02-16 22:19:32132std::string WebUIExtension::GetVariableValue(const std::string& name) {
lukaszadf18ba762017-06-09 22:24:30133 blink::WebLocalFrame* frame;
Lukasz Anforowicz02923102017-10-09 18:11:37134 RenderFrame* render_frame;
135 if (!ShouldRespondToRequest(&frame, &render_frame))
[email protected]f5c9f0882014-02-16 22:19:32136 return std::string();
[email protected]940ed1d2012-11-27 21:03:21137
Lukasz Anforowicz02923102017-10-09 18:11:37138 return WebUIExtensionData::Get(render_frame->GetRenderView())->GetValue(name);
[email protected]940ed1d2012-11-27 21:03:21139}
140
141} // namespace content