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