mirror of
				https://bitbucket.org/chromiumembedded/cef
				synced 2025-06-05 21:39:12 +02:00 
			
		
		
		
	The CefFrame::CreateURLRequest method is no longer supported in the renderer process. Usage of this method was already limited to same-origin requests due to renderer process CORS restrictions, and the underlying Blink API has now been removed in https://crbug.com/1413912 (M112+). Existing alternatives include CefURLRequest usage in the browser process, or JavaScript XMLHttpRequest/fetch API usage in the renderer process.
		
			
				
	
	
		
			319 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			319 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright (c) 2012 The Chromium Embedded Framework Authors.
 | |
| // Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
 | |
| // Use of this source code is governed by a BSD-style license that can be
 | |
| // found in the LICENSE file.
 | |
| 
 | |
| #include "libcef/renderer/blink_glue.h"
 | |
| 
 | |
| #include "third_party/blink/public/mojom/v8_cache_options.mojom-blink.h"
 | |
| #include "third_party/blink/public/platform/web_string.h"
 | |
| #include "third_party/blink/public/platform/web_url_response.h"
 | |
| #include "third_party/blink/public/web/web_document.h"
 | |
| #include "third_party/blink/public/web/web_element.h"
 | |
| #include "third_party/blink/public/web/web_local_frame_client.h"
 | |
| #include "third_party/blink/public/web/web_node.h"
 | |
| #include "third_party/blink/public/web/web_view_client.h"
 | |
| 
 | |
| #include "third_party/blink/renderer/bindings/core/v8/sanitize_script_errors.h"
 | |
| #include "third_party/blink/renderer/bindings/core/v8/script_evaluation_result.h"
 | |
| #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 | |
| #include "third_party/blink/renderer/core/dom/document.h"
 | |
| #include "third_party/blink/renderer/core/dom/element.h"
 | |
| #include "third_party/blink/renderer/core/dom/node.h"
 | |
| #include "third_party/blink/renderer/core/editing/serializers/serialization.h"
 | |
| #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 | |
| #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h"
 | |
| #include "third_party/blink/renderer/core/exported/web_view_impl.h"
 | |
| #include "third_party/blink/renderer/core/frame/frame_owner.h"
 | |
| #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 | |
| #include "third_party/blink/renderer/core/frame/local_frame.h"
 | |
| #include "third_party/blink/renderer/core/frame/settings.h"
 | |
| #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 | |
| #include "third_party/blink/renderer/core/loader/frame_load_request.h"
 | |
| #include "third_party/blink/renderer/core/page/page.h"
 | |
| #include "third_party/blink/renderer/core/script/classic_script.h"
 | |
| #include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
 | |
| #include "third_party/blink/renderer/platform/bindings/v8_binding.h"
 | |
| #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
 | |
| #include "third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h"
 | |
| #include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
 | |
| #undef LOG
 | |
| 
 | |
| #include "base/logging.h"
 | |
| 
 | |
| namespace blink_glue {
 | |
| 
 | |
| namespace {
 | |
| 
 | |
| blink::ExecutionContext* GetExecutionContext(v8::Local<v8::Context> context) {
 | |
|   blink::LocalFrame* frame = blink::ToLocalFrameIfNotDetached(context);
 | |
|   if (frame &&
 | |
|       frame->DomWindow()->CanExecuteScripts(blink::kAboutToExecuteScript)) {
 | |
|     return frame->GetDocument()->GetExecutionContext();
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| }  // namespace
 | |
| 
 | |
| const int64_t kInvalidFrameId = -1;
 | |
| 
 | |
| bool CanGoBack(blink::WebView* view) {
 | |
|   if (!view) {
 | |
|     return false;
 | |
|   }
 | |
|   return view->HistoryBackListCount() > 0;
 | |
| }
 | |
| 
 | |
| bool CanGoForward(blink::WebView* view) {
 | |
|   if (!view) {
 | |
|     return false;
 | |
|   }
 | |
|   return view->HistoryForwardListCount() > 0;
 | |
| }
 | |
| 
 | |
| void GoBack(blink::WebView* view) {
 | |
|   if (!view) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   blink::WebFrame* main_frame = view->MainFrame();
 | |
|   if (main_frame && main_frame->IsWebLocalFrame()) {
 | |
|     if (view->HistoryBackListCount() > 0) {
 | |
|       blink::Frame* core_frame = blink::WebFrame::ToCoreFrame(*main_frame);
 | |
|       blink::To<blink::LocalFrame>(core_frame)
 | |
|           ->GetLocalFrameHostRemote()
 | |
|           .GoToEntryAtOffset(-1, /*has_user_gesture=*/true, absl::nullopt);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| void GoForward(blink::WebView* view) {
 | |
|   if (!view) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   blink::WebFrame* main_frame = view->MainFrame();
 | |
|   if (main_frame && main_frame->IsWebLocalFrame()) {
 | |
|     if (view->HistoryForwardListCount() > 0) {
 | |
|       blink::Frame* core_frame = blink::WebFrame::ToCoreFrame(*main_frame);
 | |
|       blink::To<blink::LocalFrame>(core_frame)
 | |
|           ->GetLocalFrameHostRemote()
 | |
|           .GoToEntryAtOffset(1, /*has_user_gesture=*/true, absl::nullopt);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool IsInBackForwardCache(blink::WebLocalFrame* frame) {
 | |
|   blink::Frame* core_frame = blink::WebFrame::ToCoreFrame(*frame);
 | |
|   return blink::To<blink::LocalFrame>(core_frame)
 | |
|       ->GetPage()
 | |
|       ->GetPageScheduler()
 | |
|       ->IsInBackForwardCache();
 | |
| }
 | |
| 
 | |
| blink::WebString DumpDocumentText(blink::WebLocalFrame* frame) {
 | |
|   // We use the document element's text instead of the body text here because
 | |
|   // not all documents have a body, such as XML documents.
 | |
|   blink::WebElement document_element = frame->GetDocument().DocumentElement();
 | |
|   if (document_element.IsNull()) {
 | |
|     return blink::WebString();
 | |
|   }
 | |
| 
 | |
|   blink::Element* web_element = document_element.Unwrap<blink::Element>();
 | |
|   return blink::WebString(web_element->innerText());
 | |
| }
 | |
| 
 | |
| blink::WebString DumpDocumentMarkup(blink::WebLocalFrame* frame) {
 | |
|   return blink::CreateMarkup(
 | |
|       blink::To<blink::WebLocalFrameImpl>(frame)->GetFrame()->GetDocument());
 | |
| }
 | |
| 
 | |
| cef_dom_node_type_t GetNodeType(const blink::WebNode& node) {
 | |
|   const blink::Node* web_node = node.ConstUnwrap<blink::Node>();
 | |
|   switch (web_node->getNodeType()) {
 | |
|     case blink::Node::kElementNode:
 | |
|       return DOM_NODE_TYPE_ELEMENT;
 | |
|     case blink::Node::kAttributeNode:
 | |
|       return DOM_NODE_TYPE_ATTRIBUTE;
 | |
|     case blink::Node::kTextNode:
 | |
|       return DOM_NODE_TYPE_TEXT;
 | |
|     case blink::Node::kCdataSectionNode:
 | |
|       return DOM_NODE_TYPE_CDATA_SECTION;
 | |
|     case blink::Node::kProcessingInstructionNode:
 | |
|       return DOM_NODE_TYPE_PROCESSING_INSTRUCTIONS;
 | |
|     case blink::Node::kCommentNode:
 | |
|       return DOM_NODE_TYPE_COMMENT;
 | |
|     case blink::Node::kDocumentNode:
 | |
|       return DOM_NODE_TYPE_DOCUMENT;
 | |
|     case blink::Node::kDocumentTypeNode:
 | |
|       return DOM_NODE_TYPE_DOCUMENT_TYPE;
 | |
|     case blink::Node::kDocumentFragmentNode:
 | |
|       return DOM_NODE_TYPE_DOCUMENT_FRAGMENT;
 | |
|   }
 | |
|   return DOM_NODE_TYPE_UNSUPPORTED;
 | |
| }
 | |
| 
 | |
| blink::WebString GetNodeName(const blink::WebNode& node) {
 | |
|   const blink::Node* web_node = node.ConstUnwrap<blink::Node>();
 | |
|   return web_node->nodeName();
 | |
| }
 | |
| 
 | |
| blink::WebString CreateNodeMarkup(const blink::WebNode& node) {
 | |
|   const blink::Node* web_node = node.ConstUnwrap<blink::Node>();
 | |
|   return blink::CreateMarkup(web_node);
 | |
| }
 | |
| 
 | |
| bool SetNodeValue(blink::WebNode& node, const blink::WebString& value) {
 | |
|   blink::Node* web_node = node.Unwrap<blink::Node>();
 | |
|   web_node->setNodeValue(value);
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| v8::MaybeLocal<v8::Value> 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) {
 | |
|   v8::MaybeLocal<v8::Value> func_rv;
 | |
| 
 | |
|   // Execute the function call using the V8ScriptRunner so that inspector
 | |
|   // instrumentation works.
 | |
|   if (auto execution_context = GetExecutionContext(context)) {
 | |
|     func_rv = blink::V8ScriptRunner::CallFunction(
 | |
|         function, execution_context, receiver, argc, args, isolate);
 | |
|   }
 | |
| 
 | |
|   return func_rv;
 | |
| }
 | |
| 
 | |
| bool IsTextControlElement(const blink::WebElement& element) {
 | |
|   const blink::Element* web_element = element.ConstUnwrap<blink::Element>();
 | |
|   return web_element->IsTextControl();
 | |
| }
 | |
| 
 | |
| v8::Local<v8::Value> ExecuteV8ScriptAndReturnValue(
 | |
|     const blink::WebString& source,
 | |
|     const blink::WebString& source_url,
 | |
|     int start_line,
 | |
|     v8::Local<v8::Context> context,
 | |
|     v8::TryCatch& tryCatch) {
 | |
|   if (start_line < 1) {
 | |
|     start_line = 1;
 | |
|   }
 | |
| 
 | |
|   blink::LocalFrame* frame = blink::ToLocalFrameIfNotDetached(context);
 | |
|   if (!frame) {
 | |
|     return v8::Local<v8::Value>();
 | |
|   }
 | |
| 
 | |
|   auto* script = blink::ClassicScript::Create(
 | |
|       source, blink::KURL(source_url), blink::KURL(source_url),
 | |
|       blink::ScriptFetchOptions(), blink::ScriptSourceLocationType::kInternal,
 | |
|       blink::SanitizeScriptErrors::kDoNotSanitize, /*cache_handler=*/nullptr,
 | |
|       WTF::TextPosition(WTF::OrdinalNumber::FromOneBasedInt(start_line),
 | |
|                         WTF::OrdinalNumber::FromZeroBasedInt(0)));
 | |
| 
 | |
|   // The Rethrow() message is unused due to kDoNotSanitize but it still needs
 | |
|   // to be non-nullopt for exceptions to be re-thrown as expected.
 | |
|   auto result = blink::V8ScriptRunner::CompileAndRunScript(
 | |
|       blink::ScriptState::From(context), script,
 | |
|       blink::ExecuteScriptPolicy::kExecuteScriptWhenScriptsDisabled,
 | |
|       blink::V8ScriptRunner::RethrowErrorsOption::Rethrow(""));
 | |
| 
 | |
|   if (result.GetResultType() ==
 | |
|       blink::ScriptEvaluationResult::ResultType::kSuccess) {
 | |
|     return result.GetSuccessValue();
 | |
|   }
 | |
| 
 | |
|   DCHECK(tryCatch.HasCaught());
 | |
|   return v8::Local<v8::Value>();
 | |
| }
 | |
| 
 | |
| v8::MicrotaskQueue* GetMicrotaskQueue(v8::Local<v8::Context> context) {
 | |
|   if (auto execution_context = GetExecutionContext(context)) {
 | |
|     return execution_context->GetMicrotaskQueue();
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| bool IsScriptForbidden() {
 | |
|   return blink::ScriptForbiddenScope::IsScriptForbidden();
 | |
| }
 | |
| 
 | |
| std::unique_ptr<CefObserverRegistration>
 | |
| RegisterExecutionContextLifecycleStateObserver(
 | |
|     v8::Local<v8::Context> context,
 | |
|     CefExecutionContextLifecycleStateObserver* observer) {
 | |
|   class Observer : public blink::GarbageCollected<Observer>,
 | |
|                    public blink::ExecutionContextLifecycleStateObserver {
 | |
|    public:
 | |
|     Observer(blink::ExecutionContext* execution_context,
 | |
|              CefExecutionContextLifecycleStateObserver* observer)
 | |
|         : blink::ExecutionContextLifecycleStateObserver(execution_context),
 | |
|           observer_(observer) {
 | |
|       UpdateStateIfNeeded();
 | |
|     }
 | |
| 
 | |
|     void ContextLifecycleStateChanged(
 | |
|         blink::mojom::blink::FrameLifecycleState state) override {
 | |
|       observer_->ContextLifecycleStateChanged(state);
 | |
|     }
 | |
| 
 | |
|     void ContextDestroyed() override {}
 | |
| 
 | |
|    private:
 | |
|     CefExecutionContextLifecycleStateObserver* observer_;
 | |
|   };
 | |
| 
 | |
|   class Registration : public CefObserverRegistration {
 | |
|    public:
 | |
|     Registration(blink::Persistent<Observer> observer) : observer_(observer) {}
 | |
| 
 | |
|    private:
 | |
|     blink::Persistent<Observer> observer_;
 | |
|   };
 | |
| 
 | |
|   return std::make_unique<Registration>(blink::MakeGarbageCollected<Observer>(
 | |
|       blink::ExecutionContext::From(context), observer));
 | |
| }
 | |
| 
 | |
| void RegisterURLSchemeAsSupportingFetchAPI(const blink::WebString& scheme) {
 | |
|   blink::SchemeRegistry::RegisterURLSchemeAsSupportingFetchAPI(scheme);
 | |
| }
 | |
| 
 | |
| struct CefScriptForbiddenScope::Impl {
 | |
|   blink::ScriptForbiddenScope scope_;
 | |
| };
 | |
| 
 | |
| CefScriptForbiddenScope::CefScriptForbiddenScope() : impl_(new Impl()) {}
 | |
| 
 | |
| CefScriptForbiddenScope::~CefScriptForbiddenScope() {}
 | |
| 
 | |
| bool ResponseWasCached(const blink::WebURLResponse& response) {
 | |
|   return response.ToResourceResponse().WasCached();
 | |
| }
 | |
| 
 | |
| bool HasPluginFrameOwner(blink::WebLocalFrame* frame) {
 | |
|   blink::Frame* core_frame = blink::WebFrame::ToCoreFrame(*frame);
 | |
|   return core_frame->Owner() && core_frame->Owner()->IsPlugin();
 | |
| }
 | |
| 
 | |
| // Based on WebLocalFrameImpl::StartNavigation which was removed in
 | |
| // https://crrev.com/de4fc2a5fe.
 | |
| void StartNavigation(blink::WebLocalFrame* frame,
 | |
|                      const blink::WebURLRequest& request) {
 | |
|   DCHECK(!request.IsNull());
 | |
|   DCHECK(!request.Url().ProtocolIs("javascript"));
 | |
| 
 | |
|   blink::FrameLoadRequest frame_load_request(nullptr,
 | |
|                                              request.ToResourceRequest());
 | |
|   blink::Frame* core_frame = blink::WebFrame::ToCoreFrame(*frame);
 | |
|   blink::To<blink::LocalFrame>(core_frame)
 | |
|       ->Loader()
 | |
|       .StartNavigation(frame_load_request, blink::WebFrameLoadType::kStandard);
 | |
| }
 | |
| 
 | |
| }  // namespace blink_glue
 |