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.
5 #include "extensions/common/manifest_handlers/shared_module_info.h"
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"
18 namespace extensions
{
20 namespace keys
= manifest_keys
;
21 namespace values
= manifest_values
;
22 namespace errors
= manifest_errors
;
26 const char kSharedModule
[] = "shared_module";
28 static base::LazyInstance
<SharedModuleInfo
> g_empty_shared_module_info
=
29 LAZY_INSTANCE_INITIALIZER
;
31 const SharedModuleInfo
& GetSharedModuleInfo(const Extension
* extension
) {
32 SharedModuleInfo
* info
= static_cast<SharedModuleInfo
*>(
33 extension
->GetManifestData(kSharedModule
));
35 return g_empty_shared_module_info
.Get();
41 SharedModuleInfo::SharedModuleInfo() {
44 SharedModuleInfo::~SharedModuleInfo() {
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
];
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])) {
74 bool SharedModuleInfo::IsSharedModule(const Extension
* extension
) {
76 return extension
->manifest()->is_shared_module();
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
));
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
)
98 bool SharedModuleInfo::ImportsModules(const Extension
* extension
) {
99 return GetSharedModuleInfo(extension
).imports_
.size() > 0;
103 const std::vector
<SharedModuleInfo::ImportInfo
>& SharedModuleInfo::GetImports(
104 const Extension
* extension
) {
105 return GetSharedModuleInfo(extension
).imports_
;
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
)
114 if (has_import
&& has_export
) {
115 *error
= ASCIIToUTF16(errors::kInvalidImportAndExport
);
120 const base::DictionaryValue
* export_value
= NULL
;
121 if (!extension
->manifest()->GetDictionary(keys::kExport
, &export_value
)) {
122 *error
= ASCIIToUTF16(errors::kInvalidExport
);
125 const base::ListValue
* resources_list
= NULL
;
126 if (!export_value
->GetList(keys::kResources
, &resources_list
)) {
127 *error
= ASCIIToUTF16(errors::kInvalidExportResources
);
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
));
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
));
143 exported_set_
.AddPattern(
144 URLPattern(URLPattern::SCHEME_EXTENSION
, resolved_path
.spec()));
149 const base::ListValue
* import_list
= NULL
;
150 if (!extension
->manifest()->GetList(keys::kImport
, &import_list
)) {
151 *error
= ASCIIToUTF16(errors::kInvalidImport
);
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
);
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
));
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
));
176 imports_
.back().minimum_version
= min_version
;
177 Version
v(min_version
);
179 *error
= ErrorUtils::FormatErrorMessageUTF16(
180 errors::kInvalidImportVersion
, base::IntToString(i
));
190 SharedModuleHandler::SharedModuleHandler() {
193 SharedModuleHandler::~SharedModuleHandler() {
196 bool SharedModuleHandler::Parse(Extension
* extension
, string16
* error
) {
197 scoped_ptr
<SharedModuleInfo
> info(new SharedModuleInfo
);
198 if (!info
->Parse(extension
, error
))
200 extension
->SetManifestData(kSharedModule
, info
.release());
204 bool SharedModuleHandler::Validate(
205 const Extension
* extension
,
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
211 if (SharedModuleInfo::IsSharedModule(extension
) &&
212 !extension
->GetActivePermissions()->IsEmpty()) {
213 *error
= errors::kInvalidExportPermissions
;
219 const std::vector
<std::string
> SharedModuleHandler::Keys() const {
220 static const char* keys
[] = {
224 return std::vector
<std::string
>(keys
, keys
+ arraysize(keys
));
227 } // namespace extensions