diff options
Diffstat (limited to 'Source/WebCore/Modules/navigatorcontentutils')
4 files changed, 80 insertions, 127 deletions
diff --git a/Source/WebCore/Modules/navigatorcontentutils/NavigatorContentUtils.cpp b/Source/WebCore/Modules/navigatorcontentutils/NavigatorContentUtils.cpp index b5fb0266f..010efb77e 100644 --- a/Source/WebCore/Modules/navigatorcontentutils/NavigatorContentUtils.cpp +++ b/Source/WebCore/Modules/navigatorcontentutils/NavigatorContentUtils.cpp @@ -35,129 +35,91 @@ #include "Navigator.h" #include "Page.h" #include <wtf/HashSet.h> +#include <wtf/NeverDestroyed.h> namespace WebCore { -static HashSet<String>* protocolWhitelist; - -static void initProtocolHandlerWhitelist() -{ - protocolWhitelist = new HashSet<String>; - static const char* protocols[] = { - "bitcoin", - "geo", - "im", - "irc", - "ircs", - "magnet", - "mailto", - "mms", - "news", - "nntp", - "sip", - "sms", - "smsto", - "ssh", - "tel", - "urn", - "webcal", - "wtai", - "xmpp", - }; - for (size_t i = 0; i < WTF_ARRAY_LENGTH(protocols); ++i) - protocolWhitelist->add(protocols[i]); -} - -static bool verifyCustomHandlerURL(const String& baseURL, const String& url, ExceptionCode& ec) +static bool verifyCustomHandlerURL(const URL& baseURL, const String& url) { // The specification requires that it is a SYNTAX_ERR if the "%s" token is // not present. static const char token[] = "%s"; int index = url.find(token); - if (-1 == index) { - ec = SYNTAX_ERR; + if (-1 == index) return false; - } // It is also a SYNTAX_ERR if the custom handler URL, as created by removing // the "%s" token and prepending the base url, does not resolve. String newURL = url; newURL.remove(index, WTF_ARRAY_LENGTH(token) - 1); - URL base(ParsedURLString, baseURL); - URL kurl(base, newURL); + URL kurl(baseURL, newURL); - if (kurl.isEmpty() || !kurl.isValid()) { - ec = SYNTAX_ERR; + if (kurl.isEmpty() || !kurl.isValid()) return false; - } return true; } -static bool isProtocolWhitelisted(const String& scheme) +static inline bool isProtocolWhitelisted(const String& scheme) { - if (!protocolWhitelist) - initProtocolHandlerWhitelist(); - return protocolWhitelist->contains(scheme); + static NeverDestroyed<HashSet<String, ASCIICaseInsensitiveHash>> protocolWhitelist = []() { + HashSet<String, ASCIICaseInsensitiveHash> set; + for (auto* protocol : { "bitcoin", "geo", "im", "irc", "ircs", "magnet", "mailto", "mms", "news", "nntp", "sip", "sms", "smsto", "ssh", "tel", "urn", "webcal", "wtai", "xmpp" }) + set.add(protocol); + return set; + }(); + return protocolWhitelist.get().contains(scheme); } -static bool verifyProtocolHandlerScheme(const String& scheme, ExceptionCode& ec) +static bool verifyProtocolHandlerScheme(const String& scheme) { + if (isProtocolWhitelisted(scheme)) + return true; + + // FIXME: Should this be case sensitive, or should it be ASCII case-insensitive? if (scheme.startsWith("web+")) { - // The specification requires that the length of scheme is at least five characteres (including 'web+' prefix). + // The specification requires that the length of scheme is at least five characters (including 'web+' prefix). if (scheme.length() >= 5 && isValidProtocol(scheme)) return true; - ec = SECURITY_ERR; - return false; } - if (isProtocolWhitelisted(scheme)) - return true; - ec = SECURITY_ERR; return false; } NavigatorContentUtils* NavigatorContentUtils::from(Page* page) { - return static_cast<NavigatorContentUtils*>(RefCountedSupplement<Page, NavigatorContentUtils>::from(page, NavigatorContentUtils::supplementName())); + return static_cast<NavigatorContentUtils*>(Supplement<Page>::from(page, supplementName())); } NavigatorContentUtils::~NavigatorContentUtils() { } -PassRefPtr<NavigatorContentUtils> NavigatorContentUtils::create(NavigatorContentUtilsClient* client) -{ - return adoptRef(new NavigatorContentUtils(client)); -} - -void NavigatorContentUtils::registerProtocolHandler(Navigator* navigator, const String& scheme, const String& url, const String& title, ExceptionCode& ec) +ExceptionOr<void> NavigatorContentUtils::registerProtocolHandler(Navigator& navigator, const String& scheme, const String& url, const String& title) { - if (!navigator->frame()) - return; + if (!navigator.frame()) + return { }; - Document* document = navigator->frame()->document(); - if (!document) - return; + URL baseURL = navigator.frame()->document()->baseURL(); - String baseURL = document->baseURL().baseAsString(); + if (!verifyCustomHandlerURL(baseURL, url)) + return Exception { SYNTAX_ERR }; - if (!verifyCustomHandlerURL(baseURL, url, ec)) - return; + if (!verifyProtocolHandlerScheme(scheme)) + return Exception { SECURITY_ERR }; - if (!verifyProtocolHandlerScheme(scheme, ec)) - return; - - NavigatorContentUtils::from(navigator->frame()->page())->client()->registerProtocolHandler(scheme, baseURL, url, navigator->frame()->displayStringModifiedByEncoding(title)); + NavigatorContentUtils::from(navigator.frame()->page())->client()->registerProtocolHandler(scheme, baseURL, URL(ParsedURLString, url), navigator.frame()->displayStringModifiedByEncoding(title)); + return { }; } #if ENABLE(CUSTOM_SCHEME_HANDLER) + static String customHandlersStateString(const NavigatorContentUtilsClient::CustomHandlersState state) { - DEFINE_STATIC_LOCAL(const String, newHandler, (ASCIILiteral("new"))); - DEFINE_STATIC_LOCAL(const String, registeredHandler, (ASCIILiteral("registered"))); - DEFINE_STATIC_LOCAL(const String, declinedHandler, (ASCIILiteral("declined"))); + static NeverDestroyed<String> newHandler(ASCIILiteral("new")); + static NeverDestroyed<String> registeredHandler(ASCIILiteral("registered")); + static NeverDestroyed<String> declinedHandler(ASCIILiteral("declined")); switch (state) { case NavigatorContentUtilsClient::CustomHandlersNew: @@ -172,41 +134,41 @@ static String customHandlersStateString(const NavigatorContentUtilsClient::Custo return String(); } -String NavigatorContentUtils::isProtocolHandlerRegistered(Navigator* navigator, const String& scheme, const String& url, ExceptionCode& ec) +ExceptionOr<String> NavigatorContentUtils::isProtocolHandlerRegistered(Navigator& navigator, const String& scheme, const String& url) { - DEFINE_STATIC_LOCAL(const String, declined, ("declined")); + static NeverDestroyed<String> declined(ASCIILiteral("declined")); - if (!navigator->frame()) - return declined; + if (!navigator.frame()) + return String { declined }; - Document* document = navigator->frame()->document(); - String baseURL = document->baseURL().baseAsString(); + URL baseURL = navigator.frame()->document()->baseURL(); - if (!verifyCustomHandlerURL(baseURL, url, ec)) - return declined; + if (!verifyCustomHandlerURL(baseURL, url)) + return Exception { SYNTAX_ERR }; - if (!verifyProtocolHandlerScheme(scheme, ec)) - return declined; + if (!verifyProtocolHandlerScheme(scheme)) + return Exception { SECURITY_ERR }; - return customHandlersStateString(NavigatorContentUtils::from(navigator->frame()->page())->client()->isProtocolHandlerRegistered(scheme, baseURL, url)); + return customHandlersStateString(NavigatorContentUtils::from(navigator.frame()->page())->client()->isProtocolHandlerRegistered(scheme, baseURL, URL(ParsedURLString, url))); } -void NavigatorContentUtils::unregisterProtocolHandler(Navigator* navigator, const String& scheme, const String& url, ExceptionCode& ec) +ExceptionOr<void> NavigatorContentUtils::unregisterProtocolHandler(Navigator& navigator, const String& scheme, const String& url) { - if (!navigator->frame()) - return; + if (!navigator.frame()) + return { }; - Document* document = navigator->frame()->document(); - String baseURL = document->baseURL().baseAsString(); + URL baseURL = navigator.frame()->document()->baseURL(); - if (!verifyCustomHandlerURL(baseURL, url, ec)) - return; + if (!verifyCustomHandlerURL(baseURL, url)) + return Exception { SYNTAX_ERR }; - if (!verifyProtocolHandlerScheme(scheme, ec)) - return; + if (!verifyProtocolHandlerScheme(scheme)) + return Exception { SECURITY_ERR }; - NavigatorContentUtils::from(navigator->frame()->page())->client()->unregisterProtocolHandler(scheme, baseURL, url); + NavigatorContentUtils::from(navigator.frame()->page())->client()->unregisterProtocolHandler(scheme, baseURL, URL(ParsedURLString, url)); + return { }; } + #endif const char* NavigatorContentUtils::supplementName() @@ -214,12 +176,11 @@ const char* NavigatorContentUtils::supplementName() return "NavigatorContentUtils"; } -void provideNavigatorContentUtilsTo(Page* page, NavigatorContentUtilsClient* client) +void provideNavigatorContentUtilsTo(Page* page, std::unique_ptr<NavigatorContentUtilsClient> client) { - RefCountedSupplement<Page, NavigatorContentUtils>::provideTo(page, NavigatorContentUtils::supplementName(), NavigatorContentUtils::create(client)); + NavigatorContentUtils::provideTo(page, NavigatorContentUtils::supplementName(), std::make_unique<NavigatorContentUtils>(WTFMove(client))); } } // namespace WebCore #endif // ENABLE(NAVIGATOR_CONTENT_UTILS) - diff --git a/Source/WebCore/Modules/navigatorcontentutils/NavigatorContentUtils.h b/Source/WebCore/Modules/navigatorcontentutils/NavigatorContentUtils.h index 99151c287..bf2647751 100644 --- a/Source/WebCore/Modules/navigatorcontentutils/NavigatorContentUtils.h +++ b/Source/WebCore/Modules/navigatorcontentutils/NavigatorContentUtils.h @@ -24,15 +24,13 @@ * DAMAGE. */ -#ifndef NavigatorContentUtils_h -#define NavigatorContentUtils_h +#pragma once #if ENABLE(NAVIGATOR_CONTENT_UTILS) +#include "ExceptionOr.h" #include "NavigatorContentUtilsClient.h" -#include "RefCountedSupplement.h" -#include <wtf/PassRefPtr.h> -#include <wtf/text/WTFString.h> +#include "Supplementable.h" namespace WebCore { @@ -41,34 +39,30 @@ class Navigator; typedef int ExceptionCode; -class NavigatorContentUtils : public RefCountedSupplement<Page, NavigatorContentUtils> { +class NavigatorContentUtils final : public Supplement<Page> { public: + explicit NavigatorContentUtils(std::unique_ptr<NavigatorContentUtilsClient> client) + : m_client(WTFMove(client)) + { } + virtual ~NavigatorContentUtils(); static const char* supplementName(); static NavigatorContentUtils* from(Page*); - static void registerProtocolHandler(Navigator*, const String& scheme, const String& url, const String& title, ExceptionCode&); + static ExceptionOr<void> registerProtocolHandler(Navigator&, const String& scheme, const String& url, const String& title); #if ENABLE(CUSTOM_SCHEME_HANDLER) - static String isProtocolHandlerRegistered(Navigator*, const String& scheme, const String& url, ExceptionCode&); - static void unregisterProtocolHandler(Navigator*, const String& scheme, const String& url, ExceptionCode&); + static ExceptionOr<String> isProtocolHandlerRegistered(Navigator&, const String& scheme, const String& url); + static ExceptionOr<void> unregisterProtocolHandler(Navigator&, const String& scheme, const String& url); #endif - static PassRefPtr<NavigatorContentUtils> create(NavigatorContentUtilsClient*); - private: - explicit NavigatorContentUtils(NavigatorContentUtilsClient* client) - : m_client(client) - { } - - NavigatorContentUtilsClient* client() { return m_client; } + NavigatorContentUtilsClient* client() { return m_client.get(); } - NavigatorContentUtilsClient* m_client; + std::unique_ptr<NavigatorContentUtilsClient> m_client; }; } // namespace WebCore #endif // ENABLE(NAVIGATOR_CONTENT_UTILS) - -#endif // NavigatorContentUtils_h diff --git a/Source/WebCore/Modules/navigatorcontentutils/NavigatorContentUtils.idl b/Source/WebCore/Modules/navigatorcontentutils/NavigatorContentUtils.idl index a9f4b3114..f3eca86ba 100644 --- a/Source/WebCore/Modules/navigatorcontentutils/NavigatorContentUtils.idl +++ b/Source/WebCore/Modules/navigatorcontentutils/NavigatorContentUtils.idl @@ -20,8 +20,7 @@ // http://www.w3.org/TR/html5/system-state-and-capabilities.html#custom-handlers partial interface Navigator { - [Conditional=NAVIGATOR_CONTENT_UTILS, RaisesException] void registerProtocolHandler(DOMString scheme, DOMString url, DOMString title); - [Conditional=NAVIGATOR_CONTENT_UTILS&CUSTOM_SCHEME_HANDLER, RaisesException] DOMString isProtocolHandlerRegistered(DOMString scheme, DOMString url); - [Conditional=NAVIGATOR_CONTENT_UTILS&CUSTOM_SCHEME_HANDLER, RaisesException] void unregisterProtocolHandler(DOMString scheme, DOMString url); + [Conditional=NAVIGATOR_CONTENT_UTILS, MayThrowException] void registerProtocolHandler(DOMString scheme, DOMString url, DOMString title); + [Conditional=NAVIGATOR_CONTENT_UTILS&CUSTOM_SCHEME_HANDLER, MayThrowException] DOMString isProtocolHandlerRegistered(DOMString scheme, DOMString url); + [Conditional=NAVIGATOR_CONTENT_UTILS&CUSTOM_SCHEME_HANDLER, MayThrowException] void unregisterProtocolHandler(DOMString scheme, DOMString url); }; - diff --git a/Source/WebCore/Modules/navigatorcontentutils/NavigatorContentUtilsClient.h b/Source/WebCore/Modules/navigatorcontentutils/NavigatorContentUtilsClient.h index 25d67cc10..b70e896db 100644 --- a/Source/WebCore/Modules/navigatorcontentutils/NavigatorContentUtilsClient.h +++ b/Source/WebCore/Modules/navigatorcontentutils/NavigatorContentUtilsClient.h @@ -23,11 +23,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef NavigatorContentUtilsClient_h -#define NavigatorContentUtilsClient_h +#pragma once #if ENABLE(NAVIGATOR_CONTENT_UTILS) +#include "URL.h" #include <wtf/text/WTFString.h> namespace WebCore { @@ -37,7 +37,7 @@ class Page; class NavigatorContentUtilsClient { public: virtual ~NavigatorContentUtilsClient() { } - virtual void registerProtocolHandler(const String& scheme, const String& baseURL, const String& url, const String& title) = 0; + virtual void registerProtocolHandler(const String& scheme, const URL& baseURL, const URL&, const String& title) = 0; #if ENABLE(CUSTOM_SCHEME_HANDLER) enum CustomHandlersState { @@ -46,14 +46,13 @@ public: CustomHandlersDeclined }; - virtual CustomHandlersState isProtocolHandlerRegistered(const String& scheme, const String& baseURL, const String& url) = 0; - virtual void unregisterProtocolHandler(const String& scheme, const String& baseURL, const String& url) = 0; + virtual CustomHandlersState isProtocolHandlerRegistered(const String& scheme, const URL& baseURL, const URL&) = 0; + virtual void unregisterProtocolHandler(const String& scheme, const URL& baseURL, const URL&) = 0; #endif }; -void provideNavigatorContentUtilsTo(Page*, NavigatorContentUtilsClient*); +void provideNavigatorContentUtilsTo(Page*, std::unique_ptr<NavigatorContentUtilsClient>); -} +} // namespace WebCore #endif // ENABLE(NAVIGATOR_CONTENT_UTILS) -#endif // NavigatorContentUtilsClient_h |