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/sandboxed_page_info.h" 6 7 #include "base/lazy_instance.h" 8 #include "base/memory/scoped_ptr.h" 9 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/utf_string_conversions.h" 11 #include "base/values.h" 12 #include "extensions/common/csp_validator.h" 13 #include "extensions/common/error_utils.h" 14 #include "extensions/common/manifest_constants.h" 15 #include "extensions/common/url_pattern.h" 16 17 namespace extensions { 18 19 namespace { 20 21 namespace keys = extensions::manifest_keys; 22 namespace errors = manifest_errors; 23 24 const char kDefaultSandboxedPageContentSecurityPolicy[] = 25 "sandbox allow-scripts allow-forms allow-popups"; 26 27 static base::LazyInstance<SandboxedPageInfo> g_empty_sandboxed_info = 28 LAZY_INSTANCE_INITIALIZER; 29 30 const SandboxedPageInfo& GetSandboxedPageInfo(const Extension* extension) { 31 SandboxedPageInfo* info = static_cast<SandboxedPageInfo*>( 32 extension->GetManifestData(keys::kSandboxedPages)); 33 return info ? *info : g_empty_sandboxed_info.Get(); 34 } 35 36 } // namespace 37 38 SandboxedPageInfo::SandboxedPageInfo() { 39 } 40 41 SandboxedPageInfo::~SandboxedPageInfo() { 42 } 43 44 const std::string& SandboxedPageInfo::GetContentSecurityPolicy( 45 const Extension* extension) { 46 return GetSandboxedPageInfo(extension).content_security_policy; 47 } 48 49 const URLPatternSet& SandboxedPageInfo::GetPages(const Extension* extension) { 50 return GetSandboxedPageInfo(extension).pages; 51 } 52 53 bool SandboxedPageInfo::IsSandboxedPage(const Extension* extension, 54 const std::string& relative_path) { 55 return extension->ResourceMatches(GetPages(extension), relative_path); 56 } 57 58 SandboxedPageHandler::SandboxedPageHandler() { 59 } 60 61 SandboxedPageHandler::~SandboxedPageHandler() { 62 } 63 64 bool SandboxedPageHandler::Parse(Extension* extension, string16* error) { 65 scoped_ptr<SandboxedPageInfo> sandboxed_info(new SandboxedPageInfo); 66 67 const base::ListValue* list_value = NULL; 68 if (!extension->manifest()->GetList(keys::kSandboxedPages, &list_value)) { 69 *error = ASCIIToUTF16(errors::kInvalidSandboxedPagesList); 70 return false; 71 } 72 73 for (size_t i = 0; i < list_value->GetSize(); ++i) { 74 std::string relative_path; 75 if (!list_value->GetString(i, &relative_path)) { 76 *error = ErrorUtils::FormatErrorMessageUTF16( 77 errors::kInvalidSandboxedPage, base::IntToString(i)); 78 return false; 79 } 80 URLPattern pattern(URLPattern::SCHEME_EXTENSION); 81 if (pattern.Parse(extension->url().spec()) != URLPattern::PARSE_SUCCESS) { 82 *error = ErrorUtils::FormatErrorMessageUTF16( 83 errors::kInvalidURLPatternError, extension->url().spec()); 84 return false; 85 } 86 while (relative_path[0] == '/') 87 relative_path = relative_path.substr(1, relative_path.length() - 1); 88 pattern.SetPath(pattern.path() + relative_path); 89 sandboxed_info->pages.AddPattern(pattern); 90 } 91 92 if (extension->manifest()->HasPath(keys::kSandboxedPagesCSP)) { 93 if (!extension->manifest()->GetString( 94 keys::kSandboxedPagesCSP, 95 &sandboxed_info->content_security_policy)) { 96 *error = ASCIIToUTF16(errors::kInvalidSandboxedPagesCSP); 97 return false; 98 } 99 100 if (!csp_validator::ContentSecurityPolicyIsLegal( 101 sandboxed_info->content_security_policy) || 102 !csp_validator::ContentSecurityPolicyIsSandboxed( 103 sandboxed_info->content_security_policy, extension->GetType())) { 104 *error = ASCIIToUTF16(errors::kInvalidSandboxedPagesCSP); 105 return false; 106 } 107 } else { 108 sandboxed_info->content_security_policy = 109 kDefaultSandboxedPageContentSecurityPolicy; 110 CHECK(csp_validator::ContentSecurityPolicyIsSandboxed( 111 sandboxed_info->content_security_policy, extension->GetType())); 112 } 113 114 extension->SetManifestData(keys::kSandboxedPages, sandboxed_info.release()); 115 return true; 116 } 117 118 const std::vector<std::string> SandboxedPageHandler::Keys() const { 119 return SingleKey(keys::kSandboxedPages); 120 } 121 122 } // namespace extensions 123