From 1f01d6b2a80b4a48eecb7b3ec2173076654ae6c2 Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Fri, 4 Mar 2011 17:56:01 +0000 Subject: [PATCH] Allow registration of non-standard schemes (issue #195). git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@199 5089003a-bbd8-11dd-ad1f-f1f9622dbc98 --- include/cef.h | 34 +++++++++++++++++++----- include/cef_capi.h | 33 +++++++++++++++++++---- libcef/scheme_impl.cc | 26 +++++++++++------- libcef_dll/libcef_dll.cc | 4 +-- libcef_dll/wrapper/libcef_dll_wrapper.cc | 3 ++- tests/cefclient/res/xmlhttprequest.html | 5 ++-- tests/cefclient/scheme_test.cpp | 2 +- 7 files changed, 81 insertions(+), 26 deletions(-) diff --git a/include/cef.h b/include/cef.h index 9e7896875..d1fc4f28c 100644 --- a/include/cef.h +++ b/include/cef.h @@ -153,18 +153,40 @@ bool CefRegisterExtension(const CefString& extension_name, const CefString& javascript_code, CefRefPtr handler); - +// CEF supports two types of schemes, standard and non-standard. +// +// Standard schemes are subject to URL canonicalization and parsing rules as +// defined in the Common Internet Scheme Syntax RFC 1738 Section 3.1 available +// at http://www.ietf.org/rfc/rfc1738.txt +// +// In particular, the syntax for standard scheme URLs must be of the form: +// +// ://:@:/ +// +// Standard scheme URLs must have a host component that is a fully qualified +// domain name as defined in Section 3.5 of RFC 1034 [13] and Section 2.1 of RFC +// 1123. These URLs will be canonicalized to "scheme://host/path" in the +// simplest case and "scheme://username:password@host:port/path" in the most +// explicit case. For example, "scheme:host/path" and "scheme:///host/path" will +// both be canonicalized to "scheme://host/path". +// +// For non-standard scheme URLs only the "scheme:" component is parsed and +// canonicalized. The remainder of the URL will be passed to the handler as-is. +// For example, "scheme:///some%20text" will remain the same. Non-standard +// scheme URLs cannot be used as a target for form submission. +// // Register a custom scheme handler factory for the specified |scheme_name| and -// |host_name|. All URLs beginning with scheme_name://host_name/ can be handled -// by CefSchemeHandler instances returned by the factory. Specify an empty -// |host_name| value to match all host names. This function may be called on any -// thread. +// optional |host_name|. Specifying an empty |host_name| value for standard +// schemes will match all host names. The |host_name| value will be ignored for +// non-standard schemes. Set |is_standard| to true to register as a standard +// scheme or false to register a non-standard scheme. This function may be +// called on any thread. /*--cef()--*/ bool CefRegisterScheme(const CefString& scheme_name, const CefString& host_name, + bool is_standard, CefRefPtr factory); - typedef cef_thread_id_t CefThreadId; // CEF maintains multiple internal threads that are used for handling different diff --git a/include/cef_capi.h b/include/cef_capi.h index 7ea4c1a1e..7a590328e 100644 --- a/include/cef_capi.h +++ b/include/cef_capi.h @@ -123,13 +123,36 @@ CEF_EXPORT void cef_do_message_loop_work(); CEF_EXPORT int cef_register_extension(const cef_string_t* extension_name, const cef_string_t* javascript_code, struct _cef_v8handler_t* handler); +// CEF supports two types of schemes, standard and non-standard. +// +// Standard schemes are subject to URL canonicalization and parsing rules as +// defined in the Common Internet Scheme Syntax RFC 1738 Section 3.1 available +// at http://www.ietf.org/rfc/rfc1738.txt +// +// In particular, the syntax for standard scheme URLs must be of the form: +// +// ://:@:/ +// +// Standard scheme URLs must have a host component that is a fully qualified +// domain name as defined in Section 3.5 of RFC 1034 [13] and Section 2.1 of RFC +// 1123. These URLs will be canonicalized to "scheme://host/path" in the +// simplest case and "scheme://username:password@host:port/path" in the most +// explicit case. For example, "scheme:host/path" and "scheme:///host/path" will +// both be canonicalized to "scheme://host/path". +// +// For non-standard scheme URLs only the "scheme:" component is parsed and +// canonicalized. The remainder of the URL will be passed to the handler as-is. +// For example, "scheme:///some%20text" will remain the same. Non-standard +// scheme URLs cannot be used as a target for form submission. +// // Register a custom scheme handler factory for the specified |scheme_name| and -// |host_name|. All URLs beginning with scheme_name://host_name/ can be handled -// by cef_scheme_handler_t instances returned by the factory. Specify an NULL -// |host_name| value to match all host names. This function may be called on any -// thread. +// optional |host_name|. Specifying an NULL |host_name| value for standard +// schemes will match all host names. The |host_name| value will be ignored for +// non-standard schemes. Set |is_standard| to true (1) to register as a standard +// scheme or false (0) to register a non-standard scheme. This function may be +// called on any thread. CEF_EXPORT int cef_register_scheme(const cef_string_t* scheme_name, - const cef_string_t* host_name, + const cef_string_t* host_name, int is_standard, struct _cef_scheme_handler_factory_t* factory); // CEF maintains multiple internal threads that are used for handling different diff --git a/libcef/scheme_impl.cc b/libcef/scheme_impl.cc index 2b8e74763..ca5a89e72 100644 --- a/libcef/scheme_impl.cc +++ b/libcef/scheme_impl.cc @@ -360,9 +360,11 @@ CefUrlRequestFilter* CefUrlRequestFilter::shared_instance_ = NULL; class SchemeRequestJobWrapper : public CefThreadSafeBase { public: SchemeRequestJobWrapper(const std::string& scheme_name, - const std::string& host_name, - CefSchemeHandlerFactory* factory) - : factory_(factory), scheme_name_(scheme_name), host_name_(host_name) + const std::string& host_name, + bool is_standard, + CefSchemeHandlerFactory* factory) + : scheme_name_(scheme_name), host_name_(host_name), + is_standard_(is_standard), factory_(factory) { // The reference will be released when the application exits. TrackAdd(new TrackBase(factory)); @@ -370,10 +372,12 @@ public: void RegisterScheme() { - // Register the scheme as a standard scheme if it isn't already. - url_parse::Component scheme(0, scheme_name_.length()); - if (!url_util::IsStandard(scheme_name_.c_str(), scheme)) - url_util::AddStandardScheme(scheme_name_.c_str()); + if(is_standard_) { + // Register the scheme as a standard scheme if it isn't already. + url_parse::Component scheme(0, scheme_name_.length()); + if (!url_util::IsStandard(scheme_name_.c_str(), scheme)) + url_util::AddStandardScheme(scheme_name_.c_str()); + } // we need to store the pointer of this handler because // we can't pass it as a parameter to the factory method @@ -384,13 +388,15 @@ public: static bool ImplementsThreadSafeReferenceCounting() { return true; } private: - CefSchemeHandlerFactory* factory_; std::string scheme_name_; std::string host_name_; + bool is_standard_; + CefSchemeHandlerFactory* factory_; }; bool CefRegisterScheme(const CefString& scheme_name, const CefString& host_name, + bool is_standard, CefRefPtr factory) { // Verify that the context is in a valid state. @@ -404,7 +410,9 @@ bool CefRegisterScheme(const CefString& scheme_name, // will call AddRef() and Release() on the object in debug mode, resulting in // the object being deleted if it doesn't already have a reference. CefRefPtr wrapper( - new SchemeRequestJobWrapper(scheme_name, host_name, factory)); + new SchemeRequestJobWrapper(scheme_name, + (is_standard?host_name:std::string()), + is_standard, factory)); CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(wrapper.get(), &SchemeRequestJobWrapper::RegisterScheme)); diff --git a/libcef_dll/libcef_dll.cc b/libcef_dll/libcef_dll.cc index 4600826b9..8c0c579d7 100644 --- a/libcef_dll/libcef_dll.cc +++ b/libcef_dll/libcef_dll.cc @@ -120,7 +120,7 @@ CEF_EXPORT int cef_register_plugin(const cef_plugin_info_t* plugin_info) } CEF_EXPORT int cef_register_scheme(const cef_string_t* scheme_name, - const cef_string_t* host_name, + const cef_string_t* host_name, int is_standard, struct _cef_scheme_handler_factory_t* factory) { DCHECK(scheme_name); @@ -129,7 +129,7 @@ CEF_EXPORT int cef_register_scheme(const cef_string_t* scheme_name, return 0; return CefRegisterScheme(CefString(scheme_name), CefString(host_name), - CefSchemeHandlerFactoryCToCpp::Wrap(factory)); + (is_standard?true:false), CefSchemeHandlerFactoryCToCpp::Wrap(factory)); } CEF_EXPORT int cef_currently_on(cef_thread_id_t threadId) diff --git a/libcef_dll/wrapper/libcef_dll_wrapper.cc b/libcef_dll/wrapper/libcef_dll_wrapper.cc index adb8543c2..f259d4abd 100644 --- a/libcef_dll/wrapper/libcef_dll_wrapper.cc +++ b/libcef_dll/wrapper/libcef_dll_wrapper.cc @@ -97,10 +97,11 @@ bool CefRegisterPlugin(const CefPluginInfo& plugin_info) bool CefRegisterScheme(const CefString& scheme_name, const CefString& host_name, + bool is_standard, CefRefPtr factory) { return cef_register_scheme(scheme_name.GetStruct(), host_name.GetStruct(), - CefSchemeHandlerFactoryCppToC::Wrap(factory))?true:false; + is_standard, CefSchemeHandlerFactoryCppToC::Wrap(factory))?true:false; } bool CefCurrentlyOn(CefThreadId threadId) diff --git a/tests/cefclient/res/xmlhttprequest.html b/tests/cefclient/res/xmlhttprequest.html index 5115bcff4..e161d0771 100644 --- a/tests/cefclient/res/xmlhttprequest.html +++ b/tests/cefclient/res/xmlhttprequest.html @@ -4,14 +4,15 @@ function execXMLHttpRequest() { xhr = new XMLHttpRequest(); - xhr.open("GET","request",false); + xhr.open("GET",document.getElementById("url").value,false); xhr.setRequestHeader('My-Custom-Header', 'Some Value'); xhr.send(); document.getElementById('ta').value = "Request\n\n"+xhr.responseText; }
- +URL: +

diff --git a/tests/cefclient/scheme_test.cpp b/tests/cefclient/scheme_test.cpp index 6ff73d27b..f296b4773 100644 --- a/tests/cefclient/scheme_test.cpp +++ b/tests/cefclient/scheme_test.cpp @@ -142,7 +142,7 @@ public: void InitSchemeTest() { - CefRegisterScheme("client", "tests", new ClientSchemeHandlerFactory()); + CefRegisterScheme("client", "tests", true, new ClientSchemeHandlerFactory()); } void RunSchemeTest(CefRefPtr browser)