alloy: mac/linux: Support OS execution via OnProtocolExecution (fixes #1340)

This commit is contained in:
Marshall Greenblatt 2023-06-26 13:08:04 +03:00
parent 0b99f92e97
commit 71c588c16a
4 changed files with 23 additions and 76 deletions

View File

@ -5,12 +5,30 @@
#include "libcef/browser/browser_platform_delegate.h" #include "libcef/browser/browser_platform_delegate.h"
#include "libcef/browser/alloy/alloy_browser_host_impl.h" #include "libcef/browser/alloy/alloy_browser_host_impl.h"
#include "libcef/browser/thread_util.h"
#include "base/logging.h" #include "base/logging.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/shell_integration.h"
#include "content/public/browser/render_view_host.h" #include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h" #include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/render_widget_host_view.h"
namespace {
void ExecuteExternalProtocol(const GURL& url) {
CEF_REQUIRE_BLOCKING();
// Check that an application is associated with the scheme.
if (shell_integration::GetApplicationNameForScheme(url).empty()) {
return;
}
CEF_POST_TASK(TID_UI, base::BindOnce(&platform_util::OpenExternal, url));
}
} // namespace
CefBrowserPlatformDelegate::CefBrowserPlatformDelegate() = default; CefBrowserPlatformDelegate::CefBrowserPlatformDelegate() = default;
CefBrowserPlatformDelegate::~CefBrowserPlatformDelegate() { CefBrowserPlatformDelegate::~CefBrowserPlatformDelegate() {
@ -225,6 +243,11 @@ bool CefBrowserPlatformDelegate::IsNeverComposited(
return false; return false;
} }
// static
void CefBrowserPlatformDelegate::HandleExternalProtocol(const GURL& url) {
CEF_POST_USER_VISIBLE_TASK(base::BindOnce(ExecuteExternalProtocol, url));
}
CefEventHandle CefBrowserPlatformDelegate::GetEventHandle( CefEventHandle CefBrowserPlatformDelegate::GetEventHandle(
const content::NativeWebKeyboardEvent& event) const { const content::NativeWebKeyboardEvent& event) const {
DCHECK(false); DCHECK(false);

View File

@ -233,9 +233,6 @@ bool CefBrowserPlatformDelegateNativeLinux::HandleKeyboardEvent(
return false; return false;
} }
// static
void CefBrowserPlatformDelegate::HandleExternalProtocol(const GURL& url) {}
CefEventHandle CefBrowserPlatformDelegateNativeLinux::GetEventHandle( CefEventHandle CefBrowserPlatformDelegateNativeLinux::GetEventHandle(
const content::NativeWebKeyboardEvent& event) const { const content::NativeWebKeyboardEvent& event) const {
// TODO(cef): We need to return an XEvent* from this method, but // TODO(cef): We need to return an XEvent* from this method, but

View File

@ -462,9 +462,6 @@ bool CefBrowserPlatformDelegateNativeMac::HandleKeyboardEvent(
return false; return false;
} }
// static
void CefBrowserPlatformDelegate::HandleExternalProtocol(const GURL& url) {}
CefEventHandle CefBrowserPlatformDelegateNativeMac::GetEventHandle( CefEventHandle CefBrowserPlatformDelegateNativeMac::GetEventHandle(
const content::NativeWebKeyboardEvent& event) const { const content::NativeWebKeyboardEvent& event) const {
return CAST_NSEVENT_TO_CEF_EVENT_HANDLE(event.os_event); return CAST_NSEVENT_TO_CEF_EVENT_HANDLE(event.os_event);

View File

@ -18,7 +18,6 @@
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/path_service.h" #include "base/path_service.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/win/registry.h"
#include "base/win/win_util.h" #include "base/win/win_util.h"
#include "content/public/browser/native_web_keyboard_event.h" #include "content/public/browser/native_web_keyboard_event.h"
#include "third_party/blink/public/common/input/web_mouse_event.h" #include "third_party/blink/public/common/input/web_mouse_event.h"
@ -60,70 +59,6 @@ void WriteTempFileAndView(const std::string& data) {
ui::win::OpenFileViaShell(tmp_file); ui::win::OpenFileViaShell(tmp_file);
} }
bool HasExternalHandler(const std::string& scheme) {
base::win::RegKey key;
const std::wstring registry_path =
base::ASCIIToWide(scheme + "\\shell\\open\\command");
key.Open(HKEY_CLASSES_ROOT, registry_path.c_str(), KEY_READ);
if (key.Valid()) {
DWORD size = 0;
key.ReadValue(NULL, NULL, &size, NULL);
if (size > 2) {
// ShellExecute crashes the process when the command is empty.
// We check for "2" because it always returns the trailing NULL.
return true;
}
}
return false;
}
// Match the logic in chrome/browser/platform_util_win.cc
// OpenExternalOnWorkerThread.
void ExecuteExternalProtocol(const GURL& url) {
CEF_REQUIRE_BLOCKING();
if (!HasExternalHandler(url.scheme())) {
return;
}
// Quote the input scheme to be sure that the command does not have
// parameters unexpected by the external program. This url should already
// have been escaped.
std::string escaped_url = url.spec();
escaped_url.insert(0, "\"");
escaped_url += "\"";
// According to Mozilla in uriloader/exthandler/win/nsOSHelperAppService.cpp:
// "Some versions of windows (Win2k before SP3, Win XP before SP1) crash in
// ShellExecute on long URLs (bug 161357 on bugzilla.mozilla.org). IE 5 and 6
// support URLS of 2083 chars in length, 2K is safe."
//
// It may be possible to increase this. https://crbug.com/727909
const size_t kMaxUrlLength = 2048;
if (escaped_url.length() > kMaxUrlLength) {
return;
}
// Specify %windir%\system32 as the CWD so that any new proc spawned does not
// inherit this proc's CWD. Without this, uninstalls may be broken by a
// long-lived child proc that holds a handle to the browser's version
// directory (the browser's CWD). A process's CWD is in the standard list of
// directories to search when loading a DLL, and precedes the system directory
// when safe DLL search mode is disabled (not the default). Setting the CWD to
// the system directory is a nice way to mitigate a potential DLL search order
// hijack for processes that don't implement their own mitigation.
base::FilePath system_dir;
base::PathService::Get(base::DIR_SYSTEM, &system_dir);
if (reinterpret_cast<ULONG_PTR>(ShellExecuteA(
NULL, "open", escaped_url.c_str(), NULL,
system_dir.AsUTF8Unsafe().c_str(), SW_SHOWNORMAL)) <= 32) {
// On failure, it may be good to display a message to the user.
// https://crbug.com/727913
return;
}
}
gfx::Rect GetDisplayWorkAreaNearestPoint(gfx::Point dip_point) { gfx::Rect GetDisplayWorkAreaNearestPoint(gfx::Point dip_point) {
const auto display = const auto display =
display::Screen::GetScreen()->GetDisplayNearestPoint(dip_point); display::Screen::GetScreen()->GetDisplayNearestPoint(dip_point);
@ -483,11 +418,6 @@ bool CefBrowserPlatformDelegateNativeWin::HandleKeyboardEvent(
} }
} }
// static
void CefBrowserPlatformDelegate::HandleExternalProtocol(const GURL& url) {
CEF_POST_USER_VISIBLE_TASK(base::BindOnce(ExecuteExternalProtocol, url));
}
CefEventHandle CefBrowserPlatformDelegateNativeWin::GetEventHandle( CefEventHandle CefBrowserPlatformDelegateNativeWin::GetEventHandle(
const content::NativeWebKeyboardEvent& event) const { const content::NativeWebKeyboardEvent& event) const {
if (!event.os_event) { if (!event.os_event) {