JJ_MKVMaker/packages/webview_cef/common/webview_app.cc

346 lines
12 KiB
C++

// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "webview_app.h"
#include <string>
#include "include/cef_browser.h"
#include "include/cef_command_line.h"
#include "include/views/cef_browser_view.h"
#include "include/views/cef_window.h"
#include "include/wrapper/cef_helpers.h"
namespace {
// When using the Views framework this object provides the delegate
// implementation for the CefWindow that hosts the Views-based browser.
class SimpleWindowDelegate : public CefWindowDelegate {
public:
explicit SimpleWindowDelegate(CefRefPtr<CefBrowserView> browser_view)
: browser_view_(browser_view) {}
void OnWindowCreated(CefRefPtr<CefWindow> window) override {
// Add the browser view and show the window.
window->AddChildView(browser_view_);
window->Show();
// Give keyboard focus to the browser view.
browser_view_->RequestFocus();
}
void OnWindowDestroyed(CefRefPtr<CefWindow> window) override {
browser_view_ = nullptr;
}
bool CanClose(CefRefPtr<CefWindow> window) override {
// Allow the window to close if the browser says it's OK.
CefRefPtr<CefBrowser> browser = browser_view_->GetBrowser();
if (browser)
return browser->GetHost()->TryCloseBrowser();
return true;
}
CefSize GetPreferredSize(CefRefPtr<CefView> view) override {
return CefSize(1280, 720);
}
private:
CefRefPtr<CefBrowserView> browser_view_;
IMPLEMENT_REFCOUNTING(SimpleWindowDelegate);
DISALLOW_COPY_AND_ASSIGN(SimpleWindowDelegate);
};
class SimpleBrowserViewDelegate : public CefBrowserViewDelegate {
public:
SimpleBrowserViewDelegate() {}
bool OnPopupBrowserViewCreated(CefRefPtr<CefBrowserView> browser_view,
CefRefPtr<CefBrowserView> popup_browser_view,
bool is_devtools) override {
// Create a new top-level Window for the popup. It will show itself after
// creation.
CefWindow::CreateTopLevelWindow(
new SimpleWindowDelegate(popup_browser_view));
// We created the Window.
return true;
}
private:
IMPLEMENT_REFCOUNTING(SimpleBrowserViewDelegate);
DISALLOW_COPY_AND_ASSIGN(SimpleBrowserViewDelegate);
};
} // namespace
WebviewApp::WebviewApp(CefRefPtr<WebviewHandler> handler) {
m_handler = handler;
}
WebviewApp::ProcessType WebviewApp::GetProcessType(CefRefPtr<CefCommandLine> command_line)
{
// The command-line flag won't be specified for the browser process.
if (!command_line->HasSwitch("type"))
{
return BrowserProcess;
}
const std::string& process_type = command_line->GetSwitchValue("type");
if (process_type == "renderer")
return RendererProcess;
#if defined(OS_LINUX)
else if (process_type == "zygote")
return ZygoteProcess;
#endif
return OtherProcess;
}
void WebviewApp::OnBeforeCommandLineProcessing(const CefString &process_type, CefRefPtr<CefCommandLine> command_line)
{
// Pass additional command-line flags to the browser process.
if (process_type.empty())
{
#ifndef WEBVIEW_CEF_GPU_TEXTURE
// The GPU shared-texture path (OnAcceleratedPaint) requires the GPU
// compositor; only allow disabling the GPU when it is not compiled in.
if (!m_bEnableGPU)
{
command_line->AppendSwitch("disable-gpu");
command_line->AppendSwitch("disable-gpu-compositing");
}
#endif
command_line->AppendSwitch("disable-web-security"); //disable web security
command_line->AppendSwitch("allow-running-insecure-content"); //allow running insecure content in secure pages
// Don't create a "GPUCache" directory when cache-path is unspecified.
command_line->AppendSwitch("disable-gpu-shader-disk-cache"); //disable gpu shader disk cache
command_line->AppendSwitch("no-sandbox");
//http://www.chromium.org/developers/design-documents/process-models
if (m_uMode == 1)
{
command_line->AppendSwitch("process-per-site"); //each site in its own process
command_line->AppendSwitchWithValue("renderer-process-limit", "8"); //limit renderer process count to decrease memory usage
}
else if (m_uMode == 2)
{
command_line->AppendSwitch("process-per-tab"); //each tab in its own process
}
else if (m_uMode == 3)
{
command_line->AppendSwitch("single-process"); //all in one process
}
command_line->AppendSwitchWithValue("autoplay-policy", "no-user-gesture-required"); //autoplay policy for media
//Support cross domain requests
std::string values = command_line->GetSwitchValue("disable-features");
if (values == "")
{
values = "SameSiteByDefaultCookies,CookiesWithoutSameSiteMustBeSecure";
}
else
{
values += ",SameSiteByDefaultCookies,CookiesWithoutSameSiteMustBeSecure";
}
if (values.find("CalculateNativeWinOcclusion") == size_t(-1))
{
values += ",CalculateNativeWinOcclusion";
}
command_line->AppendSwitchWithValue("disable-features", values);
// for unsafe domain, add domain to whitelist
if (!m_strFilterDomain.empty())
{
command_line->AppendSwitch("ignore-certificate-errors"); //ignore certificate errors
command_line->AppendSwitchWithValue("unsafely-treat-insecure-origin-as-secure",
m_strFilterDomain);
}
}
#ifdef __APPLE__
command_line->AppendSwitch("use-mock-keychain");
// macOS now runs multi-process via bundled CEF helper apps (see the
// example Runner's "Embed CEF Helpers" phase). The process model is
// selected by m_uMode above, like the other platforms.
#endif
#ifdef __linux__
#endif
}
void WebviewApp::OnContextInitialized()
{
CEF_REQUIRE_UI_THREAD();
// CefBrowserSettings browser_settings;
// browser_settings.windowless_frame_rate = 60;
//
// CefWindowInfo window_info;
// window_info.SetAsWindowless(0);
//
// // create browser
// CefBrowserHost::CreateBrowser(window_info, m_handler, "", browser_settings, nullptr, nullptr);
}
// CefRefPtr<CefClient> WebviewApp::GetDefaultClient() {
// // Called when a new browser window is created via the Chrome runtime UI.
// return WebviewHandler::GetInstance();
// }
void WebviewApp::SetUnSafelyTreatInsecureOriginAsSecure(const CefString &strFilterDomain)
{
m_strFilterDomain = strFilterDomain;
}
void WebviewApp::OnWebKitInitialized()
{
//inject js function for jssdk
std::string extensionCode = R"(
var external = {};
var clientSdk = {};
(() => {
clientSdk.jsCmd = (functionName, arg1, arg2, arg3) => {
if (typeof arg1 === 'function') {
native function jsCmd(functionName, arg1);
return jsCmd(functionName, arg1);
}
else if (typeof arg2 === 'function') {
jsonString = arg1;
if (typeof arg1 !== 'string'){
jsonString = JSON.stringify(arg1);
}
native function jsCmd(functionName, jsonString, arg2);
return jsCmd(functionName, jsonString, arg2);
}
else if (typeof arg3 === 'function') {
jsonString = arg1;
if (typeof arg1 !== 'string'){
jsonString = JSON.stringify(arg1);
}
native function jsCmd(functionName, jsonString, arg2, arg3);
return jsCmd(functionName, jsonString, arg2, arg3);
}else {
}
};
external.JavaScriptChannel = (n,e,r) => {
var a;
null == r ? a = '' : (a = '_' + new Date + (1e3 + Math.floor(8999 * Math.random())), window[a] = function (n, e) {
return function () {
try {
e && e.call && e.call(null, arguments[1])
} finally {
delete window[n]
}
}
}(a, r));
try {
external.StartRequest(external.GetNextReqID(), n, a, JSON.stringify(e || {}), '')
} catch (l) {
console.log('messeage send')
}
}
external.EvaluateCallback = (nReqID, result) => {
native function EvaluateCallback();
EvaluateCallback(nReqID, result);
}
external.StartRequest = (nReqID, strCmd, strCallBack, strArgs, strLog) => {
native function StartRequest();
StartRequest(nReqID, strCmd, strCallBack, strArgs, strLog);
};
external.GetNextReqID = () => {
native function GetNextReqID();
return GetNextReqID();
};
})();
)";
CefRefPtr<CefJSHandler> handler = new CefJSHandler();
if (!m_render_js_bridge.get())
m_render_js_bridge.reset(new CefJSBridge);
handler->AttachJSBridge(m_render_js_bridge);
CefRegisterExtension("v8/extern", extensionCode, handler);
}
void WebviewApp::OnBrowserCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefDictionaryValue> extra_info)
{
if (!m_render_js_bridge.get()) {
m_render_js_bridge.reset(new CefJSBridge);
}
}
void WebviewApp::SetProcessMode(uint32_t uMode)
{
m_uMode = uMode;
}
void WebviewApp::SetEnableGPU(bool bEnable)
{
m_bEnableGPU = bEnable;
}
void WebviewApp::OnBeforeChildProcessLaunch(CefRefPtr<CefCommandLine> command_line)
{
}
void WebviewApp::OnBrowserDestroyed(CefRefPtr<CefBrowser> browser)
{
}
void WebviewApp::OnContextCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context)
{
}
void WebviewApp::OnContextReleased(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context)
{
if (m_render_js_bridge.get())
{
m_render_js_bridge->RemoveCallbackFuncWithFrame(frame);
}
}
void WebviewApp::OnUncaughtException(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context, CefRefPtr<CefV8Exception> exception, CefRefPtr<CefV8StackTrace> stackTrace)
{
}
void WebviewApp::OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefDOMNode> node)
{
//Get node attribute
bool is_editable = (node.get() && node->IsEditable());
CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create(kFocusedNodeChangedMessage);
message->GetArgumentList()->SetBool(0, is_editable);
if (is_editable)
{
CefRect rect = node->GetElementBounds();
message->GetArgumentList()->SetInt(1, rect.x);
message->GetArgumentList()->SetInt(2, rect.y + rect.height);
message->GetArgumentList()->SetInt(3, rect.height);
}
frame->SendProcessMessage(PID_BROWSER, message);
}
bool WebviewApp::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefProcessId source_process, CefRefPtr<CefProcessMessage> message)
{
const CefString& message_name = message->GetName();
if (message_name == kExecuteJsCallbackMessage)
{
int callbackId = message->GetArgumentList()->GetInt(0);
bool error = message->GetArgumentList()->GetBool(1);
CefString result = message->GetArgumentList()->GetString(2);
if (m_render_js_bridge.get())
{
m_render_js_bridge->ExecuteJSCallbackFunc(callbackId, error, result);
}
}
return false;
}