blob: 2e37ad5c2d9ab98173e37c4a2e5557e6235ee374 [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
Sebastien Marchandf8cbfab2019-01-25 16:02:3010#include "base/bind.h"
[email protected]940ed1d2012-11-27 21:03:2111#include "base/values.h"
Lukasz Anforowicz02923102017-10-09 18:11:3712#include "content/common/frame_messages.h"
[email protected]940ed1d2012-11-27 21:03:2113#include "content/public/common/bindings_policy.h"
14#include "content/public/common/url_constants.h"
donndbd8a6612015-12-02 02:39:5815#include "content/public/renderer/chrome_object_extensions_utils.h"
sammc7f6c6a02017-01-30 00:53:5116#include "content/public/renderer/render_frame.h"
[email protected]940ed1d2012-11-27 21:03:2117#include "content/public/renderer/render_thread.h"
18#include "content/public/renderer/render_view.h"
John Abd-El-Malek312a30bb2017-10-23 19:51:5219#include "content/public/renderer/v8_value_converter.h"
[email protected]940ed1d2012-11-27 21:03:2120#include "content/renderer/web_ui_extension_data.h"
[email protected]f5c9f0882014-02-16 22:19:3221#include "gin/arguments.h"
22#include "gin/function_template.h"
Blink Reformata30d4232018-04-07 15:31:0623#include "third_party/blink/public/web/blink.h"
24#include "third_party/blink/public/web/web_document.h"
25#include "third_party/blink/public/web/web_local_frame.h"
Blink Reformata30d4232018-04-07 15:31:0626#include "third_party/blink/public/web/web_view.h"
[email protected]707e1c42013-07-09 21:18:5827#include "url/gurl.h"
[email protected]940ed1d2012-11-27 21:03:2128#include "v8/include/v8.h"
29
30namespace content {
31
[email protected]f5c9f0882014-02-16 22:19:3232namespace {
[email protected]940ed1d2012-11-27 21:03:2133
lukaszadf18ba762017-06-09 22:24:3034bool ShouldRespondToRequest(blink::WebLocalFrame** frame_ptr,
Lukasz Anforowicz02923102017-10-09 18:11:3735 RenderFrame** render_frame_ptr) {
lukaszadf18ba762017-06-09 22:24:3036 blink::WebLocalFrame* frame = blink::WebLocalFrame::FrameForCurrentContext();
Blink Reformat1c4d759e2017-04-09 16:34:5437 if (!frame || !frame->View())
[email protected]940ed1d2012-11-27 21:03:2138 return false;
39
Blink Reformat1c4d759e2017-04-09 16:34:5440 GURL frame_url = frame->GetDocument().Url();
[email protected]940ed1d2012-11-27 21:03:2141
sammc7f6c6a02017-01-30 00:53:5142 RenderFrame* render_frame = RenderFrame::FromWebFrame(frame);
43 if (!render_frame)
44 return false;
45
[email protected]940ed1d2012-11-27 21:03:2146 bool webui_enabled =
sammc7f6c6a02017-01-30 00:53:5147 (render_frame->GetEnabledBindings() & BINDINGS_POLICY_WEB_UI) &&
[email protected]2d9748b22014-02-11 00:17:2948 (frame_url.SchemeIs(kChromeUIScheme) ||
[email protected]cca6f392014-05-28 21:32:2649 frame_url.SchemeIs(url::kDataScheme));
[email protected]940ed1d2012-11-27 21:03:2150
51 if (!webui_enabled)
52 return false;
53
54 *frame_ptr = frame;
Lukasz Anforowicz02923102017-10-09 18:11:3755 *render_frame_ptr = render_frame;
[email protected]940ed1d2012-11-27 21:03:2156 return true;
57}
58
[email protected]f5c9f0882014-02-16 22:19:3259} // namespace
60
61// Exposes two methods:
62// - chrome.send: Used to send messages to the browser. Requires the message
63// name as the first argument and can have an optional second argument that
64// should be an array.
65// - chrome.getVariableValue: Returns value for the input variable name if such
66// a value was set by the browser. Else will return an empty string.
lukaszadf18ba762017-06-09 22:24:3067void WebUIExtension::Install(blink::WebLocalFrame* frame) {
Blink Reformat1c4d759e2017-04-09 16:34:5468 v8::Isolate* isolate = blink::MainThreadIsolate();
[email protected]f5c9f0882014-02-16 22:19:3269 v8::HandleScope handle_scope(isolate);
Blink Reformat1c4d759e2017-04-09 16:34:5470 v8::Local<v8::Context> context = frame->MainWorldScriptContext();
[email protected]f5c9f0882014-02-16 22:19:3271 if (context.IsEmpty())
72 return;
73
74 v8::Context::Scope context_scope(context);
75
Dan Elphick258bbaf2019-02-01 17:37:3576 v8::Local<v8::Object> chrome = GetOrCreateChromeObject(isolate, context);
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