mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-24 16:07:42 +01:00
Add OnProtocolExecution callback to CefRequestHandler (issue #582).
git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@711 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
parent
89c70a8b11
commit
d13cc9de1c
3
cef.gyp
3
cef.gyp
@ -787,6 +787,8 @@
|
||||
'libcef/browser/origin_whitelist_impl.h',
|
||||
'libcef/browser/resource_context.cc',
|
||||
'libcef/browser/resource_context.h',
|
||||
'libcef/browser/resource_dispatcher_host_delegate.cc',
|
||||
'libcef/browser/resource_dispatcher_host_delegate.h',
|
||||
'libcef/browser/resource_request_job.cc',
|
||||
'libcef/browser/resource_request_job.h',
|
||||
'libcef/browser/scheme_impl.cc',
|
||||
@ -866,6 +868,7 @@
|
||||
'libcef/renderer/v8_impl.h',
|
||||
'libcef/renderer/webkit_glue.cc',
|
||||
'libcef/renderer/webkit_glue.h',
|
||||
# Include sources for persistent cookie storage.
|
||||
'<(DEPTH)/chrome/browser/net/clear_on_exit_policy.cc',
|
||||
'<(DEPTH)/chrome/browser/net/clear_on_exit_policy.h',
|
||||
'<(DEPTH)/chrome/browser/net/sqlite_persistent_cookie_store.cc',
|
||||
|
@ -128,6 +128,17 @@ typedef struct _cef_request_handler_t {
|
||||
struct _cef_cookie_manager_t* (CEF_CALLBACK *get_cookie_manager)(
|
||||
struct _cef_request_handler_t* self, struct _cef_browser_t* browser,
|
||||
const cef_string_t* main_url);
|
||||
|
||||
///
|
||||
// Called on the UI thread to handle requests for URLs with an unknown
|
||||
// protocol component. Set |allow_os_execution| to true (1) to attempt
|
||||
// execution via the registered OS protocol handler, if any. SECURITY WARNING:
|
||||
// YOU SHOULD USE THIS METHOD TO ENFORCE RESTRICTIONS BASED ON SCHEME, HOST OR
|
||||
// OTHER URL ANALYSIS BEFORE ALLOWING OS EXECUTION.
|
||||
///
|
||||
void (CEF_CALLBACK *on_protocol_execution)(
|
||||
struct _cef_request_handler_t* self, struct _cef_browser_t* browser,
|
||||
const cef_string_t* url, int* allow_os_execution);
|
||||
} cef_request_handler_t;
|
||||
|
||||
|
||||
|
@ -141,6 +141,18 @@ class CefRequestHandler : public virtual CefBase {
|
||||
virtual CefRefPtr<CefCookieManager> GetCookieManager(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
const CefString& main_url) { return NULL; }
|
||||
|
||||
///
|
||||
// Called on the UI thread to handle requests for URLs with an unknown
|
||||
// protocol component. Set |allow_os_execution| to true to attempt execution
|
||||
// via the registered OS protocol handler, if any.
|
||||
// SECURITY WARNING: YOU SHOULD USE THIS METHOD TO ENFORCE RESTRICTIONS BASED
|
||||
// ON SCHEME, HOST OR OTHER URL ANALYSIS BEFORE ALLOWING OS EXECUTION.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual void OnProtocolExecution(CefRefPtr<CefBrowser> browser,
|
||||
const CefString& url,
|
||||
bool& allow_os_execution) {}
|
||||
};
|
||||
|
||||
#endif // CEF_INCLUDE_CEF_REQUEST_HANDLER_H_
|
||||
|
@ -804,6 +804,24 @@ bool CefBrowserHostImpl::ViewText(const std::string& text) {
|
||||
return PlatformViewText(text);
|
||||
}
|
||||
|
||||
void CefBrowserHostImpl::HandleExternalProtocol(const GURL& url) {
|
||||
if (CEF_CURRENTLY_ON_UIT()) {
|
||||
bool allow_os_execution = false;
|
||||
|
||||
if (client_.get()) {
|
||||
CefRefPtr<CefRequestHandler> handler = client_->GetRequestHandler();
|
||||
if (handler.get())
|
||||
handler->OnProtocolExecution(this, url.spec(), allow_os_execution);
|
||||
}
|
||||
|
||||
if (allow_os_execution)
|
||||
PlatformHandleExternalProtocol(url);
|
||||
} else {
|
||||
CEF_POST_TASK(CEF_UIT,
|
||||
base::Bind(&CefBrowserHostImpl::HandleExternalProtocol, this, url));
|
||||
}
|
||||
}
|
||||
|
||||
bool CefBrowserHostImpl::HasIDMatch(int render_process_id, int render_view_id) {
|
||||
base::AutoLock lock_scope(state_lock_);
|
||||
if (render_process_id != render_process_id_)
|
||||
|
@ -176,6 +176,9 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
||||
// Open the specified text in the default text editor.
|
||||
bool ViewText(const std::string& text);
|
||||
|
||||
// Handler for URLs involving external protocols.
|
||||
void HandleExternalProtocol(const GURL& url);
|
||||
|
||||
// Returns true if this browser matches the specified ID values. If
|
||||
// |render_view_id| is 0 any browser with the specified |render_process_id|
|
||||
// will match.
|
||||
@ -325,6 +328,8 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
||||
content::WebContents* contents,
|
||||
const content::FileChooserParams& params,
|
||||
std::vector<FilePath>& files);
|
||||
// Invoke platform specific handling for the external protocol.
|
||||
void PlatformHandleExternalProtocol(const GURL& url);
|
||||
|
||||
void OnAddressChange(CefRefPtr<CefFrame> frame,
|
||||
const GURL& url);
|
||||
|
@ -138,3 +138,6 @@ void CefBrowserHostImpl::PlatformRunFileChooser(
|
||||
std::vector<FilePath>& files) {
|
||||
NOTIMPLEMENTED();
|
||||
}
|
||||
|
||||
void CefBrowserHostImpl::PlatformHandleExternalProtocol(const GURL& url) {
|
||||
}
|
||||
|
@ -237,3 +237,6 @@ void CefBrowserHostImpl::PlatformRunFileChooser(
|
||||
}
|
||||
[NSApp endSheet:openPanel];
|
||||
}
|
||||
|
||||
void CefBrowserHostImpl::PlatformHandleExternalProtocol(const GURL& url) {
|
||||
}
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include "libcef/browser/thread_util.h"
|
||||
|
||||
#include "base/string_util.h"
|
||||
#include "base/utf_string_conversions.h"
|
||||
#include "base/win/registry.h"
|
||||
#include "base/win/windows_version.h"
|
||||
#include "content/public/browser/native_web_keyboard_event.h"
|
||||
#include "content/public/browser/web_contents_view.h"
|
||||
@ -133,6 +135,31 @@ bool RunOpenMultiFileDialog(const std::wstring& filter, HWND owner,
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
// 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."
|
||||
const int kMaxAddressLengthChars = 2048;
|
||||
|
||||
bool HasExternalHandler(const std::string& scheme) {
|
||||
base::win::RegKey key;
|
||||
const std::wstring registry_path =
|
||||
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;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
@ -358,3 +385,21 @@ void CefBrowserHostImpl::PlatformRunFileChooser(
|
||||
files.push_back(file_name);
|
||||
}
|
||||
}
|
||||
|
||||
void CefBrowserHostImpl::PlatformHandleExternalProtocol(const GURL& url) {
|
||||
if (CEF_CURRENTLY_ON_FILET()) {
|
||||
if (!HasExternalHandler(url.scheme()))
|
||||
return;
|
||||
|
||||
const std::string& address = url.spec();
|
||||
if (address.length() > kMaxAddressLengthChars)
|
||||
return;
|
||||
|
||||
ShellExecuteA(NULL, "open", address.c_str(), NULL, NULL, SW_SHOWNORMAL);
|
||||
} else {
|
||||
// Execute on the FILE thread.
|
||||
CEF_POST_TASK(CEF_FILET,
|
||||
base::Bind(&CefBrowserHostImpl::PlatformHandleExternalProtocol, this,
|
||||
url));
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "libcef/browser/browser_message_filter.h"
|
||||
#include "libcef/browser/browser_settings.h"
|
||||
#include "libcef/browser/context.h"
|
||||
#include "libcef/browser/resource_dispatcher_host_delegate.h"
|
||||
#include "libcef/browser/thread_util.h"
|
||||
#include "libcef/common/cef_switches.h"
|
||||
|
||||
@ -17,6 +18,7 @@
|
||||
#include "content/public/browser/access_token_store.h"
|
||||
#include "content/public/browser/media_observer.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/browser/resource_dispatcher_host.h"
|
||||
#include "content/public/common/content_switches.h"
|
||||
#include "googleurl/src/gurl.h"
|
||||
|
||||
@ -122,6 +124,13 @@ content::AccessTokenStore* CefContentBrowserClient::CreateAccessTokenStore() {
|
||||
return new CefAccessTokenStore;
|
||||
}
|
||||
|
||||
void CefContentBrowserClient::ResourceDispatcherHostCreated() {
|
||||
resource_dispatcher_host_delegate_.reset(
|
||||
new CefResourceDispatcherHostDelegate());
|
||||
content::ResourceDispatcherHost::Get()->SetDelegate(
|
||||
resource_dispatcher_host_delegate_.get());
|
||||
}
|
||||
|
||||
void CefContentBrowserClient::OverrideWebkitPrefs(
|
||||
content::RenderViewHost* rvh,
|
||||
const GURL& url,
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
class CefBrowserMainParts;
|
||||
class CefMediaObserver;
|
||||
class CefResourceDispatcherHostDelegate;
|
||||
|
||||
namespace content {
|
||||
class SiteInstance;
|
||||
@ -38,6 +39,7 @@ class CefContentBrowserClient : public content::ContentBrowserClient {
|
||||
int child_process_id) OVERRIDE;
|
||||
virtual content::MediaObserver* GetMediaObserver() OVERRIDE;
|
||||
virtual content::AccessTokenStore* CreateAccessTokenStore() OVERRIDE;
|
||||
virtual void ResourceDispatcherHostCreated() OVERRIDE;
|
||||
virtual void OverrideWebkitPrefs(content::RenderViewHost* rvh,
|
||||
const GURL& url,
|
||||
webkit_glue::WebPreferences* prefs) OVERRIDE;
|
||||
@ -47,6 +49,8 @@ class CefContentBrowserClient : public content::ContentBrowserClient {
|
||||
CefBrowserMainParts* browser_main_parts_;
|
||||
|
||||
scoped_ptr<CefMediaObserver> media_observer_;
|
||||
scoped_ptr<CefResourceDispatcherHostDelegate>
|
||||
resource_dispatcher_host_delegate_;
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_CONTENT_BROWSER_CLIENT_H_
|
||||
|
21
libcef/browser/resource_dispatcher_host_delegate.cc
Normal file
21
libcef/browser/resource_dispatcher_host_delegate.cc
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright (c) 2012 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/resource_dispatcher_host_delegate.h"
|
||||
#include "libcef/browser/browser_host_impl.h"
|
||||
|
||||
CefResourceDispatcherHostDelegate::CefResourceDispatcherHostDelegate() {
|
||||
}
|
||||
|
||||
CefResourceDispatcherHostDelegate::~CefResourceDispatcherHostDelegate() {
|
||||
}
|
||||
|
||||
void CefResourceDispatcherHostDelegate::HandleExternalProtocol(const GURL& url,
|
||||
int child_id,
|
||||
int route_id) {
|
||||
CefRefPtr<CefBrowserHostImpl> browser =
|
||||
CefBrowserHostImpl::GetBrowserByRoutingID(child_id, route_id);
|
||||
if (browser.get())
|
||||
browser->HandleExternalProtocol(url);
|
||||
}
|
27
libcef/browser/resource_dispatcher_host_delegate.h
Normal file
27
libcef/browser/resource_dispatcher_host_delegate.h
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright (c) 2012 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.
|
||||
|
||||
#ifndef CEF_LIBCEF_BROWSER_RESOURCE_DISPATCHER_HOST_DELEGATE_H_
|
||||
#define CEF_LIBCEF_BROWSER_RESOURCE_DISPATCHER_HOST_DELEGATE_H_
|
||||
#pragma once
|
||||
|
||||
#include "content/public/browser/resource_dispatcher_host_delegate.h"
|
||||
|
||||
// Implements ResourceDispatcherHostDelegate.
|
||||
class CefResourceDispatcherHostDelegate
|
||||
: public content::ResourceDispatcherHostDelegate {
|
||||
public:
|
||||
CefResourceDispatcherHostDelegate();
|
||||
virtual ~CefResourceDispatcherHostDelegate();
|
||||
|
||||
// ResourceDispatcherHostDelegate methods.
|
||||
virtual void HandleExternalProtocol(const GURL& url,
|
||||
int child_id,
|
||||
int route_id) OVERRIDE;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(CefResourceDispatcherHostDelegate);
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_RESOURCE_DISPATCHER_HOST_DELEGATE_H_
|
@ -12,14 +12,17 @@
|
||||
|
||||
#define CEF_UIT content::BrowserThread::UI
|
||||
#define CEF_IOT content::BrowserThread::IO
|
||||
#define CEF_FILET content::BrowserThread::FILE
|
||||
|
||||
#define CEF_CURRENTLY_ON(id) content::BrowserThread::CurrentlyOn(id)
|
||||
#define CEF_CURRENTLY_ON_UIT() CEF_CURRENTLY_ON(CEF_UIT)
|
||||
#define CEF_CURRENTLY_ON_IOT() CEF_CURRENTLY_ON(CEF_IOT)
|
||||
#define CEF_CURRENTLY_ON_FILET() CEF_CURRENTLY_ON(CEF_FILET)
|
||||
|
||||
#define CEF_REQUIRE(id) DCHECK(CEF_CURRENTLY_ON(id))
|
||||
#define CEF_REQUIRE_UIT() CEF_REQUIRE(CEF_UIT)
|
||||
#define CEF_REQUIRE_IOT() CEF_REQUIRE(CEF_IOT)
|
||||
#define CEF_REQUIRE_FILET() CEF_REQUIRE(CEF_FILET)
|
||||
|
||||
#define CEF_REQUIRE_RETURN(id, var) \
|
||||
if (!CEF_CURRENTLY_ON(id)) { \
|
||||
|
@ -194,6 +194,42 @@ cef_cookie_manager_t* CEF_CALLBACK request_handler_get_cookie_manager(
|
||||
return CefCookieManagerCToCpp::Unwrap(_retval);
|
||||
}
|
||||
|
||||
void CEF_CALLBACK request_handler_on_protocol_execution(
|
||||
struct _cef_request_handler_t* self, cef_browser_t* browser,
|
||||
const cef_string_t* url, int* allow_os_execution) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return;
|
||||
// Verify param: browser; type: refptr_diff
|
||||
DCHECK(browser);
|
||||
if (!browser)
|
||||
return;
|
||||
// Verify param: url; type: string_byref_const
|
||||
DCHECK(url);
|
||||
if (!url)
|
||||
return;
|
||||
// Verify param: allow_os_execution; type: bool_byref
|
||||
DCHECK(allow_os_execution);
|
||||
if (!allow_os_execution)
|
||||
return;
|
||||
|
||||
// Translate param: allow_os_execution; type: bool_byref
|
||||
bool allow_os_executionBool = (
|
||||
allow_os_execution && *allow_os_execution)?true:false;
|
||||
|
||||
// Execute
|
||||
CefRequestHandlerCppToC::Get(self)->OnProtocolExecution(
|
||||
CefBrowserCToCpp::Wrap(browser),
|
||||
CefString(url),
|
||||
allow_os_executionBool);
|
||||
|
||||
// Restore param: allow_os_execution; type: bool_byref
|
||||
if (allow_os_execution)
|
||||
*allow_os_execution = allow_os_executionBool?true:false;
|
||||
}
|
||||
|
||||
|
||||
// CONSTRUCTOR - Do not edit by hand.
|
||||
|
||||
@ -206,6 +242,7 @@ CefRequestHandlerCppToC::CefRequestHandlerCppToC(CefRequestHandler* cls)
|
||||
struct_.struct_.on_resource_redirect = request_handler_on_resource_redirect;
|
||||
struct_.struct_.get_auth_credentials = request_handler_get_auth_credentials;
|
||||
struct_.struct_.get_cookie_manager = request_handler_get_cookie_manager;
|
||||
struct_.struct_.on_protocol_execution = request_handler_on_protocol_execution;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
@ -182,6 +182,35 @@ CefRefPtr<CefCookieManager> CefRequestHandlerCToCpp::GetCookieManager(
|
||||
return CefCookieManagerCppToC::Unwrap(_retval);
|
||||
}
|
||||
|
||||
void CefRequestHandlerCToCpp::OnProtocolExecution(CefRefPtr<CefBrowser> browser,
|
||||
const CefString& url, bool& allow_os_execution) {
|
||||
if (CEF_MEMBER_MISSING(struct_, on_protocol_execution))
|
||||
return;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Verify param: browser; type: refptr_diff
|
||||
DCHECK(browser.get());
|
||||
if (!browser.get())
|
||||
return;
|
||||
// Verify param: url; type: string_byref_const
|
||||
DCHECK(!url.empty());
|
||||
if (url.empty())
|
||||
return;
|
||||
|
||||
// Translate param: allow_os_execution; type: bool_byref
|
||||
int allow_os_executionInt = allow_os_execution;
|
||||
|
||||
// Execute
|
||||
struct_->on_protocol_execution(struct_,
|
||||
CefBrowserCppToC::Wrap(browser),
|
||||
url.GetStruct(),
|
||||
&allow_os_executionInt);
|
||||
|
||||
// Restore param:allow_os_execution; type: bool_byref
|
||||
allow_os_execution = allow_os_executionInt?true:false;
|
||||
}
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
template<> long CefCToCpp<CefRequestHandlerCToCpp, CefRequestHandler,
|
||||
|
@ -48,6 +48,8 @@ class CefRequestHandlerCToCpp
|
||||
CefRefPtr<CefAuthCallback> callback) OVERRIDE;
|
||||
virtual CefRefPtr<CefCookieManager> GetCookieManager(
|
||||
CefRefPtr<CefBrowser> browser, const CefString& main_url) OVERRIDE;
|
||||
virtual void OnProtocolExecution(CefRefPtr<CefBrowser> browser,
|
||||
const CefString& url, bool& allow_os_execution) OVERRIDE;
|
||||
};
|
||||
|
||||
#endif // BUILDING_CEF_SHARED
|
||||
|
@ -275,6 +275,14 @@ void ClientHandler::OnLoadError(CefRefPtr<CefBrowser> browser,
|
||||
if (errorCode == ERR_ABORTED)
|
||||
return;
|
||||
|
||||
// Don't display an error for external protocols that we allow the OS to
|
||||
// handle. See OnProtocolExecution().
|
||||
if (errorCode == ERR_UNKNOWN_URL_SCHEME) {
|
||||
std::string urlStr = frame->GetURL();
|
||||
if (urlStr.find("spotify:") == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// Display a load error message.
|
||||
std::stringstream ss;
|
||||
ss << "<html><body><h2>Failed to load URL " << std::string(failedUrl) <<
|
||||
@ -346,6 +354,16 @@ CefRefPtr<CefResourceHandler> ClientHandler::GetResourceHandler(
|
||||
return handler;
|
||||
}
|
||||
|
||||
void ClientHandler::OnProtocolExecution(CefRefPtr<CefBrowser> browser,
|
||||
const CefString& url,
|
||||
bool& allow_os_execution) {
|
||||
std::string urlStr = url;
|
||||
|
||||
// Allow OS execution of Spotify URIs.
|
||||
if (urlStr.find("spotify:") == 0)
|
||||
allow_os_execution = true;
|
||||
}
|
||||
|
||||
void ClientHandler::SetMainHwnd(CefWindowHandle hwnd) {
|
||||
AutoLock lock_scope(this);
|
||||
m_MainHwnd = hwnd;
|
||||
|
@ -157,6 +157,9 @@ class ClientHandler : public CefClient,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request) OVERRIDE;
|
||||
virtual void OnProtocolExecution(CefRefPtr<CefBrowser> browser,
|
||||
const CefString& url,
|
||||
bool& allow_os_execution) OVERRIDE;
|
||||
|
||||
void SetMainHwnd(CefWindowHandle hwnd);
|
||||
CefWindowHandle GetMainHwnd() { return m_MainHwnd; }
|
||||
|
Loading…
x
Reference in New Issue
Block a user