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