mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-20 14:10:40 +01:00
This is no longer required now that we have implicit exclusion of certain frame types including guest view frames. Rename GuestView to ExcludedView in the renderer process.
1418 lines
40 KiB
C++
1418 lines
40 KiB
C++
// Copyright 2020 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 "libcef/browser/browser_host_base.h"
|
|
|
|
#include <tuple>
|
|
|
|
#include "libcef/browser/browser_info_manager.h"
|
|
#include "libcef/browser/browser_platform_delegate.h"
|
|
#include "libcef/browser/context.h"
|
|
#include "libcef/browser/extensions/browser_extensions_util.h"
|
|
#include "libcef/browser/hang_monitor.h"
|
|
#include "libcef/browser/image_impl.h"
|
|
#include "libcef/browser/navigation_entry_impl.h"
|
|
#include "libcef/browser/printing/print_util.h"
|
|
#include "libcef/browser/thread_util.h"
|
|
#include "libcef/common/frame_util.h"
|
|
#include "libcef/common/net/url_util.h"
|
|
|
|
#include "base/logging.h"
|
|
#include "chrome/browser/platform_util.h"
|
|
#include "chrome/browser/spellchecker/spellcheck_factory.h"
|
|
#include "chrome/browser/spellchecker/spellcheck_service.h"
|
|
#include "chrome/browser/ui/browser_commands.h"
|
|
#include "components/favicon/core/favicon_url.h"
|
|
#include "components/spellcheck/common/spellcheck_features.h"
|
|
#include "components/zoom/page_zoom.h"
|
|
#include "components/zoom/zoom_controller.h"
|
|
#include "content/browser/renderer_host/render_frame_host_impl.h"
|
|
#include "content/public/browser/browser_context.h"
|
|
#include "content/public/browser/download_manager.h"
|
|
#include "content/public/browser/download_request_utils.h"
|
|
#include "content/public/browser/file_select_listener.h"
|
|
#include "content/public/browser/navigation_entry.h"
|
|
#include "content/public/browser/render_view_host.h"
|
|
#include "content/public/browser/render_widget_host.h"
|
|
#include "ui/base/resource/resource_scale_factor.h"
|
|
#include "ui/gfx/image/image_skia.h"
|
|
#include "ui/shell_dialogs/select_file_policy.h"
|
|
|
|
#if BUILDFLAG(IS_MAC)
|
|
#include "components/spellcheck/browser/spellcheck_platform.h"
|
|
#endif
|
|
|
|
namespace {
|
|
|
|
// Associates a CefBrowserHostBase instance with a WebContents. This object will
|
|
// be deleted automatically when the WebContents is destroyed.
|
|
class WebContentsUserDataAdapter : public base::SupportsUserData::Data {
|
|
public:
|
|
static void Register(CefRefPtr<CefBrowserHostBase> browser) {
|
|
new WebContentsUserDataAdapter(browser);
|
|
}
|
|
|
|
static CefRefPtr<CefBrowserHostBase> Get(
|
|
const content::WebContents* web_contents) {
|
|
WebContentsUserDataAdapter* adapter =
|
|
static_cast<WebContentsUserDataAdapter*>(
|
|
web_contents->GetUserData(UserDataKey()));
|
|
if (adapter) {
|
|
return adapter->browser_;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
private:
|
|
explicit WebContentsUserDataAdapter(CefRefPtr<CefBrowserHostBase> browser)
|
|
: browser_(browser) {
|
|
auto web_contents = browser->GetWebContents();
|
|
DCHECK(web_contents);
|
|
web_contents->SetUserData(UserDataKey(), base::WrapUnique(this));
|
|
}
|
|
|
|
static void* UserDataKey() {
|
|
// We just need a unique constant. Use the address of a static that
|
|
// COMDAT folding won't touch in an optimizing linker.
|
|
static int data_key = 0;
|
|
return reinterpret_cast<void*>(&data_key);
|
|
}
|
|
|
|
CefRefPtr<CefBrowserHostBase> browser_;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
// static
|
|
CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::FromBrowser(
|
|
CefRefPtr<CefBrowser> browser) {
|
|
return static_cast<CefBrowserHostBase*>(browser.get());
|
|
}
|
|
|
|
// static
|
|
CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::GetBrowserForHost(
|
|
const content::RenderViewHost* host) {
|
|
DCHECK(host);
|
|
CEF_REQUIRE_UIT();
|
|
content::WebContents* web_contents = content::WebContents::FromRenderViewHost(
|
|
const_cast<content::RenderViewHost*>(host));
|
|
if (web_contents) {
|
|
return GetBrowserForContents(web_contents);
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
// static
|
|
CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::GetBrowserForHost(
|
|
const content::RenderFrameHost* host) {
|
|
DCHECK(host);
|
|
CEF_REQUIRE_UIT();
|
|
content::WebContents* web_contents =
|
|
content::WebContents::FromRenderFrameHost(
|
|
const_cast<content::RenderFrameHost*>(host));
|
|
if (web_contents) {
|
|
return GetBrowserForContents(web_contents);
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
// static
|
|
CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::GetBrowserForContents(
|
|
const content::WebContents* contents) {
|
|
DCHECK(contents);
|
|
CEF_REQUIRE_UIT();
|
|
if (auto browser = WebContentsUserDataAdapter::Get(contents)) {
|
|
return browser;
|
|
}
|
|
|
|
// Try the owner WebContents if |contents| originates from an excluded view
|
|
// such as the PDF viewer or Print Preview. This is safe to call even if Alloy
|
|
// extensions are disabled.
|
|
if (auto* owner_contents = extensions::GetOwnerForGuestContents(contents)) {
|
|
return WebContentsUserDataAdapter::Get(owner_contents);
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
// static
|
|
CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::GetBrowserForGlobalId(
|
|
const content::GlobalRenderFrameHostId& global_id) {
|
|
if (!frame_util::IsValidGlobalId(global_id)) {
|
|
return nullptr;
|
|
}
|
|
|
|
if (CEF_CURRENTLY_ON_UIT()) {
|
|
// Use the non-thread-safe but potentially faster approach.
|
|
content::RenderFrameHost* render_frame_host =
|
|
content::RenderFrameHost::FromID(global_id);
|
|
if (!render_frame_host) {
|
|
return nullptr;
|
|
}
|
|
return GetBrowserForHost(render_frame_host);
|
|
} else {
|
|
// Use the thread-safe approach.
|
|
auto info = CefBrowserInfoManager::GetInstance()->GetBrowserInfo(global_id);
|
|
if (info) {
|
|
auto browser = info->browser();
|
|
if (!browser) {
|
|
LOG(WARNING) << "Found browser id " << info->browser_id()
|
|
<< " but no browser object matching frame "
|
|
<< frame_util::GetFrameDebugString(global_id);
|
|
}
|
|
return browser;
|
|
}
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
// static
|
|
CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::GetBrowserForGlobalToken(
|
|
const content::GlobalRenderFrameHostToken& global_token) {
|
|
if (!frame_util::IsValidGlobalToken(global_token)) {
|
|
return nullptr;
|
|
}
|
|
|
|
if (CEF_CURRENTLY_ON_UIT()) {
|
|
// Use the non-thread-safe but potentially faster approach.
|
|
content::RenderFrameHost* render_frame_host =
|
|
content::RenderFrameHost::FromFrameToken(global_token);
|
|
if (!render_frame_host) {
|
|
return nullptr;
|
|
}
|
|
return GetBrowserForHost(render_frame_host);
|
|
} else {
|
|
// Use the thread-safe approach.
|
|
auto info =
|
|
CefBrowserInfoManager::GetInstance()->GetBrowserInfo(global_token);
|
|
if (info) {
|
|
auto browser = info->browser();
|
|
if (!browser) {
|
|
LOG(WARNING) << "Found browser id " << info->browser_id()
|
|
<< " but no browser object matching frame "
|
|
<< frame_util::GetFrameDebugString(global_token);
|
|
}
|
|
return browser;
|
|
}
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
// static
|
|
CefRefPtr<CefBrowserHostBase>
|
|
CefBrowserHostBase::GetBrowserForTopLevelNativeWindow(
|
|
gfx::NativeWindow owning_window) {
|
|
DCHECK(owning_window);
|
|
CEF_REQUIRE_UIT();
|
|
|
|
for (const auto& browser_info :
|
|
CefBrowserInfoManager::GetInstance()->GetBrowserInfoList()) {
|
|
if (auto browser = browser_info->browser()) {
|
|
if (browser->GetTopLevelNativeWindow() == owning_window) {
|
|
return browser;
|
|
}
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
// static
|
|
CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::GetLikelyFocusedBrowser() {
|
|
CEF_REQUIRE_UIT();
|
|
|
|
for (const auto& browser_info :
|
|
CefBrowserInfoManager::GetInstance()->GetBrowserInfoList()) {
|
|
if (auto browser = browser_info->browser()) {
|
|
if (browser->IsFocused()) {
|
|
return browser;
|
|
}
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
CefBrowserHostBase::CefBrowserHostBase(
|
|
const CefBrowserSettings& settings,
|
|
CefRefPtr<CefClient> client,
|
|
std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
|
|
scoped_refptr<CefBrowserInfo> browser_info,
|
|
CefRefPtr<CefRequestContextImpl> request_context)
|
|
: settings_(settings),
|
|
client_(client),
|
|
platform_delegate_(std::move(platform_delegate)),
|
|
browser_info_(browser_info),
|
|
request_context_(request_context),
|
|
is_views_hosted_(platform_delegate_->IsViewsHosted()) {
|
|
CEF_REQUIRE_UIT();
|
|
DCHECK(!browser_info_->browser().get());
|
|
browser_info_->SetBrowser(this);
|
|
|
|
contents_delegate_ =
|
|
std::make_unique<CefBrowserContentsDelegate>(browser_info_);
|
|
contents_delegate_->AddObserver(this);
|
|
}
|
|
|
|
void CefBrowserHostBase::InitializeBrowser() {
|
|
CEF_REQUIRE_UIT();
|
|
|
|
// Associate the WebContents with this browser object.
|
|
DCHECK(GetWebContents());
|
|
WebContentsUserDataAdapter::Register(this);
|
|
}
|
|
|
|
void CefBrowserHostBase::DestroyBrowser() {
|
|
CEF_REQUIRE_UIT();
|
|
|
|
devtools_protocol_manager_.reset();
|
|
devtools_window_runner_.reset();
|
|
media_stream_registrar_.reset();
|
|
|
|
platform_delegate_.reset();
|
|
|
|
contents_delegate_->RemoveObserver(this);
|
|
contents_delegate_->ObserveWebContents(nullptr);
|
|
|
|
if (unresponsive_process_callback_) {
|
|
hang_monitor::Detach(unresponsive_process_callback_);
|
|
unresponsive_process_callback_.reset();
|
|
}
|
|
|
|
CefBrowserInfoManager::GetInstance()->RemoveBrowserInfo(browser_info_);
|
|
browser_info_->SetBrowser(nullptr);
|
|
}
|
|
|
|
CefRefPtr<CefBrowser> CefBrowserHostBase::GetBrowser() {
|
|
return this;
|
|
}
|
|
|
|
CefRefPtr<CefClient> CefBrowserHostBase::GetClient() {
|
|
return client_;
|
|
}
|
|
|
|
CefRefPtr<CefRequestContext> CefBrowserHostBase::GetRequestContext() {
|
|
return request_context_;
|
|
}
|
|
|
|
bool CefBrowserHostBase::CanZoom(cef_zoom_command_t command) {
|
|
// Verify that this method is being called on the UI thread.
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
DCHECK(false) << "called on invalid thread";
|
|
return false;
|
|
}
|
|
|
|
if (auto web_contents = GetWebContents()) {
|
|
switch (command) {
|
|
case CEF_ZOOM_COMMAND_OUT:
|
|
return chrome::CanZoomOut(web_contents);
|
|
case CEF_ZOOM_COMMAND_RESET:
|
|
return chrome::CanResetZoom(web_contents);
|
|
case CEF_ZOOM_COMMAND_IN:
|
|
return chrome::CanZoomIn(web_contents);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void CefBrowserHostBase::Zoom(cef_zoom_command_t command) {
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(CEF_UIT,
|
|
base::BindOnce(&CefBrowserHostBase::Zoom, this, command));
|
|
return;
|
|
}
|
|
|
|
if (auto web_contents = GetWebContents()) {
|
|
const content::PageZoom page_zoom = [command]() {
|
|
switch (command) {
|
|
case CEF_ZOOM_COMMAND_OUT:
|
|
return content::PAGE_ZOOM_OUT;
|
|
case CEF_ZOOM_COMMAND_RESET:
|
|
return content::PAGE_ZOOM_RESET;
|
|
case CEF_ZOOM_COMMAND_IN:
|
|
return content::PAGE_ZOOM_IN;
|
|
}
|
|
}();
|
|
|
|
// Same implementation as chrome::Zoom(), but explicitly specifying the
|
|
// WebContents.
|
|
zoom::PageZoom::Zoom(web_contents, page_zoom);
|
|
}
|
|
}
|
|
|
|
double CefBrowserHostBase::GetDefaultZoomLevel() {
|
|
// Verify that this method is being called on the UI thread.
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
DCHECK(false) << "called on invalid thread";
|
|
return 0.0;
|
|
}
|
|
|
|
if (auto web_contents = GetWebContents()) {
|
|
zoom::ZoomController* zoom_controller =
|
|
zoom::ZoomController::FromWebContents(web_contents);
|
|
if (zoom_controller) {
|
|
return zoom_controller->GetDefaultZoomLevel();
|
|
}
|
|
}
|
|
|
|
return 0.0;
|
|
}
|
|
|
|
double CefBrowserHostBase::GetZoomLevel() {
|
|
// Verify that this method is being called on the UI thread.
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
DCHECK(false) << "called on invalid thread";
|
|
return 0.0;
|
|
}
|
|
|
|
if (auto web_contents = GetWebContents()) {
|
|
zoom::ZoomController* zoom_controller =
|
|
zoom::ZoomController::FromWebContents(web_contents);
|
|
if (zoom_controller) {
|
|
return zoom_controller->GetZoomLevel();
|
|
}
|
|
}
|
|
|
|
return 0.0;
|
|
}
|
|
|
|
void CefBrowserHostBase::SetZoomLevel(double zoomLevel) {
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostBase::SetZoomLevel,
|
|
this, zoomLevel));
|
|
return;
|
|
}
|
|
|
|
if (auto web_contents = GetWebContents()) {
|
|
zoom::ZoomController* zoom_controller =
|
|
zoom::ZoomController::FromWebContents(web_contents);
|
|
if (zoom_controller) {
|
|
if (zoomLevel == 0.0) {
|
|
// Same logic as PageZoom::Zoom(PAGE_ZOOM_RESET).
|
|
zoomLevel = zoom_controller->GetDefaultZoomLevel();
|
|
web_contents->SetPageScale(1.f);
|
|
}
|
|
zoom_controller->SetZoomLevel(zoomLevel);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CefBrowserHostBase::HasView() {
|
|
return is_views_hosted_;
|
|
}
|
|
|
|
void CefBrowserHostBase::SetFocus(bool focus) {
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(CEF_UIT,
|
|
base::BindOnce(&CefBrowserHostBase::SetFocus, this, focus));
|
|
return;
|
|
}
|
|
|
|
if (focus) {
|
|
OnSetFocus(FOCUS_SOURCE_SYSTEM);
|
|
} else if (platform_delegate_) {
|
|
platform_delegate_->SetFocus(false);
|
|
}
|
|
}
|
|
|
|
void CefBrowserHostBase::RunFileDialog(
|
|
FileDialogMode mode,
|
|
const CefString& title,
|
|
const CefString& default_file_path,
|
|
const std::vector<CefString>& accept_filters,
|
|
CefRefPtr<CefRunFileDialogCallback> callback) {
|
|
DCHECK(callback);
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostBase::RunFileDialog,
|
|
this, mode, title, default_file_path,
|
|
accept_filters, callback));
|
|
return;
|
|
}
|
|
|
|
if (!callback || !EnsureFileDialogManager()) {
|
|
LOG(ERROR) << "File dialog canceled due to invalid state.";
|
|
if (callback) {
|
|
callback->OnFileDialogDismissed({});
|
|
}
|
|
return;
|
|
}
|
|
|
|
file_dialog_manager_->RunFileDialog(mode, title, default_file_path,
|
|
accept_filters, callback);
|
|
}
|
|
|
|
void CefBrowserHostBase::StartDownload(const CefString& url) {
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(
|
|
CEF_UIT, base::BindOnce(&CefBrowserHostBase::StartDownload, this, url));
|
|
return;
|
|
}
|
|
|
|
GURL gurl = GURL(url.ToString());
|
|
if (gurl.is_empty() || !gurl.is_valid()) {
|
|
return;
|
|
}
|
|
|
|
auto web_contents = GetWebContents();
|
|
if (!web_contents) {
|
|
return;
|
|
}
|
|
|
|
auto browser_context = web_contents->GetBrowserContext();
|
|
if (!browser_context) {
|
|
return;
|
|
}
|
|
|
|
content::DownloadManager* manager = browser_context->GetDownloadManager();
|
|
if (!manager) {
|
|
return;
|
|
}
|
|
|
|
std::unique_ptr<download::DownloadUrlParameters> params(
|
|
content::DownloadRequestUtils::CreateDownloadForWebContentsMainFrame(
|
|
web_contents, gurl, MISSING_TRAFFIC_ANNOTATION));
|
|
manager->DownloadUrl(std::move(params));
|
|
}
|
|
|
|
void CefBrowserHostBase::DownloadImage(
|
|
const CefString& image_url,
|
|
bool is_favicon,
|
|
uint32_t max_image_size,
|
|
bool bypass_cache,
|
|
CefRefPtr<CefDownloadImageCallback> callback) {
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(
|
|
CEF_UIT,
|
|
base::BindOnce(&CefBrowserHostBase::DownloadImage, this, image_url,
|
|
is_favicon, max_image_size, bypass_cache, callback));
|
|
return;
|
|
}
|
|
|
|
if (!callback) {
|
|
return;
|
|
}
|
|
|
|
GURL gurl = GURL(image_url.ToString());
|
|
if (gurl.is_empty() || !gurl.is_valid()) {
|
|
return;
|
|
}
|
|
|
|
auto web_contents = GetWebContents();
|
|
if (!web_contents) {
|
|
return;
|
|
}
|
|
|
|
const float scale = ui::GetScaleForMaxSupportedResourceScaleFactor();
|
|
web_contents->DownloadImage(
|
|
gurl, is_favicon, gfx::Size(max_image_size, max_image_size),
|
|
max_image_size * scale, bypass_cache,
|
|
base::BindOnce(
|
|
[](uint32_t max_image_size,
|
|
CefRefPtr<CefDownloadImageCallback> callback, int id,
|
|
int http_status_code, const GURL& image_url,
|
|
const std::vector<SkBitmap>& bitmaps,
|
|
const std::vector<gfx::Size>& sizes) {
|
|
CEF_REQUIRE_UIT();
|
|
|
|
CefRefPtr<CefImageImpl> image_impl;
|
|
|
|
if (!bitmaps.empty()) {
|
|
image_impl = new CefImageImpl();
|
|
image_impl->AddBitmaps(max_image_size, bitmaps);
|
|
}
|
|
|
|
callback->OnDownloadImageFinished(
|
|
image_url.spec(), http_status_code, image_impl.get());
|
|
},
|
|
max_image_size, callback));
|
|
}
|
|
|
|
void CefBrowserHostBase::Print() {
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostBase::Print, this));
|
|
return;
|
|
}
|
|
|
|
auto web_contents = GetWebContents();
|
|
if (!web_contents) {
|
|
return;
|
|
}
|
|
|
|
const bool print_preview_disabled =
|
|
!platform_delegate_ || !platform_delegate_->IsPrintPreviewSupported();
|
|
print_util::Print(web_contents, print_preview_disabled);
|
|
}
|
|
|
|
void CefBrowserHostBase::PrintToPDF(const CefString& path,
|
|
const CefPdfPrintSettings& settings,
|
|
CefRefPtr<CefPdfPrintCallback> callback) {
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostBase::PrintToPDF, this,
|
|
path, settings, callback));
|
|
return;
|
|
}
|
|
|
|
auto web_contents = GetWebContents();
|
|
if (!web_contents) {
|
|
return;
|
|
}
|
|
|
|
print_util::PrintToPDF(web_contents, path, settings, callback);
|
|
}
|
|
|
|
void CefBrowserHostBase::ShowDevTools(const CefWindowInfo& windowInfo,
|
|
CefRefPtr<CefClient> client,
|
|
const CefBrowserSettings& settings,
|
|
const CefPoint& inspect_element_at) {
|
|
auto params = std::make_unique<CefShowDevToolsParams>(
|
|
windowInfo, client, settings, inspect_element_at);
|
|
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(CEF_UIT,
|
|
base::BindOnce(&CefBrowserHostBase::ShowDevToolsOnUIThread,
|
|
this, std::move(params)));
|
|
} else {
|
|
ShowDevToolsOnUIThread(std::move(params));
|
|
}
|
|
}
|
|
|
|
void CefBrowserHostBase::CloseDevTools() {
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(CEF_UIT,
|
|
base::BindOnce(&CefBrowserHostBase::CloseDevTools, this));
|
|
return;
|
|
}
|
|
|
|
if (devtools_window_runner_) {
|
|
devtools_window_runner_->CloseDevTools();
|
|
}
|
|
}
|
|
|
|
bool CefBrowserHostBase::HasDevTools() {
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
DCHECK(false) << "called on invalid thread";
|
|
return false;
|
|
}
|
|
|
|
if (devtools_window_runner_) {
|
|
return devtools_window_runner_->HasDevTools();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CefBrowserHostBase::SendDevToolsMessage(const void* message,
|
|
size_t message_size) {
|
|
if (!message || message_size == 0) {
|
|
return false;
|
|
}
|
|
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
std::string message_str(static_cast<const char*>(message), message_size);
|
|
CEF_POST_TASK(
|
|
CEF_UIT,
|
|
base::BindOnce(
|
|
[](CefRefPtr<CefBrowserHostBase> self, std::string message_str) {
|
|
self->SendDevToolsMessage(message_str.data(), message_str.size());
|
|
},
|
|
CefRefPtr<CefBrowserHostBase>(this), std::move(message_str)));
|
|
return false;
|
|
}
|
|
|
|
if (!EnsureDevToolsProtocolManager()) {
|
|
return false;
|
|
}
|
|
return devtools_protocol_manager_->SendDevToolsMessage(message, message_size);
|
|
}
|
|
|
|
int CefBrowserHostBase::ExecuteDevToolsMethod(
|
|
int message_id,
|
|
const CefString& method,
|
|
CefRefPtr<CefDictionaryValue> params) {
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(
|
|
CEF_UIT, base::BindOnce(base::IgnoreResult(
|
|
&CefBrowserHostBase::ExecuteDevToolsMethod),
|
|
this, message_id, method, params));
|
|
return 0;
|
|
}
|
|
|
|
if (!EnsureDevToolsProtocolManager()) {
|
|
return 0;
|
|
}
|
|
return devtools_protocol_manager_->ExecuteDevToolsMethod(message_id, method,
|
|
params);
|
|
}
|
|
|
|
CefRefPtr<CefRegistration> CefBrowserHostBase::AddDevToolsMessageObserver(
|
|
CefRefPtr<CefDevToolsMessageObserver> observer) {
|
|
if (!observer) {
|
|
return nullptr;
|
|
}
|
|
auto registration = CefDevToolsProtocolManager::CreateRegistration(observer);
|
|
InitializeDevToolsRegistrationOnUIThread(registration);
|
|
return registration.get();
|
|
}
|
|
|
|
void CefBrowserHostBase::GetNavigationEntries(
|
|
CefRefPtr<CefNavigationEntryVisitor> visitor,
|
|
bool current_only) {
|
|
DCHECK(visitor.get());
|
|
if (!visitor.get()) {
|
|
return;
|
|
}
|
|
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(
|
|
CEF_UIT, base::BindOnce(&CefBrowserHostBase::GetNavigationEntries, this,
|
|
visitor, current_only));
|
|
return;
|
|
}
|
|
|
|
auto web_contents = GetWebContents();
|
|
if (!web_contents) {
|
|
return;
|
|
}
|
|
|
|
content::NavigationController& controller = web_contents->GetController();
|
|
const int total = controller.GetEntryCount();
|
|
const int current = controller.GetCurrentEntryIndex();
|
|
|
|
if (current_only) {
|
|
// Visit only the current entry.
|
|
CefRefPtr<CefNavigationEntryImpl> entry =
|
|
new CefNavigationEntryImpl(controller.GetEntryAtIndex(current));
|
|
visitor->Visit(entry.get(), true, current, total);
|
|
std::ignore = entry->Detach(nullptr);
|
|
} else {
|
|
// Visit all entries.
|
|
bool cont = true;
|
|
for (int i = 0; i < total && cont; ++i) {
|
|
CefRefPtr<CefNavigationEntryImpl> entry =
|
|
new CefNavigationEntryImpl(controller.GetEntryAtIndex(i));
|
|
cont = visitor->Visit(entry.get(), (i == current), i, total);
|
|
std::ignore = entry->Detach(nullptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
CefRefPtr<CefNavigationEntry> CefBrowserHostBase::GetVisibleNavigationEntry() {
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
DCHECK(false) << "called on invalid thread";
|
|
return nullptr;
|
|
}
|
|
|
|
content::NavigationEntry* entry = nullptr;
|
|
auto web_contents = GetWebContents();
|
|
if (web_contents) {
|
|
entry = web_contents->GetController().GetVisibleEntry();
|
|
}
|
|
|
|
if (!entry) {
|
|
return nullptr;
|
|
}
|
|
|
|
return new CefNavigationEntryImpl(entry);
|
|
}
|
|
|
|
void CefBrowserHostBase::NotifyMoveOrResizeStarted() {
|
|
#if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC))
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(
|
|
CEF_UIT,
|
|
base::BindOnce(&CefBrowserHostBase::NotifyMoveOrResizeStarted, this));
|
|
return;
|
|
}
|
|
|
|
if (platform_delegate_) {
|
|
platform_delegate_->NotifyMoveOrResizeStarted();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
bool CefBrowserHostBase::IsFullscreen() {
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
DCHECK(false) << "called on invalid thread";
|
|
return false;
|
|
}
|
|
|
|
if (auto web_contents = GetWebContents()) {
|
|
return web_contents->IsFullscreen();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void CefBrowserHostBase::ExitFullscreen(bool will_cause_resize) {
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostBase::ExitFullscreen,
|
|
this, will_cause_resize));
|
|
return;
|
|
}
|
|
|
|
auto web_contents = GetWebContents();
|
|
if (web_contents && web_contents->IsFullscreen()) {
|
|
web_contents->ExitFullscreen(will_cause_resize);
|
|
}
|
|
}
|
|
|
|
bool CefBrowserHostBase::IsRenderProcessUnresponsive() {
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
DCHECK(false) << "called on invalid thread";
|
|
return false;
|
|
}
|
|
|
|
if (auto* web_contents = GetWebContents()) {
|
|
if (auto* rvh = web_contents->GetRenderViewHost()) {
|
|
if (auto* rwh = rvh->GetWidget()) {
|
|
return rwh->IsCurrentlyUnresponsive();
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
cef_runtime_style_t CefBrowserHostBase::GetRuntimeStyle() {
|
|
return IsAlloyStyle() ? CEF_RUNTIME_STYLE_ALLOY : CEF_RUNTIME_STYLE_CHROME;
|
|
}
|
|
|
|
void CefBrowserHostBase::ReplaceMisspelling(const CefString& word) {
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(
|
|
CEF_UIT,
|
|
base::BindOnce(&CefBrowserHostBase::ReplaceMisspelling, this, word));
|
|
return;
|
|
}
|
|
|
|
auto web_contents = GetWebContents();
|
|
if (web_contents) {
|
|
web_contents->ReplaceMisspelling(word);
|
|
}
|
|
}
|
|
|
|
void CefBrowserHostBase::AddWordToDictionary(const CefString& word) {
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(
|
|
CEF_UIT,
|
|
base::BindOnce(&CefBrowserHostBase::AddWordToDictionary, this, word));
|
|
return;
|
|
}
|
|
|
|
auto web_contents = GetWebContents();
|
|
if (!web_contents) {
|
|
return;
|
|
}
|
|
|
|
SpellcheckService* spellcheck = nullptr;
|
|
content::BrowserContext* browser_context = web_contents->GetBrowserContext();
|
|
if (browser_context) {
|
|
spellcheck = SpellcheckServiceFactory::GetForContext(browser_context);
|
|
if (spellcheck) {
|
|
spellcheck->GetCustomDictionary()->AddWord(word);
|
|
}
|
|
}
|
|
#if BUILDFLAG(IS_MAC)
|
|
if (spellcheck && spellcheck::UseBrowserSpellChecker()) {
|
|
spellcheck_platform::AddWord(spellcheck->platform_spell_checker(), word);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void CefBrowserHostBase::SendKeyEvent(const CefKeyEvent& event) {
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostBase::SendKeyEvent,
|
|
this, event));
|
|
return;
|
|
}
|
|
|
|
if (platform_delegate_) {
|
|
platform_delegate_->SendKeyEvent(event);
|
|
}
|
|
}
|
|
|
|
void CefBrowserHostBase::SendMouseClickEvent(const CefMouseEvent& event,
|
|
MouseButtonType type,
|
|
bool mouseUp,
|
|
int clickCount) {
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(CEF_UIT,
|
|
base::BindOnce(&CefBrowserHostBase::SendMouseClickEvent, this,
|
|
event, type, mouseUp, clickCount));
|
|
return;
|
|
}
|
|
|
|
if (platform_delegate_) {
|
|
platform_delegate_->SendMouseClickEvent(event, type, mouseUp, clickCount);
|
|
}
|
|
}
|
|
|
|
void CefBrowserHostBase::SendMouseMoveEvent(const CefMouseEvent& event,
|
|
bool mouseLeave) {
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(CEF_UIT,
|
|
base::BindOnce(&CefBrowserHostBase::SendMouseMoveEvent, this,
|
|
event, mouseLeave));
|
|
return;
|
|
}
|
|
|
|
if (platform_delegate_) {
|
|
platform_delegate_->SendMouseMoveEvent(event, mouseLeave);
|
|
}
|
|
}
|
|
|
|
void CefBrowserHostBase::SendMouseWheelEvent(const CefMouseEvent& event,
|
|
int deltaX,
|
|
int deltaY) {
|
|
if (deltaX == 0 && deltaY == 0) {
|
|
// Nothing to do.
|
|
return;
|
|
}
|
|
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(CEF_UIT,
|
|
base::BindOnce(&CefBrowserHostBase::SendMouseWheelEvent, this,
|
|
event, deltaX, deltaY));
|
|
return;
|
|
}
|
|
|
|
if (platform_delegate_) {
|
|
platform_delegate_->SendMouseWheelEvent(event, deltaX, deltaY);
|
|
}
|
|
}
|
|
|
|
bool CefBrowserHostBase::IsValid() {
|
|
return browser_info_->browser() == this;
|
|
}
|
|
|
|
CefRefPtr<CefBrowserHost> CefBrowserHostBase::GetHost() {
|
|
return this;
|
|
}
|
|
|
|
bool CefBrowserHostBase::CanGoBack() {
|
|
base::AutoLock lock_scope(state_lock_);
|
|
return can_go_back_;
|
|
}
|
|
|
|
void CefBrowserHostBase::GoBack() {
|
|
auto callback = base::BindOnce(&CefBrowserHostBase::GoBack, this);
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(CEF_UIT, std::move(callback));
|
|
return;
|
|
}
|
|
|
|
if (browser_info_->IsNavigationLocked(std::move(callback))) {
|
|
return;
|
|
}
|
|
|
|
auto wc = GetWebContents();
|
|
if (wc && wc->GetController().CanGoBack()) {
|
|
wc->GetController().GoBack();
|
|
}
|
|
}
|
|
|
|
bool CefBrowserHostBase::CanGoForward() {
|
|
base::AutoLock lock_scope(state_lock_);
|
|
return can_go_forward_;
|
|
}
|
|
|
|
void CefBrowserHostBase::GoForward() {
|
|
auto callback = base::BindOnce(&CefBrowserHostBase::GoForward, this);
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(CEF_UIT, std::move(callback));
|
|
return;
|
|
}
|
|
|
|
if (browser_info_->IsNavigationLocked(std::move(callback))) {
|
|
return;
|
|
}
|
|
|
|
auto wc = GetWebContents();
|
|
if (wc && wc->GetController().CanGoForward()) {
|
|
wc->GetController().GoForward();
|
|
}
|
|
}
|
|
|
|
bool CefBrowserHostBase::IsLoading() {
|
|
base::AutoLock lock_scope(state_lock_);
|
|
return is_loading_;
|
|
}
|
|
|
|
void CefBrowserHostBase::Reload() {
|
|
auto callback = base::BindOnce(&CefBrowserHostBase::Reload, this);
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(CEF_UIT, std::move(callback));
|
|
return;
|
|
}
|
|
|
|
if (browser_info_->IsNavigationLocked(std::move(callback))) {
|
|
return;
|
|
}
|
|
|
|
auto wc = GetWebContents();
|
|
if (wc) {
|
|
wc->GetController().Reload(content::ReloadType::NORMAL, true);
|
|
}
|
|
}
|
|
|
|
void CefBrowserHostBase::ReloadIgnoreCache() {
|
|
auto callback = base::BindOnce(&CefBrowserHostBase::ReloadIgnoreCache, this);
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(CEF_UIT, std::move(callback));
|
|
return;
|
|
}
|
|
|
|
if (browser_info_->IsNavigationLocked(std::move(callback))) {
|
|
return;
|
|
}
|
|
|
|
auto wc = GetWebContents();
|
|
if (wc) {
|
|
wc->GetController().Reload(content::ReloadType::BYPASSING_CACHE, true);
|
|
}
|
|
}
|
|
|
|
void CefBrowserHostBase::StopLoad() {
|
|
auto callback = base::BindOnce(&CefBrowserHostBase::StopLoad, this);
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(CEF_UIT, std::move(callback));
|
|
return;
|
|
}
|
|
|
|
if (browser_info_->IsNavigationLocked(std::move(callback))) {
|
|
return;
|
|
}
|
|
|
|
auto wc = GetWebContents();
|
|
if (wc) {
|
|
wc->Stop();
|
|
}
|
|
}
|
|
|
|
int CefBrowserHostBase::GetIdentifier() {
|
|
return browser_id();
|
|
}
|
|
|
|
bool CefBrowserHostBase::IsSame(CefRefPtr<CefBrowser> that) {
|
|
auto impl = FromBrowser(that);
|
|
return (impl.get() == this);
|
|
}
|
|
|
|
bool CefBrowserHostBase::HasDocument() {
|
|
base::AutoLock lock_scope(state_lock_);
|
|
return has_document_;
|
|
}
|
|
|
|
bool CefBrowserHostBase::IsPopup() {
|
|
return browser_info_->is_popup();
|
|
}
|
|
|
|
CefRefPtr<CefFrame> CefBrowserHostBase::GetMainFrame() {
|
|
return browser_info_->GetMainFrame();
|
|
}
|
|
|
|
CefRefPtr<CefFrame> CefBrowserHostBase::GetFocusedFrame() {
|
|
{
|
|
base::AutoLock lock_scope(state_lock_);
|
|
if (focused_frame_) {
|
|
return focused_frame_;
|
|
}
|
|
}
|
|
|
|
// The main frame is focused by default.
|
|
return browser_info_->GetMainFrame();
|
|
}
|
|
|
|
CefRefPtr<CefFrame> CefBrowserHostBase::GetFrameByIdentifier(
|
|
const CefString& identifier) {
|
|
const auto& global_token = frame_util::ParseFrameIdentifier(identifier);
|
|
if (!global_token) {
|
|
return nullptr;
|
|
}
|
|
|
|
return browser_info_->GetFrameForGlobalToken(*global_token);
|
|
}
|
|
|
|
CefRefPtr<CefFrame> CefBrowserHostBase::GetFrameByName(const CefString& name) {
|
|
for (const auto& frame : browser_info_->GetAllFrames()) {
|
|
if (frame->GetName() == name) {
|
|
return frame;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
size_t CefBrowserHostBase::GetFrameCount() {
|
|
return browser_info_->GetAllFrames().size();
|
|
}
|
|
|
|
void CefBrowserHostBase::GetFrameIdentifiers(
|
|
std::vector<CefString>& identifiers) {
|
|
if (identifiers.size() > 0) {
|
|
identifiers.clear();
|
|
}
|
|
|
|
const auto frames = browser_info_->GetAllFrames();
|
|
if (frames.empty()) {
|
|
return;
|
|
}
|
|
|
|
identifiers.reserve(frames.size());
|
|
for (const auto& frame : frames) {
|
|
identifiers.push_back(frame->GetIdentifier());
|
|
}
|
|
}
|
|
|
|
void CefBrowserHostBase::GetFrameNames(std::vector<CefString>& names) {
|
|
if (names.size() > 0) {
|
|
names.clear();
|
|
}
|
|
|
|
const auto frames = browser_info_->GetAllFrames();
|
|
if (frames.empty()) {
|
|
return;
|
|
}
|
|
|
|
names.reserve(frames.size());
|
|
for (const auto& frame : frames) {
|
|
names.push_back(frame->GetName());
|
|
}
|
|
}
|
|
|
|
void CefBrowserHostBase::SetAccessibilityState(
|
|
cef_state_t accessibility_state) {
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(CEF_UIT,
|
|
base::BindOnce(&CefBrowserHostBase::SetAccessibilityState,
|
|
this, accessibility_state));
|
|
return;
|
|
}
|
|
|
|
if (platform_delegate_) {
|
|
platform_delegate_->SetAccessibilityState(accessibility_state);
|
|
}
|
|
}
|
|
|
|
void CefBrowserHostBase::OnStateChanged(CefBrowserContentsState state_changed) {
|
|
// Make sure that CefBrowser state is consistent before the associated
|
|
// CefClient callback is executed.
|
|
base::AutoLock lock_scope(state_lock_);
|
|
if ((state_changed & CefBrowserContentsState::kNavigation) ==
|
|
CefBrowserContentsState::kNavigation) {
|
|
is_loading_ = contents_delegate_->is_loading();
|
|
can_go_back_ = contents_delegate_->can_go_back();
|
|
can_go_forward_ = contents_delegate_->can_go_forward();
|
|
}
|
|
if ((state_changed & CefBrowserContentsState::kDocument) ==
|
|
CefBrowserContentsState::kDocument) {
|
|
has_document_ = contents_delegate_->has_document();
|
|
}
|
|
if ((state_changed & CefBrowserContentsState::kFullscreen) ==
|
|
CefBrowserContentsState::kFullscreen) {
|
|
is_fullscreen_ = contents_delegate_->is_fullscreen();
|
|
}
|
|
if ((state_changed & CefBrowserContentsState::kFocusedFrame) ==
|
|
CefBrowserContentsState::kFocusedFrame) {
|
|
focused_frame_ = contents_delegate_->focused_frame();
|
|
}
|
|
}
|
|
|
|
void CefBrowserHostBase::OnWebContentsDestroyed(
|
|
content::WebContents* web_contents) {}
|
|
|
|
CefRefPtr<CefFrame> CefBrowserHostBase::GetFrameForHost(
|
|
const content::RenderFrameHost* host) {
|
|
CEF_REQUIRE_UIT();
|
|
if (!host) {
|
|
return nullptr;
|
|
}
|
|
|
|
return browser_info_->GetFrameForHost(host);
|
|
}
|
|
|
|
CefRefPtr<CefFrame> CefBrowserHostBase::GetFrameForGlobalId(
|
|
const content::GlobalRenderFrameHostId& global_id) {
|
|
return browser_info_->GetFrameForGlobalId(global_id);
|
|
}
|
|
|
|
CefRefPtr<CefFrame> CefBrowserHostBase::GetFrameForGlobalToken(
|
|
const content::GlobalRenderFrameHostToken& global_token) {
|
|
return browser_info_->GetFrameForGlobalToken(global_token);
|
|
}
|
|
|
|
void CefBrowserHostBase::AddObserver(Observer* observer) {
|
|
CEF_REQUIRE_UIT();
|
|
observers_.AddObserver(observer);
|
|
}
|
|
|
|
void CefBrowserHostBase::RemoveObserver(Observer* observer) {
|
|
CEF_REQUIRE_UIT();
|
|
observers_.RemoveObserver(observer);
|
|
}
|
|
|
|
bool CefBrowserHostBase::HasObserver(Observer* observer) const {
|
|
CEF_REQUIRE_UIT();
|
|
return observers_.HasObserver(observer);
|
|
}
|
|
|
|
void CefBrowserHostBase::LoadMainFrameURL(
|
|
const content::OpenURLParams& params) {
|
|
auto callback =
|
|
base::BindOnce(&CefBrowserHostBase::LoadMainFrameURL, this, params);
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(CEF_UIT, std::move(callback));
|
|
return;
|
|
}
|
|
|
|
if (browser_info_->IsNavigationLocked(std::move(callback))) {
|
|
return;
|
|
}
|
|
|
|
if (Navigate(params)) {
|
|
OnSetFocus(FOCUS_SOURCE_NAVIGATION);
|
|
}
|
|
}
|
|
|
|
bool CefBrowserHostBase::Navigate(const content::OpenURLParams& params) {
|
|
CEF_REQUIRE_UIT();
|
|
auto web_contents = GetWebContents();
|
|
if (web_contents) {
|
|
GURL gurl = params.url;
|
|
if (!url_util::FixupGURL(gurl)) {
|
|
return false;
|
|
}
|
|
|
|
web_contents->GetController().LoadURL(
|
|
gurl, params.referrer, params.transition, params.extra_headers);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void CefBrowserHostBase::ShowDevToolsOnUIThread(
|
|
std::unique_ptr<CefShowDevToolsParams> params) {
|
|
CEF_REQUIRE_UIT();
|
|
GetDevToolsWindowRunner()->ShowDevTools(this, std::move(params));
|
|
}
|
|
|
|
void CefBrowserHostBase::ViewText(const std::string& text) {
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(CEF_UIT,
|
|
base::BindOnce(&CefBrowserHostBase::ViewText, this, text));
|
|
return;
|
|
}
|
|
|
|
if (platform_delegate_) {
|
|
platform_delegate_->ViewText(text);
|
|
}
|
|
}
|
|
|
|
void CefBrowserHostBase::RunFileChooserForBrowser(
|
|
const blink::mojom::FileChooserParams& params,
|
|
CefFileDialogManager::RunFileChooserCallback callback) {
|
|
if (!EnsureFileDialogManager()) {
|
|
LOG(ERROR) << "File dialog canceled due to invalid state.";
|
|
std::move(callback).Run({});
|
|
return;
|
|
}
|
|
file_dialog_manager_->RunFileChooser(params, std::move(callback));
|
|
}
|
|
|
|
void CefBrowserHostBase::RunSelectFile(
|
|
ui::SelectFileDialog::Listener* listener,
|
|
std::unique_ptr<ui::SelectFilePolicy> policy,
|
|
ui::SelectFileDialog::Type type,
|
|
const std::u16string& title,
|
|
const base::FilePath& default_path,
|
|
const ui::SelectFileDialog::FileTypeInfo* file_types,
|
|
int file_type_index,
|
|
const base::FilePath::StringType& default_extension,
|
|
gfx::NativeWindow owning_window,
|
|
void* params) {
|
|
if (!EnsureFileDialogManager()) {
|
|
LOG(ERROR) << "File dialog canceled due to invalid state.";
|
|
listener->FileSelectionCanceled(params);
|
|
return;
|
|
}
|
|
file_dialog_manager_->RunSelectFile(listener, std::move(policy), type, title,
|
|
default_path, file_types, file_type_index,
|
|
default_extension, owning_window, params);
|
|
}
|
|
|
|
void CefBrowserHostBase::SelectFileListenerDestroyed(
|
|
ui::SelectFileDialog::Listener* listener) {
|
|
if (file_dialog_manager_) {
|
|
file_dialog_manager_->SelectFileListenerDestroyed(listener);
|
|
}
|
|
}
|
|
|
|
bool CefBrowserHostBase::MaybeAllowNavigation(
|
|
content::RenderFrameHost* opener,
|
|
const content::OpenURLParams& params) {
|
|
return true;
|
|
}
|
|
|
|
void CefBrowserHostBase::OnAfterCreated() {
|
|
CEF_REQUIRE_UIT();
|
|
if (client_) {
|
|
if (auto handler = client_->GetLifeSpanHandler()) {
|
|
handler->OnAfterCreated(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CefBrowserHostBase::OnBeforeClose() {
|
|
CEF_REQUIRE_UIT();
|
|
if (client_) {
|
|
if (auto handler = client_->GetLifeSpanHandler()) {
|
|
handler->OnBeforeClose(this);
|
|
}
|
|
}
|
|
browser_info_->SetClosing();
|
|
}
|
|
|
|
void CefBrowserHostBase::OnBrowserDestroyed() {
|
|
CEF_REQUIRE_UIT();
|
|
|
|
// Destroy any platform constructs.
|
|
if (file_dialog_manager_) {
|
|
file_dialog_manager_->Destroy();
|
|
file_dialog_manager_.reset();
|
|
}
|
|
|
|
for (auto& observer : observers_) {
|
|
observer.OnBrowserDestroyed(this);
|
|
}
|
|
}
|
|
|
|
int CefBrowserHostBase::browser_id() const {
|
|
return browser_info_->browser_id();
|
|
}
|
|
|
|
SkColor CefBrowserHostBase::GetBackgroundColor() const {
|
|
// Don't use |platform_delegate_| because it's not thread-safe.
|
|
return CefContext::Get()->GetBackgroundColor(
|
|
&settings_, IsWindowless() ? STATE_ENABLED : STATE_DISABLED);
|
|
}
|
|
|
|
content::WebContents* CefBrowserHostBase::GetWebContents() const {
|
|
CEF_REQUIRE_UIT();
|
|
return contents_delegate_->web_contents();
|
|
}
|
|
|
|
content::BrowserContext* CefBrowserHostBase::GetBrowserContext() const {
|
|
CEF_REQUIRE_UIT();
|
|
auto web_contents = GetWebContents();
|
|
if (web_contents) {
|
|
return web_contents->GetBrowserContext();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
CefMediaStreamRegistrar* CefBrowserHostBase::GetMediaStreamRegistrar() {
|
|
CEF_REQUIRE_UIT();
|
|
if (!media_stream_registrar_) {
|
|
media_stream_registrar_ = std::make_unique<CefMediaStreamRegistrar>(this);
|
|
}
|
|
return media_stream_registrar_.get();
|
|
}
|
|
|
|
CefDevToolsWindowRunner* CefBrowserHostBase::GetDevToolsWindowRunner() {
|
|
if (!devtools_window_runner_) {
|
|
devtools_window_runner_ = CefDevToolsWindowRunner::Create();
|
|
}
|
|
return devtools_window_runner_.get();
|
|
}
|
|
|
|
views::Widget* CefBrowserHostBase::GetWindowWidget() const {
|
|
CEF_REQUIRE_UIT();
|
|
if (!platform_delegate_) {
|
|
return nullptr;
|
|
}
|
|
return platform_delegate_->GetWindowWidget();
|
|
}
|
|
|
|
CefRefPtr<CefBrowserView> CefBrowserHostBase::GetBrowserView() const {
|
|
CEF_REQUIRE_UIT();
|
|
if (is_views_hosted_ && platform_delegate_) {
|
|
return platform_delegate_->GetBrowserView();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
gfx::NativeWindow CefBrowserHostBase::GetTopLevelNativeWindow() const {
|
|
CEF_REQUIRE_UIT();
|
|
// Windowless browsers always return nullptr from GetTopLevelNativeWindow().
|
|
if (!IsWindowless()) {
|
|
auto web_contents = GetWebContents();
|
|
if (web_contents) {
|
|
return web_contents->GetTopLevelNativeWindow();
|
|
}
|
|
}
|
|
return gfx::NativeWindow();
|
|
}
|
|
|
|
bool CefBrowserHostBase::IsFocused() const {
|
|
CEF_REQUIRE_UIT();
|
|
auto web_contents = GetWebContents();
|
|
if (web_contents) {
|
|
return static_cast<content::RenderFrameHostImpl*>(
|
|
web_contents->GetPrimaryMainFrame())
|
|
->IsFocused();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CefBrowserHostBase::IsVisible() const {
|
|
CEF_REQUIRE_UIT();
|
|
// Windowless browsers always return nullptr from GetNativeView().
|
|
if (!IsWindowless()) {
|
|
auto web_contents = GetWebContents();
|
|
if (web_contents) {
|
|
return platform_util::IsVisible(web_contents->GetNativeView());
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CefBrowserHostBase::EnsureDevToolsProtocolManager() {
|
|
CEF_REQUIRE_UIT();
|
|
if (!contents_delegate_->web_contents()) {
|
|
return false;
|
|
}
|
|
|
|
if (!devtools_protocol_manager_) {
|
|
devtools_protocol_manager_ =
|
|
std::make_unique<CefDevToolsProtocolManager>(this);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void CefBrowserHostBase::InitializeDevToolsRegistrationOnUIThread(
|
|
CefRefPtr<CefRegistration> registration) {
|
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
CEF_POST_TASK(
|
|
CEF_UIT,
|
|
base::BindOnce(
|
|
&CefBrowserHostBase::InitializeDevToolsRegistrationOnUIThread, this,
|
|
registration));
|
|
return;
|
|
}
|
|
|
|
if (!EnsureDevToolsProtocolManager()) {
|
|
return;
|
|
}
|
|
devtools_protocol_manager_->InitializeRegistrationOnUIThread(registration);
|
|
}
|
|
|
|
bool CefBrowserHostBase::EnsureFileDialogManager() {
|
|
CEF_REQUIRE_UIT();
|
|
if (!contents_delegate_->web_contents()) {
|
|
return false;
|
|
}
|
|
|
|
if (!file_dialog_manager_) {
|
|
file_dialog_manager_ = std::make_unique<CefFileDialogManager>(this);
|
|
}
|
|
return true;
|
|
}
|