blob: dac750eb44f4d6834818bdce7a028ff85feff9f5 [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);
Dan Elphick12bdce12019-04-04 20:18:5477 chrome
78 ->Set(context, gin::StringToSymbol(isolate, "send"),
danakjab3475802019-05-22 19:05:1779 gin::CreateFunctionTemplate(
80 isolate, base::BindRepeating(&WebUIExtension::Send))
Dan Elphick12bdce12019-04-04 20:18:5481 ->GetFunction(context)
82 .ToLocalChecked())
83 .Check();
84 chrome
85 ->Set(context, gin::StringToSymbol(isolate, "getVariableValue"),
86 gin::CreateFunctionTemplate(
danakjab3475802019-05-22 19:05:1787 isolate, base::BindRepeating(&WebUIExtension::GetVariableValue))
Dan Elphick12bdce12019-04-04 20:18:5488 ->GetFunction(context)
89 .ToLocalChecked())
90 .Check();
[email protected]f5c9f0882014-02-16 22:19:3291}
92
[email protected]940ed1d2012-11-27 21:03:2193// static
[email protected]f5c9f0882014-02-16 22:19:3294void WebUIExtension::Send(gin::Arguments* args) {
lukaszadf18ba762017-06-09 22:24:3095 blink::WebLocalFrame* frame;
Lukasz Anforowicz02923102017-10-09 18:11:3796 RenderFrame* render_frame;
97 if (!ShouldRespondToRequest(&frame, &render_frame))
[email protected]187a3532013-06-13 20:25:0198 return;
[email protected]940ed1d2012-11-27 21:03:2199
[email protected]f5c9f0882014-02-16 22:19:32100 std::string message;
101 if (!args->GetNext(&message)) {
102 args->ThrowError();
[email protected]187a3532013-06-13 20:25:01103 return;
[email protected]f5c9f0882014-02-16 22:19:32104 }
[email protected]940ed1d2012-11-27 21:03:21105
106 // If they've provided an optional message parameter, convert that into a
107 // Value to send to the browser process.
dchengcedca5612016-04-09 01:40:15108 std::unique_ptr<base::ListValue> content;
[email protected]f5c9f0882014-02-16 22:19:32109 if (args->PeekNext().IsEmpty() || args->PeekNext()->IsUndefined()) {
[email protected]85ecd7e2013-12-23 21:58:45110 content.reset(new base::ListValue());
[email protected]940ed1d2012-11-27 21:03:21111 } else {
deepak.s750d68f2015-04-30 07:32:41112 v8::Local<v8::Object> obj;
[email protected]f5c9f0882014-02-16 22:19:32113 if (!args->GetNext(&obj)) {
114 args->ThrowError();
[email protected]187a3532013-06-13 20:25:01115 return;
[email protected]f5c9f0882014-02-16 22:19:32116 }
[email protected]940ed1d2012-11-27 21:03:21117
rdevlin.cronin694c6052017-06-13 22:07:35118 content = base::ListValue::From(V8ValueConverter::Create()->FromV8Value(
119 obj, frame->MainWorldScriptContext()));
dcheng0232f572016-05-27 17:47:44120 DCHECK(content);
Rob Wu90585e652017-12-26 17:09:25121 // The conversion of |obj| could have triggered arbitrary JavaScript code,
122 // so check that the frame is still valid to avoid dereferencing a stale
123 // pointer.
124 if (frame != blink::WebLocalFrame::FrameForCurrentContext()) {
125 NOTREACHED();
126 return;
127 }
[email protected]940ed1d2012-11-27 21:03:21128 }
129
130 // Send the message up to the browser.
Lukasz Anforowicz02923102017-10-09 18:11:37131 render_frame->Send(new FrameHostMsg_WebUISend(render_frame->GetRoutingID(),
Lukasz Anforowicz02923102017-10-09 18:11:37132 message, *content));
[email protected]940ed1d2012-11-27 21:03:21133}
134
135// static
[email protected]f5c9f0882014-02-16 22:19:32136std::string WebUIExtension::GetVariableValue(const std::string& name) {
lukaszadf18ba762017-06-09 22:24:30137 blink::WebLocalFrame* frame;
Lukasz Anforowicz02923102017-10-09 18:11:37138 RenderFrame* render_frame;
139 if (!ShouldRespondToRequest(&frame, &render_frame))
[email protected]f5c9f0882014-02-16 22:19:32140 return std::string();
[email protected]940ed1d2012-11-27 21:03:21141
Nasko Oskovdce1a622019-11-06 23:58:33142 return WebUIExtensionData::Get(render_frame)->GetValue(name);
[email protected]940ed1d2012-11-27 21:03:21143}
144
145} // namespace content