| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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 "chrome/browser/chromeos/extensions/file_browser_handler.h" | |
| 6 | |
| 7 #include "base/logging.h" | |
| 8 #include "base/string_util.h" | |
| 9 #include "base/strings/string_number_conversions.h" | |
| 10 #include "base/utf_string_conversions.h" | |
| 11 #include "base/values.h" | |
| 12 #include "chrome/common/extensions/extension_constants.h" | |
| 13 #include "chrome/common/extensions/extension_manifest_constants.h" | |
| 14 #include "chrome/common/extensions/manifest.h" | |
| 15 #include "content/public/common/url_constants.h" | |
| 16 #include "extensions/common/error_utils.h" | |
| 17 #include "extensions/common/url_pattern.h" | |
| 18 #include "googleurl/src/gurl.h" | |
| 19 #include "googleurl/src/url_util.h" | |
| 20 | |
| 21 namespace keys = extension_manifest_keys; | |
| 22 namespace errors = extension_manifest_errors; | |
| 23 | |
| 24 namespace { | |
| 25 | |
| 26 const char kReadAccessString[] = "read"; | |
| 27 const char kReadWriteAccessString[] = "read-write"; | |
| 28 const char kCreateAccessString[] = "create"; | |
| 29 | |
| 30 unsigned int kPermissionsNotDefined = 0; | |
| 31 unsigned int kReadPermission = 1; | |
| 32 unsigned int kWritePermission = 1 << 1; | |
| 33 unsigned int kCreatePermission = 1 << 2; | |
| 34 unsigned int kInvalidPermission = 1 << 3; | |
| 35 | |
| 36 unsigned int GetAccessPermissionFlagFromString(const std::string& access_str) { | |
| 37 if (access_str == kReadAccessString) | |
| 38 return kReadPermission; | |
| 39 if (access_str == kReadWriteAccessString) | |
| 40 return kReadPermission | kWritePermission; | |
| 41 if (access_str == kCreateAccessString) | |
| 42 return kCreatePermission; | |
| 43 return kInvalidPermission; | |
| 44 } | |
| 45 | |
| 46 // Stored on the Extension. | |
| 47 struct FileBrowserHandlerInfo : public extensions::Extension::ManifestData { | |
| 48 FileBrowserHandler::List file_browser_handlers; | |
| 49 | |
| 50 FileBrowserHandlerInfo(); | |
| 51 virtual ~FileBrowserHandlerInfo(); | |
| 52 }; | |
| 53 | |
| 54 FileBrowserHandlerInfo::FileBrowserHandlerInfo() { | |
| 55 } | |
| 56 | |
| 57 FileBrowserHandlerInfo::~FileBrowserHandlerInfo() { | |
| 58 } | |
| 59 | |
| 60 } // namespace | |
| 61 | |
| 62 FileBrowserHandler::FileBrowserHandler() | |
| 63 : file_access_permission_flags_(kPermissionsNotDefined) { | |
| 64 } | |
| 65 | |
| 66 FileBrowserHandler::~FileBrowserHandler() { | |
| 67 } | |
| 68 | |
| 69 void FileBrowserHandler::AddPattern(const URLPattern& pattern) { | |
| 70 url_set_.AddPattern(pattern); | |
| 71 } | |
| 72 | |
| 73 void FileBrowserHandler::ClearPatterns() { | |
| 74 url_set_.ClearPatterns(); | |
| 75 } | |
| 76 | |
| 77 bool FileBrowserHandler::MatchesURL(const GURL& url) const { | |
| 78 return url_set_.MatchesURL(url); | |
| 79 } | |
| 80 | |
| 81 bool FileBrowserHandler::AddFileAccessPermission( | |
| 82 const std::string& access) { | |
| 83 file_access_permission_flags_ |= GetAccessPermissionFlagFromString(access); | |
| 84 return (file_access_permission_flags_ & kInvalidPermission) != 0U; | |
| 85 } | |
| 86 | |
| 87 bool FileBrowserHandler::ValidateFileAccessPermissions() { | |
| 88 bool is_invalid = (file_access_permission_flags_ & kInvalidPermission) != 0U; | |
| 89 bool can_create = (file_access_permission_flags_ & kCreatePermission) != 0U; | |
| 90 bool can_read_or_write = (file_access_permission_flags_ & | |
| 91 (kReadPermission | kWritePermission)) != 0U; | |
| 92 if (is_invalid || (can_create && can_read_or_write)) { | |
| 93 file_access_permission_flags_ = kInvalidPermission; | |
| 94 return false; | |
| 95 } | |
| 96 | |
| 97 if (file_access_permission_flags_ == kPermissionsNotDefined) | |
| 98 file_access_permission_flags_ = kReadPermission | kWritePermission; | |
| 99 return true; | |
| 100 } | |
| 101 | |
| 102 bool FileBrowserHandler::CanRead() const { | |
| 103 DCHECK(!(file_access_permission_flags_ & kInvalidPermission)); | |
| 104 return (file_access_permission_flags_ & kReadPermission) != 0; | |
| 105 } | |
| 106 | |
| 107 bool FileBrowserHandler::CanWrite() const { | |
| 108 DCHECK(!(file_access_permission_flags_ & kInvalidPermission)); | |
| 109 return (file_access_permission_flags_ & kWritePermission) != 0; | |
| 110 } | |
| 111 | |
| 112 bool FileBrowserHandler::HasCreateAccessPermission() const { | |
| 113 DCHECK(!(file_access_permission_flags_ & kInvalidPermission)); | |
| 114 return (file_access_permission_flags_ & kCreatePermission) != 0; | |
| 115 } | |
| 116 | |
| 117 // static | |
| 118 FileBrowserHandler::List* | |
| 119 FileBrowserHandler::GetHandlers(const extensions::Extension* extension) { | |
| 120 FileBrowserHandlerInfo* info = static_cast<FileBrowserHandlerInfo*>( | |
| 121 extension->GetManifestData(keys::kFileBrowserHandlers)); | |
| 122 if (info) | |
| 123 return &info->file_browser_handlers; | |
| 124 return NULL; | |
| 125 } | |
| 126 | |
| 127 FileBrowserHandlerParser::FileBrowserHandlerParser() { | |
| 128 } | |
| 129 | |
| 130 FileBrowserHandlerParser::~FileBrowserHandlerParser() { | |
| 131 } | |
| 132 | |
| 133 namespace { | |
| 134 | |
| 135 FileBrowserHandler* LoadFileBrowserHandler( | |
| 136 const std::string& extension_id, | |
| 137 const DictionaryValue* file_browser_handler, | |
| 138 string16* error) { | |
| 139 scoped_ptr<FileBrowserHandler> result(new FileBrowserHandler()); | |
| 140 result->set_extension_id(extension_id); | |
| 141 | |
| 142 std::string handler_id; | |
| 143 // Read the file action |id| (mandatory). | |
| 144 if (!file_browser_handler->HasKey(keys::kPageActionId) || | |
| 145 !file_browser_handler->GetString(keys::kPageActionId, &handler_id)) { | |
| 146 *error = ASCIIToUTF16(errors::kInvalidPageActionId); | |
| 147 return NULL; | |
| 148 } | |
| 149 result->set_id(handler_id); | |
| 150 | |
| 151 // Read the page action title from |default_title| (mandatory). | |
| 152 std::string title; | |
| 153 if (!file_browser_handler->HasKey(keys::kPageActionDefaultTitle) || | |
| 154 !file_browser_handler->GetString(keys::kPageActionDefaultTitle, &title)) { | |
| 155 *error = ASCIIToUTF16(errors::kInvalidPageActionDefaultTitle); | |
| 156 return NULL; | |
| 157 } | |
| 158 result->set_title(title); | |
| 159 | |
| 160 // Initialize access permissions (optional). | |
| 161 const ListValue* access_list_value = NULL; | |
| 162 if (file_browser_handler->HasKey(keys::kFileAccessList)) { | |
| 163 if (!file_browser_handler->GetList(keys::kFileAccessList, | |
| 164 &access_list_value) || | |
| 165 access_list_value->empty()) { | |
| 166 *error = ASCIIToUTF16(errors::kInvalidFileAccessList); | |
| 167 return NULL; | |
| 168 } | |
| 169 for (size_t i = 0; i < access_list_value->GetSize(); ++i) { | |
| 170 std::string access; | |
| 171 if (!access_list_value->GetString(i, &access) || | |
| 172 result->AddFileAccessPermission(access)) { | |
| 173 *error = extensions::ErrorUtils::FormatErrorMessageUTF16( | |
| 174 errors::kInvalidFileAccessValue, base::IntToString(i)); | |
| 175 return NULL; | |
| 176 } | |
| 177 } | |
| 178 } | |
| 179 if (!result->ValidateFileAccessPermissions()) { | |
| 180 *error = ASCIIToUTF16(errors::kInvalidFileAccessList); | |
| 181 return NULL; | |
| 182 } | |
| 183 | |
| 184 // Initialize file filters (mandatory, unless "create" access is specified, | |
| 185 // in which case is ignored). | |
| 186 if (!result->HasCreateAccessPermission()) { | |
| 187 const ListValue* file_filters = NULL; | |
| 188 if (!file_browser_handler->HasKey(keys::kFileFilters) || | |
| 189 !file_browser_handler->GetList(keys::kFileFilters, &file_filters) || | |
| 190 file_filters->empty()) { | |
| 191 *error = ASCIIToUTF16(errors::kInvalidFileFiltersList); | |
| 192 return NULL; | |
| 193 } | |
| 194 for (size_t i = 0; i < file_filters->GetSize(); ++i) { | |
| 195 std::string filter; | |
| 196 if (!file_filters->GetString(i, &filter)) { | |
| 197 *error = extensions::ErrorUtils::FormatErrorMessageUTF16( | |
| 198 errors::kInvalidFileFilterValue, base::IntToString(i)); | |
| 199 return NULL; | |
| 200 } | |
| 201 StringToLowerASCII(&filter); | |
| 202 if (!StartsWithASCII(filter, | |
| 203 std::string(chrome::kFileSystemScheme) + ':', | |
| 204 true)) { | |
| 205 *error = extensions::ErrorUtils::FormatErrorMessageUTF16( | |
| 206 errors::kInvalidURLPatternError, filter); | |
| 207 return NULL; | |
| 208 } | |
| 209 // The user inputs filesystem:*; we don't actually implement scheme | |
| 210 // wildcards in URLPattern, so transform to what will match correctly. | |
| 211 filter.replace(0, 11, "chrome-extension://*/"); | |
| 212 URLPattern pattern(URLPattern::SCHEME_EXTENSION); | |
| 213 if (pattern.Parse(filter) != URLPattern::PARSE_SUCCESS) { | |
| 214 *error = extensions::ErrorUtils::FormatErrorMessageUTF16( | |
| 215 errors::kInvalidURLPatternError, filter); | |
| 216 return NULL; | |
| 217 } | |
| 218 std::string path = pattern.path(); | |
| 219 bool allowed = path == "/*" || path == "/*.*" || | |
| 220 (path.compare(0, 3, "/*.") == 0 && | |
| 221 path.find_first_of('*', 3) == std::string::npos); | |
| 222 if (!allowed) { | |
| 223 *error = extensions::ErrorUtils::FormatErrorMessageUTF16( | |
| 224 errors::kInvalidURLPatternError, filter); | |
| 225 return NULL; | |
| 226 } | |
| 227 result->AddPattern(pattern); | |
| 228 } | |
| 229 } | |
| 230 | |
| 231 std::string default_icon; | |
| 232 // Read the file browser action |default_icon| (optional). | |
| 233 if (file_browser_handler->HasKey(keys::kPageActionDefaultIcon)) { | |
| 234 if (!file_browser_handler->GetString( | |
| 235 keys::kPageActionDefaultIcon, &default_icon) || | |
| 236 default_icon.empty()) { | |
| 237 *error = ASCIIToUTF16(errors::kInvalidPageActionIconPath); | |
| 238 return NULL; | |
| 239 } | |
| 240 result->set_icon_path(default_icon); | |
| 241 } | |
| 242 | |
| 243 return result.release(); | |
| 244 } | |
| 245 | |
| 246 // Loads FileBrowserHandlers from |extension_actions| into a list in |result|. | |
| 247 bool LoadFileBrowserHandlers( | |
| 248 const std::string& extension_id, | |
| 249 const ListValue* extension_actions, | |
| 250 FileBrowserHandler::List* result, | |
| 251 string16* error) { | |
| 252 for (ListValue::const_iterator iter = extension_actions->begin(); | |
| 253 iter != extension_actions->end(); | |
| 254 ++iter) { | |
| 255 if (!(*iter)->IsType(Value::TYPE_DICTIONARY)) { | |
| 256 *error = ASCIIToUTF16(errors::kInvalidFileBrowserHandler); | |
| 257 return false; | |
| 258 } | |
| 259 scoped_ptr<FileBrowserHandler> action( | |
| 260 LoadFileBrowserHandler( | |
| 261 extension_id, reinterpret_cast<DictionaryValue*>(*iter), error)); | |
| 262 if (!action.get()) | |
| 263 return false; // Failed to parse file browser action definition. | |
| 264 result->push_back(linked_ptr<FileBrowserHandler>(action.release())); | |
| 265 } | |
| 266 return true; | |
| 267 } | |
| 268 | |
| 269 } // namespace | |
| 270 | |
| 271 bool FileBrowserHandlerParser::Parse(extensions::Extension* extension, | |
| 272 string16* error) { | |
| 273 const ListValue* file_browser_handlers_value = NULL; | |
| 274 if (!extension->manifest()->GetList(keys::kFileBrowserHandlers, | |
| 275 &file_browser_handlers_value)) { | |
| 276 *error = ASCIIToUTF16(errors::kInvalidFileBrowserHandler); | |
| 277 return false; | |
| 278 } | |
| 279 scoped_ptr<FileBrowserHandlerInfo> info(new FileBrowserHandlerInfo); | |
| 280 if (!LoadFileBrowserHandlers(extension->id(), | |
| 281 file_browser_handlers_value, | |
| 282 &info->file_browser_handlers, | |
| 283 error)) { | |
| 284 return false; // Failed to parse file browser actions definition. | |
| 285 } | |
| 286 | |
| 287 extension->SetManifestData(keys::kFileBrowserHandlers, info.release()); | |
| 288 return true; | |
| 289 } | |
| 290 | |
| 291 const std::vector<std::string> FileBrowserHandlerParser::Keys() const { | |
| 292 return SingleKey(keys::kFileBrowserHandlers); | |
| 293 } | |
| OLD | NEW |