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 33 namespace blink { 34 35 static URLSchemesMap& localURLSchemes() 36 { 37 DEFINE_STATIC_LOCAL(URLSchemesMap, localSchemes, ()); 38 39 if (localSchemes.isEmpty()) 40 localSchemes.add("file"); 41 42 return localSchemes; 43 } 44 45 static URLSchemesMap& displayIsolatedURLSchemes() 46 { 47 DEFINE_STATIC_LOCAL(URLSchemesMap, displayIsolatedSchemes, ()); 48 return displayIsolatedSchemes; 49 } 50 51 static 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 65 static 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 80 static URLSchemesMap& emptyDocumentSchemes() 81 { 82 DEFINE_STATIC_LOCAL(URLSchemesMap, emptyDocumentSchemes, ()); 83 84 if (emptyDocumentSchemes.isEmpty()) 85 emptyDocumentSchemes.add("about"); 86 87 return emptyDocumentSchemes; 88 } 89 90 static HashSet<String>& schemesForbiddenFromDomainRelaxation() 91 { 92 DEFINE_STATIC_LOCAL(HashSet<String>, schemes, ()); 93 return schemes; 94 } 95 96 static 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 108 static URLSchemesMap& notAllowingJavascriptURLsSchemes() 109 { 110 DEFINE_STATIC_LOCAL(URLSchemesMap, notAllowingJavascriptURLsSchemes, ()); 111 return notAllowingJavascriptURLsSchemes; 112 } 113 114 void SchemeRegistry::registerURLSchemeAsLocal(const String& scheme) 115 { 116 localURLSchemes().add(scheme); 117 } 118 119 void SchemeRegistry::removeURLSchemeRegisteredAsLocal(const String& scheme) 120 { 121 if (scheme == "file") 122 return; 123 localURLSchemes().remove(scheme); 124 } 125 126 const URLSchemesMap& SchemeRegistry::localSchemes() 127 { 128 return localURLSchemes(); 129 } 130 131 static 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 145 static 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 157 static URLSchemesMap& ContentSecurityPolicyBypassingSchemes() 158 { 159 DEFINE_STATIC_LOCAL(URLSchemesMap, schemes, ()); 160 return schemes; 161 } 162 163 bool SchemeRegistry::shouldTreatURLSchemeAsLocal(const String& scheme) 164 { 165 if (scheme.isEmpty()) 166 return false; 167 return localURLSchemes().contains(scheme); 168 } 169 170 void SchemeRegistry::registerURLSchemeAsNoAccess(const String& scheme) 171 { 172 schemesWithUniqueOrigins().add(scheme); 173 } 174 175 bool SchemeRegistry::shouldTreatURLSchemeAsNoAccess(const String& scheme) 176 { 177 if (scheme.isEmpty()) 178 return false; 179 return schemesWithUniqueOrigins().contains(scheme); 180 } 181 182 void SchemeRegistry::registerURLSchemeAsDisplayIsolated(const String& scheme) 183 { 184 displayIsolatedURLSchemes().add(scheme); 185 } 186 187 bool SchemeRegistry::shouldTreatURLSchemeAsDisplayIsolated(const String& scheme) 188 { 189 if (scheme.isEmpty()) 190 return false; 191 return displayIsolatedURLSchemes().contains(scheme); 192 } 193 194 void SchemeRegistry::registerURLSchemeAsSecure(const String& scheme) 195 { 196 secureSchemes().add(scheme); 197 } 198 199 bool SchemeRegistry::shouldTreatURLSchemeAsSecure(const String& scheme) 200 { 201 if (scheme.isEmpty()) 202 return false; 203 return secureSchemes().contains(scheme); 204 } 205 206 void SchemeRegistry::registerURLSchemeAsEmptyDocument(const String& scheme) 207 { 208 emptyDocumentSchemes().add(scheme); 209 } 210 211 bool SchemeRegistry::shouldLoadURLSchemeAsEmptyDocument(const String& scheme) 212 { 213 if (scheme.isEmpty()) 214 return false; 215 return emptyDocumentSchemes().contains(scheme); 216 } 217 218 void 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 229 bool SchemeRegistry::isDomainRelaxationForbiddenForURLScheme(const String& scheme) 230 { 231 if (scheme.isEmpty()) 232 return false; 233 return schemesForbiddenFromDomainRelaxation().contains(scheme); 234 } 235 236 bool SchemeRegistry::canDisplayOnlyIfCanRequest(const String& scheme) 237 { 238 if (scheme.isEmpty()) 239 return false; 240 return canDisplayOnlyIfCanRequestSchemes().contains(scheme); 241 } 242 243 void SchemeRegistry::registerAsCanDisplayOnlyIfCanRequest(const String& scheme) 244 { 245 canDisplayOnlyIfCanRequestSchemes().add(scheme); 246 } 247 248 void SchemeRegistry::registerURLSchemeAsNotAllowingJavascriptURLs(const String& scheme) 249 { 250 notAllowingJavascriptURLsSchemes().add(scheme); 251 } 252 253 bool SchemeRegistry::shouldTreatURLSchemeAsNotAllowingJavascriptURLs(const String& scheme) 254 { 255 if (scheme.isEmpty()) 256 return false; 257 return notAllowingJavascriptURLsSchemes().contains(scheme); 258 } 259 260 void SchemeRegistry::registerURLSchemeAsCORSEnabled(const String& scheme) 261 { 262 CORSEnabledSchemes().add(scheme); 263 } 264 265 bool SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(const String& scheme) 266 { 267 if (scheme.isEmpty()) 268 return false; 269 return CORSEnabledSchemes().contains(scheme); 270 } 271 272 String 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 289 void SchemeRegistry::registerURLSchemeAsLegacy(const String& scheme) 290 { 291 LegacySchemes().add(scheme); 292 } 293 294 bool SchemeRegistry::shouldTreatURLSchemeAsLegacy(const String& scheme) 295 { 296 if (scheme.isEmpty()) 297 return false; 298 return LegacySchemes().contains(scheme); 299 } 300 301 void SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme) 302 { 303 ContentSecurityPolicyBypassingSchemes().add(scheme); 304 } 305 306 void SchemeRegistry::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(const String& scheme) 307 { 308 ContentSecurityPolicyBypassingSchemes().remove(scheme); 309 } 310 311 bool SchemeRegistry::schemeShouldBypassContentSecurityPolicy(const String& scheme) 312 { 313 if (scheme.isEmpty()) 314 return false; 315 return ContentSecurityPolicyBypassingSchemes().contains(scheme); 316 } 317 318 } // namespace blink 319