12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 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) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/api/file_handlers/file_handlers_parser.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/extension_manifest_constants.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/manifest.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/error_utils.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace keys = extension_manifest_keys; 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace extensions { 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FileHandlerInfo::FileHandlerInfo() {} 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FileHandlerInfo::~FileHandlerInfo() {} 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FileHandlers::FileHandlers() {} 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FileHandlers::~FileHandlers() {} 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::vector<FileHandlerInfo>* FileHandlers::GetFileHandlers( 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Extension* extension) { 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FileHandlers* info = static_cast<FileHandlers*>( 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension->GetManifestData(extension_manifest_keys::kFileHandlers)); 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return info ? &info->file_handlers : NULL; 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FileHandlersParser::FileHandlersParser() { 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FileHandlersParser::~FileHandlersParser() { 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool LoadFileHandler(const std::string& handler_id, 407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::DictionaryValue& handler_info, 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<FileHandlerInfo>* file_handlers, 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) string16* error) { 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(error); 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FileHandlerInfo handler; 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) handler.id = handler_id; 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::ListValue* mime_types = NULL; 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (handler_info.HasKey(keys::kFileHandlerTypes) && 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !handler_info.GetList(keys::kFileHandlerTypes, &mime_types)) { 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *error = ErrorUtils::FormatErrorMessageUTF16( 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension_manifest_errors::kInvalidFileHandlerType, handler_id); 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::ListValue* file_extensions = NULL; 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (handler_info.HasKey(keys::kFileHandlerExtensions) && 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !handler_info.GetList(keys::kFileHandlerExtensions, &file_extensions)) { 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *error = ErrorUtils::FormatErrorMessageUTF16( 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extension_manifest_errors::kInvalidFileHandlerExtension, handler_id); 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if ((!mime_types || mime_types->GetSize() == 0) && 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (!file_extensions || file_extensions->GetSize() == 0)) { 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *error = ErrorUtils::FormatErrorMessageUTF16( 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extension_manifest_errors::kInvalidFileHandlerNoTypeOrExtension, 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) handler_id); 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (handler_info.HasKey(keys::kFileHandlerTitle) && 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !handler_info.GetString(keys::kFileHandlerTitle, &handler.title)) { 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *error = ASCIIToUTF16(extension_manifest_errors::kInvalidFileHandlerTitle); 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (mime_types) { 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string type; 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < mime_types->GetSize(); ++i) { 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!mime_types->GetString(i, &type)) { 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *error = ErrorUtils::FormatErrorMessageUTF16( 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extension_manifest_errors::kInvalidFileHandlerTypeElement, 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) handler_id, 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string(base::IntToString(i))); 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) handler.types.insert(type); 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (file_extensions) { 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string file_extension; 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < file_extensions->GetSize(); ++i) { 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!file_extensions->GetString(i, &file_extension)) { 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *error = ErrorUtils::FormatErrorMessageUTF16( 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extension_manifest_errors::kInvalidFileHandlerExtensionElement, 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) handler_id, 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string(base::IntToString(i))); 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) handler.extensions.insert(file_extension); 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) file_handlers->push_back(handler); 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool FileHandlersParser::Parse(Extension* extension, string16* error) { 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<FileHandlers> info(new FileHandlers); 1127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::DictionaryValue* all_handlers = NULL; 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!extension->manifest()->GetDictionary(keys::kFileHandlers, 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &all_handlers)) { 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *error = ASCIIToUTF16(extension_manifest_errors::kInvalidFileHandlers); 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(extension->is_platform_app()); 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) for (base::DictionaryValue::Iterator iter(*all_handlers); !iter.IsAtEnd(); 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter.Advance()) { 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // A file handler entry is a title and a list of MIME types to handle. 1247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::DictionaryValue* handler = NULL; 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (iter.value().GetAsDictionary(&handler)) { 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!LoadFileHandler(iter.key(), *handler, &info->file_handlers, error)) 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *error = ASCIIToUTF16(extension_manifest_errors::kInvalidFileHandlers); 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension->SetManifestData(keys::kFileHandlers, info.release()); 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::vector<std::string> FileHandlersParser::Keys() const { 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return SingleKey(keys::kFileHandlers); 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace extensions 143