alloy: mac/linux: Support OS execution via OnProtocolExecution (fixes #1340)
This commit is contained in:
parent
0b99f92e97
commit
71c588c16a
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue