diff --git a/cef.gyp b/cef.gyp index 4bbd71990..9738995ef 100644 --- a/cef.gyp +++ b/cef.gyp @@ -557,6 +557,8 @@ 'libcef_dll/ctocpp/load_handler_ctocpp.h', 'libcef_dll/ctocpp/menu_handler_ctocpp.cc', 'libcef_dll/ctocpp/menu_handler_ctocpp.h', + 'libcef_dll/ctocpp/permission_handler_ctocpp.cc', + 'libcef_dll/ctocpp/permission_handler_ctocpp.h', 'libcef_dll/ctocpp/print_handler_ctocpp.cc', 'libcef_dll/ctocpp/print_handler_ctocpp.h', 'libcef_dll/ctocpp/proxy_handler_ctocpp.cc', diff --git a/cef_paths.gypi b/cef_paths.gypi index 6dce703ce..9a9917b46 100644 --- a/cef_paths.gypi +++ b/cef_paths.gypi @@ -159,6 +159,8 @@ 'libcef_dll/cpptoc/load_handler_cpptoc.h', 'libcef_dll/cpptoc/menu_handler_cpptoc.cc', 'libcef_dll/cpptoc/menu_handler_cpptoc.h', + 'libcef_dll/cpptoc/permission_handler_cpptoc.cc', + 'libcef_dll/cpptoc/permission_handler_cpptoc.h', 'libcef_dll/cpptoc/print_handler_cpptoc.cc', 'libcef_dll/cpptoc/print_handler_cpptoc.h', 'libcef_dll/cpptoc/proxy_handler_cpptoc.cc', diff --git a/include/cef.h b/include/cef.h index a3a24bafe..b4f191acb 100644 --- a/include/cef.h +++ b/include/cef.h @@ -1536,6 +1536,28 @@ public: }; +/// +// Implement this interface to handle events related to browser permissions. +// The methods of this class will be called on the UI thread. +/// +/*--cef(source=client)--*/ +class CefPermissionHandler : public virtual CefBase +{ +public: + /// + // Called on the UI thread before a script extension is loaded. + // Return false to let the extension load normally. + /// + /*--cef()--*/ + virtual bool OnBeforeScriptExtensionLoad(CefRefPtr browser, + CefRefPtr frame, + const CefString& extensionName) + { + return false; + } +}; + + /// // Implement this interface to handle events related to printing. The methods of // this class will be called on the UI thread. @@ -1842,6 +1864,14 @@ public: /*--cef()--*/ virtual CefRefPtr GetMenuHandler() { return NULL; } + /// + // Return the handler for browser permission events. + /// + /*--cef()--*/ + virtual CefRefPtr GetPermissionHandler() { + return NULL; + } + /// // Return the handler for printing events. /// diff --git a/include/cef_capi.h b/include/cef_capi.h index 3e7d72528..c45dd2239 100644 --- a/include/cef_capi.h +++ b/include/cef_capi.h @@ -1334,6 +1334,26 @@ typedef struct _cef_menu_handler_t } cef_menu_handler_t; +/// +// Implement this structure to handle events related to browser permissions. The +// functions of this structure will be called on the UI thread. +/// +typedef struct _cef_permission_handler_t +{ + // Base structure. + cef_base_t base; + + /// + // Called on the UI thread before a script extension is loaded. Return false + // (0) to let the extension load normally. + /// + int (CEF_CALLBACK *on_before_script_extension_load)( + struct _cef_permission_handler_t* self, struct _cef_browser_t* browser, + struct _cef_frame_t* frame, const cef_string_t* extensionName); + +} cef_permission_handler_t; + + /// // Implement this structure to handle events related to printing. The functions // of this structure will be called on the UI thread. @@ -1620,6 +1640,12 @@ typedef struct _cef_client_t struct _cef_menu_handler_t* (CEF_CALLBACK *get_menu_handler)( struct _cef_client_t* self); + /// + // Return the handler for browser permission events. + /// + struct _cef_permission_handler_t* (CEF_CALLBACK *get_permission_handler)( + struct _cef_client_t* self); + /// // Return the handler for printing events. /// diff --git a/libcef/browser_webview_delegate.cc b/libcef/browser_webview_delegate.cc index c791ae294..036f49b9c 100644 --- a/libcef/browser_webview_delegate.cc +++ b/libcef/browser_webview_delegate.cc @@ -474,6 +474,25 @@ int BrowserWebViewDelegate::historyForwardListCount() { - current_index - 1; } +// WebPermissionClient ------------------------------------------------------- + +bool BrowserWebViewDelegate::allowScriptExtension( + WebKit::WebFrame* frame, + const WebKit::WebString& extensionName, + int extensionGroup) { + bool allowExtension = true; + CefRefPtr client = browser_->GetClient(); + if (client.get()) { + CefRefPtr handler = client->GetPermissionHandler(); + if (handler.get()) { + CefString extensionNameStr = string16(extensionName); + allowExtension = !handler->OnBeforeScriptExtensionLoad( + browser_, browser_->UIT_GetCefFrame(frame), extensionNameStr); + } + } + return allowExtension; +} + // WebPluginPageDelegate ----------------------------------------------------- WebCookieJar* BrowserWebViewDelegate::GetCookieJar() { diff --git a/libcef/browser_webview_delegate.h b/libcef/browser_webview_delegate.h index e74d78adb..eddc4f56a 100644 --- a/libcef/browser_webview_delegate.h +++ b/libcef/browser_webview_delegate.h @@ -21,6 +21,7 @@ #include "third_party/WebKit/Source/WebKit/chromium/public/WebFileChooserParams.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebFileSystem.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrameClient.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebPermissionClient.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebViewClient.h" #include "webkit/glue/webcursor.h" @@ -48,6 +49,7 @@ class FilePath; class BrowserWebViewDelegate : public WebKit::WebViewClient, public WebKit::WebFrameClient, + public WebKit::WebPermissionClient, public webkit::npapi::WebPluginPageDelegate, public base::SupportsWeakPtr { public: @@ -195,6 +197,12 @@ class BrowserWebViewDelegate : public WebKit::WebViewClient, bool create, WebKit::WebFileSystemCallbacks* callbacks) OVERRIDE; + // WebKit::WebPermissionClient + virtual bool allowScriptExtension( + WebKit::WebFrame*, + const WebKit::WebString& extensionName, + int extensionGroup) OVERRIDE; + // webkit_glue::WebPluginPageDelegate virtual webkit::npapi::WebPluginDelegate* CreatePluginDelegate( const FilePath& file_path, diff --git a/libcef/webview_host_gtk.cc b/libcef/webview_host_gtk.cc index 27405d00f..e06988c82 100644 --- a/libcef/webview_host_gtk.cc +++ b/libcef/webview_host_gtk.cc @@ -40,6 +40,7 @@ WebViewHost* WebViewHost::Create(GtkWidget* parent_view, host->webwidget_ = WebView::create(delegate); #endif host->webview()->setDevToolsAgentClient(dev_tools_client); + host->webview()->setPermissionClient(delegate); prefs.Apply(host->webview()); host->webview()->initializeMainFrame(delegate); host->webwidget_->layout(); diff --git a/libcef/webview_host_mac.mm b/libcef/webview_host_mac.mm index a0ccbe8d3..de990cc5c 100644 --- a/libcef/webview_host_mac.mm +++ b/libcef/webview_host_mac.mm @@ -46,6 +46,7 @@ WebViewHost* WebViewHost::Create(NSView* parent_view, host->webwidget_ = WebView::create(delegate); #endif host->webview()->setDevToolsAgentClient(dev_tools_client); + host->webview()->setPermissionClient(delegate); prefs.Apply(host->webview()); host->webview()->initializeMainFrame(delegate); host->webwidget_->resize(WebSize(content_rect.size.width, diff --git a/libcef/webview_host_win.cc b/libcef/webview_host_win.cc index 15b7537e5..193230cfe 100644 --- a/libcef/webview_host_win.cc +++ b/libcef/webview_host_win.cc @@ -60,6 +60,7 @@ WebViewHost* WebViewHost::Create(HWND parent_view, host->webwidget_ = WebView::create(delegate); #endif host->webview()->setDevToolsAgentClient(dev_tools_client); + host->webview()->setPermissionClient(delegate); prefs.Apply(host->webview()); host->webview()->initializeMainFrame(delegate); diff --git a/libcef_dll/cpptoc/client_cpptoc.cc b/libcef_dll/cpptoc/client_cpptoc.cc index 8ce967656..f8ff70c34 100644 --- a/libcef_dll/cpptoc/client_cpptoc.cc +++ b/libcef_dll/cpptoc/client_cpptoc.cc @@ -20,6 +20,7 @@ #include "libcef_dll/cpptoc/life_span_handler_cpptoc.h" #include "libcef_dll/cpptoc/load_handler_cpptoc.h" #include "libcef_dll/cpptoc/menu_handler_cpptoc.h" +#include "libcef_dll/cpptoc/permission_handler_cpptoc.h" #include "libcef_dll/cpptoc/print_handler_cpptoc.h" #include "libcef_dll/cpptoc/render_handler_cpptoc.h" #include "libcef_dll/cpptoc/request_handler_cpptoc.h" @@ -154,6 +155,24 @@ cef_menu_handler_t* CEF_CALLBACK client_get_menu_handler( } +cef_permission_handler_t* CEF_CALLBACK client_get_permission_handler( + struct _cef_client_t* self) +{ + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefClientCppToC::Get( + self)->GetPermissionHandler(); + + // Return type: refptr_same + return CefPermissionHandlerCppToC::Wrap(_retval); +} + + cef_print_handler_t* CEF_CALLBACK client_get_print_handler( struct _cef_client_t* self) { @@ -275,6 +294,7 @@ CefClientCppToC::CefClientCppToC(CefClient* cls) struct_.struct_.get_focus_handler = client_get_focus_handler; struct_.struct_.get_keyboard_handler = client_get_keyboard_handler; struct_.struct_.get_menu_handler = client_get_menu_handler; + struct_.struct_.get_permission_handler = client_get_permission_handler; struct_.struct_.get_print_handler = client_get_print_handler; struct_.struct_.get_find_handler = client_get_find_handler; struct_.struct_.get_jsdialog_handler = client_get_jsdialog_handler; diff --git a/libcef_dll/ctocpp/client_ctocpp.cc b/libcef_dll/ctocpp/client_ctocpp.cc index f3f39360a..305d9adef 100644 --- a/libcef_dll/ctocpp/client_ctocpp.cc +++ b/libcef_dll/ctocpp/client_ctocpp.cc @@ -20,6 +20,7 @@ #include "libcef_dll/ctocpp/life_span_handler_ctocpp.h" #include "libcef_dll/ctocpp/load_handler_ctocpp.h" #include "libcef_dll/ctocpp/menu_handler_ctocpp.h" +#include "libcef_dll/ctocpp/permission_handler_ctocpp.h" #include "libcef_dll/ctocpp/print_handler_ctocpp.h" #include "libcef_dll/ctocpp/render_handler_ctocpp.h" #include "libcef_dll/ctocpp/request_handler_ctocpp.h" @@ -133,6 +134,21 @@ CefRefPtr CefClientCToCpp::GetMenuHandler() } +CefRefPtr CefClientCToCpp::GetPermissionHandler() +{ + if (CEF_MEMBER_MISSING(struct_, get_permission_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_permission_handler_t* _retval = struct_->get_permission_handler(struct_); + + // Return type: refptr_same + return CefPermissionHandlerCToCpp::Wrap(_retval); +} + + CefRefPtr CefClientCToCpp::GetPrintHandler() { if (CEF_MEMBER_MISSING(struct_, get_print_handler)) diff --git a/libcef_dll/ctocpp/client_ctocpp.h b/libcef_dll/ctocpp/client_ctocpp.h index 48c5a36ef..973a8d612 100644 --- a/libcef_dll/ctocpp/client_ctocpp.h +++ b/libcef_dll/ctocpp/client_ctocpp.h @@ -39,6 +39,7 @@ public: virtual CefRefPtr GetFocusHandler() OVERRIDE; virtual CefRefPtr GetKeyboardHandler() OVERRIDE; virtual CefRefPtr GetMenuHandler() OVERRIDE; + virtual CefRefPtr GetPermissionHandler() OVERRIDE; virtual CefRefPtr GetPrintHandler() OVERRIDE; virtual CefRefPtr GetFindHandler() OVERRIDE; virtual CefRefPtr GetJSDialogHandler() OVERRIDE; diff --git a/libcef_dll/libcef_dll.cc b/libcef_dll/libcef_dll.cc index 6d5610bd5..d271519ec 100644 --- a/libcef_dll/libcef_dll.cc +++ b/libcef_dll/libcef_dll.cc @@ -44,6 +44,7 @@ #include "libcef_dll/ctocpp/life_span_handler_ctocpp.h" #include "libcef_dll/ctocpp/load_handler_ctocpp.h" #include "libcef_dll/ctocpp/menu_handler_ctocpp.h" +#include "libcef_dll/ctocpp/permission_handler_ctocpp.h" #include "libcef_dll/ctocpp/print_handler_ctocpp.h" #include "libcef_dll/ctocpp/proxy_handler_ctocpp.h" #include "libcef_dll/ctocpp/read_handler_ctocpp.h" @@ -117,6 +118,7 @@ CEF_EXPORT void cef_shutdown() DCHECK(CefLifeSpanHandlerCToCpp::DebugObjCt == 0); DCHECK(CefLoadHandlerCToCpp::DebugObjCt == 0); DCHECK(CefMenuHandlerCToCpp::DebugObjCt == 0); + DCHECK(CefPermissionHandlerCToCpp::DebugObjCt == 0); DCHECK(CefPostDataCppToC::DebugObjCt == 0); DCHECK(CefPostDataElementCppToC::DebugObjCt == 0); DCHECK(CefPrintHandlerCToCpp::DebugObjCt == 0); diff --git a/libcef_dll/wrapper/libcef_dll_wrapper.cc b/libcef_dll/wrapper/libcef_dll_wrapper.cc index 802571593..77522d965 100644 --- a/libcef_dll/wrapper/libcef_dll_wrapper.cc +++ b/libcef_dll/wrapper/libcef_dll_wrapper.cc @@ -26,6 +26,7 @@ #include "libcef_dll/cpptoc/life_span_handler_cpptoc.h" #include "libcef_dll/cpptoc/load_handler_cpptoc.h" #include "libcef_dll/cpptoc/menu_handler_cpptoc.h" +#include "libcef_dll/cpptoc/permission_handler_cpptoc.h" #include "libcef_dll/cpptoc/print_handler_cpptoc.h" #include "libcef_dll/cpptoc/proxy_handler_cpptoc.h" #include "libcef_dll/cpptoc/read_handler_cpptoc.h" @@ -119,6 +120,7 @@ CEF_GLOBAL void CefShutdown() DCHECK(CefLifeSpanHandlerCppToC::DebugObjCt == 0); DCHECK(CefLoadHandlerCppToC::DebugObjCt == 0); DCHECK(CefMenuHandlerCppToC::DebugObjCt == 0); + DCHECK(CefPermissionHandlerCppToC::DebugObjCt == 0); DCHECK(CefPostDataCToCpp::DebugObjCt == 0); DCHECK(CefPostDataElementCToCpp::DebugObjCt == 0); DCHECK(CefPrintHandlerCppToC::DebugObjCt == 0); diff --git a/tests/unittests/test_handler.h b/tests/unittests/test_handler.h index 04d23f3d6..67b49f3e3 100644 --- a/tests/unittests/test_handler.h +++ b/tests/unittests/test_handler.h @@ -28,7 +28,8 @@ class TestHandler : public CefClient, public CefLifeSpanHandler, public CefLoadHandler, public CefRequestHandler, - public CefV8ContextHandler + public CefV8ContextHandler, + public CefPermissionHandler { public: TestHandler(); @@ -48,7 +49,9 @@ public: { return this; } virtual CefRefPtr GetV8ContextHandler() OVERRIDE { return this; } - + virtual CefRefPtr GetPermissionHandler() OVERRIDE + { return this; } + // CefLifeSpanHandler methods virtual void OnAfterCreated(CefRefPtr browser) OVERRIDE; virtual void OnBeforeClose(CefRefPtr browser) OVERRIDE; diff --git a/tests/unittests/v8_unittest.cc b/tests/unittests/v8_unittest.cc index 2dc191389..3f18f161d 100644 --- a/tests/unittests/v8_unittest.cc +++ b/tests/unittests/v8_unittest.cc @@ -1748,3 +1748,53 @@ TEST(V8Test, Exception) EXPECT_TRUE(handler->got_exception_[i]) << "test = " << i+1; } } + +namespace { + +class TestPermissionsHandler : public V8TestHandler +{ +public: + TestPermissionsHandler(bool denyExtensions) : V8TestHandler(false) { + deny_extensions_ = denyExtensions; + } + + virtual bool OnBeforeScriptExtensionLoad(CefRefPtr browser, + CefRefPtr frame, + const CefString& extensionName) + { + return deny_extensions_; + } + + bool deny_extensions_; +}; + +}; // namespace + +// Verify extension permissions +TEST(V8Test, Permissions) +{ + g_V8TestV8HandlerExecuteCalled = false; + + std::string extensionCode = + "var test;" + "if (!test)" + " test = {};" + "(function() {" + " test.execute = function(a,b,c,d,e,f,g,h,i) {" + " native function execute();" + " return execute(a,b,c,d,e,f,g,h,i);" + " };" + "})();"; + CefRegisterExtension("v8/test", extensionCode, new V8TestV8Handler(false)); + + CefRefPtr deny_handler = new TestPermissionsHandler(true); + deny_handler->ExecuteTest(); + + ASSERT_FALSE(g_V8TestV8HandlerExecuteCalled); + + CefRefPtr allow_handler = new TestPermissionsHandler(false); + allow_handler->ExecuteTest(); + + ASSERT_TRUE(g_V8TestV8HandlerExecuteCalled); +} +