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, 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 = ASCIIToUTF16(errors::kInvalidContentSecurityPolicy); 101 return false; 102 } 103 if (!ContentSecurityPolicyIsLegal(content_security_policy)) { 104 *error = ASCIIToUTF16(errors::kInvalidContentSecurityPolicy); 105 return false; 106 } 107 if (extension->manifest_version() >= 2 && 108 !ContentSecurityPolicyIsSecure(content_security_policy, 109 extension->GetType())) { 110 *error = 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