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