1/* 2 * Copyright (C) 2010 Apple Inc. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * 25 */ 26 27#include "config.h" 28#include "platform/weborigin/SchemeRegistry.h" 29 30#include "wtf/MainThread.h" 31#include "wtf/text/StringBuilder.h" 32 33namespace blink { 34 35static URLSchemesMap& localURLSchemes() 36{ 37 DEFINE_STATIC_LOCAL(URLSchemesMap, localSchemes, ()); 38 39 if (localSchemes.isEmpty()) 40 localSchemes.add("file"); 41 42 return localSchemes; 43} 44 45static URLSchemesMap& displayIsolatedURLSchemes() 46{ 47 DEFINE_STATIC_LOCAL(URLSchemesMap, displayIsolatedSchemes, ()); 48 return displayIsolatedSchemes; 49} 50 51static URLSchemesMap& secureSchemes() 52{ 53 DEFINE_STATIC_LOCAL(URLSchemesMap, secureSchemes, ()); 54 55 if (secureSchemes.isEmpty()) { 56 secureSchemes.add("https"); 57 secureSchemes.add("about"); 58 secureSchemes.add("data"); 59 secureSchemes.add("wss"); 60 } 61 62 return secureSchemes; 63} 64 65static URLSchemesMap& schemesWithUniqueOrigins() 66{ 67 DEFINE_STATIC_LOCAL(URLSchemesMap, schemesWithUniqueOrigins, ()); 68 69 if (schemesWithUniqueOrigins.isEmpty()) { 70 schemesWithUniqueOrigins.add("about"); 71 schemesWithUniqueOrigins.add("javascript"); 72 // This is a willful violation of HTML5. 73 // See https://bugs.webkit.org/show_bug.cgi?id=11885 74 schemesWithUniqueOrigins.add("data"); 75 } 76 77 return schemesWithUniqueOrigins; 78} 79 80static URLSchemesMap& emptyDocumentSchemes() 81{ 82 DEFINE_STATIC_LOCAL(URLSchemesMap, emptyDocumentSchemes, ()); 83 84 if (emptyDocumentSchemes.isEmpty()) 85 emptyDocumentSchemes.add("about"); 86 87 return emptyDocumentSchemes; 88} 89 90static HashSet<String>& schemesForbiddenFromDomainRelaxation() 91{ 92 DEFINE_STATIC_LOCAL(HashSet<String>, schemes, ()); 93 return schemes; 94} 95 96static URLSchemesMap& canDisplayOnlyIfCanRequestSchemes() 97{ 98 DEFINE_STATIC_LOCAL(URLSchemesMap, canDisplayOnlyIfCanRequestSchemes, ()); 99 100 if (canDisplayOnlyIfCanRequestSchemes.isEmpty()) { 101 canDisplayOnlyIfCanRequestSchemes.add("blob"); 102 canDisplayOnlyIfCanRequestSchemes.add("filesystem"); 103 } 104 105 return canDisplayOnlyIfCanRequestSchemes; 106} 107 108static URLSchemesMap& notAllowingJavascriptURLsSchemes() 109{ 110 DEFINE_STATIC_LOCAL(URLSchemesMap, notAllowingJavascriptURLsSchemes, ()); 111 return notAllowingJavascriptURLsSchemes; 112} 113 114void SchemeRegistry::registerURLSchemeAsLocal(const String& scheme) 115{ 116 localURLSchemes().add(scheme); 117} 118 119void SchemeRegistry::removeURLSchemeRegisteredAsLocal(const String& scheme) 120{ 121 if (scheme == "file") 122 return; 123 localURLSchemes().remove(scheme); 124} 125 126const URLSchemesMap& SchemeRegistry::localSchemes() 127{ 128 return localURLSchemes(); 129} 130 131static URLSchemesMap& CORSEnabledSchemes() 132{ 133 // FIXME: http://bugs.webkit.org/show_bug.cgi?id=77160 134 DEFINE_STATIC_LOCAL(URLSchemesMap, CORSEnabledSchemes, ()); 135 136 if (CORSEnabledSchemes.isEmpty()) { 137 CORSEnabledSchemes.add("http"); 138 CORSEnabledSchemes.add("https"); 139 CORSEnabledSchemes.add("data"); 140 } 141 142 return CORSEnabledSchemes; 143} 144 145static URLSchemesMap& LegacySchemes() 146{ 147 DEFINE_STATIC_LOCAL(URLSchemesMap, LegacySchemes, ()); 148 149 if (LegacySchemes.isEmpty()) { 150 LegacySchemes.add("ftp"); 151 LegacySchemes.add("gopher"); 152 } 153 154 return LegacySchemes; 155} 156 157static URLSchemesMap& ContentSecurityPolicyBypassingSchemes() 158{ 159 DEFINE_STATIC_LOCAL(URLSchemesMap, schemes, ()); 160 return schemes; 161} 162 163bool SchemeRegistry::shouldTreatURLSchemeAsLocal(const String& scheme) 164{ 165 if (scheme.isEmpty()) 166 return false; 167 return localURLSchemes().contains(scheme); 168} 169 170void SchemeRegistry::registerURLSchemeAsNoAccess(const String& scheme) 171{ 172 schemesWithUniqueOrigins().add(scheme); 173} 174 175bool SchemeRegistry::shouldTreatURLSchemeAsNoAccess(const String& scheme) 176{ 177 if (scheme.isEmpty()) 178 return false; 179 return schemesWithUniqueOrigins().contains(scheme); 180} 181 182void SchemeRegistry::registerURLSchemeAsDisplayIsolated(const String& scheme) 183{ 184 displayIsolatedURLSchemes().add(scheme); 185} 186 187bool SchemeRegistry::shouldTreatURLSchemeAsDisplayIsolated(const String& scheme) 188{ 189 if (scheme.isEmpty()) 190 return false; 191 return displayIsolatedURLSchemes().contains(scheme); 192} 193 194void SchemeRegistry::registerURLSchemeAsSecure(const String& scheme) 195{ 196 secureSchemes().add(scheme); 197} 198 199bool SchemeRegistry::shouldTreatURLSchemeAsSecure(const String& scheme) 200{ 201 if (scheme.isEmpty()) 202 return false; 203 return secureSchemes().contains(scheme); 204} 205 206void SchemeRegistry::registerURLSchemeAsEmptyDocument(const String& scheme) 207{ 208 emptyDocumentSchemes().add(scheme); 209} 210 211bool SchemeRegistry::shouldLoadURLSchemeAsEmptyDocument(const String& scheme) 212{ 213 if (scheme.isEmpty()) 214 return false; 215 return emptyDocumentSchemes().contains(scheme); 216} 217 218void SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(bool forbidden, const String& scheme) 219{ 220 if (scheme.isEmpty()) 221 return; 222 223 if (forbidden) 224 schemesForbiddenFromDomainRelaxation().add(scheme); 225 else 226 schemesForbiddenFromDomainRelaxation().remove(scheme); 227} 228 229bool SchemeRegistry::isDomainRelaxationForbiddenForURLScheme(const String& scheme) 230{ 231 if (scheme.isEmpty()) 232 return false; 233 return schemesForbiddenFromDomainRelaxation().contains(scheme); 234} 235 236bool SchemeRegistry::canDisplayOnlyIfCanRequest(const String& scheme) 237{ 238 if (scheme.isEmpty()) 239 return false; 240 return canDisplayOnlyIfCanRequestSchemes().contains(scheme); 241} 242 243void SchemeRegistry::registerAsCanDisplayOnlyIfCanRequest(const String& scheme) 244{ 245 canDisplayOnlyIfCanRequestSchemes().add(scheme); 246} 247 248void SchemeRegistry::registerURLSchemeAsNotAllowingJavascriptURLs(const String& scheme) 249{ 250 notAllowingJavascriptURLsSchemes().add(scheme); 251} 252 253bool SchemeRegistry::shouldTreatURLSchemeAsNotAllowingJavascriptURLs(const String& scheme) 254{ 255 if (scheme.isEmpty()) 256 return false; 257 return notAllowingJavascriptURLsSchemes().contains(scheme); 258} 259 260void SchemeRegistry::registerURLSchemeAsCORSEnabled(const String& scheme) 261{ 262 CORSEnabledSchemes().add(scheme); 263} 264 265bool SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(const String& scheme) 266{ 267 if (scheme.isEmpty()) 268 return false; 269 return CORSEnabledSchemes().contains(scheme); 270} 271 272String SchemeRegistry::listOfCORSEnabledURLSchemes() 273{ 274 StringBuilder builder; 275 const URLSchemesMap& corsEnabledSchemes = CORSEnabledSchemes(); 276 277 bool addSeparator = false; 278 for (URLSchemesMap::const_iterator it = corsEnabledSchemes.begin(); it != corsEnabledSchemes.end(); ++it) { 279 if (addSeparator) 280 builder.appendLiteral(", "); 281 else 282 addSeparator = true; 283 284 builder.append(*it); 285 } 286 return builder.toString(); 287} 288 289void SchemeRegistry::registerURLSchemeAsLegacy(const String& scheme) 290{ 291 LegacySchemes().add(scheme); 292} 293 294bool SchemeRegistry::shouldTreatURLSchemeAsLegacy(const String& scheme) 295{ 296 if (scheme.isEmpty()) 297 return false; 298 return LegacySchemes().contains(scheme); 299} 300 301void SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme) 302{ 303 ContentSecurityPolicyBypassingSchemes().add(scheme); 304} 305 306void SchemeRegistry::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(const String& scheme) 307{ 308 ContentSecurityPolicyBypassingSchemes().remove(scheme); 309} 310 311bool SchemeRegistry::schemeShouldBypassContentSecurityPolicy(const String& scheme) 312{ 313 if (scheme.isEmpty()) 314 return false; 315 return ContentSecurityPolicyBypassingSchemes().contains(scheme); 316} 317 318} // namespace blink 319