1 // Copyright (c) 2012 The Chromium Embedded Framework Authors.
2 // Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5
6 #include "libcef/renderer/blink_glue.h"
7
8 #include "third_party/blink/public/mojom/v8_cache_options.mojom-blink.h"
9 #include "third_party/blink/public/platform/scheduler/web_resource_loading_task_runner_handle.h"
10 #include "third_party/blink/public/platform/web_string.h"
11 #include "third_party/blink/public/platform/web_url_response.h"
12 #include "third_party/blink/public/web/web_document.h"
13 #include "third_party/blink/public/web/web_element.h"
14 #include "third_party/blink/public/web/web_local_frame_client.h"
15 #include "third_party/blink/public/web/web_node.h"
16 #include "third_party/blink/public/web/web_view_client.h"
17
18 #include "third_party/blink/renderer/bindings/core/v8/sanitize_script_errors.h"
19 #include "third_party/blink/renderer/bindings/core/v8/script_evaluation_result.h"
20 #include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
21 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
22 #include "third_party/blink/renderer/core/dom/document.h"
23 #include "third_party/blink/renderer/core/dom/element.h"
24 #include "third_party/blink/renderer/core/dom/node.h"
25 #include "third_party/blink/renderer/core/editing/serializers/serialization.h"
26 #include "third_party/blink/renderer/core/exported/web_view_impl.h"
27 #include "third_party/blink/renderer/core/frame/frame_owner.h"
28 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
29 #include "third_party/blink/renderer/core/frame/local_frame.h"
30 #include "third_party/blink/renderer/core/frame/settings.h"
31 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
32 #include "third_party/blink/renderer/core/loader/frame_load_request.h"
33 #include "third_party/blink/renderer/core/script/classic_script.h"
34 #include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
35 #include "third_party/blink/renderer/platform/bindings/v8_binding.h"
36 #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
37 #include "third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h"
38 #include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
39 #include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
40 #undef LOG
41
42 #include "base/logging.h"
43
44 namespace blink_glue {
45
46 const int64_t kInvalidFrameId = -1;
47
CanGoBack(blink::WebView * view)48 bool CanGoBack(blink::WebView* view) {
49 if (!view)
50 return false;
51 return view->HistoryBackListCount() > 0;
52 }
53
CanGoForward(blink::WebView * view)54 bool CanGoForward(blink::WebView* view) {
55 if (!view)
56 return false;
57 return view->HistoryForwardListCount() > 0;
58 }
59
GoBack(blink::WebView * view)60 void GoBack(blink::WebView* view) {
61 if (!view)
62 return;
63
64 blink::WebFrame* main_frame = view->MainFrame();
65 if (main_frame && main_frame->IsWebLocalFrame()) {
66 if (view->HistoryBackListCount() > 0) {
67 blink::Frame* core_frame = blink::WebFrame::ToCoreFrame(*main_frame);
68 blink::To<blink::LocalFrame>(core_frame)
69 ->GetLocalFrameHostRemote()
70 .GoToEntryAtOffset(-1, true /* has_user_gesture */);
71 }
72 }
73 }
74
GoForward(blink::WebView * view)75 void GoForward(blink::WebView* view) {
76 if (!view)
77 return;
78
79 blink::WebFrame* main_frame = view->MainFrame();
80 if (main_frame && main_frame->IsWebLocalFrame()) {
81 if (view->HistoryForwardListCount() > 0) {
82 blink::Frame* core_frame = blink::WebFrame::ToCoreFrame(*main_frame);
83 blink::To<blink::LocalFrame>(core_frame)
84 ->GetLocalFrameHostRemote()
85 .GoToEntryAtOffset(1, true /* has_user_gesture */);
86 }
87 }
88 }
89
DumpDocumentText(blink::WebLocalFrame * frame)90 std::string DumpDocumentText(blink::WebLocalFrame* frame) {
91 // We use the document element's text instead of the body text here because
92 // not all documents have a body, such as XML documents.
93 blink::WebElement document_element = frame->GetDocument().DocumentElement();
94 if (document_element.IsNull())
95 return std::string();
96
97 blink::Element* web_element = document_element.Unwrap<blink::Element>();
98 return blink::WebString(web_element->innerText()).Utf8();
99 }
100
DumpDocumentMarkup(blink::WebLocalFrame * frame)101 std::string DumpDocumentMarkup(blink::WebLocalFrame* frame) {
102 const auto& string = blink::CreateMarkup(
103 blink::To<blink::WebLocalFrameImpl>(frame)->GetFrame()->GetDocument());
104 return string.Utf8();
105 }
106
GetNodeType(const blink::WebNode & node)107 cef_dom_node_type_t GetNodeType(const blink::WebNode& node) {
108 const blink::Node* web_node = node.ConstUnwrap<blink::Node>();
109 switch (web_node->getNodeType()) {
110 case blink::Node::kElementNode:
111 return DOM_NODE_TYPE_ELEMENT;
112 case blink::Node::kAttributeNode:
113 return DOM_NODE_TYPE_ATTRIBUTE;
114 case blink::Node::kTextNode:
115 return DOM_NODE_TYPE_TEXT;
116 case blink::Node::kCdataSectionNode:
117 return DOM_NODE_TYPE_CDATA_SECTION;
118 case blink::Node::kProcessingInstructionNode:
119 return DOM_NODE_TYPE_PROCESSING_INSTRUCTIONS;
120 case blink::Node::kCommentNode:
121 return DOM_NODE_TYPE_COMMENT;
122 case blink::Node::kDocumentNode:
123 return DOM_NODE_TYPE_DOCUMENT;
124 case blink::Node::kDocumentTypeNode:
125 return DOM_NODE_TYPE_DOCUMENT_TYPE;
126 case blink::Node::kDocumentFragmentNode:
127 return DOM_NODE_TYPE_DOCUMENT_FRAGMENT;
128 }
129 return DOM_NODE_TYPE_UNSUPPORTED;
130 }
131
GetNodeName(const blink::WebNode & node)132 blink::WebString GetNodeName(const blink::WebNode& node) {
133 const blink::Node* web_node = node.ConstUnwrap<blink::Node>();
134 return web_node->nodeName();
135 }
136
CreateNodeMarkup(const blink::WebNode & node)137 blink::WebString CreateNodeMarkup(const blink::WebNode& node) {
138 const blink::Node* web_node = node.ConstUnwrap<blink::Node>();
139 return blink::CreateMarkup(web_node);
140 }
141
SetNodeValue(blink::WebNode & node,const blink::WebString & value)142 bool SetNodeValue(blink::WebNode& node, const blink::WebString& value) {
143 blink::Node* web_node = node.Unwrap<blink::Node>();
144 web_node->setNodeValue(value);
145 return true;
146 }
147
CallV8Function(v8::Local<v8::Context> context,v8::Local<v8::Function> function,v8::Local<v8::Object> receiver,int argc,v8::Local<v8::Value> args[],v8::Isolate * isolate)148 v8::MaybeLocal<v8::Value> CallV8Function(v8::Local<v8::Context> context,
149 v8::Local<v8::Function> function,
150 v8::Local<v8::Object> receiver,
151 int argc,
152 v8::Local<v8::Value> args[],
153 v8::Isolate* isolate) {
154 v8::MaybeLocal<v8::Value> func_rv;
155
156 // Execute the function call using the V8ScriptRunner so that inspector
157 // instrumentation works.
158 blink::LocalFrame* frame = blink::ToLocalFrameIfNotDetached(context);
159 DCHECK(frame);
160 if (frame &&
161 frame->DomWindow()->CanExecuteScripts(blink::kAboutToExecuteScript)) {
162 func_rv = blink::V8ScriptRunner::CallFunction(
163 function, frame->GetDocument()->GetExecutionContext(), receiver, argc,
164 args, isolate);
165 }
166
167 return func_rv;
168 }
169
IsTextControlElement(const blink::WebElement & element)170 bool IsTextControlElement(const blink::WebElement& element) {
171 const blink::Element* web_element = element.ConstUnwrap<blink::Element>();
172 return web_element->IsTextControl();
173 }
174
ExecuteV8ScriptAndReturnValue(const blink::WebString & source,const blink::WebString & source_url,int start_line,v8::Local<v8::Context> context,v8::TryCatch & tryCatch)175 v8::Local<v8::Value> ExecuteV8ScriptAndReturnValue(
176 const blink::WebString& source,
177 const blink::WebString& source_url,
178 int start_line,
179 v8::Local<v8::Context> context,
180 v8::TryCatch& tryCatch) {
181 if (start_line < 1)
182 start_line = 1;
183
184 blink::LocalFrame* frame = blink::ToLocalFrameIfNotDetached(context);
185 if (!frame)
186 return v8::Local<v8::Value>();
187
188 const blink::ScriptSourceCode ssc = blink::ScriptSourceCode(
189 source, blink::ScriptSourceLocationType::kInternal,
190 nullptr, /* cache_handler */
191 blink::KURL(source_url),
192 WTF::TextPosition(WTF::OrdinalNumber::FromOneBasedInt(start_line),
193 WTF::OrdinalNumber::FromZeroBasedInt(0)));
194
195 auto* script = blink::MakeGarbageCollected<blink::ClassicScript>(
196 ssc, ssc.Url(), blink::ScriptFetchOptions(),
197 blink::SanitizeScriptErrors::kDoNotSanitize);
198
199 // The Rethrow() message is unused due to kDoNotSanitize but it still needs
200 // to be non-nullopt for exceptions to be re-thrown as expected.
201 auto result = blink::V8ScriptRunner::CompileAndRunScript(
202 blink::ScriptState::From(context), script,
203 blink::ExecuteScriptPolicy::kExecuteScriptWhenScriptsDisabled,
204 blink::V8ScriptRunner::RethrowErrorsOption::Rethrow(""));
205
206 if (result.GetResultType() ==
207 blink::ScriptEvaluationResult::ResultType::kSuccess) {
208 return result.GetSuccessValue();
209 }
210
211 DCHECK(tryCatch.HasCaught());
212 return v8::Local<v8::Value>();
213 }
214
IsScriptForbidden()215 bool IsScriptForbidden() {
216 return blink::ScriptForbiddenScope::IsScriptForbidden();
217 }
218
RegisterURLSchemeAsSupportingFetchAPI(const blink::WebString & scheme)219 void RegisterURLSchemeAsSupportingFetchAPI(const blink::WebString& scheme) {
220 blink::SchemeRegistry::RegisterURLSchemeAsSupportingFetchAPI(scheme);
221 }
222
223 struct CefScriptForbiddenScope::Impl {
224 blink::ScriptForbiddenScope scope_;
225 };
226
CefScriptForbiddenScope()227 CefScriptForbiddenScope::CefScriptForbiddenScope() : impl_(new Impl()) {}
228
~CefScriptForbiddenScope()229 CefScriptForbiddenScope::~CefScriptForbiddenScope() {}
230
ResponseWasCached(const blink::WebURLResponse & response)231 bool ResponseWasCached(const blink::WebURLResponse& response) {
232 return response.ToResourceResponse().WasCached();
233 }
234
HasPluginFrameOwner(blink::WebLocalFrame * frame)235 bool HasPluginFrameOwner(blink::WebLocalFrame* frame) {
236 blink::Frame* core_frame = blink::WebFrame::ToCoreFrame(*frame);
237 return core_frame->Owner() && core_frame->Owner()->IsPlugin();
238 }
239
240 // Based on WebLocalFrameImpl::StartNavigation which was removed in
241 // https://crrev.com/de4fc2a5fe.
StartNavigation(blink::WebLocalFrame * frame,const blink::WebURLRequest & request)242 void StartNavigation(blink::WebLocalFrame* frame,
243 const blink::WebURLRequest& request) {
244 DCHECK(!request.IsNull());
245 DCHECK(!request.Url().ProtocolIs("javascript"));
246
247 blink::FrameLoadRequest frame_load_request(nullptr,
248 request.ToResourceRequest());
249 blink::Frame* core_frame = blink::WebFrame::ToCoreFrame(*frame);
250 blink::To<blink::LocalFrame>(core_frame)
251 ->Loader()
252 .StartNavigation(frame_load_request, blink::WebFrameLoadType::kStandard);
253 }
254
255 std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>
CreateResourceLoadingTaskRunnerHandle(blink::WebLocalFrame * frame)256 CreateResourceLoadingTaskRunnerHandle(blink::WebLocalFrame* frame) {
257 blink::Frame* core_frame = blink::WebFrame::ToCoreFrame(*frame);
258 return blink::To<blink::LocalFrame>(core_frame)
259 ->GetFrameScheduler()
260 ->CreateResourceLoadingTaskRunnerHandle();
261 }
262
263 std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>
CreateResourceLoadingMaybeUnfreezableTaskRunnerHandle(blink::WebLocalFrame * frame)264 CreateResourceLoadingMaybeUnfreezableTaskRunnerHandle(
265 blink::WebLocalFrame* frame) {
266 blink::Frame* core_frame = blink::WebFrame::ToCoreFrame(*frame);
267 return blink::To<blink::LocalFrame>(core_frame)
268 ->GetFrameScheduler()
269 ->CreateResourceLoadingMaybeUnfreezableTaskRunnerHandle();
270 }
271
272 } // namespace blink_glue
273