完善浏览器
This commit is contained in:
parent
c41a936bbf
commit
8ff67ba1cd
28
app.manifest
28
app.manifest
@ -1,28 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
|
||||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
|
||||||
<description>ctai</description>
|
|
||||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
|
||||||
<security>
|
|
||||||
<requestedPrivileges>
|
|
||||||
<requestedExecutionLevel
|
|
||||||
level="asInvoker"
|
|
||||||
uiAccess="false"
|
|
||||||
/>
|
|
||||||
</requestedPrivileges>
|
|
||||||
</security>
|
|
||||||
</trustInfo>
|
|
||||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
|
||||||
<application>
|
|
||||||
<!-- Windows 10 -->
|
|
||||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
|
||||||
<!-- Windows 8.1 -->
|
|
||||||
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
|
|
||||||
<!-- Windows Vista -->
|
|
||||||
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
|
|
||||||
<!-- Windows 7 -->
|
|
||||||
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
|
|
||||||
<!-- Windows 8 -->
|
|
||||||
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
|
|
||||||
</application>
|
|
||||||
</compatibility>
|
|
||||||
</assembly>
|
|
||||||
46
compatibility.manifest
Normal file
46
compatibility.manifest
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||||
|
<assemblyIdentity type="Win32" name="ctai" version="6.0.0.0" processorArchitecture="x86" />
|
||||||
|
<file name="chrome_100_percent.pak" loadFrom=".\cef_binary\chrome_100_percent.pak"></file>
|
||||||
|
<file name="chrome_200_percent.pak" loadFrom=".\cef_binary\chrome_200_percent.pak"></file>
|
||||||
|
<file name="chrome_elf.dll" loadFrom=".\cef_binary\chrome_elf.dll"></file>
|
||||||
|
<file name="d3dcompiler_47.dll" loadFrom=".\cef_binary\d3dcompiler_47.dll"></file>
|
||||||
|
<file name="dxcompiler.dll" loadFrom=".\cef_binary\dxcompiler.dll"></file>
|
||||||
|
<file name="dxil.dll" loadFrom=".\cef_binary\dxil.dll"></file>
|
||||||
|
<file name="icudtl.dat" loadFrom=".\cef_binary\icudtl.dat"></file>
|
||||||
|
<file name="libcef.dll" loadFrom=".\cef_binary\libcef.dll"></file>
|
||||||
|
<file name="libEGL.dll" loadFrom=".\cef_binary\libEGL.dll"></file>
|
||||||
|
<file name="libGLESv2.dll" loadFrom=".\cef_binary\libGLESv2.dll"></file>
|
||||||
|
<file name="resources.pak" loadFrom=".\cef_binary\resources.pak"></file>
|
||||||
|
<file name="snapshot_blob.bin" loadFrom=".\cef_binary\snapshot_blob.bin"></file>
|
||||||
|
<file name="v8_context_snapshot.bin" loadFrom=".\cef_binary\v8_context_snapshot.bin"></file>
|
||||||
|
<file name="vk_swiftshader.dll" loadFrom=".\cef_binary\vk_swiftshader.dll"></file>
|
||||||
|
<file name="vk_swiftshader_icd.json" loadFrom=".\cef_binary\vk_swiftshader_icd.json"></file>
|
||||||
|
<file name="vulkan-1.dll" loadFrom=".\cef_binary\vulkan-1.dll"></file>
|
||||||
|
|
||||||
|
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<security>
|
||||||
|
<requestedPrivileges>
|
||||||
|
<requestedExecutionLevel level="asInvoker" />
|
||||||
|
</requestedPrivileges>
|
||||||
|
</security>
|
||||||
|
</trustInfo>
|
||||||
|
|
||||||
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
|
<application>
|
||||||
|
<!--The ID below indicates application support for Windows Vista -->
|
||||||
|
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
|
||||||
|
<!--The ID below indicates application support for Windows 7 -->
|
||||||
|
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
|
||||||
|
<!--The ID below indicates application support for Windows 8 -->
|
||||||
|
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
|
||||||
|
<!--The ID below indicates application support for Windows 8.1 -->
|
||||||
|
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
|
||||||
|
<!--The ID below indicates application support for Windows 10 -->
|
||||||
|
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||||
|
<!-- This tag is required for XAML islands usage in the process for media scenarios. -->
|
||||||
|
<!-- This version corresponds to the Windows 10 May 2019 Update. -->
|
||||||
|
<maxversiontested Id="10.0.18362.0"/>
|
||||||
|
</application>
|
||||||
|
</compatibility>
|
||||||
|
</assembly>
|
||||||
@ -1,73 +0,0 @@
|
|||||||
#include "CefViewAppBase.h"
|
|
||||||
|
|
||||||
#include "../Common/CefViewCoreLog.h"
|
|
||||||
#include <CefViewCoreProtocol.h>
|
|
||||||
|
|
||||||
// These flags must match the Chromium values.
|
|
||||||
const char kProcessType[] = "type";
|
|
||||||
const char kZygoteProcess[] = "zygote";
|
|
||||||
const char kRendererProcess[] = "renderer";
|
|
||||||
|
|
||||||
CefViewAppBase::CefViewAppBase(const CefString& scheme_name)
|
|
||||||
: builtin_scheme_name_(scheme_name)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
CefViewAppBase::ProcessType
|
|
||||||
CefViewAppBase::GetProcessType(CefRefPtr<CefCommandLine> command_line)
|
|
||||||
{
|
|
||||||
// The command-line flag won't be specified for the browser process.
|
|
||||||
if (!command_line->HasSwitch(kProcessType))
|
|
||||||
return UnkownProcess;
|
|
||||||
|
|
||||||
auto process_type = command_line->GetSwitchValue(kProcessType);
|
|
||||||
logI("process type parameter is: %s", process_type.c_str());
|
|
||||||
if (process_type == kZygoteProcess) {
|
|
||||||
// for linux only
|
|
||||||
return ZygoteProcess;
|
|
||||||
} else if (process_type == kRendererProcess) {
|
|
||||||
return RendererProcess;
|
|
||||||
}
|
|
||||||
|
|
||||||
return OtherProcess;
|
|
||||||
}
|
|
||||||
|
|
||||||
CefString
|
|
||||||
CefViewAppBase::GetBridgeObjectName(CefRefPtr<CefCommandLine> command_line)
|
|
||||||
{
|
|
||||||
if (!command_line->HasSwitch(kCefViewBridgeObjectNameKey))
|
|
||||||
return "";
|
|
||||||
|
|
||||||
auto name = command_line->GetSwitchValue(kCefViewBridgeObjectNameKey);
|
|
||||||
logI("bridge object name: %s", name.c_str());
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
CefString
|
|
||||||
CefViewAppBase::GetBuiltinSchemeName(CefRefPtr<CefCommandLine> command_line)
|
|
||||||
{
|
|
||||||
if (!command_line->HasSwitch(kCefViewBuiltinSchemeNameKey))
|
|
||||||
return "";
|
|
||||||
|
|
||||||
auto name = command_line->GetSwitchValue(kCefViewBuiltinSchemeNameKey);
|
|
||||||
logI("built-in scheme name: %s", name.c_str());
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewAppBase::OnRegisterCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar)
|
|
||||||
{
|
|
||||||
if (registrar) {
|
|
||||||
int options = 0 //
|
|
||||||
| CEF_SCHEME_OPTION_STANDARD //
|
|
||||||
| CEF_SCHEME_OPTION_SECURE //
|
|
||||||
| CEF_SCHEME_OPTION_CORS_ENABLED //
|
|
||||||
| CEF_SCHEME_OPTION_FETCH_ENABLED //
|
|
||||||
| 0;
|
|
||||||
auto scheme = builtin_scheme_name_.empty() ? kCefViewDefaultBuiltinSchemaName : builtin_scheme_name_;
|
|
||||||
if (!registrar->AddCustomScheme(scheme, options)) {
|
|
||||||
logE("faield to add built-in scheme: %s", scheme.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
//
|
|
||||||
// CefWingAppBase.hpp
|
|
||||||
// CefViewWing
|
|
||||||
//
|
|
||||||
// Created by Sheen Tian on 2020/6/17.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef CefAppBase_h
|
|
||||||
#define CefAppBase_h
|
|
||||||
|
|
||||||
#pragma region stl_headers
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#pragma endregion
|
|
||||||
|
|
||||||
#pragma region cef_headers
|
|
||||||
#include <include/cef_app.h>
|
|
||||||
#pragma endregion
|
|
||||||
|
|
||||||
class CefViewAppBase : public CefApp
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
CefString builtin_scheme_name_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
CefViewAppBase(const CefString& scheme_name);
|
|
||||||
|
|
||||||
enum ProcessType
|
|
||||||
{
|
|
||||||
UnkownProcess,
|
|
||||||
ZygoteProcess,
|
|
||||||
RendererProcess,
|
|
||||||
OtherProcess,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the current process type
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="command_line">The command line</param>
|
|
||||||
/// <returns>The process type</returns>
|
|
||||||
static ProcessType GetProcessType(CefRefPtr<CefCommandLine> command_line);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the bridge object name from command line
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="command_line">The command line</param>
|
|
||||||
/// <returns>The bridge object name</returns>
|
|
||||||
static CefString GetBridgeObjectName(CefRefPtr<CefCommandLine> command_line);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the built-in scheme name
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="command_line">The command line</param>
|
|
||||||
/// <returns>The built-in scheme name</returns>
|
|
||||||
static CefString GetBuiltinSchemeName(CefRefPtr<CefCommandLine> command_line);
|
|
||||||
|
|
||||||
private:
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="registrar"></param>
|
|
||||||
virtual void OnRegisterCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
#include "CefViewOtherApp.h"
|
|
||||||
|
|
||||||
CefViewOtherApp::CefViewOtherApp(const CefString& scheme_name)
|
|
||||||
: CefViewAppBase(scheme_name)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
//
|
|
||||||
// CefOtherApp.hpp
|
|
||||||
// CefViewWing
|
|
||||||
//
|
|
||||||
// Created by Sheen Tian on 2020/6/17.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef CefOtherApp_h
|
|
||||||
#define CefOtherApp_h
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "CefViewAppBase.h"
|
|
||||||
|
|
||||||
class CefViewOtherApp : public CefViewAppBase
|
|
||||||
{
|
|
||||||
IMPLEMENT_REFCOUNTING(CefViewOtherApp);
|
|
||||||
|
|
||||||
public:
|
|
||||||
CefViewOtherApp(const CefString& scheme_name);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,208 +0,0 @@
|
|||||||
#include "CefViewRenderApp.h"
|
|
||||||
|
|
||||||
#pragma region cef_headers
|
|
||||||
#include <include/cef_browser.h>
|
|
||||||
#include <include/cef_command_line.h>
|
|
||||||
#include <include/wrapper/cef_helpers.h>
|
|
||||||
#pragma endregion
|
|
||||||
|
|
||||||
#include "../Common/CefViewCoreLog.h"
|
|
||||||
|
|
||||||
#include <CefViewCoreProtocol.h>
|
|
||||||
|
|
||||||
CefViewRenderApp::CefViewRenderApp(const CefString& scheme_name, const CefString& bridge_name)
|
|
||||||
: CefViewAppBase(scheme_name)
|
|
||||||
, bridge_object_name_(bridge_name)
|
|
||||||
, last_node_is_editable_(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CefViewRenderApp::~CefViewRenderApp() {}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
CefRefPtr<CefRenderProcessHandler>
|
|
||||||
CefViewRenderApp::GetRenderProcessHandler()
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewRenderApp::OnWebKitInitialized()
|
|
||||||
{
|
|
||||||
CEF_REQUIRE_RENDERER_THREAD();
|
|
||||||
|
|
||||||
CefMessageRouterConfig config;
|
|
||||||
config.js_query_function = kCefViewQueryFuntionName;
|
|
||||||
config.js_cancel_function = kCefViewQueryCancelFunctionName;
|
|
||||||
message_router_ = CefMessageRouterRendererSide::Create(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewRenderApp::OnBrowserCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefDictionaryValue> extra_info)
|
|
||||||
{
|
|
||||||
CEF_REQUIRE_RENDERER_THREAD();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewRenderApp::OnBrowserDestroyed(CefRefPtr<CefBrowser> browser)
|
|
||||||
{
|
|
||||||
CEF_REQUIRE_RENDERER_THREAD();
|
|
||||||
}
|
|
||||||
|
|
||||||
CefRefPtr<CefLoadHandler>
|
|
||||||
CefViewRenderApp::GetLoadHandler()
|
|
||||||
{
|
|
||||||
CEF_REQUIRE_RENDERER_THREAD();
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewRenderApp::OnContextCreated(CefRefPtr<CefBrowser> browser,
|
|
||||||
CefRefPtr<CefFrame> frame,
|
|
||||||
CefRefPtr<CefV8Context> context)
|
|
||||||
{
|
|
||||||
CEF_REQUIRE_RENDERER_THREAD();
|
|
||||||
|
|
||||||
// [Javascript Context]
|
|
||||||
// V8 context for this frame has been initialized already,
|
|
||||||
// but the script of the page hasn't been executed now
|
|
||||||
message_router_->OnContextCreated(browser, frame, context);
|
|
||||||
|
|
||||||
// log this event
|
|
||||||
frame->ExecuteJavaScript("console.info('[JSRuntime]:frame context created')", frame->GetURL(), 0);
|
|
||||||
|
|
||||||
// binding bridge object and functions
|
|
||||||
auto frameId = frame->GetIdentifier();
|
|
||||||
auto it = frame_id_to_bridge_obj_map_.find(frameId);
|
|
||||||
if (it == frame_id_to_bridge_obj_map_.end()) {
|
|
||||||
// create and insert the bridge Object into this frame.window object
|
|
||||||
CefRefPtr<CefV8Value> objWindow = context->GetGlobal();
|
|
||||||
CefRefPtr<CefViewBridgeObject> objClient = new CefViewBridgeObject(browser, frame, objWindow, bridge_object_name_);
|
|
||||||
if (!objClient) {
|
|
||||||
log_error("Failed to create the client object");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
frame_id_to_bridge_obj_map_[frameId] = objClient;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewRenderApp::OnContextReleased(CefRefPtr<CefBrowser> browser,
|
|
||||||
CefRefPtr<CefFrame> frame,
|
|
||||||
CefRefPtr<CefV8Context> context)
|
|
||||||
{
|
|
||||||
CEF_REQUIRE_RENDERER_THREAD();
|
|
||||||
|
|
||||||
message_router_->OnContextReleased(browser, frame, context);
|
|
||||||
|
|
||||||
auto frameId = frame->GetIdentifier();
|
|
||||||
auto it = frame_id_to_bridge_obj_map_.find(frameId);
|
|
||||||
if (it != frame_id_to_bridge_obj_map_.end()) {
|
|
||||||
frame_id_to_bridge_obj_map_.erase(it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewRenderApp::OnUncaughtException(CefRefPtr<CefBrowser> browser,
|
|
||||||
CefRefPtr<CefFrame> frame,
|
|
||||||
CefRefPtr<CefV8Context> context,
|
|
||||||
CefRefPtr<CefV8Exception> exception,
|
|
||||||
CefRefPtr<CefV8StackTrace> stackTrace)
|
|
||||||
{
|
|
||||||
CEF_REQUIRE_RENDERER_THREAD();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewRenderApp::OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser,
|
|
||||||
CefRefPtr<CefFrame> frame,
|
|
||||||
CefRefPtr<CefDOMNode> node)
|
|
||||||
{
|
|
||||||
CEF_REQUIRE_RENDERER_THREAD();
|
|
||||||
|
|
||||||
bool is_editable = (node.get() && node->IsEditable());
|
|
||||||
if (is_editable != last_node_is_editable_) {
|
|
||||||
// Notify the browser of the change in focused element type.
|
|
||||||
last_node_is_editable_ = is_editable;
|
|
||||||
CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create(kCefViewClientRenderFocusedNodeChangedMessage);
|
|
||||||
message->GetArgumentList()->SetBool(0, is_editable);
|
|
||||||
frame->SendProcessMessage(PID_BROWSER, message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CefViewRenderApp::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
|
|
||||||
CefRefPtr<CefFrame> frame,
|
|
||||||
CefProcessId source_process,
|
|
||||||
CefRefPtr<CefProcessMessage> message)
|
|
||||||
{
|
|
||||||
CEF_REQUIRE_RENDERER_THREAD();
|
|
||||||
|
|
||||||
bool handled = false;
|
|
||||||
|
|
||||||
if (message_router_->OnProcessMessageReceived(browser, frame, source_process, message)) {
|
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (OnTriggerEventNotifyMessage(browser, frame, source_process, message)) {
|
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return handled;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CefViewRenderApp::OnTriggerEventNotifyMessage(CefRefPtr<CefBrowser> browser,
|
|
||||||
CefRefPtr<CefFrame> frame,
|
|
||||||
CefProcessId source_process,
|
|
||||||
CefRefPtr<CefProcessMessage> message)
|
|
||||||
{
|
|
||||||
if (message->GetName() == kCefViewClientBrowserTriggerEventMessage) {
|
|
||||||
CefRefPtr<CefListValue> args = message->GetArgumentList()->Copy();
|
|
||||||
//** arguments(CefValueList)
|
|
||||||
//** +------------+
|
|
||||||
//** | event name |
|
|
||||||
//** | event arg1 |
|
|
||||||
//** | event arg2 |
|
|
||||||
//** | event arg3 |
|
|
||||||
//** | event arg4 |
|
|
||||||
//** | ... |
|
|
||||||
//** | ... |
|
|
||||||
//** | ... |
|
|
||||||
//** | ... |
|
|
||||||
//** +------------+
|
|
||||||
if (!args || args->GetSize() <= 0) {
|
|
||||||
log_error("Invalid message arguments, event name is required");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CefValueType::VTYPE_STRING != args->GetType(0)) {
|
|
||||||
log_error("Invalid message arguments, invalid type for event name");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto name = args->GetString(0);
|
|
||||||
args->Remove(0);
|
|
||||||
ExecuteEventListener(browser, frame, name, args);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewRenderApp::ExecuteEventListener(CefRefPtr<CefBrowser> browser,
|
|
||||||
CefRefPtr<CefFrame> frame,
|
|
||||||
const CefString& name,
|
|
||||||
CefRefPtr<CefListValue> args)
|
|
||||||
{
|
|
||||||
if (browser && frame) {
|
|
||||||
auto frameId = frame->GetIdentifier();
|
|
||||||
auto it = frame_id_to_bridge_obj_map_.find(frameId);
|
|
||||||
if (it != frame_id_to_bridge_obj_map_.end()) {
|
|
||||||
const CefRefPtr<CefViewBridgeObject>& objClient = it->second;
|
|
||||||
objClient->ExecuteEventListener(name, args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,180 +0,0 @@
|
|||||||
#ifndef CefRenderApp_h
|
|
||||||
#define CefRenderApp_h
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#pragma region stl_headers
|
|
||||||
#include <unordered_map>
|
|
||||||
#pragma endregion
|
|
||||||
|
|
||||||
#pragma region cef_headers
|
|
||||||
#include <include/wrapper/cef_message_router.h>
|
|
||||||
#pragma endregion
|
|
||||||
|
|
||||||
#include <CefViewCoreGlobal.h>
|
|
||||||
|
|
||||||
#include "CefViewAppBase.h"
|
|
||||||
#include "../Bridge/CefViewBridgeObject.h"
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
class CefViewRenderApp
|
|
||||||
: public CefViewAppBase
|
|
||||||
, public CefRenderProcessHandler
|
|
||||||
{
|
|
||||||
// Include the default reference counting implementation.
|
|
||||||
IMPLEMENT_REFCOUNTING(CefViewRenderApp);
|
|
||||||
|
|
||||||
private:
|
|
||||||
CefString bridge_object_name_;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
CefRefPtr<CefMessageRouterRendererSide> message_router_;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
typedef std::unordered_map<CefFrameId, CefRefPtr<CefViewBridgeObject>> FrameID2BridgeObjMap;
|
|
||||||
FrameID2BridgeObjMap frame_id_to_bridge_obj_map_;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
bool last_node_is_editable_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
CefViewRenderApp(const CefString& scheme_name, const CefString& bridge_name);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
~CefViewRenderApp();
|
|
||||||
|
|
||||||
private:
|
|
||||||
#pragma region CefApp
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
virtual CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() override;
|
|
||||||
|
|
||||||
#pragma endregion
|
|
||||||
|
|
||||||
#pragma region CefRenderProcessHandler
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
virtual void OnWebKitInitialized() override;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="browser"></param>
|
|
||||||
/// <param name="extra_info"></param>
|
|
||||||
virtual void OnBrowserCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefDictionaryValue> extra_info) override;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="browser"></param>
|
|
||||||
virtual void OnBrowserDestroyed(CefRefPtr<CefBrowser> browser) override;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
virtual CefRefPtr<CefLoadHandler> GetLoadHandler() override;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="browser"></param>
|
|
||||||
/// <param name="frame"></param>
|
|
||||||
/// <param name="context"></param>
|
|
||||||
virtual void OnContextCreated(CefRefPtr<CefBrowser> browser,
|
|
||||||
CefRefPtr<CefFrame> frame,
|
|
||||||
CefRefPtr<CefV8Context> context) override;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="browser"></param>
|
|
||||||
/// <param name="frame"></param>
|
|
||||||
/// <param name="context"></param>
|
|
||||||
virtual void OnContextReleased(CefRefPtr<CefBrowser> browser,
|
|
||||||
CefRefPtr<CefFrame> frame,
|
|
||||||
CefRefPtr<CefV8Context> context) override;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="browser"></param>
|
|
||||||
/// <param name="frame"></param>
|
|
||||||
/// <param name="context"></param>
|
|
||||||
/// <param name="exception"></param>
|
|
||||||
/// <param name="stackTrace"></param>
|
|
||||||
virtual void OnUncaughtException(CefRefPtr<CefBrowser> browser,
|
|
||||||
CefRefPtr<CefFrame> frame,
|
|
||||||
CefRefPtr<CefV8Context> context,
|
|
||||||
CefRefPtr<CefV8Exception> exception,
|
|
||||||
CefRefPtr<CefV8StackTrace> stackTrace) override;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="browser"></param>
|
|
||||||
/// <param name="frame"></param>
|
|
||||||
/// <param name="node"></param>
|
|
||||||
virtual void OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser,
|
|
||||||
CefRefPtr<CefFrame> frame,
|
|
||||||
CefRefPtr<CefDOMNode> node) override;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="browser"></param>
|
|
||||||
/// <param name="frame"></param>
|
|
||||||
/// <param name="source_process"></param>
|
|
||||||
/// <param name="message"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
virtual bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
|
|
||||||
CefRefPtr<CefFrame> frame,
|
|
||||||
CefProcessId source_process,
|
|
||||||
CefRefPtr<CefProcessMessage> message) override;
|
|
||||||
|
|
||||||
#pragma endregion
|
|
||||||
|
|
||||||
private:
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="browser"></param>
|
|
||||||
/// <param name="frame"></param>
|
|
||||||
/// <param name="source_process"></param>
|
|
||||||
/// <param name="message"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
bool OnTriggerEventNotifyMessage(CefRefPtr<CefBrowser> browser,
|
|
||||||
CefRefPtr<CefFrame> frame,
|
|
||||||
CefProcessId source_process,
|
|
||||||
CefRefPtr<CefProcessMessage> message);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="browser"></param>
|
|
||||||
/// <param name="frame"></param>
|
|
||||||
/// <param name="name"></param>
|
|
||||||
/// <param name="list"></param>
|
|
||||||
void ExecuteEventListener(CefRefPtr<CefBrowser> browser,
|
|
||||||
CefRefPtr<CefFrame> frame,
|
|
||||||
const CefString& name,
|
|
||||||
CefRefPtr<CefListValue> args);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,517 +0,0 @@
|
|||||||
#include "CefViewBridgeObject.h"
|
|
||||||
|
|
||||||
#include <include/cef_version.h>
|
|
||||||
|
|
||||||
#include "../Common/CefViewCoreLog.h"
|
|
||||||
#include <CefViewCoreProtocol.h>
|
|
||||||
|
|
||||||
|
|
||||||
#if CEF_VERSION_MAJOR >= 119
|
|
||||||
class CefViewArrayBuffer : public CefV8ArrayBufferReleaseCallback
|
|
||||||
{
|
|
||||||
IMPLEMENT_REFCOUNTING(CefViewArrayBuffer);
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(CefViewArrayBuffer);
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="v"></param>
|
|
||||||
CefViewArrayBuffer(CefBinaryValue* v)
|
|
||||||
: m_size(0)
|
|
||||||
, m_buffer(nullptr)
|
|
||||||
{
|
|
||||||
if (v) {
|
|
||||||
auto l = v->GetSize();
|
|
||||||
if (l) {
|
|
||||||
m_buffer = std::make_unique<uint8_t[]>(l);
|
|
||||||
v->GetData(m_buffer.get(), l, 0);
|
|
||||||
m_size = l;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
~CefViewArrayBuffer()
|
|
||||||
{
|
|
||||||
m_buffer.reset();
|
|
||||||
m_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
void* GetBuffer()
|
|
||||||
{
|
|
||||||
// get under layer buffer address
|
|
||||||
return m_buffer.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
size_t GetSize()
|
|
||||||
{
|
|
||||||
// return size
|
|
||||||
return m_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="buffer"></param>
|
|
||||||
void ReleaseBuffer(void* buffer) override
|
|
||||||
{
|
|
||||||
// release under layer buffer
|
|
||||||
m_buffer.reset();
|
|
||||||
m_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
size_t m_size;
|
|
||||||
std::unique_ptr<uint8_t[]> m_buffer;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CefViewBridgeObject::V8Handler::V8Handler(CefViewBridgeObject* object)
|
|
||||||
: object_(object)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CefViewBridgeObject::V8Handler::Execute(const CefString& function,
|
|
||||||
CefRefPtr<CefV8Value> object,
|
|
||||||
const CefV8ValueList& arguments,
|
|
||||||
CefRefPtr<CefV8Value>& retval,
|
|
||||||
CefString& exception)
|
|
||||||
{
|
|
||||||
if (function == kCefViewInvokeMethodFunctionName)
|
|
||||||
ExecuteNativeMethod(object, arguments, retval, exception);
|
|
||||||
else if (function == kCefViewAddEventListenerFunctionName)
|
|
||||||
ExecuteAddEventListener(object, arguments, retval, exception);
|
|
||||||
else if (function == kCefViewRemoveEventListenerFunctionName)
|
|
||||||
ExecuteRemoveEventListener(object, arguments, retval, exception);
|
|
||||||
else if (function == kCefViewReportJSResultFunctionName)
|
|
||||||
ExecuteReportJSResult(object, arguments, retval, exception);
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewBridgeObject::V8Handler::ExecuteNativeMethod(CefRefPtr<CefV8Value> object,
|
|
||||||
const CefV8ValueList& arguments,
|
|
||||||
CefRefPtr<CefV8Value>& retval,
|
|
||||||
CefString& exception)
|
|
||||||
{
|
|
||||||
object_->AsyncExecuteNativeMethod(arguments);
|
|
||||||
retval = CefV8Value::CreateUndefined();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewBridgeObject::V8Handler::ExecuteAddEventListener(CefRefPtr<CefV8Value> object,
|
|
||||||
const CefV8ValueList& arguments,
|
|
||||||
CefRefPtr<CefV8Value>& retval,
|
|
||||||
CefString& exception)
|
|
||||||
{
|
|
||||||
bool bRet = false;
|
|
||||||
|
|
||||||
if (arguments.size() == 2) {
|
|
||||||
if (arguments[0]->IsString()) {
|
|
||||||
if (arguments[1]->IsFunction()) {
|
|
||||||
CefString eventName = arguments[0]->GetStringValue();
|
|
||||||
EventListener listener;
|
|
||||||
listener.callback_ = arguments[1];
|
|
||||||
listener.context_ = CefV8Context::GetCurrentContext();
|
|
||||||
object_->AddEventListener(eventName, listener);
|
|
||||||
bRet = true;
|
|
||||||
} else
|
|
||||||
exception = "Invalid arguments; argument 2 must be a function";
|
|
||||||
} else
|
|
||||||
exception = "Invalid arguments; argument 1 must be a string";
|
|
||||||
} else
|
|
||||||
exception = "Invalid arguments; expecting 2 arguments";
|
|
||||||
|
|
||||||
retval = CefV8Value::CreateBool(bRet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewBridgeObject::V8Handler::ExecuteRemoveEventListener(CefRefPtr<CefV8Value> object,
|
|
||||||
const CefV8ValueList& arguments,
|
|
||||||
CefRefPtr<CefV8Value>& retval,
|
|
||||||
CefString& exception)
|
|
||||||
{
|
|
||||||
bool bRet = false;
|
|
||||||
|
|
||||||
if (arguments.size() == 2) {
|
|
||||||
if (arguments[0]->IsString()) {
|
|
||||||
if (arguments[1]->IsFunction()) {
|
|
||||||
CefString eventName = arguments[0]->GetStringValue();
|
|
||||||
EventListener listener;
|
|
||||||
listener.callback_ = arguments[1];
|
|
||||||
listener.context_ = CefV8Context::GetCurrentContext();
|
|
||||||
object_->RemoveEventListener(eventName, listener);
|
|
||||||
bRet = true;
|
|
||||||
} else
|
|
||||||
exception = "Invalid arguments; argument 2 must be a function";
|
|
||||||
} else
|
|
||||||
exception = "Invalid arguments; argument 1 must be a string";
|
|
||||||
} else
|
|
||||||
exception = "Invalid arguments; expecting 2 arguments";
|
|
||||||
|
|
||||||
retval = CefV8Value::CreateBool(bRet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewBridgeObject::V8Handler::ExecuteReportJSResult(CefRefPtr<CefV8Value> object,
|
|
||||||
const CefV8ValueList& arguments,
|
|
||||||
CefRefPtr<CefV8Value>& retval,
|
|
||||||
CefString& exception)
|
|
||||||
{
|
|
||||||
if (arguments.size() == 2) {
|
|
||||||
if (arguments[0]->IsString()) {
|
|
||||||
object_->AsyncExecuteReportJSResult(arguments);
|
|
||||||
} else
|
|
||||||
exception = "Invalid argument; argument 1 must be a double";
|
|
||||||
} else
|
|
||||||
exception = "Invalid argument; expecting 2 argument";
|
|
||||||
|
|
||||||
retval = CefV8Value::CreateUndefined();
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
CefViewBridgeObject::CefViewBridgeObject(CefRefPtr<CefBrowser> browser,
|
|
||||||
CefRefPtr<CefFrame> frame,
|
|
||||||
CefRefPtr<CefV8Value> global,
|
|
||||||
const CefString& name)
|
|
||||||
: name_(name.empty() ? kCefViewDefaultBridgeObjectName : name)
|
|
||||||
, bridgeObject_(nullptr)
|
|
||||||
, reportJSResultFunction_(nullptr)
|
|
||||||
, browser_(browser)
|
|
||||||
, frame_(frame)
|
|
||||||
, v8Handler_(new V8Handler(this))
|
|
||||||
{
|
|
||||||
// create bridge object and mount it on the global context(window)
|
|
||||||
bridgeObject_ = CefV8Value::CreateObject(nullptr, nullptr);
|
|
||||||
|
|
||||||
// create function "invokeMethod"
|
|
||||||
CefRefPtr<CefV8Value> funcInvokeMethod = CefV8Value::CreateFunction(kCefViewInvokeMethodFunctionName, v8Handler_);
|
|
||||||
// add this function to window object
|
|
||||||
bridgeObject_->SetValue(kCefViewInvokeMethodFunctionName,
|
|
||||||
funcInvokeMethod,
|
|
||||||
static_cast<CefV8Value::PropertyAttribute>(V8_PROPERTY_ATTRIBUTE_READONLY |
|
|
||||||
V8_PROPERTY_ATTRIBUTE_DONTENUM |
|
|
||||||
V8_PROPERTY_ATTRIBUTE_DONTDELETE));
|
|
||||||
|
|
||||||
// create function addEventListener
|
|
||||||
CefRefPtr<CefV8Value> funcAddEventListener =
|
|
||||||
CefV8Value::CreateFunction(kCefViewAddEventListenerFunctionName, v8Handler_);
|
|
||||||
// add this function to window object
|
|
||||||
bridgeObject_->SetValue(kCefViewAddEventListenerFunctionName,
|
|
||||||
funcAddEventListener,
|
|
||||||
static_cast<CefV8Value::PropertyAttribute>(V8_PROPERTY_ATTRIBUTE_READONLY |
|
|
||||||
V8_PROPERTY_ATTRIBUTE_DONTENUM |
|
|
||||||
V8_PROPERTY_ATTRIBUTE_DONTDELETE));
|
|
||||||
|
|
||||||
// create function removeListener
|
|
||||||
CefRefPtr<CefV8Value> funcRemoveEventListener =
|
|
||||||
CefV8Value::CreateFunction(kCefViewRemoveEventListenerFunctionName, v8Handler_);
|
|
||||||
// add this function to window object
|
|
||||||
bridgeObject_->SetValue(kCefViewRemoveEventListenerFunctionName,
|
|
||||||
funcRemoveEventListener,
|
|
||||||
static_cast<CefV8Value::PropertyAttribute>(V8_PROPERTY_ATTRIBUTE_READONLY |
|
|
||||||
V8_PROPERTY_ATTRIBUTE_DONTENUM |
|
|
||||||
V8_PROPERTY_ATTRIBUTE_DONTDELETE));
|
|
||||||
|
|
||||||
// mount the client object to the global context(usually the window object)
|
|
||||||
global->SetValue(name_,
|
|
||||||
bridgeObject_,
|
|
||||||
static_cast<CefV8Value::PropertyAttribute>(V8_PROPERTY_ATTRIBUTE_READONLY |
|
|
||||||
V8_PROPERTY_ATTRIBUTE_DONTENUM |
|
|
||||||
V8_PROPERTY_ATTRIBUTE_DONTDELETE));
|
|
||||||
frame_->ExecuteJavaScript("console.info('[JSRuntime]:window." + name_.ToString() + " [object] created');", frame_->GetURL(), 0);
|
|
||||||
|
|
||||||
// create "__cefview_report_js_result__" function and mount it on the global context(window)
|
|
||||||
reportJSResultFunction_ = CefV8Value::CreateFunction(kCefViewReportJSResultFunctionName, v8Handler_);
|
|
||||||
global->SetValue(kCefViewReportJSResultFunctionName,
|
|
||||||
reportJSResultFunction_,
|
|
||||||
static_cast<CefV8Value::PropertyAttribute>(V8_PROPERTY_ATTRIBUTE_READONLY |
|
|
||||||
V8_PROPERTY_ATTRIBUTE_DONTENUM |
|
|
||||||
V8_PROPERTY_ATTRIBUTE_DONTDELETE));
|
|
||||||
frame_->ExecuteJavaScript("console.info('[JSRuntime]:window." kCefViewReportJSResultFunctionName
|
|
||||||
" [function] created');",
|
|
||||||
frame_->GetURL(),
|
|
||||||
0);
|
|
||||||
}
|
|
||||||
|
|
||||||
CefRefPtr<CefV8Value>
|
|
||||||
CefViewBridgeObject::CefValueToV8Value(CefValue* cefValue)
|
|
||||||
{
|
|
||||||
CefRefPtr<CefV8Value> v8Value = CefV8Value::CreateNull();
|
|
||||||
if (!cefValue) {
|
|
||||||
return v8Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto type = cefValue->GetType();
|
|
||||||
switch (type) {
|
|
||||||
case CefValueType::VTYPE_INVALID: {
|
|
||||||
v8Value = CefV8Value::CreateUndefined();
|
|
||||||
} break;
|
|
||||||
case CefValueType::VTYPE_NULL: {
|
|
||||||
v8Value = CefV8Value::CreateNull();
|
|
||||||
} break;
|
|
||||||
case CefValueType::VTYPE_BOOL: {
|
|
||||||
auto v = cefValue->GetBool();
|
|
||||||
v8Value = CefV8Value::CreateBool(v);
|
|
||||||
} break;
|
|
||||||
case CefValueType::VTYPE_INT: {
|
|
||||||
auto v = cefValue->GetInt();
|
|
||||||
v8Value = CefV8Value::CreateInt(v);
|
|
||||||
} break;
|
|
||||||
case CefValueType::VTYPE_DOUBLE: {
|
|
||||||
auto v = cefValue->GetDouble();
|
|
||||||
v8Value = CefV8Value::CreateDouble(v);
|
|
||||||
} break;
|
|
||||||
case CefValueType::VTYPE_STRING: {
|
|
||||||
auto v = cefValue->GetString();
|
|
||||||
v8Value = CefV8Value::CreateString(v);
|
|
||||||
} break;
|
|
||||||
case CefValueType::VTYPE_BINARY: {
|
|
||||||
#if CEF_VERSION_MAJOR >= 119
|
|
||||||
auto v = cefValue->GetBinary();
|
|
||||||
auto arryBuffer = new CefViewArrayBuffer(v.get());
|
|
||||||
v8Value = CefV8Value::CreateArrayBuffer(arryBuffer->GetBuffer(), arryBuffer->GetSize(), arryBuffer);
|
|
||||||
#else
|
|
||||||
// currently not supported
|
|
||||||
#endif
|
|
||||||
} break;
|
|
||||||
case CefValueType::VTYPE_DICTIONARY: {
|
|
||||||
auto cDict = cefValue->GetDictionary();
|
|
||||||
CefDictionaryValue::KeyList cKeys;
|
|
||||||
cDict->GetKeys(cKeys);
|
|
||||||
v8Value = CefV8Value::CreateObject(nullptr, nullptr);
|
|
||||||
for (auto& key : cKeys) {
|
|
||||||
auto cVal = cDict->GetValue(key);
|
|
||||||
auto v8Val = CefValueToV8Value(cVal.get());
|
|
||||||
v8Value->SetValue(key, v8Val.get(), V8_PROPERTY_ATTRIBUTE_NONE);
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
case CefValueType::VTYPE_LIST: {
|
|
||||||
auto cList = cefValue->GetList();
|
|
||||||
int cCount = static_cast<int>(cList->GetSize());
|
|
||||||
v8Value = CefV8Value::CreateArray(static_cast<int>(cCount));
|
|
||||||
for (int i = 0; i < cCount; i++) {
|
|
||||||
auto cVal = cList->GetValue(i);
|
|
||||||
auto v8Val = CefValueToV8Value(cVal.get());
|
|
||||||
v8Value->SetValue(i, v8Val.get());
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return v8Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
CefRefPtr<CefValue>
|
|
||||||
CefViewBridgeObject::V8ValueToCefValue(CefV8Value* v8Value)
|
|
||||||
{
|
|
||||||
CefRefPtr<CefValue> cefValue = CefValue::Create();
|
|
||||||
if (!v8Value) {
|
|
||||||
return cefValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The IsDouble, IsInt and IsUint methods return a boolean value indicating whether the CefV8Value instance is an
|
|
||||||
* target type or can be converted to the target type.If the value can be converted to the target type, the methods
|
|
||||||
* will attempt to do so and return true. If the value is not the target type or cannot be converted to the target
|
|
||||||
* type, the method will return false.
|
|
||||||
*
|
|
||||||
* For example the code below:
|
|
||||||
* auto v = CefV8Value::CreateInt(1000);
|
|
||||||
* auto isDouble = v->IsDouble();
|
|
||||||
* logD("isDouble: %d", isDouble); // true
|
|
||||||
* auto isUnint = v->IsUInt();
|
|
||||||
* logD("isUnint: %d", isUnint); // true
|
|
||||||
* auto isInt = v->IsInt();
|
|
||||||
* logD("isInt: %d", isInt); // true
|
|
||||||
*
|
|
||||||
* auto v = CefV8Value::CreateDouble(0.1);
|
|
||||||
* auto isDouble = v->IsDouble();
|
|
||||||
* logD("isDouble: %d", isDouble); // true
|
|
||||||
* auto isUnint = v->IsUInt();
|
|
||||||
* logD("isUnint: %d", isUnint); // false
|
|
||||||
* auto isInt = v->IsInt();
|
|
||||||
* logD("isInt: %d", isInt); // false
|
|
||||||
*
|
|
||||||
* so we need to keep the testing order, IsInt/IsUint - IsDouble
|
|
||||||
* since there is no Uint type in JavaScript, we just ignore it.
|
|
||||||
* Please refer to this test souce:
|
|
||||||
* https://github.com/svn2github/cef/blob/master/tests/cefclient/binding_test.cpp
|
|
||||||
*/
|
|
||||||
if (v8Value->IsNull() || v8Value->IsUndefined())
|
|
||||||
cefValue->SetNull();
|
|
||||||
else if (v8Value->IsBool())
|
|
||||||
cefValue->SetBool(v8Value->GetBoolValue());
|
|
||||||
else if (v8Value->IsInt())
|
|
||||||
cefValue->SetInt(v8Value->GetIntValue());
|
|
||||||
else if (v8Value->IsDouble())
|
|
||||||
cefValue->SetDouble(v8Value->GetDoubleValue());
|
|
||||||
else if (v8Value->IsString())
|
|
||||||
cefValue->SetString(v8Value->GetStringValue());
|
|
||||||
else if (v8Value->IsArrayBuffer()) {
|
|
||||||
#if CEF_VERSION_MAJOR >= 119
|
|
||||||
auto size = v8Value->GetArrayBufferByteLength();
|
|
||||||
auto data = v8Value->GetArrayBufferData();
|
|
||||||
cefValue->SetBinary(CefBinaryValue::Create(data, size));
|
|
||||||
#else
|
|
||||||
// currently not supported
|
|
||||||
#endif
|
|
||||||
} else if (v8Value->IsArray()) {
|
|
||||||
auto s = v8Value->GetArrayLength();
|
|
||||||
auto cefList = CefListValue::Create();
|
|
||||||
for (int i = 0; i < s; i++) {
|
|
||||||
auto v8Val = v8Value->GetValue(i);
|
|
||||||
auto cefVal = V8ValueToCefValue(v8Val.get());
|
|
||||||
cefList->SetValue(i, cefVal);
|
|
||||||
}
|
|
||||||
cefValue->SetList(cefList);
|
|
||||||
} else if (v8Value->IsObject()) {
|
|
||||||
CefDictionaryValue::KeyList keys;
|
|
||||||
v8Value->GetKeys(keys);
|
|
||||||
auto cefDict = CefDictionaryValue::Create();
|
|
||||||
for (auto& key : keys) {
|
|
||||||
auto v8Val = v8Value->GetValue(key);
|
|
||||||
auto cefVal = V8ValueToCefValue(v8Val.get());
|
|
||||||
cefDict->SetValue(key, cefVal.get());
|
|
||||||
}
|
|
||||||
cefValue->SetDictionary(cefDict);
|
|
||||||
} else
|
|
||||||
cefValue->SetNull();
|
|
||||||
|
|
||||||
return cefValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewBridgeObject::AsyncExecuteNativeMethod(const CefV8ValueList& arguments)
|
|
||||||
{
|
|
||||||
CefRefPtr<CefProcessMessage> msg = CefProcessMessage::Create(kCefViewClientRenderInvokeMethodMessage);
|
|
||||||
|
|
||||||
//** arguments(CefValueList)
|
|
||||||
//** +-------+
|
|
||||||
//** |0 name | <- the method name
|
|
||||||
//** |1 arg1 |
|
|
||||||
//** |2 arg2 |
|
|
||||||
//** |3 arg3 |
|
|
||||||
//** |4 arg4 |
|
|
||||||
//** | ... |
|
|
||||||
//** | ... |
|
|
||||||
//** | ... |
|
|
||||||
//** | ... |
|
|
||||||
//** +-------+
|
|
||||||
CefRefPtr<CefListValue> args = msg->GetArgumentList();
|
|
||||||
|
|
||||||
// push back all the arguments
|
|
||||||
for (std::size_t i = 0; i < arguments.size(); i++) {
|
|
||||||
auto cefValue = V8ValueToCefValue(arguments[i].get());
|
|
||||||
args->SetValue(i, cefValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
// send the message
|
|
||||||
if (browser_)
|
|
||||||
frame_->SendProcessMessage(PID_BROWSER, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewBridgeObject::AsyncExecuteReportJSResult(const CefV8ValueList& arguments)
|
|
||||||
{
|
|
||||||
CefRefPtr<CefProcessMessage> msg = CefProcessMessage::Create(kCefViewClientRenderReportJSResultMessage);
|
|
||||||
|
|
||||||
//** arguments(CefValueList)
|
|
||||||
//** +_------+
|
|
||||||
//** |0 arg | <- the context (string)
|
|
||||||
//** |1 arg | <- the result value
|
|
||||||
//** +-------+
|
|
||||||
CefRefPtr<CefListValue> args = msg->GetArgumentList();
|
|
||||||
|
|
||||||
// push back the result value
|
|
||||||
for (std::size_t i = 0; i < arguments.size(); i++) {
|
|
||||||
auto cefValue = V8ValueToCefValue(arguments[i].get());
|
|
||||||
args->SetValue(i, cefValue.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
// send the message
|
|
||||||
if (browser_)
|
|
||||||
frame_->SendProcessMessage(PID_BROWSER, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewBridgeObject::AddEventListener(const CefString& name, const EventListener& listener)
|
|
||||||
{
|
|
||||||
auto itListenerList = eventListenerListMap_.find(name);
|
|
||||||
if (itListenerList == eventListenerListMap_.end()) {
|
|
||||||
EventListenerList eventListenerList;
|
|
||||||
eventListenerList.push_back(listener);
|
|
||||||
eventListenerListMap_[name] = eventListenerList;
|
|
||||||
} else {
|
|
||||||
EventListenerList& eventListenerList = itListenerList->second;
|
|
||||||
// does this listener exist?
|
|
||||||
bool found = false;
|
|
||||||
for (auto item : eventListenerList) {
|
|
||||||
if (item.callback_->IsSame(listener.callback_)) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found)
|
|
||||||
eventListenerList.push_back(listener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewBridgeObject::RemoveEventListener(const CefString& name, const EventListener& listener)
|
|
||||||
{
|
|
||||||
auto itListenerList = eventListenerListMap_.find(name);
|
|
||||||
if (itListenerList != eventListenerListMap_.end()) {
|
|
||||||
EventListenerList& eventListenerList = itListenerList->second;
|
|
||||||
for (auto itListener = eventListenerList.begin(); itListener != eventListenerList.end(); itListener++) {
|
|
||||||
if (itListener->callback_->IsSame(listener.callback_)) {
|
|
||||||
eventListenerList.erase(itListener);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewBridgeObject::ExecuteEventListener(const CefString eventName, CefRefPtr<CefListValue> args)
|
|
||||||
{
|
|
||||||
// find the listeners
|
|
||||||
auto itListenerList = eventListenerListMap_.find(eventName);
|
|
||||||
if (itListenerList == eventListenerListMap_.end()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
EventListenerList& eventListenerList = itListenerList->second;
|
|
||||||
for (auto listener : eventListenerList) {
|
|
||||||
listener.context_->Enter();
|
|
||||||
|
|
||||||
// convert argument list from CefValue to CefV8Value
|
|
||||||
CefV8ValueList v8ArgList;
|
|
||||||
for (size_t i = 0; i < args->GetSize(); i++) {
|
|
||||||
auto cefValue = args->GetValue(i);
|
|
||||||
auto v8Value = CefValueToV8Value(cefValue.get());
|
|
||||||
v8ArgList.push_back(v8Value.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
listener.callback_->ExecuteFunction(bridgeObject_, v8ArgList);
|
|
||||||
listener.context_->Exit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,221 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#pragma region stl_headers
|
|
||||||
#include <list>
|
|
||||||
#include <map>
|
|
||||||
#pragma endregion
|
|
||||||
|
|
||||||
#pragma region cef_headers
|
|
||||||
#include <include/cef_v8.h>
|
|
||||||
#pragma endregion
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
class CefViewBridgeObject : public CefBaseRefCounted
|
|
||||||
{
|
|
||||||
IMPLEMENT_REFCOUNTING(CefViewBridgeObject);
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(CefViewBridgeObject);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
typedef struct _EventListener
|
|
||||||
{
|
|
||||||
CefRefPtr<CefV8Value> callback_;
|
|
||||||
CefRefPtr<CefV8Context> context_;
|
|
||||||
} EventListener;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
typedef std::list<EventListener> EventListenerList;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
typedef std::map<CefString, std::list<EventListener>> EventListenerListMap;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
class V8Handler : public CefV8Handler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="client"></param>
|
|
||||||
V8Handler(CefViewBridgeObject* object);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="function"></param>
|
|
||||||
/// <param name="object"></param>
|
|
||||||
/// <param name="arguments"></param>
|
|
||||||
/// <param name="retval"></param>
|
|
||||||
/// <param name="exception"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
virtual bool Execute(const CefString& function,
|
|
||||||
CefRefPtr<CefV8Value> object,
|
|
||||||
const CefV8ValueList& arguments,
|
|
||||||
CefRefPtr<CefV8Value>& retval,
|
|
||||||
CefString& exception) override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="object"></param>
|
|
||||||
/// <param name="arguments"></param>
|
|
||||||
/// <param name="retval"></param>
|
|
||||||
/// <param name="exception"></param>
|
|
||||||
void ExecuteNativeMethod(CefRefPtr<CefV8Value> object,
|
|
||||||
const CefV8ValueList& arguments,
|
|
||||||
CefRefPtr<CefV8Value>& retval,
|
|
||||||
CefString& exception);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="object"></param>
|
|
||||||
/// <param name="arguments"></param>
|
|
||||||
/// <param name="retval"></param>
|
|
||||||
/// <param name="exception"></param>
|
|
||||||
void ExecuteAddEventListener(CefRefPtr<CefV8Value> object,
|
|
||||||
const CefV8ValueList& arguments,
|
|
||||||
CefRefPtr<CefV8Value>& retval,
|
|
||||||
CefString& exception);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="object"></param>
|
|
||||||
/// <param name="arguments"></param>
|
|
||||||
/// <param name="retval"></param>
|
|
||||||
/// <param name="exception"></param>
|
|
||||||
void ExecuteRemoveEventListener(CefRefPtr<CefV8Value> object,
|
|
||||||
const CefV8ValueList& arguments,
|
|
||||||
CefRefPtr<CefV8Value>& retval,
|
|
||||||
CefString& exception);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="object"></param>
|
|
||||||
/// <param name="arguments"></param>
|
|
||||||
/// <param name="retval"></param>
|
|
||||||
/// <param name="exception"></param>
|
|
||||||
void ExecuteReportJSResult(CefRefPtr<CefV8Value> object,
|
|
||||||
const CefV8ValueList& arguments,
|
|
||||||
CefRefPtr<CefV8Value>& retval,
|
|
||||||
CefString& exception);
|
|
||||||
|
|
||||||
private:
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
CefViewBridgeObject* object_;
|
|
||||||
|
|
||||||
private:
|
|
||||||
IMPLEMENT_REFCOUNTING(V8Handler);
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="browser"></param>
|
|
||||||
/// <param name="frame"></param>
|
|
||||||
/// <param name="global"></param>
|
|
||||||
/// <param name="name"></param>
|
|
||||||
CefViewBridgeObject(CefRefPtr<CefBrowser> browser,
|
|
||||||
CefRefPtr<CefFrame> frame,
|
|
||||||
CefRefPtr<CefV8Value> global,
|
|
||||||
const CefString& name);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="v8Value"></param>
|
|
||||||
/// <param name="cefValue"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
CefRefPtr<CefV8Value> CefValueToV8Value(CefValue* cefValue);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="v8Value"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
CefRefPtr<CefValue> V8ValueToCefValue(CefV8Value* v8Value);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="arguments"></param>
|
|
||||||
void AsyncExecuteNativeMethod(const CefV8ValueList& arguments);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="arguments"></param>
|
|
||||||
void AsyncExecuteReportJSResult(const CefV8ValueList& arguments);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="name"></param>
|
|
||||||
/// <param name="listener"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
void AddEventListener(const CefString& name, const EventListener& listener);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="name"></param>
|
|
||||||
/// <param name="listener"></param>
|
|
||||||
void RemoveEventListener(const CefString& name, const EventListener& listener);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="eventName"></param>
|
|
||||||
/// <param name="args"></param>
|
|
||||||
void ExecuteEventListener(const CefString eventName, CefRefPtr<CefListValue> args);
|
|
||||||
|
|
||||||
private:
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
CefString name_;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
CefRefPtr<CefV8Value> bridgeObject_;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
CefRefPtr<CefV8Value> reportJSResultFunction_;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
CefRefPtr<CefBrowser> browser_;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
CefRefPtr<CefFrame> frame_;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
CefRefPtr<V8Handler> v8Handler_;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
CefViewBridgeObject::EventListenerListMap eventListenerListMap_;
|
|
||||||
};
|
|
||||||
@ -1,128 +0,0 @@
|
|||||||
#include "CefViewWidget.h"
|
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
|
||||||
#include <windows.h>
|
|
||||||
#elif defined(Q_OS_MAC)
|
|
||||||
#elif defined(Q_OS_LINUX)
|
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <QColor>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QPainterPath>
|
|
||||||
#include <QRandomGenerator>
|
|
||||||
#include <QResizeEvent>
|
|
||||||
#include <QWindow>
|
|
||||||
|
|
||||||
#include "DownloadManager.h"
|
|
||||||
|
|
||||||
CefViewWidget::CefViewWidget(const QString url, const QCefSetting* setting, QWidget* parent /* = 0*/)
|
|
||||||
: QCefView(url, setting, parent)
|
|
||||||
{
|
|
||||||
// setStyleSheet("background: blue;");
|
|
||||||
|
|
||||||
connect(this, &CefViewWidget::draggableRegionChanged, this, &CefViewWidget::onDraggableRegionChanged);
|
|
||||||
connect(this, &CefViewWidget::nativeBrowserCreated, this, &CefViewWidget::onNativeBrowserWindowCreated);
|
|
||||||
}
|
|
||||||
|
|
||||||
CefViewWidget::~CefViewWidget() {}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewWidget::onScreenChanged(QScreen* screen)
|
|
||||||
{
|
|
||||||
if (!m_pCefWindow)
|
|
||||||
return;
|
|
||||||
|
|
||||||
updateMask();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewWidget::onNativeBrowserWindowCreated(QWindow* window)
|
|
||||||
{
|
|
||||||
m_pCefWindow = window;
|
|
||||||
if (!m_pCefWindow)
|
|
||||||
return;
|
|
||||||
|
|
||||||
connect(this->window()->windowHandle(), SIGNAL(screenChanged(QScreen*)), this, SLOT(onScreenChanged(QScreen*)));
|
|
||||||
|
|
||||||
updateMask();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewWidget::onDraggableRegionChanged(const QRegion& draggableRegion, const QRegion& nonDraggableRegion)
|
|
||||||
{
|
|
||||||
m_draggableRegion = draggableRegion;
|
|
||||||
m_nonDraggableRegion = nonDraggableRegion;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CefViewWidget::onNewPopup(const QCefFrameId& sourceFrameId,
|
|
||||||
const QString& targetUrl,
|
|
||||||
QString& targetFrameName,
|
|
||||||
QCefView::CefWindowOpenDisposition targetDisposition,
|
|
||||||
QRect& rect,
|
|
||||||
QCefSetting& settings,
|
|
||||||
bool& disableJavascriptAccess)
|
|
||||||
{
|
|
||||||
// create new QCefView as popup browser
|
|
||||||
// settings.setBackgroundColor(Qt::red);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewWidget::onNewDownloadItem(const QSharedPointer<QCefDownloadItem>& item, const QString& suggestedName)
|
|
||||||
{
|
|
||||||
// keep the item into list or map, and call item->start() to allow the download
|
|
||||||
|
|
||||||
DownloadManager::getInstance().AddNewDownloadItem(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewWidget::onUpdateDownloadItem(const QSharedPointer<QCefDownloadItem>& item)
|
|
||||||
{
|
|
||||||
|
|
||||||
// control the download by invoking item->pause(), item->resume(), item->cancel()
|
|
||||||
|
|
||||||
DownloadManager::getInstance().UpdateDownloadItem(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewWidget::resizeEvent(QResizeEvent* event)
|
|
||||||
{
|
|
||||||
// update mask first, because the new mask will be
|
|
||||||
// used in the QCefView::resizeEvent
|
|
||||||
updateMask();
|
|
||||||
|
|
||||||
QCefView::resizeEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewWidget::mousePressEvent(QMouseEvent* event)
|
|
||||||
{
|
|
||||||
QCefView::mousePressEvent(event);
|
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
|
||||||
if (event->buttons().testFlag(Qt::LeftButton) && m_draggableRegion.contains(event->pos())) {
|
|
||||||
HWND hWnd = ::GetAncestor((HWND)(window()->windowHandle()->winId()), GA_ROOT);
|
|
||||||
POINT pt;
|
|
||||||
::GetCursorPos(&pt);
|
|
||||||
::ReleaseCapture();
|
|
||||||
::SendMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, POINTTOPOINTS(pt));
|
|
||||||
}
|
|
||||||
#elif defined(Q_OS_MAC)
|
|
||||||
#elif defined(Q_OS_LINUX)
|
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CefViewWidget::updateMask()
|
|
||||||
{
|
|
||||||
// create a rect with rounded corner (50px radius) as mask
|
|
||||||
QPainterPath path;
|
|
||||||
path.addRoundedRect(rect(), 50, 50);
|
|
||||||
QRegion mask = QRegion(path.toFillPolygon().toPolygon());
|
|
||||||
|
|
||||||
// apply the mask
|
|
||||||
setMask(mask);
|
|
||||||
}
|
|
||||||
@ -1,58 +0,0 @@
|
|||||||
#ifndef CUSTOMCEFVIEW_H
|
|
||||||
#define CUSTOMCEFVIEW_H
|
|
||||||
|
|
||||||
#include <QScreen>
|
|
||||||
|
|
||||||
#include <QCefView.h>
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents the customized QCefView
|
|
||||||
/// </summary>
|
|
||||||
class CefViewWidget : public QCefView
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
CefViewWidget(const QString url, const QCefSetting* setting, QWidget* parent = 0);
|
|
||||||
|
|
||||||
~CefViewWidget();
|
|
||||||
|
|
||||||
protected slots:
|
|
||||||
void onScreenChanged(QScreen* screen);
|
|
||||||
|
|
||||||
void onNativeBrowserWindowCreated(QWindow* window);
|
|
||||||
|
|
||||||
void onDraggableRegionChanged(const QRegion& draggableRegion, const QRegion& nonDraggableRegion);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool onNewPopup(const QCefFrameId& sourceFrameId,
|
|
||||||
const QString& targetUrl,
|
|
||||||
QString& targetFrameName,
|
|
||||||
QCefView::CefWindowOpenDisposition targetDisposition,
|
|
||||||
QRect& rect,
|
|
||||||
QCefSetting& settings,
|
|
||||||
bool& disableJavascriptAccess) override;
|
|
||||||
|
|
||||||
void onNewDownloadItem(const QSharedPointer<QCefDownloadItem>& item, const QString& suggestedName) override;
|
|
||||||
|
|
||||||
void onUpdateDownloadItem(const QSharedPointer<QCefDownloadItem>& item) override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void resizeEvent(QResizeEvent* event) override;
|
|
||||||
|
|
||||||
void mousePressEvent(QMouseEvent* event) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void updateMask();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QWindow* m_pCefWindow = nullptr;
|
|
||||||
|
|
||||||
int m_iCornerRadius = 50;
|
|
||||||
|
|
||||||
QRegion m_draggableRegion;
|
|
||||||
|
|
||||||
QRegion m_nonDraggableRegion;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CUSTOMCEFVIEW_H
|
|
||||||
@ -67,7 +67,7 @@ void CefWidget::initBrowser()
|
|||||||
m_CefWidget = nullptr;
|
m_CefWidget = nullptr;
|
||||||
}
|
}
|
||||||
setting.setHardwareAcceleration(true);
|
setting.setHardwareAcceleration(true);
|
||||||
m_CefWidget = new CefViewWidget("", &setting, this);
|
m_CefWidget = new QCefView("about:blank", &setting, this);
|
||||||
connect(m_CefWidget, &QCefView::invokeMethod, this, &CefWidget::onInvokeMethod);
|
connect(m_CefWidget, &QCefView::invokeMethod, this, &CefWidget::onInvokeMethod);
|
||||||
connect(m_CefWidget, &QCefView::cefUrlRequest, this, &CefWidget::onQCefUrlRequest);
|
connect(m_CefWidget, &QCefView::cefUrlRequest, this, &CefWidget::onQCefUrlRequest);
|
||||||
connect(m_CefWidget, &QCefView::cefQueryRequest, this, &CefWidget::onQCefQueryRequest);
|
connect(m_CefWidget, &QCefView::cefQueryRequest, this, &CefWidget::onQCefQueryRequest);
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include "CefViewWidget.h"
|
#include <QCefView.h>
|
||||||
|
|
||||||
class CefWidget : public QWidget
|
class CefWidget : public QWidget
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,141 +0,0 @@
|
|||||||
//
|
|
||||||
// CefViewCoreLog.cpp
|
|
||||||
// CefViewCore
|
|
||||||
//
|
|
||||||
// Created by Sheen Tian on 2020/6/19.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "CefViewCoreLog.h"
|
|
||||||
|
|
||||||
#include <cstdarg>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
typedef enum log_level
|
|
||||||
{
|
|
||||||
ll_debug = 1,
|
|
||||||
ll_info,
|
|
||||||
ll_error,
|
|
||||||
ll_fatal,
|
|
||||||
} log_level;
|
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
#include <os/log.h>
|
|
||||||
void
|
|
||||||
cefView_log(log_level level, const char* message)
|
|
||||||
{
|
|
||||||
switch (level) {
|
|
||||||
case ll_debug:
|
|
||||||
os_log_debug(OS_LOG_DEFAULT, "[DEBUG]%s", message);
|
|
||||||
break;
|
|
||||||
case ll_info:
|
|
||||||
os_log_info(OS_LOG_DEFAULT, "[INFO]%s", message);
|
|
||||||
break;
|
|
||||||
case ll_error:
|
|
||||||
os_log_error(OS_LOG_DEFAULT, "[ERROR]%s", message);
|
|
||||||
break;
|
|
||||||
case ll_fatal:
|
|
||||||
os_log_fault(OS_LOG_DEFAULT, "[FATAL]%s", message);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#elif defined(_WIN32)
|
|
||||||
#include <Windows.h>
|
|
||||||
void
|
|
||||||
cefView_log(log_level level, const char* message)
|
|
||||||
{
|
|
||||||
std::string msg;
|
|
||||||
switch (level) {
|
|
||||||
case ll_debug:
|
|
||||||
msg = "[DEBUG]";
|
|
||||||
break;
|
|
||||||
case ll_info:
|
|
||||||
msg = "[INFO]";
|
|
||||||
break;
|
|
||||||
case ll_error:
|
|
||||||
msg = "[ERROR]";
|
|
||||||
break;
|
|
||||||
case ll_fatal:
|
|
||||||
msg = "[FATAL]";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
msg = "[]";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
msg += message;
|
|
||||||
msg += "\r\n";
|
|
||||||
OutputDebugStringA(msg.c_str());
|
|
||||||
}
|
|
||||||
#elif defined(__linux__)
|
|
||||||
#include <syslog.h>
|
|
||||||
void
|
|
||||||
cefView_log(log_level level, const char* message)
|
|
||||||
{
|
|
||||||
switch (level) {
|
|
||||||
case ll_debug:
|
|
||||||
syslog(LOG_USER | LOG_DEBUG, "[DEBUG]%s", message);
|
|
||||||
break;
|
|
||||||
case ll_info:
|
|
||||||
syslog(LOG_USER | LOG_INFO, "[INFO]%s", message);
|
|
||||||
break;
|
|
||||||
case ll_error:
|
|
||||||
syslog(LOG_USER | LOG_ERR, "[ERROR]%s", message);
|
|
||||||
break;
|
|
||||||
case ll_fatal:
|
|
||||||
syslog(LOG_USER | LOG_CRIT, "[FATAL]%s", message);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#error "unsupported platform"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LOG_MSG_BUFFER_LIMIT 4096
|
|
||||||
|
|
||||||
void
|
|
||||||
log_debug(const char* fmt, ...)
|
|
||||||
{
|
|
||||||
std::vector<char> msg(LOG_MSG_BUFFER_LIMIT, 0);
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
vsnprintf(msg.data(), LOG_MSG_BUFFER_LIMIT, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
cefView_log(ll_debug, msg.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
log_info(const char* fmt, ...)
|
|
||||||
{
|
|
||||||
std::vector<char> msg(LOG_MSG_BUFFER_LIMIT, 0);
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
vsnprintf(msg.data(), LOG_MSG_BUFFER_LIMIT, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
cefView_log(ll_info, msg.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
log_error(const char* fmt, ...)
|
|
||||||
{
|
|
||||||
std::vector<char> msg(LOG_MSG_BUFFER_LIMIT, 0);
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
vsnprintf(msg.data(), LOG_MSG_BUFFER_LIMIT, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
cefView_log(ll_error, msg.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
log_fatal(const char* fmt, ...)
|
|
||||||
{
|
|
||||||
std::vector<char> msg(LOG_MSG_BUFFER_LIMIT, 0);
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
vsnprintf(msg.data(), LOG_MSG_BUFFER_LIMIT, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
cefView_log(ll_fatal, msg.data());
|
|
||||||
}
|
|
||||||
@ -1,57 +0,0 @@
|
|||||||
//
|
|
||||||
// CefViewCoreLog.h
|
|
||||||
// CefViewCore
|
|
||||||
//
|
|
||||||
// Created by Sheen Tian on 2020/6/19.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef CefViewCoreLog_h
|
|
||||||
#define CefViewCoreLog_h
|
|
||||||
#pragma once
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
void
|
|
||||||
log_debug(const char* fmt, ...);
|
|
||||||
void
|
|
||||||
log_info(const char* fmt, ...);
|
|
||||||
void
|
|
||||||
log_error(const char* fmt, ...);
|
|
||||||
void
|
|
||||||
log_fatal(const char* fmt, ...);
|
|
||||||
|
|
||||||
class ScopeLogger
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ScopeLogger(const std::string& fn)
|
|
||||||
: functionName_(fn)
|
|
||||||
{
|
|
||||||
// enter scope
|
|
||||||
log_debug("+++ %s", functionName_.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
~ScopeLogger()
|
|
||||||
{
|
|
||||||
// leave scope
|
|
||||||
log_debug("--- %s", functionName_.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string functionName_;
|
|
||||||
};
|
|
||||||
|
|
||||||
#if (defined(DEBUG) || defined(_DEBUG) || !defined(NDEBUG))
|
|
||||||
// DEBUG BUILD
|
|
||||||
#define logD(format, ...) log_debug(format, ##__VA_ARGS__)
|
|
||||||
#define logI(format, ...) log_info(format, ##__VA_ARGS__)
|
|
||||||
#define logE(format, ...) log_error(format, ##__VA_ARGS__)
|
|
||||||
#define logF(format, ...) log_fatal(format, ##__VA_ARGS__)
|
|
||||||
#define logScope() ScopeLogger __scope_logger__(__FUNCTION__);
|
|
||||||
#else
|
|
||||||
// RELEASE BUILD
|
|
||||||
#define logD(format, ...)
|
|
||||||
#define logI(format, ...) log_info(format, ##__VA_ARGS__)
|
|
||||||
#define logE(format, ...) log_error(format, ##__VA_ARGS__)
|
|
||||||
#define logF(format, ...) log_fatal(format, ##__VA_ARGS__)
|
|
||||||
#define logScope()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* CefViewCoreLog_hpp */
|
|
||||||
@ -1,64 +0,0 @@
|
|||||||
//
|
|
||||||
// CefViewCoreLog.cpp
|
|
||||||
// CefViewCore
|
|
||||||
//
|
|
||||||
// Created by leashi on 2022/5/10.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <CefViewCoreGlobal.h>
|
|
||||||
|
|
||||||
#include "CefViewDebug.h"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
std::string
|
|
||||||
toString(CefRefPtr<CefBrowser> browser)
|
|
||||||
{
|
|
||||||
std::string msg;
|
|
||||||
|
|
||||||
msg += "( ";
|
|
||||||
msg += "CefBrowser:";
|
|
||||||
msg += ", ptr=" + std::to_string((int64_t)browser.get());
|
|
||||||
#if CEF_VERSION_MAJOR > 91
|
|
||||||
msg += ", IsValid=" + std::to_string(browser->IsValid());
|
|
||||||
#endif
|
|
||||||
msg += ", GetHost=" + std::to_string((int64_t)browser->GetHost().get());
|
|
||||||
msg += ", CanGoBack=" + std::to_string(browser->CanGoBack());
|
|
||||||
msg += ", CanGoForward=" + std::to_string(browser->CanGoForward());
|
|
||||||
msg += ", IsLoading=" + std::to_string(browser->IsLoading());
|
|
||||||
msg += ", GetIdentifier=" + std::to_string(browser->GetIdentifier());
|
|
||||||
msg += ", IsPopup=" + std::to_string(browser->IsPopup());
|
|
||||||
msg += ", HasDocument=" + std::to_string(browser->HasDocument());
|
|
||||||
msg += ", GetMainFrame=" + std::to_string((int64_t)browser->GetMainFrame().get());
|
|
||||||
msg += ", GetFocusedFrame=" + std::to_string((int64_t)browser->GetFocusedFrame().get());
|
|
||||||
msg += ", GetFrameCount=" + std::to_string(browser->GetFrameCount());
|
|
||||||
msg += " )";
|
|
||||||
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
|
||||||
toString(CefRefPtr<CefFrame> frame)
|
|
||||||
{
|
|
||||||
std::string msg;
|
|
||||||
|
|
||||||
msg += "( ";
|
|
||||||
msg += "CefFrame:";
|
|
||||||
msg += ", ptr=" + std::to_string((int64_t)frame.get());
|
|
||||||
msg += ", IsValid=" + std::to_string(frame->IsValid());
|
|
||||||
msg += ", IsMain=" + std::to_string(frame->IsMain());
|
|
||||||
msg += ", IsFocused=" + std::to_string(frame->IsFocused());
|
|
||||||
msg += ", GetName=" + frame->GetName().ToString();
|
|
||||||
#if CEF_VERSION_MAJOR < 122
|
|
||||||
msg += ", GetIdentifier=" + std::to_string(frame->GetIdentifier());
|
|
||||||
#else
|
|
||||||
msg += ", GetIdentifier=" + frame->GetIdentifier().ToString();
|
|
||||||
#endif
|
|
||||||
msg += ", GetParent=" + std::to_string((int64_t)frame->GetParent().get());
|
|
||||||
msg += ", GetURL=" + frame->GetURL().ToString();
|
|
||||||
msg += ", GetBrowser=" + std::to_string((int64_t)frame->GetBrowser().get());
|
|
||||||
// msg += ", GetV8Context=" + std::to_string((int64_t)frame->GetV8Context().get());
|
|
||||||
msg += " )";
|
|
||||||
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
//
|
|
||||||
// CefViewDebug.h
|
|
||||||
// CefViewCore
|
|
||||||
//
|
|
||||||
// Created by leashi on 2022/5/10.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef CefViewDebug_h
|
|
||||||
#define CefViewDebug_h
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <include/cef_browser.h>
|
|
||||||
#include <include/cef_frame.h>
|
|
||||||
|
|
||||||
|
|
||||||
std::string toString(CefRefPtr<CefBrowser> browser);
|
|
||||||
std::string toString(CefRefPtr<CefFrame> frame);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* CefViewDebug_h */
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
#include "DownloadManager.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
DownloadManager&
|
|
||||||
DownloadManager::getInstance()
|
|
||||||
{
|
|
||||||
static DownloadManager s_instance;
|
|
||||||
return s_instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
DownloadManager::AddNewDownloadItem(const QSharedPointer<QCefDownloadItem>& item)
|
|
||||||
{
|
|
||||||
qDebug() << "DownloadManager::AddNewDownloadItem:"
|
|
||||||
<< " id: " << item->id() << "\n"
|
|
||||||
<< " name: " << item->suggestedFileName() << "\n"
|
|
||||||
<< " path: " << item->fullPath() << "\n"
|
|
||||||
<< " percent: " << item->percentComplete() << "%, " << item->totalBytes() << "/" << item->receivedBytes()
|
|
||||||
<< "\n"
|
|
||||||
<< " canceled: " << item->isCanceled() << "\n"
|
|
||||||
<< " complete: " << item->isComplete();
|
|
||||||
|
|
||||||
m_mapDownloadingItem[item->id()] = item;
|
|
||||||
item->start("", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
DownloadManager::UpdateDownloadItem(const QSharedPointer<QCefDownloadItem>& item)
|
|
||||||
{
|
|
||||||
qDebug() << "DownloadManager::UpdateDownloadItem:"
|
|
||||||
<< " id: " << item->id() << "\n"
|
|
||||||
<< " name: " << item->suggestedFileName() << "\n"
|
|
||||||
<< " path: " << item->fullPath() << "\n"
|
|
||||||
<< " percent: " << item->percentComplete() << "%, " << item->totalBytes() << "/" << item->receivedBytes()
|
|
||||||
<< "\n"
|
|
||||||
<< " canceled: " << item->isCanceled() << "\n"
|
|
||||||
<< " complete: " << item->isComplete();
|
|
||||||
|
|
||||||
if (item->isCanceled() || item->isComplete())
|
|
||||||
m_mapDownloadingItem.remove(item->id());
|
|
||||||
}
|
|
||||||
|
|
||||||
DownloadManager::DownloadManager() {}
|
|
||||||
|
|
||||||
DownloadManager::~DownloadManager()
|
|
||||||
{
|
|
||||||
for (auto& item : m_mapDownloadingItem) {
|
|
||||||
item->cancel();
|
|
||||||
}
|
|
||||||
m_mapDownloadingItem.clear();
|
|
||||||
}
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
#ifndef DOWNLOADMANAGER_H
|
|
||||||
#define DOWNLOADMANAGER_H
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QMap>
|
|
||||||
#include <QSharedPointer>
|
|
||||||
|
|
||||||
#include <QCefDownloadItem.h>
|
|
||||||
|
|
||||||
class DownloadManager
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static DownloadManager& getInstance();
|
|
||||||
|
|
||||||
void AddNewDownloadItem(const QSharedPointer<QCefDownloadItem>& item);
|
|
||||||
|
|
||||||
void UpdateDownloadItem(const QSharedPointer<QCefDownloadItem>& item);
|
|
||||||
|
|
||||||
private:
|
|
||||||
DownloadManager();
|
|
||||||
~DownloadManager();
|
|
||||||
|
|
||||||
QMap<qint32, QSharedPointer<QCefDownloadItem>> m_mapDownloadingItem;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,317 +0,0 @@
|
|||||||
#include "MainWindow.h"
|
|
||||||
|
|
||||||
#include <QCoreApplication>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QDir>
|
|
||||||
#include <QHBoxLayout>
|
|
||||||
#include <QJsonDocument>
|
|
||||||
#include <QJsonValue>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QRandomGenerator>
|
|
||||||
|
|
||||||
#include <QCefContext.h>
|
|
||||||
|
|
||||||
#define URL_ROOT "http://QCefViewDoc"
|
|
||||||
#define LEFT_INDEX_URL URL_ROOT "/left.html"
|
|
||||||
#define RIGHT_INDEX_URL URL_ROOT "/right.html"
|
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget* parent)
|
|
||||||
: QMainWindow(parent /*, Qt::FramelessWindowHint*/)
|
|
||||||
{
|
|
||||||
m_ui.setupUi(this);
|
|
||||||
|
|
||||||
#ifdef Q_OS_MACOS
|
|
||||||
this->m_ui.nativeContainer->setContentsMargins(0, 28, 0, 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
setupWindow();
|
|
||||||
// setWindowFlags(Qt::FramelessWindowHint);
|
|
||||||
// setAttribute(Qt::WA_TranslucentBackground);
|
|
||||||
|
|
||||||
connect(m_ui.btn_showDevTools, &QPushButton::clicked, this, &MainWindow::onBtnShowDevToolsClicked);
|
|
||||||
connect(m_ui.btn_reloadRight, &QPushButton::clicked, this, &MainWindow::onBtnReloadRightViewClicked);
|
|
||||||
connect(m_ui.btn_recreateRight, &QPushButton::clicked, this, &MainWindow::onBtnRecreateRightViewClicked);
|
|
||||||
connect(m_ui.btn_changeColor, &QPushButton::clicked, this, &MainWindow::onBtnChangeColorClicked);
|
|
||||||
connect(m_ui.btn_setFocus, &QPushButton::clicked, this, &MainWindow::onBtnSetFocusClicked);
|
|
||||||
connect(m_ui.btn_callJSCode, &QPushButton::clicked, this, &MainWindow::onBtnCallJSCodeClicked);
|
|
||||||
connect(m_ui.btn_newBrowser, &QPushButton::clicked, this, &MainWindow::onBtnNewBrowserClicked);
|
|
||||||
connect(m_ui.btn_quitApp, &QPushButton::clicked, qApp, &QCoreApplication::quit);
|
|
||||||
|
|
||||||
// build the path to the web resource
|
|
||||||
QDir dir = QCoreApplication::applicationDirPath();
|
|
||||||
// #if defined(Q_OS_MACOS)
|
|
||||||
// QString webResourceDir = /*QString("file://") +*/ QDir::toNativeSeparators(dir.filePath("../Resources/webres"));
|
|
||||||
// #else
|
|
||||||
// QString webResourceDir = /*QString("file://") +*/ QDir::toNativeSeparators(dir.filePath("webres"));
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// // add a local folder to URL map (global)
|
|
||||||
// QCefContext::instance()->addLocalFolderResource(webResourceDir, URL_ROOT);
|
|
||||||
|
|
||||||
createLeftCefView();
|
|
||||||
createRightCefView();
|
|
||||||
}
|
|
||||||
|
|
||||||
MainWindow::~MainWindow() {}
|
|
||||||
|
|
||||||
void
|
|
||||||
MainWindow::createLeftCefView()
|
|
||||||
{
|
|
||||||
if (m_pLeftCefViewWidget) {
|
|
||||||
m_pLeftCefViewWidget->deleteLater();
|
|
||||||
m_pLeftCefViewWidget = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
QCefSetting setting;
|
|
||||||
setting.setWindowlessFrameRate(1000);
|
|
||||||
setting.setHardwareAcceleration(true);
|
|
||||||
setting.setWindowInitialSize(QSize(1000,800));
|
|
||||||
// setting.setBackgroundColor(Qt::magenta);
|
|
||||||
m_pLeftCefViewWidget = new CefViewWidget("https://www.testufo.com/", &setting, this);
|
|
||||||
// connect the invokeMethod to the slot
|
|
||||||
connect(m_pLeftCefViewWidget, &QCefView::invokeMethod, this, &MainWindow::onInvokeMethod);
|
|
||||||
|
|
||||||
// connect the cefQueryRequest to the slot
|
|
||||||
connect(m_pLeftCefViewWidget, &QCefView::cefUrlRequest, this, &MainWindow::onQCefUrlRequest);
|
|
||||||
connect(m_pLeftCefViewWidget, &QCefView::cefQueryRequest, this, &MainWindow::onQCefQueryRequest);
|
|
||||||
connect(m_pLeftCefViewWidget, &QCefView::reportJavascriptResult, this, &MainWindow::onJavascriptResult);
|
|
||||||
connect(m_pLeftCefViewWidget, &QCefView::loadStart, this, &MainWindow::onLoadStart);
|
|
||||||
connect(m_pLeftCefViewWidget, &QCefView::loadEnd, this, &MainWindow::onLoadEnd);
|
|
||||||
connect(m_pLeftCefViewWidget, &QCefView::loadError, this, &MainWindow::onLoadError);
|
|
||||||
|
|
||||||
m_ui.leftCefViewContainer->layout()->addWidget(m_pLeftCefViewWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MainWindow::createRightCefView()
|
|
||||||
{
|
|
||||||
if (m_pRightCefViewWidget) {
|
|
||||||
m_pRightCefViewWidget->deleteLater();
|
|
||||||
m_pRightCefViewWidget = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// build settings for per QCefView
|
|
||||||
QCefSetting setting;
|
|
||||||
#if CEF_VERSION_MAJOR < 100
|
|
||||||
setting.setPlugins(false);
|
|
||||||
#endif
|
|
||||||
setting.setWindowlessFrameRate(1000);
|
|
||||||
setting.setHardwareAcceleration(true);
|
|
||||||
QColor background(0, 255, 0, 255);
|
|
||||||
setting.setBackgroundColor(background);
|
|
||||||
setting.setWindowInitialSize(QSize(1000,800));
|
|
||||||
// create the QCefView widget and add it to the layout container
|
|
||||||
// m_pRightCefViewWidget = new QCefView(RIGHT_INDEX_URL, &setting, this);
|
|
||||||
m_pRightCefViewWidget = new QCefView("https://www.testufo.com/", &setting, this);
|
|
||||||
|
|
||||||
// auto vl = new QVBoxLayout(m_pRightCefViewWidget);
|
|
||||||
// auto btn = new QPushButton("TEST BUTTON OVERLAY", m_pRightCefViewWidget);
|
|
||||||
//// btn->setFixedSize(320, 240);
|
|
||||||
// btn->setStyleSheet("background-color: rgba(1, 1, 1, 0);");
|
|
||||||
// btn->setAttribute(Qt::WA_TranslucentBackground);
|
|
||||||
// btn->setWindowFlags(Qt::FramelessWindowHint);
|
|
||||||
// btn->setAttribute(Qt::WA_NoSystemBackground);
|
|
||||||
// vl->setAlignment(Qt::AlignVCenter);
|
|
||||||
|
|
||||||
// vl->addWidget(btn);
|
|
||||||
// m_pRightCefViewWidget->setLayout(vl);
|
|
||||||
|
|
||||||
// all the following values will disable the context menu for both NCW and OSR mode
|
|
||||||
// m_pRightCefViewWidget->setContextMenuPolicy(Qt::NoContextMenu);
|
|
||||||
// m_pRightCefViewWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
|
|
||||||
// m_pRightCefViewWidget->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
||||||
// m_pRightCefViewWidget->setContextMenuPolicy(Qt::PreventContextMenu);
|
|
||||||
m_pRightCefViewWidget->setContextMenuPolicy(Qt::DefaultContextMenu);
|
|
||||||
|
|
||||||
// add the QCefView widget to the layout
|
|
||||||
m_ui.rightCefViewContainer->layout()->addWidget(m_pRightCefViewWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MainWindow::onInvokeMethod(const QCefBrowserId& browserId,
|
|
||||||
const QCefFrameId& frameId,
|
|
||||||
const QString& method,
|
|
||||||
const QVariantList& arguments)
|
|
||||||
{
|
|
||||||
// extract the arguments and dispatch the invocation to corresponding handler
|
|
||||||
if (0 == method.compare("TestMethod")) {
|
|
||||||
QString title("QCef InvokeMethod Notify");
|
|
||||||
QString text = QString("================== Current Thread: QT_UI ==================\r\n"
|
|
||||||
"Frame: %1\r\n"
|
|
||||||
"Method: %2\r\n"
|
|
||||||
"Arguments:\r\n")
|
|
||||||
.arg(frameId)
|
|
||||||
.arg(method);
|
|
||||||
|
|
||||||
for (int i = 0; i < arguments.size(); i++) {
|
|
||||||
auto jv = QJsonValue::fromVariant(arguments[i]);
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
text.append(
|
|
||||||
QString("%1 Type:%2, Value:%3\r\n")
|
|
||||||
.arg(i).arg(arguments[i].typeName()).arg(arguments[i].toString())
|
|
||||||
);
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
auto jsonValue = QJsonDocument::fromVariant(arguments);
|
|
||||||
auto jsonString = QString(jsonValue.toJson());
|
|
||||||
text.append(QString("\r\nArguments List in JSON format:\r\n%1").arg(jsonString));
|
|
||||||
|
|
||||||
QMessageBox::information(this->window(), title, text);
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MainWindow::onQCefUrlRequest(const QCefBrowserId& browserId, const QCefFrameId& frameId, const QString& url)
|
|
||||||
{
|
|
||||||
QString title("QCef URL Request");
|
|
||||||
QString text = QString("Current Thread: QT_UI\r\n"
|
|
||||||
"URL: %1")
|
|
||||||
.arg(url);
|
|
||||||
|
|
||||||
QMessageBox::information(this->window(), title, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MainWindow::onQCefQueryRequest(const QCefBrowserId& browserId, const QCefFrameId& frameId, const QCefQuery& query)
|
|
||||||
{
|
|
||||||
QString title("QCef Query Request");
|
|
||||||
QString text = QString("Current Thread: QT_UI\r\n"
|
|
||||||
"Query: %1")
|
|
||||||
.arg(query.request());
|
|
||||||
|
|
||||||
QMessageBox::information(this->window(), title, text);
|
|
||||||
|
|
||||||
QString response = query.request().toUpper();
|
|
||||||
query.setResponseResult(true, response);
|
|
||||||
m_pLeftCefViewWidget->responseQCefQuery(query);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MainWindow::onJavascriptResult(const QCefBrowserId& browserId,
|
|
||||||
const QCefFrameId& frameId,
|
|
||||||
const QString& context,
|
|
||||||
const QVariant& result)
|
|
||||||
{
|
|
||||||
auto jsonValue = QJsonDocument::fromVariant(result);
|
|
||||||
auto jsonString = QString(jsonValue.toJson());
|
|
||||||
|
|
||||||
QString title("Javascript result notification");
|
|
||||||
QString text = QString("Context: %1\r\nResult in JSON format:\r\n%2").arg(context).arg(jsonString);
|
|
||||||
|
|
||||||
QMessageBox::information(this->window(), title, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MainWindow::onLoadingStateChanged(const QCefBrowserId& browserId, bool isLoading, bool canGoBack, bool canGoForward)
|
|
||||||
{
|
|
||||||
qDebug() << "onLoadingStateChanged, browserId:" << browserId << ", isLoading:" << isLoading
|
|
||||||
<< ", canGoBack:" << canGoBack << ", canGoForward:" << canGoForward;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MainWindow::onLoadStart(const QCefBrowserId& browserId,
|
|
||||||
const QCefFrameId& frameId,
|
|
||||||
bool isMainFrame,
|
|
||||||
int transitionType)
|
|
||||||
{
|
|
||||||
qDebug() << "onLoadStart, browserId:" << browserId << ", frameId:" << frameId << ", isMainFrame:" << isMainFrame
|
|
||||||
<< ", transitionType:" << transitionType;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MainWindow::onLoadEnd(const QCefBrowserId& browserId, const QCefFrameId& frameId, bool isMainFrame, int httpStatusCode)
|
|
||||||
{
|
|
||||||
qDebug() << "onLoadEnd, browserId:" << browserId << ", frameId:" << frameId << ", isMainFrame:" << isMainFrame
|
|
||||||
<< ", httpStatusCode:" << httpStatusCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MainWindow::onLoadError(const QCefBrowserId& browserId,
|
|
||||||
const QCefFrameId& frameId,
|
|
||||||
bool isMainFrame,
|
|
||||||
int errorCode,
|
|
||||||
const QString& errorMsg,
|
|
||||||
const QString& failedUrl)
|
|
||||||
{
|
|
||||||
qDebug() << "onLoadError, browserId:" << browserId << ", frameId:" << frameId << ", isMainFrame:" << isMainFrame
|
|
||||||
<< ", errorCode:" << errorCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MainWindow::onBtnShowDevToolsClicked()
|
|
||||||
{
|
|
||||||
if (m_pLeftCefViewWidget) {
|
|
||||||
m_pLeftCefViewWidget->showDevTools();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MainWindow::onBtnReloadRightViewClicked()
|
|
||||||
{
|
|
||||||
if (m_pRightCefViewWidget) {
|
|
||||||
m_pRightCefViewWidget->navigateToUrl("https://www.google.com");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MainWindow::onBtnRecreateRightViewClicked()
|
|
||||||
{
|
|
||||||
createRightCefView();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MainWindow::onBtnChangeColorClicked()
|
|
||||||
{
|
|
||||||
if (m_pLeftCefViewWidget) {
|
|
||||||
// create a random color
|
|
||||||
QColor color(QRandomGenerator::global()->generate());
|
|
||||||
|
|
||||||
// create the cef event and set the arguments
|
|
||||||
QCefEvent event("colorChange");
|
|
||||||
event.arguments().append(QVariant::fromValue(color.name(QColor::HexArgb)));
|
|
||||||
|
|
||||||
// broadcast the event to all frames in all browsers created by this QCefView widget
|
|
||||||
m_pLeftCefViewWidget->broadcastEvent(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MainWindow::onBtnCallJSCodeClicked()
|
|
||||||
{
|
|
||||||
QString context = "helloQCefView";
|
|
||||||
QString code = "alert('hello QCefView'); return {k1: 'str', k2: true, k3: 100};";
|
|
||||||
m_pLeftCefViewWidget->executeJavascriptWithResult(QCefView::MainFrameID, code, "", context);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MainWindow::onBtnSetFocusClicked()
|
|
||||||
{
|
|
||||||
if (m_pLeftCefViewWidget) {
|
|
||||||
m_pLeftCefViewWidget->setFocus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MainWindow::onBtnNewBrowserClicked()
|
|
||||||
{
|
|
||||||
QMainWindow* w = new QMainWindow(nullptr);
|
|
||||||
w->setAttribute(Qt::WA_DeleteOnClose);
|
|
||||||
|
|
||||||
QCefSetting settings;
|
|
||||||
QCefView* view = new QCefView("https://cefview.github.io/QCefView/", &settings, w);
|
|
||||||
|
|
||||||
w->setCentralWidget(view);
|
|
||||||
w->resize(1024, 768);
|
|
||||||
w->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef Q_OS_MACOS
|
|
||||||
void
|
|
||||||
MainWindow::setupWindow()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@ -1,77 +0,0 @@
|
|||||||
#ifndef QCEFVIEWTEST_H
|
|
||||||
#define QCEFVIEWTEST_H
|
|
||||||
|
|
||||||
#include <QCloseEvent>
|
|
||||||
#include <QMainWindow>
|
|
||||||
|
|
||||||
#include "ui_MainWindow.h"
|
|
||||||
|
|
||||||
#include "CefViewWidget.h"
|
|
||||||
|
|
||||||
class MainWindow : public QMainWindow
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
MainWindow(QWidget* parent = 0);
|
|
||||||
~MainWindow();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void createLeftCefView();
|
|
||||||
void createRightCefView();
|
|
||||||
void setupWindow();
|
|
||||||
|
|
||||||
// QCefView slots
|
|
||||||
protected slots:
|
|
||||||
|
|
||||||
void onInvokeMethod(const QCefBrowserId& browserId,
|
|
||||||
const QCefFrameId& frameId,
|
|
||||||
const QString& method,
|
|
||||||
const QVariantList& arguments);
|
|
||||||
|
|
||||||
void onQCefUrlRequest(const QCefBrowserId& browserId, const QCefFrameId& frameId, const QString& url);
|
|
||||||
|
|
||||||
void onQCefQueryRequest(const QCefBrowserId& browserId, const QCefFrameId& frameId, const QCefQuery& query);
|
|
||||||
|
|
||||||
void onJavascriptResult(const QCefBrowserId& browserId,
|
|
||||||
const QCefFrameId& frameId,
|
|
||||||
const QString& context,
|
|
||||||
const QVariant& result);
|
|
||||||
|
|
||||||
void onLoadingStateChanged(const QCefBrowserId& browserId, bool isLoading, bool canGoBack, bool canGoForward);
|
|
||||||
|
|
||||||
void onLoadStart(const QCefBrowserId& browserId, const QCefFrameId& frameId, bool isMainFrame, int transitionType);
|
|
||||||
|
|
||||||
void onLoadEnd(const QCefBrowserId& browserId, const QCefFrameId& frameId, bool isMainFrame, int httpStatusCode);
|
|
||||||
|
|
||||||
void onLoadError(const QCefBrowserId& browserId,
|
|
||||||
const QCefFrameId& frameId,
|
|
||||||
bool isMainFrame,
|
|
||||||
int errorCode,
|
|
||||||
const QString& errorMsg,
|
|
||||||
const QString& failedUrl);
|
|
||||||
|
|
||||||
// ui slots
|
|
||||||
protected slots:
|
|
||||||
void onBtnShowDevToolsClicked();
|
|
||||||
|
|
||||||
void onBtnReloadRightViewClicked();
|
|
||||||
|
|
||||||
void onBtnRecreateRightViewClicked();
|
|
||||||
|
|
||||||
void onBtnChangeColorClicked();
|
|
||||||
|
|
||||||
void onBtnSetFocusClicked();
|
|
||||||
|
|
||||||
void onBtnCallJSCodeClicked();
|
|
||||||
|
|
||||||
void onBtnNewBrowserClicked();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::MainWindow m_ui;
|
|
||||||
|
|
||||||
QCefView* m_pLeftCefViewWidget = nullptr;
|
|
||||||
QCefView* m_pRightCefViewWidget = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // QCEFVIEWTEST_H
|
|
||||||
@ -1,250 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>MainWindow</class>
|
|
||||||
<widget class="QMainWindow" name="MainWindow">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>1280</width>
|
|
||||||
<height>900</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>QCefViewTest</string>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="centralWidget">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>3</number>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QWidget" name="nativeContainer" native="true">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="styleSheet">
|
|
||||||
<string notr="true">
|
|
||||||
#nativeContainer {
|
|
||||||
background-color: rgb(170, 255, 255);
|
|
||||||
}
|
|
||||||
</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_nativeContainer">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>6</number>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="styleSheet">
|
|
||||||
<string notr="true">
|
|
||||||
#label{
|
|
||||||
font: 12pt "MS Shell Dlg 2";
|
|
||||||
}
|
|
||||||
</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Native Area</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btn_showDevTools">
|
|
||||||
<property name="text">
|
|
||||||
<string>Show Left DevTools</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btn_reloadRight">
|
|
||||||
<property name="text">
|
|
||||||
<string>Reload Right QCefView</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btn_recreateRight">
|
|
||||||
<property name="text">
|
|
||||||
<string>Recreate Right QCefView</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btn_changeColor">
|
|
||||||
<property name="text">
|
|
||||||
<string>ChangeColor</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLineEdit" name="lineEdit"/>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btn_setFocus">
|
|
||||||
<property name="text">
|
|
||||||
<string>SetFocus</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLineEdit" name="lineEdit_2"/>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btn_callJSCode">
|
|
||||||
<property name="text">
|
|
||||||
<string>CallJSCode</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLineEdit" name="lineEdit_3"/>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btn_newBrowser">
|
|
||||||
<property name="text">
|
|
||||||
<string>NewBrowser</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btn_quitApp">
|
|
||||||
<property name="text">
|
|
||||||
<string>Exit App</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QSplitter" name="splitter">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="frameShadow">
|
|
||||||
<enum>QFrame::Plain</enum>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="leftCefViewContainer" native="true">
|
|
||||||
<property name="styleSheet">
|
|
||||||
<string notr="true">QWidget#leftCefViewContainer {
|
|
||||||
background-color: rgb(217, 183, 255);
|
|
||||||
}</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_cefContainer">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="rightCefViewContainer" native="true">
|
|
||||||
<property name="styleSheet">
|
|
||||||
<string notr="true">QWidget#rightCefViewContainer {
|
|
||||||
background-color: rgb(217, 183, 255);
|
|
||||||
}</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_cefContainer_2">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
|
||||||
<tabstops>
|
|
||||||
<tabstop>btn_showDevTools</tabstop>
|
|
||||||
<tabstop>btn_reloadRight</tabstop>
|
|
||||||
<tabstop>btn_recreateRight</tabstop>
|
|
||||||
<tabstop>btn_changeColor</tabstop>
|
|
||||||
<tabstop>lineEdit</tabstop>
|
|
||||||
<tabstop>lineEdit_2</tabstop>
|
|
||||||
<tabstop>btn_callJSCode</tabstop>
|
|
||||||
<tabstop>lineEdit_3</tabstop>
|
|
||||||
<tabstop>btn_newBrowser</tabstop>
|
|
||||||
<tabstop>btn_quitApp</tabstop>
|
|
||||||
</tabstops>
|
|
||||||
<resources/>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
||||||
259
src/main.cpp
259
src/main.cpp
@ -7,141 +7,142 @@
|
|||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QCefContext.h>
|
#include <QCefContext.h>
|
||||||
#include "QCefWidget/MainWindow.h"
|
#include "QCefWidget/CefWidget.h"
|
||||||
#include <include/cef_app.h>
|
#define DEBUG_PRINT true
|
||||||
#include <include/cef_client.h>
|
void debug_print_argv(int argc, char *argv[])
|
||||||
#include <include/cef_render_handler.h>
|
{
|
||||||
#include <include/cef_browser.h>
|
if(!argc){
|
||||||
// // 自定义 CefApp 类
|
return;
|
||||||
// class CefAppQt : public CefApp, public CefBrowserProcessHandler
|
}
|
||||||
// {
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
// public:
|
DWORD process_id = GetCurrentProcessId();
|
||||||
// CefAppQt() {}
|
std::cout << "Process ID:"<<process_id<<" Argvs"<<std::endl;
|
||||||
|
for (int i = 0; i < argc; ++i)
|
||||||
// // 重写 CefApp 方法
|
{
|
||||||
// CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() override
|
std::cout << "Process ID:"<<process_id<<" Argv:" << i << ": " << argv[i]<<std::endl;
|
||||||
// {
|
}
|
||||||
// return this;
|
}
|
||||||
// }
|
QString curExeDir(){
|
||||||
|
return QDir::currentPath();
|
||||||
// // 重写 CefBrowserProcessHandler 方法
|
}
|
||||||
// void OnContextInitialized() override
|
void exsMkDir(QString Dir){
|
||||||
// {
|
if(!QDir(Dir).exists()){
|
||||||
// CefWindowInfo window_info;
|
QDir().mkdir(Dir);
|
||||||
// CefBrowserSettings browser_settings;
|
}
|
||||||
// browser_settings.windowless_frame_rate = 60;
|
}
|
||||||
// CefBrowserHost::CreateBrowser(window_info, nullptr, "https://html5test.opensuse.org", browser_settings, nullptr, nullptr);
|
bool exeCinfog(int argc,char *argv[]){
|
||||||
// }
|
if(argc<=0){
|
||||||
|
return true;
|
||||||
// IMPLEMENT_REFCOUNTING(CefAppQt);
|
}
|
||||||
// };
|
std::string ex_1="renderer";
|
||||||
|
std::string ex_2="utility";
|
||||||
// int main(int argc, char *argv[])
|
for (int i = 0; i < argc; ++i){
|
||||||
// {
|
std::string arg = argv[i];
|
||||||
// HINSTANCE hInstance = GetModuleHandle(NULL);
|
if (arg.find(ex_1) == std::string::npos||arg.find(ex_2)== std::string::npos){
|
||||||
// CefMainArgs main_args(hInstance);
|
return true;
|
||||||
|
}
|
||||||
// // 处理多进程逻辑
|
}
|
||||||
// CefRefPtr<CefAppQt> app(new CefAppQt);
|
return false;
|
||||||
// int exit_code = CefExecuteProcess(main_args, app, nullptr);
|
}
|
||||||
// if (exit_code >= 0)
|
void initConfig(int argc,char *argv[],QCefConfig &config,QString currentDir)
|
||||||
// {
|
{
|
||||||
// std::cerr << "exit code:" << exit_code << std::endl;
|
//检测自定义缓存路径
|
||||||
// return exit_code;
|
exsMkDir(currentDir+"/user");
|
||||||
// }
|
exsMkDir(currentDir+"/user/userCache");
|
||||||
|
//子进程路径和名字,可以利用本进程复用,
|
||||||
// // 初始化 CEF
|
//Mingw编译下多进程情况需要设置否则程序会退出因为无法拉起子进程
|
||||||
// CefSettings settings;
|
if(exeCinfog(argc,argv)){
|
||||||
// settings.windowless_rendering_enabled = true;
|
config.setBrowserSubProcessPath(currentDir+"/ctai.exe");
|
||||||
// settings.multi_threaded_message_loop = false;
|
}
|
||||||
// settings.external_message_pump = false;
|
config.setRootCachePath(currentDir+"/user");
|
||||||
// settings.no_sandbox = true;
|
config.setCachePath(currentDir+"/user/userCache");
|
||||||
|
config.setResourceDirectoryPath(currentDir+"/cef_binary");
|
||||||
// // 自定义 root_cache_path
|
config.setLocalesDirectoryPath(currentDir+"/cef_binary/locales");
|
||||||
// QString cache = QDir::currentPath() + "/usercache";
|
//浏览器标识
|
||||||
// CefString(&settings.root_cache_path) = cache.toStdString();
|
config.setUserAgent("Mozilla/5.0 (Windows NT 10.0; CEF/3.2272.2035) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 SoftwareInformer/1.6.1400");
|
||||||
// if (!CefInitialize(main_args, settings, app, nullptr))
|
//日志输出级别
|
||||||
// {
|
config.setLogLevel(QCefConfig::LOGSEVERITY_VERBOSE);
|
||||||
// std::cerr << "CEF initialization failed." << std::endl;
|
//桥名字
|
||||||
// return 1;
|
config.setBridgeObjectName("CtaiClient");
|
||||||
// }
|
//内置的协议方案名称
|
||||||
// std::cout << "init CefWidget" << std::endl;
|
config.setBuiltinSchemeName("Ctai");
|
||||||
// // 初始化 Qt 应用
|
//无窗口渲染模式
|
||||||
// QApplication a(argc, argv);
|
config.setWindowlessRenderingEnabled(true);
|
||||||
// std::cout << "CefRunMessageLoop" << std::endl;
|
//远程Debug端口
|
||||||
// // 运行 CEF 消息循环
|
//config.setRemoteDebuggingPort(9000);
|
||||||
// CefRunMessageLoop();
|
//请求头的语言
|
||||||
// std::cout << "CefShutdown" << std::endl;
|
config.setAcceptLanguageList("zh-CN");
|
||||||
// // 关闭 CEF
|
//允许忽略 localhost 上的 TLS/SSL 错误
|
||||||
// CefShutdown();
|
config.addCommandLineSwitch("allow-insecure-localhost");
|
||||||
|
config.addCommandLineSwitch("ignore-certificate-errors-spki-list");
|
||||||
// return a.exec();
|
config.addCommandLineSwitch("ignore-ssl-errors");
|
||||||
// }
|
//单进程模式
|
||||||
|
// config.addCommandLineSwitch("single-process");
|
||||||
|
//启用GPU加速
|
||||||
|
config.addCommandLineSwitch("enable-gpu");
|
||||||
|
//GPU加速合成
|
||||||
|
config.addCommandLineSwitch("enable-gpu-compositing");
|
||||||
|
//在进程中使用GPU渲染-开启后只有一个进程
|
||||||
|
config.addCommandLineSwitch("in-process-gpu");
|
||||||
|
//无头模式
|
||||||
|
config.addCommandLineSwitch("headless");
|
||||||
|
//密钥链
|
||||||
|
config.addCommandLineSwitch("use-mock-keychain");
|
||||||
|
//chrome运行时环境
|
||||||
|
config.addCommandLineSwitch("enable-chrome-runtime");
|
||||||
|
//Alloy 风格
|
||||||
|
config.addCommandLineSwitch("use-alloy-style");
|
||||||
|
//离屏渲染
|
||||||
|
config.addCommandLineSwitch("off-screen-rendering-enabled");
|
||||||
|
//网络服务In进程
|
||||||
|
config.addCommandLineSwitchWithValue("enable-features", "NetworkServiceInProcess");
|
||||||
|
//语言
|
||||||
|
config.addCommandLineSwitchWithValue("lang", "zh-CN");
|
||||||
|
//跨域进行远程
|
||||||
|
//config.addCommandLineSwitchWithValue("remote-allow-origins", "*");
|
||||||
|
// 禁用沙盒
|
||||||
|
config.addCommandLineSwitchWithValue("no-sandbox", "ture");
|
||||||
|
//渲染进程限制
|
||||||
|
config.addCommandLineSwitchWithValue("renderer-process-limit", "1");
|
||||||
|
//外部消息循环
|
||||||
|
config.addCommandLineSwitchWithValue("external-message-pump", "false");
|
||||||
|
//多线程消息循环
|
||||||
|
config.addCommandLineSwitchWithValue("multi-threaded-message-loop", "true");
|
||||||
|
}
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
if (DEBUG_PRINT)
|
||||||
QString currentDir=QDir::currentPath();
|
{
|
||||||
qDebug() << "UI线程ID-1: " << QThread::currentThreadId();
|
debug_print_argv(argc, argv);
|
||||||
|
}
|
||||||
QApplication a(argc, argv);
|
QApplication a(argc, argv);
|
||||||
QCefConfig config;
|
QCefConfig config;
|
||||||
config.setUserAgent("Mozilla/5.0 (Windows NT 10.0; CEF/3.2272.2035) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 SoftwareInformer/1.6.1400");
|
//初始化上下文的配置
|
||||||
config.setLogLevel(QCefConfig::LOGSEVERITY_VERBOSE);
|
initConfig(argc,argv,config,curExeDir());
|
||||||
config.setBridgeObjectName("CtaiClient");
|
//初始化浏览器上下文
|
||||||
config.setBuiltinSchemeName("Ctai");
|
|
||||||
config.setWindowlessRenderingEnabled(false);
|
|
||||||
config.setRemoteDebuggingPort(9000);
|
|
||||||
//config.setCachePath(currentDir+"/user/userData");
|
|
||||||
//config.setRootCachePath(currentDir+"/user/userCache");
|
|
||||||
//config.setResourceDirectoryPath(currentDir+"/Resources");
|
|
||||||
//config.setLocalesDirectoryPath(currentDir+"/locales");
|
|
||||||
config.setAcceptLanguageList("zh-CN");
|
|
||||||
config.setBrowserSubProcessPath(currentDir+"/ctai.exe");
|
|
||||||
//config.addCommandLineSwitch("single-process");
|
|
||||||
//config.addCommandLineSwitch("enable-gpu");
|
|
||||||
//config.addCommandLineSwitch("in-process-gpu");
|
|
||||||
//config.addCommandLineSwitch("disable-gpu-compositing");
|
|
||||||
config.addCommandLineSwitch("headless");
|
|
||||||
config.addCommandLineSwitch("use-mock-keychain");
|
|
||||||
config.addCommandLineSwitch("disable-chrome-runtime");
|
|
||||||
config.addCommandLineSwitchWithValue("enable-features","NetworkServiceInProcess");
|
|
||||||
config.addCommandLineSwitchWithValue("log-severity","verbose");
|
|
||||||
config.addCommandLineSwitchWithValue("lang","zh-CN");
|
|
||||||
config.addCommandLineSwitchWithValue("builtin-scheme-name","Ctai");
|
|
||||||
config.addCommandLineSwitchWithValue("bridge-obj-name","CtaiClient");
|
|
||||||
config.addCommandLineSwitchWithValue("pack_loading_disabled","false");
|
|
||||||
//config.addCommandLineSwitchWithValue("user-data-dir","false");
|
|
||||||
//config.addCommandLineSwitchWithValue("log-file","false");
|
|
||||||
config.addCommandLineSwitchWithValue("remote-allow-origins", "*");
|
|
||||||
//禁用沙盒
|
|
||||||
config.addCommandLineSwitchWithValue("no-sandbox","ture");
|
|
||||||
//禁止多线程会话循环(单进程为true,多进程为false);
|
|
||||||
config.addCommandLineSwitchWithValue("renderer-process-limit", "1");
|
|
||||||
config.addCommandLineSwitchWithValue("external-message-pump","false");
|
|
||||||
config.addCommandLineSwitchWithValue("multi-threaded-message-loop","true");
|
|
||||||
QCefContext cefContext(&a, argc, argv, &config);
|
QCefContext cefContext(&a, argc, argv, &config);
|
||||||
MainWindow cw;
|
//初始化浏览器
|
||||||
|
CefWidget cw;
|
||||||
cw.show();
|
cw.show();
|
||||||
qDebug() << "UI线程ID-2: " << QThread::currentThreadId();
|
// qputenv("QT_QPA_PLATFORM", "windows:fontengine=freetype");
|
||||||
// qputenv("QT_QPA_PLATFORM", "windows:fontengine=freetype");
|
// // 加载语言包
|
||||||
// // 加载语言包
|
// QTranslator qtBaseTranslator;
|
||||||
// QTranslator qtBaseTranslator;
|
// if (!qtBaseTranslator.load(QStringLiteral(":/res/translator/qtbase_zh_CN.qm")))
|
||||||
// if (!qtBaseTranslator.load(QStringLiteral(":/res/translator/qtbase_zh_CN.qm")))
|
// {
|
||||||
// {
|
// // 处理加载翻译文件失败的情况
|
||||||
// // 处理加载翻译文件失败的情况
|
// qDebug() << "Failed to load translation file.";
|
||||||
// qDebug() << "Failed to load translation file.";
|
// return -1;
|
||||||
// return -1;
|
// }
|
||||||
// }
|
// a.installTranslator(&qtBaseTranslator);
|
||||||
// a.installTranslator(&qtBaseTranslator);
|
// // 读取窗体的配置并初始化
|
||||||
// // 读取窗体的配置并初始化
|
// sui_init_config();
|
||||||
// sui_init_config();
|
// ctai x;
|
||||||
// ctai x;
|
// x.init_layout();
|
||||||
// x.init_layout();
|
// // 仅限于windows平台
|
||||||
// // 仅限于windows平台
|
// #if defined(__WIN32__)
|
||||||
// #if defined(__WIN32__)
|
// x.title()->set_type(QD_TYPE::QD_EXIT);
|
||||||
// x.title()->set_type(QD_TYPE::QD_EXIT);
|
// #endif
|
||||||
// #endif
|
// x.show();
|
||||||
// x.show();
|
|
||||||
a.exec();
|
a.exec();
|
||||||
qDebug() << "EXIT";
|
qDebug() << "EXIT";
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user