update
This commit is contained in:
parent
3799234c56
commit
0245968901
@ -13,7 +13,11 @@
|
||||
<!-- 引入 jsPDF 库用于导出 PDF -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
|
||||
<style>
|
||||
html{
|
||||
background-color: white;
|
||||
}
|
||||
body {
|
||||
background-color: white;
|
||||
font-family: Arial, sans-serif;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
73
src/QCefWidget/App/CefViewAppBase.cpp
Normal file
73
src/QCefWidget/App/CefViewAppBase.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
#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());
|
||||
}
|
||||
}
|
||||
}
|
||||
67
src/QCefWidget/App/CefViewAppBase.h
Normal file
67
src/QCefWidget/App/CefViewAppBase.h
Normal file
@ -0,0 +1,67 @@
|
||||
//
|
||||
// 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
|
||||
6
src/QCefWidget/App/CefViewOtherApp.cpp
Normal file
6
src/QCefWidget/App/CefViewOtherApp.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include "CefViewOtherApp.h"
|
||||
|
||||
CefViewOtherApp::CefViewOtherApp(const CefString& scheme_name)
|
||||
: CefViewAppBase(scheme_name)
|
||||
{
|
||||
}
|
||||
22
src/QCefWidget/App/CefViewOtherApp.h
Normal file
22
src/QCefWidget/App/CefViewOtherApp.h
Normal file
@ -0,0 +1,22 @@
|
||||
//
|
||||
// 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
|
||||
208
src/QCefWidget/App/CefViewRenderApp.cpp
Normal file
208
src/QCefWidget/App/CefViewRenderApp.cpp
Normal file
@ -0,0 +1,208 @@
|
||||
#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);
|
||||
}
|
||||
}
|
||||
}
|
||||
180
src/QCefWidget/App/CefViewRenderApp.h
Normal file
180
src/QCefWidget/App/CefViewRenderApp.h
Normal file
@ -0,0 +1,180 @@
|
||||
#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
|
||||
517
src/QCefWidget/Bridge/CefViewBridgeObject.cpp
Normal file
517
src/QCefWidget/Bridge/CefViewBridgeObject.cpp
Normal file
@ -0,0 +1,517 @@
|
||||
#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();
|
||||
}
|
||||
}
|
||||
221
src/QCefWidget/Bridge/CefViewBridgeObject.h
Normal file
221
src/QCefWidget/Bridge/CefViewBridgeObject.h
Normal file
@ -0,0 +1,221 @@
|
||||
#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_;
|
||||
};
|
||||
127
src/QCefWidget/CefViewWidget.cpp
Normal file
127
src/QCefWidget/CefViewWidget.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
#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(), 0, 0);
|
||||
QRegion mask = QRegion(path.toFillPolygon().toPolygon());
|
||||
|
||||
// apply the mask
|
||||
setMask(mask);
|
||||
}
|
||||
57
src/QCefWidget/CefViewWidget.h
Normal file
57
src/QCefWidget/CefViewWidget.h
Normal file
@ -0,0 +1,57 @@
|
||||
#ifndef CUSTOMCEFVIEW_H
|
||||
#define CUSTOMCEFVIEW_H
|
||||
|
||||
#include <QScreen>
|
||||
#include <QPainter>
|
||||
#include <QCefView.h>
|
||||
#include <CefViewBrowserClient.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
|
||||
@ -55,6 +55,7 @@ CefWidget::CefWidget(QWidget *parent)
|
||||
setWindowFlags(Qt::Window); // 使用标准窗口样式
|
||||
setAttribute(Qt::WA_TranslucentBackground, false);
|
||||
initBrowser();
|
||||
setObjectName("CefWidget");
|
||||
}
|
||||
|
||||
CefWidget::~CefWidget()
|
||||
@ -70,9 +71,7 @@ void CefWidget::initBrowser()
|
||||
}
|
||||
setting.setWindowlessFrameRate(1000);
|
||||
setting.setHardwareAcceleration(true);
|
||||
QColor background(0, 255, 0, 255);
|
||||
setting.setBackgroundColor(background);
|
||||
m_CefWidget = new QCefView("about:blank", &setting, this);
|
||||
m_CefWidget = new CefViewWidget("about:blank", &setting, this);
|
||||
connect(m_CefWidget, &QCefView::invokeMethod, this, &CefWidget::onInvokeMethod);
|
||||
connect(m_CefWidget, &QCefView::cefUrlRequest, this, &CefWidget::onQCefUrlRequest);
|
||||
connect(m_CefWidget, &QCefView::cefQueryRequest, this, &CefWidget::onQCefQueryRequest);
|
||||
@ -86,6 +85,7 @@ void CefWidget::initBrowser()
|
||||
m_CefWidget->navigateToString(html_template);
|
||||
}
|
||||
}
|
||||
|
||||
void CefWidget::initResHtmlTemplate(){
|
||||
QString template_file = ":/res/template/cmarkdown_template.html";
|
||||
QFile file(template_file);
|
||||
|
||||
@ -7,8 +7,8 @@
|
||||
#include <QWidget>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QCefView.h>
|
||||
|
||||
//#include <QCefView.h>
|
||||
#include "CefViewWidget.h"
|
||||
class CefWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -32,7 +32,7 @@ private:
|
||||
QLineEdit* m_TextToUrl={};
|
||||
QPushButton* m_BtnToUrl={};
|
||||
QPushButton* m_BtnToString={};
|
||||
QCefView* m_CefWidget ={};
|
||||
CefViewWidget* m_CefWidget ={};
|
||||
QCefSetting setting;
|
||||
bool DevMode=true;
|
||||
QString html_template;
|
||||
|
||||
141
src/QCefWidget/Common/CefViewCoreLog.cpp
Normal file
141
src/QCefWidget/Common/CefViewCoreLog.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
//
|
||||
// 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());
|
||||
}
|
||||
57
src/QCefWidget/Common/CefViewCoreLog.h
Normal file
57
src/QCefWidget/Common/CefViewCoreLog.h
Normal file
@ -0,0 +1,57 @@
|
||||
//
|
||||
// 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 */
|
||||
64
src/QCefWidget/Common/CefViewDebug.cpp
Normal file
64
src/QCefWidget/Common/CefViewDebug.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
21
src/QCefWidget/Common/CefViewDebug.h
Normal file
21
src/QCefWidget/Common/CefViewDebug.h
Normal file
@ -0,0 +1,21 @@
|
||||
//
|
||||
// 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 */
|
||||
52
src/QCefWidget/DownloadManager.cpp
Normal file
52
src/QCefWidget/DownloadManager.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
#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();
|
||||
}
|
||||
26
src/QCefWidget/DownloadManager.h
Normal file
26
src/QCefWidget/DownloadManager.h
Normal file
@ -0,0 +1,26 @@
|
||||
#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
|
||||
Loading…
Reference in New Issue
Block a user