281 lines
9.2 KiB
C++
281 lines
9.2 KiB
C++
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
|
// Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "include/cef_browser.h"
|
|
#include "libcef/browser/alloy/alloy_browser_host_impl.h"
|
|
#include "libcef/browser/chrome/chrome_browser_host_impl.h"
|
|
#include "libcef/browser/chrome/views/chrome_child_window.h"
|
|
#include "libcef/browser/context.h"
|
|
#include "libcef/browser/thread_util.h"
|
|
#include "libcef/features/runtime.h"
|
|
|
|
namespace {
|
|
|
|
class CreateBrowserHelper {
|
|
public:
|
|
CreateBrowserHelper(const CefWindowInfo& windowInfo,
|
|
CefRefPtr<CefClient> client,
|
|
const CefString& url,
|
|
const CefBrowserSettings& settings,
|
|
CefRefPtr<CefDictionaryValue> extra_info,
|
|
CefRefPtr<CefRequestContext> request_context)
|
|
: window_info_(windowInfo),
|
|
client_(client),
|
|
url_(url),
|
|
settings_(settings),
|
|
extra_info_(extra_info),
|
|
request_context_(request_context) {}
|
|
|
|
void Run() {
|
|
CefBrowserHost::CreateBrowserSync(window_info_, client_, url_, settings_,
|
|
extra_info_, request_context_);
|
|
}
|
|
|
|
CefWindowInfo window_info_;
|
|
CefRefPtr<CefClient> client_;
|
|
CefString url_;
|
|
CefBrowserSettings settings_;
|
|
CefRefPtr<CefDictionaryValue> extra_info_;
|
|
CefRefPtr<CefRequestContext> request_context_;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
// static
|
|
bool CefBrowserHost::CreateBrowser(
|
|
const CefWindowInfo& windowInfo,
|
|
CefRefPtr<CefClient> client,
|
|
const CefString& url,
|
|
const CefBrowserSettings& settings,
|
|
CefRefPtr<CefDictionaryValue> extra_info,
|
|
CefRefPtr<CefRequestContext> request_context) {
|
|
// Verify that the context is in a valid state.
|
|
if (!CONTEXT_STATE_VALID()) {
|
|
DCHECK(false) << "context not valid";
|
|
return false;
|
|
}
|
|
|
|
// Verify that the settings structure is a valid size.
|
|
if (settings.size != sizeof(cef_browser_settings_t)) {
|
|
DCHECK(false) << "invalid CefBrowserSettings structure size";
|
|
return false;
|
|
}
|
|
|
|
// Verify windowless rendering requirements.
|
|
if (windowInfo.windowless_rendering_enabled &&
|
|
(!client || !client->GetRenderHandler().get())) {
|
|
LOG(ERROR)
|
|
<< "Windowless rendering requires a CefRenderHandler implementation";
|
|
return false;
|
|
}
|
|
|
|
if (windowInfo.windowless_rendering_enabled &&
|
|
!CefContext::Get()->settings().windowless_rendering_enabled) {
|
|
LOG(ERROR) << "Creating a windowless browser without setting "
|
|
"CefSettings.windowless_rendering_enabled may result in "
|
|
"reduced performance or runtime errors.";
|
|
}
|
|
|
|
if (!request_context) {
|
|
request_context = CefRequestContext::GetGlobalContext();
|
|
}
|
|
|
|
auto helper = std::make_unique<CreateBrowserHelper>(
|
|
windowInfo, client, url, settings, extra_info, request_context);
|
|
|
|
auto request_context_impl =
|
|
static_cast<CefRequestContextImpl*>(request_context.get());
|
|
|
|
// Wait for the browser context to be initialized before creating the browser.
|
|
request_context_impl->ExecuteWhenBrowserContextInitialized(base::BindOnce(
|
|
[](std::unique_ptr<CreateBrowserHelper> helper) {
|
|
// Always execute asynchronously to avoid potential issues if we're
|
|
// being called synchronously during app initialization.
|
|
CEF_POST_TASK(CEF_UIT, base::BindOnce(&CreateBrowserHelper::Run,
|
|
std::move(helper)));
|
|
},
|
|
std::move(helper)));
|
|
|
|
return true;
|
|
}
|
|
|
|
// static
|
|
CefRefPtr<CefBrowser> CefBrowserHost::CreateBrowserSync(
|
|
const CefWindowInfo& windowInfo,
|
|
CefRefPtr<CefClient> client,
|
|
const CefString& url,
|
|
const CefBrowserSettings& settings,
|
|
CefRefPtr<CefDictionaryValue> extra_info,
|
|
CefRefPtr<CefRequestContext> request_context) {
|
|
// Verify that the context is in a valid state.
|
|
if (!CONTEXT_STATE_VALID()) {
|
|
DCHECK(false) << "context not valid";
|
|
return nullptr;
|
|
}
|
|
|
|
// Verify that the settings structure is a valid size.
|
|
if (settings.size != sizeof(cef_browser_settings_t)) {
|
|
DCHECK(false) << "invalid CefBrowserSettings structure size";
|
|
return nullptr;
|
|
}
|
|
|
|
if (!request_context) {
|
|
request_context = CefRequestContext::GetGlobalContext();
|
|
}
|
|
|
|
// Verify that the browser context is valid.
|
|
auto request_context_impl =
|
|
static_cast<CefRequestContextImpl*>(request_context.get());
|
|
if (!request_context_impl->VerifyBrowserContext()) {
|
|
return nullptr;
|
|
}
|
|
|
|
// Verify windowless rendering requirements.
|
|
if (windowInfo.windowless_rendering_enabled &&
|
|
(!client || !client->GetRenderHandler().get())) {
|
|
LOG(ERROR)
|
|
<< "Windowless rendering requires a CefRenderHandler implementation";
|
|
return nullptr;
|
|
}
|
|
|
|
CefBrowserCreateParams create_params;
|
|
create_params.MaybeSetWindowInfo(windowInfo, /*allow_alloy_style=*/true,
|
|
/*allow_chrome_style=*/true);
|
|
create_params.client = client;
|
|
create_params.url = url;
|
|
create_params.settings = settings;
|
|
create_params.extra_info = extra_info;
|
|
create_params.request_context = request_context;
|
|
|
|
return CefBrowserHostBase::Create(create_params);
|
|
}
|
|
|
|
// static
|
|
bool CefBrowserCreateParams::IsChromeStyle(const CefWindowInfo* window_info) {
|
|
if (!cef::IsChromeRuntimeEnabled()) {
|
|
return false;
|
|
}
|
|
if (!window_info) {
|
|
return true;
|
|
}
|
|
|
|
// Both CHROME and DEFAULT indicate Chrome style with Chrome bootstrap.
|
|
return window_info->runtime_style == CEF_RUNTIME_STYLE_CHROME ||
|
|
window_info->runtime_style == CEF_RUNTIME_STYLE_DEFAULT;
|
|
}
|
|
|
|
bool CefBrowserCreateParams::IsChromeStyle() const {
|
|
if (!cef::IsChromeRuntimeEnabled()) {
|
|
return false;
|
|
}
|
|
|
|
const bool chrome_style_via_window_info = IsChromeStyle(window_info.get());
|
|
|
|
if (popup_with_alloy_style_opener) {
|
|
// Creating a popup where the opener is Alloy style.
|
|
if (chrome_style_via_window_info &&
|
|
window_info->runtime_style == CEF_RUNTIME_STYLE_CHROME) {
|
|
// Only use Chrome style for the popup if the client explicitly sets
|
|
// CHROME (and not DEFAULT) via CefWindowInfo.runtime_style.
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if (browser_view) {
|
|
// Must match the BrowserView style. GetRuntimeStyle() will not return
|
|
// DEFAULT.
|
|
return browser_view->GetRuntimeStyle() == CEF_RUNTIME_STYLE_CHROME;
|
|
}
|
|
|
|
// Chrome style does not support windowless rendering.
|
|
return chrome_style_via_window_info && !IsWindowless();
|
|
}
|
|
|
|
bool CefBrowserCreateParams::IsWindowless() const {
|
|
return window_info && window_info->windowless_rendering_enabled && client &&
|
|
client->GetRenderHandler().get();
|
|
}
|
|
|
|
// static
|
|
void CefBrowserCreateParams::InitWindowInfo(CefWindowInfo* window_info,
|
|
CefBrowserHostBase* opener) {
|
|
#if BUILDFLAG(IS_WIN)
|
|
window_info->SetAsPopup(nullptr, CefString());
|
|
#endif
|
|
|
|
if (cef::IsChromeRuntimeEnabled() && opener->IsAlloyStyle()) {
|
|
// Give the popup the same runtime style as the opener.
|
|
window_info->runtime_style = CEF_RUNTIME_STYLE_ALLOY;
|
|
}
|
|
}
|
|
|
|
void CefBrowserCreateParams::MaybeSetWindowInfo(
|
|
const CefWindowInfo& new_window_info,
|
|
bool allow_alloy_style,
|
|
bool allow_chrome_style) {
|
|
if (!cef::IsChromeRuntimeEnabled()) {
|
|
// Chrome style is not supported wih the Alloy bootstrap.
|
|
allow_chrome_style = false;
|
|
}
|
|
|
|
if (allow_chrome_style && new_window_info.windowless_rendering_enabled) {
|
|
// Chrome style is not supported with windowles rendering.
|
|
allow_chrome_style = false;
|
|
}
|
|
|
|
#if BUILDFLAG(IS_MAC)
|
|
if (allow_chrome_style &&
|
|
chrome_child_window::HasParentHandle(new_window_info)) {
|
|
// Chrome style is not supported with native parent on MacOS. See issue
|
|
// #3294.
|
|
allow_chrome_style = false;
|
|
}
|
|
#endif
|
|
|
|
DCHECK(allow_alloy_style || allow_chrome_style);
|
|
|
|
bool reset_style = false;
|
|
if (new_window_info.runtime_style == CEF_RUNTIME_STYLE_ALLOY &&
|
|
!allow_alloy_style) {
|
|
LOG(ERROR) << "Alloy style is not supported for this browser";
|
|
reset_style = true;
|
|
} else if (new_window_info.runtime_style == CEF_RUNTIME_STYLE_CHROME &&
|
|
!allow_chrome_style) {
|
|
LOG(ERROR) << "Chrome style is not supported for this browser";
|
|
reset_style = true;
|
|
}
|
|
|
|
const bool is_chrome_style =
|
|
allow_chrome_style && IsChromeStyle(&new_window_info);
|
|
if (!is_chrome_style ||
|
|
chrome_child_window::HasParentHandle(new_window_info)) {
|
|
window_info = std::make_unique<CefWindowInfo>(new_window_info);
|
|
if (cef::IsChromeRuntimeEnabled() && !allow_chrome_style) {
|
|
// Only Alloy style is allowed.
|
|
window_info->runtime_style = CEF_RUNTIME_STYLE_ALLOY;
|
|
} else if (reset_style) {
|
|
// Use the default style.
|
|
window_info->runtime_style = CEF_RUNTIME_STYLE_DEFAULT;
|
|
}
|
|
}
|
|
}
|
|
|
|
// static
|
|
CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::Create(
|
|
CefBrowserCreateParams& create_params) {
|
|
if (create_params.IsChromeStyle()) {
|
|
if (auto browser =
|
|
chrome_child_window::MaybeCreateChildBrowser(create_params)) {
|
|
return browser.get();
|
|
}
|
|
auto browser = ChromeBrowserHostImpl::Create(create_params);
|
|
return browser.get();
|
|
}
|
|
|
|
auto browser = AlloyBrowserHostImpl::Create(create_params);
|
|
return browser.get();
|
|
}
|