• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
FileHandlerInfo()24 FileHandlerInfo::FileHandlerInfo() {}
~FileHandlerInfo()25 FileHandlerInfo::~FileHandlerInfo() {}
26 
FileHandlers()27 FileHandlers::FileHandlers() {}
~FileHandlers()28 FileHandlers::~FileHandlers() {}
29 
30 // static
GetFileHandlers(const Extension * extension)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 
FileHandlersParser()38 FileHandlersParser::FileHandlersParser() {
39 }
40 
~FileHandlersParser()41 FileHandlersParser::~FileHandlersParser() {
42 }
43 
LoadFileHandler(const std::string & handler_id,const base::DictionaryValue & handler_info,FileHandlersInfo * file_handlers,base::string16 * error)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 
Parse(Extension * extension,base::string16 * error)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 
Keys() const156 const std::vector<std::string> FileHandlersParser::Keys() const {
157   return SingleKey(keys::kFileHandlers);
158 }
159 
160 }  // namespace extensions
161