Home | History | Annotate | Download | only in weborigin
      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