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/file_handler_info.h" 6 7 #include "base/memory/scoped_ptr.h" 8 #include "base/strings/string_number_conversions.h" 9 #include "base/strings/utf_string_conversions.h" 10 #include "base/values.h" 11 #include "extensions/common/error_utils.h" 12 #include "extensions/common/manifest.h" 13 #include "extensions/common/manifest_constants.h" 14 15 namespace extensions { 16 17 namespace keys = manifest_keys; 18 namespace errors = manifest_errors; 19 20 namespace { 21 const int kMaxTypeAndExtensionHandlers = 200; 22 } 23 24 FileHandlerInfo::FileHandlerInfo() {} 25 FileHandlerInfo::~FileHandlerInfo() {} 26 27 FileHandlers::FileHandlers() {} 28 FileHandlers::~FileHandlers() {} 29 30 // static 31 const FileHandlersInfo* FileHandlers::GetFileHandlers( 32 const Extension* extension) { 33 FileHandlers* info = static_cast<FileHandlers*>( 34 extension->GetManifestData(keys::kFileHandlers)); 35 return info ? &info->file_handlers : NULL; 36 } 37 38 FileHandlersParser::FileHandlersParser() { 39 } 40 41 FileHandlersParser::~FileHandlersParser() { 42 } 43 44 bool LoadFileHandler(const std::string& handler_id, 45 const base::DictionaryValue& handler_info, 46 FileHandlersInfo* file_handlers, 47 base::string16* error) { 48 DCHECK(error); 49 FileHandlerInfo handler; 50 51 handler.id = handler_id; 52 53 const base::ListValue* mime_types = NULL; 54 if (handler_info.HasKey(keys::kFileHandlerTypes) && 55 !handler_info.GetList(keys::kFileHandlerTypes, &mime_types)) { 56 *error = ErrorUtils::FormatErrorMessageUTF16( 57 errors::kInvalidFileHandlerType, handler_id); 58 return false; 59 } 60 61 const base::ListValue* file_extensions = NULL; 62 if (handler_info.HasKey(keys::kFileHandlerExtensions) && 63 !handler_info.GetList(keys::kFileHandlerExtensions, &file_extensions)) { 64 *error = ErrorUtils::FormatErrorMessageUTF16( 65 errors::kInvalidFileHandlerExtension, handler_id); 66 return false; 67 } 68 69 if ((!mime_types || mime_types->empty()) && 70 (!file_extensions || file_extensions->empty())) { 71 *error = ErrorUtils::FormatErrorMessageUTF16( 72 errors::kInvalidFileHandlerNoTypeOrExtension, 73 handler_id); 74 return false; 75 } 76 77 if (handler_info.HasKey(keys::kFileHandlerTitle) && 78 !handler_info.GetString(keys::kFileHandlerTitle, &handler.title)) { 79 *error = base::ASCIIToUTF16(errors::kInvalidFileHandlerTitle); 80 return false; 81 } 82 83 if (mime_types) { 84 std::string type; 85 for (size_t i = 0; i < mime_types->GetSize(); ++i) { 86 if (!mime_types->GetString(i, &type)) { 87 *error = ErrorUtils::FormatErrorMessageUTF16( 88 errors::kInvalidFileHandlerTypeElement, 89 handler_id, 90 std::string(base::IntToString(i))); 91 return false; 92 } 93 handler.types.insert(type); 94 } 95 } 96 97 if (file_extensions) { 98 std::string file_extension; 99 for (size_t i = 0; i < file_extensions->GetSize(); ++i) { 100 if (!file_extensions->GetString(i, &file_extension)) { 101 *error = ErrorUtils::FormatErrorMessageUTF16( 102 errors::kInvalidFileHandlerExtensionElement, 103 handler_id, 104 std::string(base::IntToString(i))); 105 return false; 106 } 107 handler.extensions.insert(file_extension); 108 } 109 } 110 111 file_handlers->push_back(handler); 112 return true; 113 } 114 115 bool FileHandlersParser::Parse(Extension* extension, base::string16* error) { 116 scoped_ptr<FileHandlers> info(new FileHandlers); 117 const base::DictionaryValue* all_handlers = NULL; 118 if (!extension->manifest()->GetDictionary(keys::kFileHandlers, 119 &all_handlers)) { 120 *error = base::ASCIIToUTF16(errors::kInvalidFileHandlers); 121 return false; 122 } 123 124 for (base::DictionaryValue::Iterator iter(*all_handlers); 125 !iter.IsAtEnd(); 126 iter.Advance()) { 127 // A file handler entry is a title and a list of MIME types to handle. 128 const base::DictionaryValue* handler = NULL; 129 if (iter.value().GetAsDictionary(&handler)) { 130 if (!LoadFileHandler(iter.key(), *handler, &info->file_handlers, error)) 131 return false; 132 } else { 133 *error = base::ASCIIToUTF16(errors::kInvalidFileHandlers); 134 return false; 135 } 136 } 137 138 int filter_count = 0; 139 for (FileHandlersInfo::const_iterator iter = info->file_handlers.begin(); 140 iter != info->file_handlers.end(); 141 iter++) { 142 filter_count += iter->types.size(); 143 filter_count += iter->extensions.size(); 144 } 145 146 if (filter_count > kMaxTypeAndExtensionHandlers) { 147 *error = base::ASCIIToUTF16( 148 errors::kInvalidFileHandlersTooManyTypesAndExtensions); 149 return false; 150 } 151 152 extension->SetManifestData(keys::kFileHandlers, info.release()); 153 return true; 154 } 155 156 const std::vector<std::string> FileHandlersParser::Keys() const { 157 return SingleKey(keys::kFileHandlers); 158 } 159 160 } // namespace extensions 161