NavigatorContentUtils.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /*
  2. * Copyright (C) 2011, Google Inc. All rights reserved.
  3. * Copyright (C) 2012, Samsung Electronics. All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  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.
  13. *
  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
  24. * DAMAGE.
  25. */
  26. #include "config.h"
  27. #include "NavigatorContentUtils.h"
  28. #if ENABLE(NAVIGATOR_CONTENT_UTILS)
  29. #include "Document.h"
  30. #include "ExceptionCode.h"
  31. #include "Frame.h"
  32. #include "Navigator.h"
  33. #include "Page.h"
  34. #include <wtf/HashSet.h>
  35. namespace WebCore {
  36. static HashSet<String>* protocolWhitelist;
  37. static void initProtocolHandlerWhitelist()
  38. {
  39. protocolWhitelist = new HashSet<String>;
  40. #if !PLATFORM(BLACKBERRY)
  41. static const char* protocols[] = {
  42. "irc",
  43. "mailto",
  44. "mms",
  45. "news",
  46. "nntp",
  47. "sms",
  48. "smsto",
  49. "tel",
  50. "urn",
  51. "webcal",
  52. };
  53. for (size_t i = 0; i < WTF_ARRAY_LENGTH(protocols); ++i)
  54. protocolWhitelist->add(protocols[i]);
  55. #endif
  56. }
  57. static bool verifyCustomHandlerURL(const String& baseURL, const String& url, ExceptionCode& ec)
  58. {
  59. // The specification requires that it is a SYNTAX_ERR if the "%s" token is
  60. // not present.
  61. static const char token[] = "%s";
  62. int index = url.find(token);
  63. if (-1 == index) {
  64. ec = SYNTAX_ERR;
  65. return false;
  66. }
  67. // It is also a SYNTAX_ERR if the custom handler URL, as created by removing
  68. // the "%s" token and prepending the base url, does not resolve.
  69. String newURL = url;
  70. newURL.remove(index, WTF_ARRAY_LENGTH(token) - 1);
  71. KURL base(ParsedURLString, baseURL);
  72. KURL kurl(base, newURL);
  73. if (kurl.isEmpty() || !kurl.isValid()) {
  74. ec = SYNTAX_ERR;
  75. return false;
  76. }
  77. return true;
  78. }
  79. static bool isProtocolWhitelisted(const String& scheme)
  80. {
  81. if (!protocolWhitelist)
  82. initProtocolHandlerWhitelist();
  83. return protocolWhitelist->contains(scheme);
  84. }
  85. static bool verifyProtocolHandlerScheme(const String& scheme, ExceptionCode& ec)
  86. {
  87. if (scheme.startsWith("web+")) {
  88. if (isValidProtocol(scheme))
  89. return true;
  90. ec = SECURITY_ERR;
  91. return false;
  92. }
  93. if (isProtocolWhitelisted(scheme))
  94. return true;
  95. ec = SECURITY_ERR;
  96. return false;
  97. }
  98. NavigatorContentUtils* NavigatorContentUtils::from(Page* page)
  99. {
  100. return static_cast<NavigatorContentUtils*>(RefCountedSupplement<Page, NavigatorContentUtils>::from(page, NavigatorContentUtils::supplementName()));
  101. }
  102. NavigatorContentUtils::~NavigatorContentUtils()
  103. {
  104. }
  105. PassRefPtr<NavigatorContentUtils> NavigatorContentUtils::create(NavigatorContentUtilsClient* client)
  106. {
  107. return adoptRef(new NavigatorContentUtils(client));
  108. }
  109. void NavigatorContentUtils::registerProtocolHandler(Navigator* navigator, const String& scheme, const String& url, const String& title, ExceptionCode& ec)
  110. {
  111. if (!navigator->frame())
  112. return;
  113. Document* document = navigator->frame()->document();
  114. if (!document)
  115. return;
  116. String baseURL = document->baseURL().baseAsString();
  117. if (!verifyCustomHandlerURL(baseURL, url, ec))
  118. return;
  119. if (!verifyProtocolHandlerScheme(scheme, ec))
  120. return;
  121. NavigatorContentUtils::from(navigator->frame()->page())->client()->registerProtocolHandler(scheme, baseURL, url, navigator->frame()->displayStringModifiedByEncoding(title));
  122. }
  123. #if ENABLE(CUSTOM_SCHEME_HANDLER)
  124. static String customHandlersStateString(const NavigatorContentUtilsClient::CustomHandlersState state)
  125. {
  126. DEFINE_STATIC_LOCAL(const String, newHandler, (ASCIILiteral("new")));
  127. DEFINE_STATIC_LOCAL(const String, registeredHandler, (ASCIILiteral("registered")));
  128. DEFINE_STATIC_LOCAL(const String, declinedHandler, (ASCIILiteral("declined")));
  129. switch (state) {
  130. case NavigatorContentUtilsClient::CustomHandlersNew:
  131. return newHandler;
  132. case NavigatorContentUtilsClient::CustomHandlersRegistered:
  133. return registeredHandler;
  134. case NavigatorContentUtilsClient::CustomHandlersDeclined:
  135. return declinedHandler;
  136. }
  137. ASSERT_NOT_REACHED();
  138. return String();
  139. }
  140. String NavigatorContentUtils::isProtocolHandlerRegistered(Navigator* navigator, const String& scheme, const String& url, ExceptionCode& ec)
  141. {
  142. DEFINE_STATIC_LOCAL(const String, declined, ("declined"));
  143. if (!navigator->frame())
  144. return declined;
  145. Document* document = navigator->frame()->document();
  146. String baseURL = document->baseURL().baseAsString();
  147. if (!verifyCustomHandlerURL(baseURL, url, ec))
  148. return declined;
  149. if (!verifyProtocolHandlerScheme(scheme, ec))
  150. return declined;
  151. return customHandlersStateString(NavigatorContentUtils::from(navigator->frame()->page())->client()->isProtocolHandlerRegistered(scheme, baseURL, url));
  152. }
  153. void NavigatorContentUtils::unregisterProtocolHandler(Navigator* navigator, const String& scheme, const String& url, ExceptionCode& ec)
  154. {
  155. if (!navigator->frame())
  156. return;
  157. Document* document = navigator->frame()->document();
  158. String baseURL = document->baseURL().baseAsString();
  159. if (!verifyCustomHandlerURL(baseURL, url, ec))
  160. return;
  161. if (!verifyProtocolHandlerScheme(scheme, ec))
  162. return;
  163. NavigatorContentUtils::from(navigator->frame()->page())->client()->unregisterProtocolHandler(scheme, baseURL, url);
  164. }
  165. #endif
  166. const char* NavigatorContentUtils::supplementName()
  167. {
  168. return "NavigatorContentUtils";
  169. }
  170. void provideNavigatorContentUtilsTo(Page* page, NavigatorContentUtilsClient* client)
  171. {
  172. RefCountedSupplement<Page, NavigatorContentUtils>::provideTo(page, NavigatorContentUtils::supplementName(), NavigatorContentUtils::create(client));
  173. }
  174. } // namespace WebCore
  175. #endif // ENABLE(NAVIGATOR_CONTENT_UTILS)