Index: chrome/common/extensions/manifest_handlers/shared_module_info.cc |
diff --git a/chrome/common/extensions/manifest_handlers/shared_module_info.cc b/chrome/common/extensions/manifest_handlers/shared_module_info.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..3ead0166a66e7eb89a21295f5aee91d00cd5ab07 |
--- /dev/null |
+++ b/chrome/common/extensions/manifest_handlers/shared_module_info.cc |
@@ -0,0 +1,229 @@ |
+// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/common/extensions/manifest_handlers/shared_module_info.h" |
+ |
+#include "base/lazy_instance.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/string_util.h" |
+#include "base/strings/string_number_conversions.h" |
+#include "base/utf_string_conversions.h" |
+#include "base/version.h" |
+#include "chrome/common/extensions/extension_constants.h" |
+#include "chrome/common/extensions/extension_manifest_constants.h" |
+#include "chrome/common/extensions/permissions/permission_set.h" |
+#include "extensions/common/error_utils.h" |
+ |
+using base::DictionaryValue; |
+namespace keys = extension_manifest_keys; |
+namespace values = extension_manifest_values; |
+namespace errors = extension_manifest_errors; |
+ |
+namespace extensions { |
+ |
+namespace { |
+ |
+const char kSharedModule[] = "shared_module"; |
+ |
+static base::LazyInstance<SharedModuleInfo> g_empty_shared_module_info = |
+ LAZY_INSTANCE_INITIALIZER; |
+ |
+const SharedModuleInfo& GetSharedModuleInfo(const Extension* extension) { |
+ SharedModuleInfo* info = static_cast<SharedModuleInfo*>( |
+ extension->GetManifestData(kSharedModule)); |
+ if (!info) |
+ return g_empty_shared_module_info.Get(); |
+ return *info; |
+} |
+ |
+} // namespace |
+ |
+SharedModuleInfo::SharedModuleInfo() { |
+} |
+ |
+SharedModuleInfo::~SharedModuleInfo() { |
+} |
+ |
+// static |
+void SharedModuleInfo::ParseImportedPath(const std::string& path, |
+ std::string* import_id, |
+ std::string* import_relative_path) { |
+ std::vector<std::string> tokens; |
+ Tokenize(path, std::string("/"), &tokens); |
+ if (tokens.size() > 2 && tokens[0] == extension_filenames::kModulesDir && |
+ Extension::IdIsValid(tokens[1])) { |
+ *import_id = tokens[1]; |
+ *import_relative_path = tokens[2]; |
+ for (size_t i = 3; i < tokens.size(); ++i) |
+ *import_relative_path += "/" + tokens[i]; |
+ } |
+} |
+ |
+// static |
+bool SharedModuleInfo::IsImportedPath(const std::string& path) { |
+ std::vector<std::string> tokens; |
+ Tokenize(path, std::string("/"), &tokens); |
+ if (tokens.size() > 2 && tokens[0] == extension_filenames::kModulesDir && |
+ Extension::IdIsValid(tokens[1])) { |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+// static |
+bool SharedModuleInfo::IsSharedModule(const Extension* extension) { |
+ CHECK(extension); |
+ return extension->manifest()->is_shared_module(); |
+} |
+ |
+// static |
+bool SharedModuleInfo::IsExportAllowed(const Extension* extension, |
+ const std::string& relative_path) { |
+ return GetSharedModuleInfo(extension). |
+ exported_set_.MatchesURL(extension->url().Resolve(relative_path)); |
+} |
+ |
+// static |
+bool SharedModuleInfo::ImportsExtensionById(const Extension* extension, |
+ const std::string& other_id) { |
+ const SharedModuleInfo& info = GetSharedModuleInfo(extension); |
+ for (size_t i = 0; i < info.imports_.size(); i++) { |
+ if (info.imports_[i].extension_id == other_id) |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+// static |
+bool SharedModuleInfo::ImportsModules(const Extension* extension) { |
+ return GetSharedModuleInfo(extension).imports_.size() > 0; |
+} |
+ |
+// static |
+const std::vector<SharedModuleInfo::ImportInfo>& SharedModuleInfo::GetImports( |
+ const Extension* extension) { |
+ return GetSharedModuleInfo(extension).imports_; |
+} |
+ |
+bool SharedModuleInfo::Parse(const Extension* extension, string16* error) { |
+ bool has_import = extension->manifest()->HasKey(keys::kImport); |
+ bool has_export = extension->manifest()->HasKey(keys::kExport); |
+ if (!has_import && !has_export) |
+ return true; |
+ |
+ if (has_import && has_export) { |
+ *error = ASCIIToUTF16(errors::kInvalidImportAndExport); |
+ return false; |
+ } |
+ |
+ if (has_export) { |
+ const DictionaryValue* export_value = NULL; |
+ if (!extension->manifest()->GetDictionary(keys::kExport, &export_value)) { |
+ *error = ASCIIToUTF16(errors::kInvalidExport); |
+ return false; |
+ } |
+ const ListValue* resources_list = NULL; |
+ if (!export_value->GetList(keys::kResources, &resources_list)) { |
+ *error = ASCIIToUTF16(errors::kInvalidExportResources); |
+ return false; |
+ } |
+ for (size_t i = 0; i < resources_list->GetSize(); ++i) { |
+ std::string resource_path; |
+ if (!resources_list->GetString(i, &resource_path)) { |
+ *error = ErrorUtils::FormatErrorMessageUTF16( |
+ errors::kInvalidExportResourcesString, base::IntToString(i)); |
+ return false; |
+ } |
+ const GURL& resolved_path = extension->url().Resolve(resource_path); |
+ if (!resolved_path.is_valid()) { |
+ *error = ErrorUtils::FormatErrorMessageUTF16( |
+ errors::kInvalidExportResourcesString, base::IntToString(i)); |
+ return false; |
+ } |
+ exported_set_.AddPattern( |
+ URLPattern(URLPattern::SCHEME_EXTENSION, resolved_path.spec())); |
+ } |
+ } |
+ |
+ if (has_import) { |
+ const ListValue* import_list = NULL; |
+ if (!extension->manifest()->GetList(keys::kImport, &import_list)) { |
+ *error = ASCIIToUTF16(errors::kInvalidImport); |
+ return false; |
+ } |
+ for (size_t i = 0; i < import_list->GetSize(); ++i) { |
+ const DictionaryValue* import_entry = NULL; |
+ if (!import_list->GetDictionary(i, &import_entry)) { |
+ *error = ASCIIToUTF16(errors::kInvalidImport); |
+ return false; |
+ } |
+ std::string extension_id; |
+ imports_.push_back(ImportInfo()); |
+ if (!import_entry->GetString(keys::kId, &extension_id) || |
+ !Extension::IdIsValid(extension_id)) { |
+ *error = ErrorUtils::FormatErrorMessageUTF16( |
+ errors::kInvalidImportId, base::IntToString(i)); |
+ return false; |
+ } |
+ imports_.back().extension_id = extension_id; |
+ if (import_entry->HasKey(keys::kMinimumVersion)) { |
+ std::string min_version; |
+ if (!import_entry->GetString(keys::kMinimumVersion, &min_version)) { |
+ *error = ErrorUtils::FormatErrorMessageUTF16( |
+ errors::kInvalidImportVersion, base::IntToString(i)); |
+ return false; |
+ } |
+ imports_.back().minimum_version = min_version; |
+ Version v(min_version); |
+ if (!v.IsValid()) { |
+ *error = ErrorUtils::FormatErrorMessageUTF16( |
+ errors::kInvalidImportVersion, base::IntToString(i)); |
+ return false; |
+ } |
+ } |
+ } |
+ } |
+ return true; |
+} |
+ |
+ |
+SharedModuleHandler::SharedModuleHandler() { |
+} |
+ |
+SharedModuleHandler::~SharedModuleHandler() { |
+} |
+ |
+bool SharedModuleHandler::Parse(Extension* extension, string16* error) { |
+ scoped_ptr<SharedModuleInfo> info(new SharedModuleInfo); |
+ if (!info->Parse(extension, error)) |
+ return false; |
+ extension->SetManifestData(kSharedModule, info.release()); |
+ return true; |
+} |
+ |
+bool SharedModuleHandler::Validate( |
+ const Extension* extension, |
+ std::string* error, |
+ std::vector<InstallWarning>* warnings) const { |
+ // Extensions that export resources should not have any permissions of their |
+ // own, instead they rely on the permissions of the extensions which import |
+ // them. |
+ if (SharedModuleInfo::IsSharedModule(extension) && |
+ !extension->GetActivePermissions()->IsEmpty()) { |
+ *error = errors::kInvalidExportPermissions; |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+const std::vector<std::string> SharedModuleHandler::Keys() const { |
+ static const char* keys[] = { |
+ keys::kExport, |
+ keys::kImport |
+ }; |
+ return std::vector<std::string>(keys, keys + arraysize(keys)); |
+} |
+ |
+} // extensions |
+ |