2 * Copyright (C) 2011, Google Inc. All rights reserved.
3 * Copyright (C) 2012, Samsung Electronics. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
28 #include "NavigatorContentUtils.h"
30 #if ENABLE(NAVIGATOR_CONTENT_UTILS)
33 #include "ExceptionCode.h"
35 #include "Navigator.h"
37 #include <wtf/HashSet.h>
41 static HashSet<String>* protocolWhitelist;
43 static void initProtocolHandlerWhitelist()
45 protocolWhitelist = new HashSet<String>;
46 #if !PLATFORM(BLACKBERRY)
47 static const char* protocols[] = {
64 for (size_t i = 0; i < WTF_ARRAY_LENGTH(protocols); ++i)
65 protocolWhitelist->add(protocols[i]);
69 static bool verifyCustomHandlerURL(const String& baseURL, const String& url, ExceptionCode& ec)
71 // The specification requires that it is a SYNTAX_ERR if the "%s" token is
73 static const char token[] = "%s";
74 int index = url.find(token);
80 // It is also a SYNTAX_ERR if the custom handler URL, as created by removing
81 // the "%s" token and prepending the base url, does not resolve.
83 newURL.remove(index, WTF_ARRAY_LENGTH(token) - 1);
85 KURL base(ParsedURLString, baseURL);
86 KURL kurl(base, newURL);
88 if (kurl.isEmpty() || !kurl.isValid()) {
96 static bool isProtocolWhitelisted(const String& scheme)
98 if (!protocolWhitelist)
99 initProtocolHandlerWhitelist();
100 return protocolWhitelist->contains(scheme);
103 static bool verifyProtocolHandlerScheme(const String& scheme, ExceptionCode& ec)
105 if (scheme.startsWith("web+")) {
106 if (isValidProtocol(scheme))
112 if (isProtocolWhitelisted(scheme))
118 NavigatorContentUtils* NavigatorContentUtils::from(Page* page)
120 return static_cast<NavigatorContentUtils*>(RefCountedSupplement<Page, NavigatorContentUtils>::from(page, NavigatorContentUtils::supplementName()));
123 NavigatorContentUtils::~NavigatorContentUtils()
127 PassRefPtr<NavigatorContentUtils> NavigatorContentUtils::create(NavigatorContentUtilsClient* client)
129 return adoptRef(new NavigatorContentUtils(client));
132 void NavigatorContentUtils::registerProtocolHandler(Navigator* navigator, const String& scheme, const String& url, const String& title, ExceptionCode& ec)
134 if (!navigator->frame())
137 Document* document = navigator->frame()->document();
141 String baseURL = document->baseURL().baseAsString();
143 if (!verifyCustomHandlerURL(baseURL, url, ec))
146 if (!verifyProtocolHandlerScheme(scheme, ec))
149 NavigatorContentUtils::from(navigator->frame()->page())->client()->registerProtocolHandler(scheme, baseURL, url, navigator->frame()->displayStringModifiedByEncoding(title));
152 #if ENABLE(CUSTOM_SCHEME_HANDLER)
153 static String customHandlersStateString(const NavigatorContentUtilsClient::CustomHandlersState state)
155 DEFINE_STATIC_LOCAL(const String, newHandler, (ASCIILiteral("new")));
156 DEFINE_STATIC_LOCAL(const String, registeredHandler, (ASCIILiteral("registered")));
157 DEFINE_STATIC_LOCAL(const String, declinedHandler, (ASCIILiteral("declined")));
160 case NavigatorContentUtilsClient::CustomHandlersNew:
162 case NavigatorContentUtilsClient::CustomHandlersRegistered:
163 return registeredHandler;
164 case NavigatorContentUtilsClient::CustomHandlersDeclined:
165 return declinedHandler;
168 ASSERT_NOT_REACHED();
172 String NavigatorContentUtils::isProtocolHandlerRegistered(Navigator* navigator, const String& scheme, const String& url, ExceptionCode& ec)
174 DEFINE_STATIC_LOCAL(const String, declined, ("declined"));
176 if (!navigator->frame())
179 Document* document = navigator->frame()->document();
180 String baseURL = document->baseURL().baseAsString();
182 if (!verifyCustomHandlerURL(baseURL, url, ec))
185 if (!verifyProtocolHandlerScheme(scheme, ec))
188 return customHandlersStateString(NavigatorContentUtils::from(navigator->frame()->page())->client()->isProtocolHandlerRegistered(scheme, baseURL, url));
191 void NavigatorContentUtils::unregisterProtocolHandler(Navigator* navigator, const String& scheme, const String& url, ExceptionCode& ec)
193 if (!navigator->frame())
196 Document* document = navigator->frame()->document();
197 String baseURL = document->baseURL().baseAsString();
199 if (!verifyCustomHandlerURL(baseURL, url, ec))
202 if (!verifyProtocolHandlerScheme(scheme, ec))
205 NavigatorContentUtils::from(navigator->frame()->page())->client()->unregisterProtocolHandler(scheme, baseURL, url);
209 const char* NavigatorContentUtils::supplementName()
211 return "NavigatorContentUtils";
214 void provideNavigatorContentUtilsTo(Page* page, NavigatorContentUtilsClient* client)
216 RefCountedSupplement<Page, NavigatorContentUtils>::provideTo(page, NavigatorContentUtils::supplementName(), NavigatorContentUtils::create(client));
219 } // namespace WebCore
221 #endif // ENABLE(NAVIGATOR_CONTENT_UTILS)