• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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/shared_module_info.h"
6 
7 #include "base/lazy_instance.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/version.h"
13 #include "extensions/common/constants.h"
14 #include "extensions/common/error_utils.h"
15 #include "extensions/common/manifest_constants.h"
16 #include "extensions/common/permissions/permission_set.h"
17 
18 namespace extensions {
19 
20 namespace keys = manifest_keys;
21 namespace values = manifest_values;
22 namespace errors = manifest_errors;
23 
24 namespace {
25 
26 const char kSharedModule[] = "shared_module";
27 
28 static base::LazyInstance<SharedModuleInfo> g_empty_shared_module_info =
29     LAZY_INSTANCE_INITIALIZER;
30 
GetSharedModuleInfo(const Extension * extension)31 const SharedModuleInfo& GetSharedModuleInfo(const Extension* extension) {
32   SharedModuleInfo* info = static_cast<SharedModuleInfo*>(
33       extension->GetManifestData(kSharedModule));
34   if (!info)
35     return g_empty_shared_module_info.Get();
36   return *info;
37 }
38 
39 }  // namespace
40 
SharedModuleInfo()41 SharedModuleInfo::SharedModuleInfo() {
42 }
43 
~SharedModuleInfo()44 SharedModuleInfo::~SharedModuleInfo() {
45 }
46 
47 // static
ParseImportedPath(const std::string & path,std::string * import_id,std::string * import_relative_path)48 void SharedModuleInfo::ParseImportedPath(const std::string& path,
49                                          std::string* import_id,
50                                          std::string* import_relative_path) {
51   std::vector<std::string> tokens;
52   Tokenize(path, std::string("/"), &tokens);
53   if (tokens.size() > 2 && tokens[0] == kModulesDir &&
54       Extension::IdIsValid(tokens[1])) {
55     *import_id = tokens[1];
56     *import_relative_path = tokens[2];
57     for (size_t i = 3; i < tokens.size(); ++i)
58       *import_relative_path += "/" + tokens[i];
59   }
60 }
61 
62 // static
IsImportedPath(const std::string & path)63 bool SharedModuleInfo::IsImportedPath(const std::string& path) {
64   std::vector<std::string> tokens;
65   Tokenize(path, std::string("/"), &tokens);
66   if (tokens.size() > 2 && tokens[0] == kModulesDir &&
67       Extension::IdIsValid(tokens[1])) {
68     return true;
69   }
70   return false;
71 }
72 
73 // static
IsSharedModule(const Extension * extension)74 bool SharedModuleInfo::IsSharedModule(const Extension* extension) {
75   CHECK(extension);
76   return extension->manifest()->is_shared_module();
77 }
78 
79 // static
IsExportAllowed(const Extension * extension,const std::string & relative_path)80 bool SharedModuleInfo::IsExportAllowed(const Extension* extension,
81                                        const std::string& relative_path) {
82   return GetSharedModuleInfo(extension).
83       exported_set_.MatchesURL(extension->url().Resolve(relative_path));
84 }
85 
86 // static
ImportsExtensionById(const Extension * extension,const std::string & other_id)87 bool SharedModuleInfo::ImportsExtensionById(const Extension* extension,
88                                             const std::string& other_id) {
89   const SharedModuleInfo& info = GetSharedModuleInfo(extension);
90   for (size_t i = 0; i < info.imports_.size(); i++) {
91     if (info.imports_[i].extension_id == other_id)
92       return true;
93   }
94   return false;
95 }
96 
97 // static
ImportsModules(const Extension * extension)98 bool SharedModuleInfo::ImportsModules(const Extension* extension) {
99   return GetSharedModuleInfo(extension).imports_.size() > 0;
100 }
101 
102 // static
GetImports(const Extension * extension)103 const std::vector<SharedModuleInfo::ImportInfo>& SharedModuleInfo::GetImports(
104     const Extension* extension) {
105   return GetSharedModuleInfo(extension).imports_;
106 }
107 
Parse(const Extension * extension,string16 * error)108 bool SharedModuleInfo::Parse(const Extension* extension, string16* error) {
109   bool has_import = extension->manifest()->HasKey(keys::kImport);
110   bool has_export = extension->manifest()->HasKey(keys::kExport);
111   if (!has_import && !has_export)
112     return true;
113 
114   if (has_import && has_export) {
115     *error = ASCIIToUTF16(errors::kInvalidImportAndExport);
116     return false;
117   }
118 
119   if (has_export) {
120     const base::DictionaryValue* export_value = NULL;
121     if (!extension->manifest()->GetDictionary(keys::kExport, &export_value)) {
122       *error = ASCIIToUTF16(errors::kInvalidExport);
123       return false;
124     }
125     const base::ListValue* resources_list = NULL;
126     if (!export_value->GetList(keys::kResources, &resources_list)) {
127       *error = ASCIIToUTF16(errors::kInvalidExportResources);
128       return false;
129     }
130     for (size_t i = 0; i < resources_list->GetSize(); ++i) {
131       std::string resource_path;
132       if (!resources_list->GetString(i, &resource_path)) {
133         *error = ErrorUtils::FormatErrorMessageUTF16(
134             errors::kInvalidExportResourcesString, base::IntToString(i));
135         return false;
136       }
137       const GURL& resolved_path = extension->url().Resolve(resource_path);
138       if (!resolved_path.is_valid()) {
139         *error = ErrorUtils::FormatErrorMessageUTF16(
140             errors::kInvalidExportResourcesString, base::IntToString(i));
141         return false;
142       }
143       exported_set_.AddPattern(
144           URLPattern(URLPattern::SCHEME_EXTENSION, resolved_path.spec()));
145     }
146   }
147 
148   if (has_import) {
149     const base::ListValue* import_list = NULL;
150     if (!extension->manifest()->GetList(keys::kImport, &import_list)) {
151       *error = ASCIIToUTF16(errors::kInvalidImport);
152       return false;
153     }
154     for (size_t i = 0; i < import_list->GetSize(); ++i) {
155       const base::DictionaryValue* import_entry = NULL;
156       if (!import_list->GetDictionary(i, &import_entry)) {
157         *error = ASCIIToUTF16(errors::kInvalidImport);
158         return false;
159       }
160       std::string extension_id;
161       imports_.push_back(ImportInfo());
162       if (!import_entry->GetString(keys::kId, &extension_id) ||
163           !Extension::IdIsValid(extension_id)) {
164         *error = ErrorUtils::FormatErrorMessageUTF16(
165             errors::kInvalidImportId, base::IntToString(i));
166         return false;
167       }
168       imports_.back().extension_id = extension_id;
169       if (import_entry->HasKey(keys::kMinimumVersion)) {
170         std::string min_version;
171         if (!import_entry->GetString(keys::kMinimumVersion, &min_version)) {
172           *error = ErrorUtils::FormatErrorMessageUTF16(
173               errors::kInvalidImportVersion, base::IntToString(i));
174           return false;
175         }
176         imports_.back().minimum_version = min_version;
177         Version v(min_version);
178         if (!v.IsValid()) {
179           *error = ErrorUtils::FormatErrorMessageUTF16(
180               errors::kInvalidImportVersion, base::IntToString(i));
181           return false;
182         }
183       }
184     }
185   }
186   return true;
187 }
188 
189 
SharedModuleHandler()190 SharedModuleHandler::SharedModuleHandler() {
191 }
192 
~SharedModuleHandler()193 SharedModuleHandler::~SharedModuleHandler() {
194 }
195 
Parse(Extension * extension,string16 * error)196 bool SharedModuleHandler::Parse(Extension* extension, string16* error) {
197   scoped_ptr<SharedModuleInfo> info(new SharedModuleInfo);
198   if (!info->Parse(extension, error))
199     return false;
200   extension->SetManifestData(kSharedModule, info.release());
201   return true;
202 }
203 
Validate(const Extension * extension,std::string * error,std::vector<InstallWarning> * warnings) const204 bool SharedModuleHandler::Validate(
205     const Extension* extension,
206     std::string* error,
207     std::vector<InstallWarning>* warnings) const {
208   // Extensions that export resources should not have any permissions of their
209   // own, instead they rely on the permissions of the extensions which import
210   // them.
211   if (SharedModuleInfo::IsSharedModule(extension) &&
212       !extension->GetActivePermissions()->IsEmpty()) {
213     *error = errors::kInvalidExportPermissions;
214     return false;
215   }
216   return true;
217 }
218 
Keys() const219 const std::vector<std::string> SharedModuleHandler::Keys() const {
220   static const char* keys[] = {
221     keys::kExport,
222     keys::kImport
223   };
224   return std::vector<std::string>(keys, keys + arraysize(keys));
225 }
226 
227 }  // namespace extensions
228