Home | History | Annotate | Download | only in manifest_handlers
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "extensions/common/manifest_handlers/csp_info.h"
      6 
      7 #include "base/memory/scoped_ptr.h"
      8 #include "base/strings/string_util.h"
      9 #include "base/strings/utf_string_conversions.h"
     10 #include "base/values.h"
     11 #include "extensions/common/csp_validator.h"
     12 #include "extensions/common/manifest_constants.h"
     13 #include "extensions/common/manifest_handlers/sandboxed_page_info.h"
     14 
     15 namespace extensions {
     16 
     17 namespace keys = manifest_keys;
     18 namespace errors = manifest_errors;
     19 
     20 using csp_validator::ContentSecurityPolicyIsLegal;
     21 using csp_validator::ContentSecurityPolicyIsSecure;
     22 
     23 namespace {
     24 
     25 const char kDefaultContentSecurityPolicy[] =
     26     "script-src 'self' chrome-extension-resource:; object-src 'self'";
     27 
     28 #define PLATFORM_APP_LOCAL_CSP_SOURCES \
     29     "'self' data: chrome-extension-resource:"
     30 const char kDefaultPlatformAppContentSecurityPolicy[] =
     31     // Platform apps can only use local resources by default.
     32     "default-src 'self' chrome-extension-resource:;"
     33     // For remote resources, they can fetch them via XMLHttpRequest.
     34     "connect-src *;"
     35     // And serve them via data: or same-origin (blob:, filesystem:) URLs
     36     "style-src " PLATFORM_APP_LOCAL_CSP_SOURCES " 'unsafe-inline';"
     37     "img-src " PLATFORM_APP_LOCAL_CSP_SOURCES ";"
     38     "frame-src " PLATFORM_APP_LOCAL_CSP_SOURCES ";"
     39     "font-src " PLATFORM_APP_LOCAL_CSP_SOURCES ";"
     40     // Media can be loaded from remote resources since:
     41     // 1. <video> and <audio> have good fallback behavior when offline or under
     42     //    spotty connectivity.
     43     // 2. Fetching via XHR and serving via blob: URLs currently does not allow
     44     //    streaming or partial buffering.
     45     "media-src *;";
     46 
     47 }  // namespace
     48 
     49 CSPInfo::CSPInfo(const std::string& security_policy)
     50     : content_security_policy(security_policy) {
     51 }
     52 
     53 CSPInfo::~CSPInfo() {
     54 }
     55 
     56 // static
     57 const std::string& CSPInfo::GetContentSecurityPolicy(
     58     const Extension* extension) {
     59   CSPInfo* csp_info = static_cast<CSPInfo*>(
     60           extension->GetManifestData(keys::kContentSecurityPolicy));
     61   return csp_info ? csp_info->content_security_policy : base::EmptyString();
     62 }
     63 
     64 // static
     65 const std::string& CSPInfo::GetResourceContentSecurityPolicy(
     66     const Extension* extension,
     67     const std::string& relative_path) {
     68   return SandboxedPageInfo::IsSandboxedPage(extension, relative_path) ?
     69       SandboxedPageInfo::GetContentSecurityPolicy(extension) :
     70       GetContentSecurityPolicy(extension);
     71 }
     72 
     73 CSPHandler::CSPHandler(bool is_platform_app)
     74     : is_platform_app_(is_platform_app) {
     75 }
     76 
     77 CSPHandler::~CSPHandler() {
     78 }
     79 
     80 bool CSPHandler::Parse(Extension* extension, base::string16* error) {
     81   const std::string key = Keys()[0];
     82   if (!extension->manifest()->HasPath(key)) {
     83     if (extension->manifest_version() >= 2) {
     84       // TODO(abarth): Should we continue to let extensions override the
     85       //               default Content-Security-Policy?
     86       std::string content_security_policy = is_platform_app_ ?
     87           kDefaultPlatformAppContentSecurityPolicy :
     88           kDefaultContentSecurityPolicy;
     89 
     90       CHECK(ContentSecurityPolicyIsSecure(content_security_policy,
     91                                           extension->GetType()));
     92       extension->SetManifestData(keys::kContentSecurityPolicy,
     93                                  new CSPInfo(content_security_policy));
     94     }
     95     return true;
     96   }
     97 
     98   std::string content_security_policy;
     99   if (!extension->manifest()->GetString(key, &content_security_policy)) {
    100     *error = base::ASCIIToUTF16(errors::kInvalidContentSecurityPolicy);
    101     return false;
    102   }
    103   if (!ContentSecurityPolicyIsLegal(content_security_policy)) {
    104     *error = base::ASCIIToUTF16(errors::kInvalidContentSecurityPolicy);
    105     return false;
    106   }
    107   if (extension->manifest_version() >= 2 &&
    108       !ContentSecurityPolicyIsSecure(content_security_policy,
    109                                      extension->GetType())) {
    110     *error = base::ASCIIToUTF16(errors::kInsecureContentSecurityPolicy);
    111     return false;
    112   }
    113 
    114   extension->SetManifestData(keys::kContentSecurityPolicy,
    115                              new CSPInfo(content_security_policy));
    116   return true;
    117 }
    118 
    119 bool CSPHandler::AlwaysParseForType(Manifest::Type type) const {
    120   if (is_platform_app_)
    121     return type == Manifest::TYPE_PLATFORM_APP;
    122   else
    123     return type == Manifest::TYPE_EXTENSION ||
    124         type == Manifest::TYPE_LEGACY_PACKAGED_APP;
    125 }
    126 
    127 const std::vector<std::string> CSPHandler::Keys() const {
    128   const std::string& key = is_platform_app_ ?
    129       keys::kPlatformAppContentSecurityPolicy : keys::kContentSecurityPolicy;
    130   return SingleKey(key);
    131 }
    132 
    133 }  // namespace extensions
    134