1// Copyright 2014 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/webview_info.h" 6 7#include "base/memory/scoped_ptr.h" 8#include "base/strings/string_number_conversions.h" 9#include "base/strings/string_util.h" 10#include "base/strings/utf_string_conversions.h" 11#include "base/values.h" 12#include "extensions/common/error_utils.h" 13#include "extensions/common/manifest.h" 14#include "extensions/common/manifest_constants.h" 15 16namespace extensions { 17 18namespace keys = extensions::manifest_keys; 19namespace errors = extensions::manifest_errors; 20 21namespace { 22 23const WebviewInfo* GetResourcesInfo( 24 const Extension& extension) { 25 return static_cast<WebviewInfo*>( 26 extension.GetManifestData(keys::kWebviewAccessibleResources)); 27} 28 29} // namespace 30 31// A PartitionItem represents a set of accessible resources given a partition 32// ID pattern. 33class PartitionItem { 34 public: 35 explicit PartitionItem(const std::string& partition_pattern) 36 : partition_pattern_(partition_pattern) { 37 } 38 39 virtual ~PartitionItem() { 40 } 41 42 bool Matches(const std::string& partition_id) const { 43 return MatchPattern(partition_id, partition_pattern_); 44 } 45 46 // Adds a pattern to the set. Returns true if a new pattern was inserted, 47 // false if the pattern was already in the set. 48 bool AddPattern(const URLPattern& pattern) { 49 return accessible_resources_.AddPattern(pattern); 50 } 51 52 const URLPatternSet& accessible_resources() const { 53 return accessible_resources_; 54 } 55 private: 56 // A pattern string that matches partition IDs. 57 const std::string partition_pattern_; 58 // A URL pattern set of resources accessible to the given 59 // |partition_pattern_|. 60 URLPatternSet accessible_resources_; 61}; 62 63 64WebviewInfo::WebviewInfo() { 65} 66 67WebviewInfo::~WebviewInfo() { 68} 69 70// static 71bool WebviewInfo::IsResourceWebviewAccessible( 72 const Extension* extension, 73 const std::string& partition_id, 74 const std::string& relative_path) { 75 if (!extension) 76 return false; 77 78 const WebviewInfo* info = GetResourcesInfo(*extension); 79 if (!info) 80 return false; 81 82 for (size_t i = 0; i < info->partition_items_.size(); ++i) { 83 const PartitionItem* const item = info->partition_items_[i]; 84 if (item->Matches(partition_id) && 85 extension->ResourceMatches(item->accessible_resources(), 86 relative_path)) { 87 return true; 88 } 89 } 90 91 return false; 92} 93 94void WebviewInfo::AddPartitionItem(scoped_ptr<PartitionItem> item) { 95 partition_items_.push_back(item.release()); 96} 97 98WebviewHandler::WebviewHandler() { 99} 100 101WebviewHandler::~WebviewHandler() { 102} 103 104bool WebviewHandler::Parse(Extension* extension, base::string16* error) { 105 scoped_ptr<WebviewInfo> info(new WebviewInfo()); 106 107 const base::DictionaryValue* dict_value = NULL; 108 if (!extension->manifest()->GetDictionary(keys::kWebview, 109 &dict_value)) { 110 *error = base::ASCIIToUTF16(errors::kInvalidWebview); 111 return false; 112 } 113 114 const base::ListValue* partition_list = NULL; 115 if (!dict_value->GetList(keys::kWebviewPartitions, &partition_list)) { 116 *error = base::ASCIIToUTF16(errors::kInvalidWebviewPartitionsList); 117 return false; 118 } 119 120 // The partition list must have at least one entry. 121 if (partition_list->GetSize() == 0) { 122 *error = base::ASCIIToUTF16(errors::kInvalidWebviewPartitionsList); 123 return false; 124 } 125 126 for (size_t i = 0; i < partition_list->GetSize(); ++i) { 127 const base::DictionaryValue* partition = NULL; 128 if (!partition_list->GetDictionary(i, &partition)) { 129 *error = ErrorUtils::FormatErrorMessageUTF16( 130 errors::kInvalidWebviewPartition, base::IntToString(i)); 131 return false; 132 } 133 134 std::string partition_pattern; 135 if (!partition->GetString(keys::kWebviewName, &partition_pattern)) { 136 *error = ErrorUtils::FormatErrorMessageUTF16( 137 errors::kInvalidWebviewPartitionName, base::IntToString(i)); 138 return false; 139 } 140 141 const base::ListValue* url_list = NULL; 142 if (!partition->GetList(keys::kWebviewAccessibleResources, 143 &url_list)) { 144 *error = base::ASCIIToUTF16( 145 errors::kInvalidWebviewAccessibleResourcesList); 146 return false; 147 } 148 149 // The URL list should have at least one entry. 150 if (url_list->GetSize() == 0) { 151 *error = base::ASCIIToUTF16( 152 errors::kInvalidWebviewAccessibleResourcesList); 153 return false; 154 } 155 156 scoped_ptr<PartitionItem> partition_item( 157 new PartitionItem(partition_pattern)); 158 159 for (size_t i = 0; i < url_list->GetSize(); ++i) { 160 std::string relative_path; 161 if (!url_list->GetString(i, &relative_path)) { 162 *error = ErrorUtils::FormatErrorMessageUTF16( 163 errors::kInvalidWebviewAccessibleResource, base::IntToString(i)); 164 return false; 165 } 166 URLPattern pattern(URLPattern::SCHEME_EXTENSION, 167 Extension::GetResourceURL(extension->url(), 168 relative_path).spec()); 169 partition_item->AddPattern(pattern); 170 } 171 info->AddPartitionItem(partition_item.Pass()); 172 } 173 174 extension->SetManifestData(keys::kWebviewAccessibleResources, info.release()); 175 return true; 176} 177 178const std::vector<std::string> WebviewHandler::Keys() const { 179 return SingleKey(keys::kWebview); 180} 181 182} // namespace extensions 183