Home | History | Annotate | Download | only in manifest_handlers
      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