1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/common/manifest_handlers/file_handler_info.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/strings/stringprintf.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/error_utils.h" 133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/manifest.h" 14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "extensions/common/manifest_constants.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace extensions { 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace keys = manifest_keys; 19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace errors = manifest_errors; 20d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace { 22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const int kMaxTypeAndExtensionHandlers = 200; 23116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst char kNotRecognized[] = "'%s' is not a recognized file handler property."; 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)FileHandlerInfo::FileHandlerInfo() {} 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)FileHandlerInfo::~FileHandlerInfo() {} 28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FileHandlers::FileHandlers() {} 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FileHandlers::~FileHandlers() {} 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const FileHandlersInfo* FileHandlers::GetFileHandlers( 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Extension* extension) { 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FileHandlers* info = static_cast<FileHandlers*>( 363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) extension->GetManifestData(keys::kFileHandlers)); 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return info ? &info->file_handlers : NULL; 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FileHandlersParser::FileHandlersParser() { 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FileHandlersParser::~FileHandlersParser() { 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool LoadFileHandler(const std::string& handler_id, 477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::DictionaryValue& handler_info, 48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FileHandlersInfo* file_handlers, 49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::string16* error, 50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::vector<InstallWarning>* install_warnings) { 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(error); 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FileHandlerInfo handler; 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) handler.id = handler_id; 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::ListValue* mime_types = NULL; 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (handler_info.HasKey(keys::kFileHandlerTypes) && 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !handler_info.GetList(keys::kFileHandlerTypes, &mime_types)) { 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *error = ErrorUtils::FormatErrorMessageUTF16( 603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) errors::kInvalidFileHandlerType, handler_id); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::ListValue* file_extensions = NULL; 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (handler_info.HasKey(keys::kFileHandlerExtensions) && 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !handler_info.GetList(keys::kFileHandlerExtensions, &file_extensions)) { 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *error = ErrorUtils::FormatErrorMessageUTF16( 683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) errors::kInvalidFileHandlerExtension, handler_id); 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if ((!mime_types || mime_types->empty()) && 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) (!file_extensions || file_extensions->empty())) { 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *error = ErrorUtils::FormatErrorMessageUTF16( 753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) errors::kInvalidFileHandlerNoTypeOrExtension, 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) handler_id); 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (mime_types) { 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string type; 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < mime_types->GetSize(); ++i) { 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!mime_types->GetString(i, &type)) { 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *error = ErrorUtils::FormatErrorMessageUTF16( 853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) errors::kInvalidFileHandlerTypeElement, 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) handler_id, 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string(base::IntToString(i))); 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) handler.types.insert(type); 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (file_extensions) { 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string file_extension; 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < file_extensions->GetSize(); ++i) { 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!file_extensions->GetString(i, &file_extension)) { 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *error = ErrorUtils::FormatErrorMessageUTF16( 993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) errors::kInvalidFileHandlerExtensionElement, 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) handler_id, 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string(base::IntToString(i))); 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) handler.extensions.insert(file_extension); 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) file_handlers->push_back(handler); 109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Check for unknown keys. 111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (base::DictionaryValue::Iterator it(handler_info); !it.IsAtEnd(); 112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch it.Advance()) { 113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (it.key() != keys::kFileHandlerExtensions && 114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch it.key() != keys::kFileHandlerTypes) { 115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch install_warnings->push_back( 116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch InstallWarning(base::StringPrintf(kNotRecognized, it.key().c_str()), 117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch keys::kFileHandlers, 118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch it.key())); 119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool FileHandlersParser::Parse(Extension* extension, base::string16* error) { 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<FileHandlers> info(new FileHandlers); 1277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::DictionaryValue* all_handlers = NULL; 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!extension->manifest()->GetDictionary(keys::kFileHandlers, 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &all_handlers)) { 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *error = base::ASCIIToUTF16(errors::kInvalidFileHandlers); 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::vector<InstallWarning> install_warnings; 135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (base::DictionaryValue::Iterator iter(*all_handlers); 136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) !iter.IsAtEnd(); 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter.Advance()) { 1387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::DictionaryValue* handler = NULL; 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (iter.value().GetAsDictionary(&handler)) { 140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!LoadFileHandler(iter.key(), 141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *handler, 142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &info->file_handlers, 143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch error, 144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &install_warnings)) 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *error = base::ASCIIToUTF16(errors::kInvalidFileHandlers); 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int filter_count = 0; 153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (FileHandlersInfo::const_iterator iter = info->file_handlers.begin(); 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) iter != info->file_handlers.end(); 155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) iter++) { 156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) filter_count += iter->types.size(); 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) filter_count += iter->extensions.size(); 158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (filter_count > kMaxTypeAndExtensionHandlers) { 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *error = base::ASCIIToUTF16( 162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) errors::kInvalidFileHandlersTooManyTypesAndExtensions); 163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension->SetManifestData(keys::kFileHandlers, info.release()); 167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extension->AddInstallWarnings(install_warnings); 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::vector<std::string> FileHandlersParser::Keys() const { 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return SingleKey(keys::kFileHandlers); 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace extensions 176