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