summaryrefslogtreecommitdiffstats
path: root/extensions/common/manifest_handler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/common/manifest_handler.cc')
-rw-r--r--extensions/common/manifest_handler.cc205
1 files changed, 205 insertions, 0 deletions
diff --git a/extensions/common/manifest_handler.cc b/extensions/common/manifest_handler.cc
new file mode 100644
index 0000000..43e6bd8
--- /dev/null
+++ b/extensions/common/manifest_handler.cc
@@ -0,0 +1,205 @@
+// 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 "extensions/common/manifest_handler.h"
+
+#include <map>
+
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "chrome/common/extensions/extension.h"
+
+namespace extensions {
+
+namespace {
+
+static base::LazyInstance<ManifestHandlerRegistry> g_registry =
+ LAZY_INSTANCE_INITIALIZER;
+static ManifestHandlerRegistry* g_registry_override = NULL;
+
+ManifestHandlerRegistry* GetRegistry() {
+ if (!g_registry_override)
+ return g_registry.Pointer();
+ return g_registry_override;
+}
+
+} // namespace
+
+ManifestHandler::ManifestHandler() {
+}
+
+ManifestHandler::~ManifestHandler() {
+}
+
+bool ManifestHandler::Validate(const Extension* extension,
+ std::string* error,
+ std::vector<InstallWarning>* warnings) const {
+ return true;
+}
+
+bool ManifestHandler::AlwaysParseForType(Manifest::Type type) const {
+ return false;
+}
+
+bool ManifestHandler::AlwaysValidateForType(Manifest::Type type) const {
+ return false;
+}
+
+const std::vector<std::string> ManifestHandler::PrerequisiteKeys() const {
+ return std::vector<std::string>();
+}
+
+void ManifestHandler::Register() {
+ linked_ptr<ManifestHandler> this_linked(this);
+ const std::vector<std::string> keys = Keys();
+ for (size_t i = 0; i < keys.size(); ++i)
+ GetRegistry()->RegisterManifestHandler(keys[i], this_linked);
+}
+
+// static
+void ManifestHandler::FinalizeRegistration() {
+ GetRegistry()->Finalize();
+}
+
+// static
+bool ManifestHandler::IsRegistrationFinalized() {
+ return GetRegistry()->is_finalized_;
+}
+
+// static
+bool ManifestHandler::ParseExtension(Extension* extension, string16* error) {
+ return GetRegistry()->ParseExtension(extension, error);
+}
+
+// static
+bool ManifestHandler::ValidateExtension(const Extension* extension,
+ std::string* error,
+ std::vector<InstallWarning>* warnings) {
+ return GetRegistry()->ValidateExtension(extension, error, warnings);
+}
+
+// static
+const std::vector<std::string> ManifestHandler::SingleKey(
+ const std::string& key) {
+ return std::vector<std::string>(1, key);
+}
+
+ManifestHandlerRegistry::ManifestHandlerRegistry() : is_finalized_(false) {
+}
+
+ManifestHandlerRegistry::~ManifestHandlerRegistry() {
+}
+
+void ManifestHandlerRegistry::Finalize() {
+ CHECK(!is_finalized_);
+ SortManifestHandlers();
+ is_finalized_ = true;
+}
+
+void ManifestHandlerRegistry::RegisterManifestHandler(
+ const std::string& key, linked_ptr<ManifestHandler> handler) {
+ CHECK(!is_finalized_);
+ handlers_[key] = handler;
+}
+
+bool ManifestHandlerRegistry::ParseExtension(Extension* extension,
+ string16* error) {
+ std::map<int, ManifestHandler*> handlers_by_priority;
+ for (ManifestHandlerMap::iterator iter = handlers_.begin();
+ iter != handlers_.end(); ++iter) {
+ ManifestHandler* handler = iter->second.get();
+ if (extension->manifest()->HasPath(iter->first) ||
+ handler->AlwaysParseForType(extension->GetType())) {
+ handlers_by_priority[priority_map_[handler]] = handler;
+ }
+ }
+ for (std::map<int, ManifestHandler*>::iterator iter =
+ handlers_by_priority.begin();
+ iter != handlers_by_priority.end(); ++iter) {
+ if (!(iter->second)->Parse(extension, error))
+ return false;
+ }
+ return true;
+}
+
+bool ManifestHandlerRegistry::ValidateExtension(
+ const Extension* extension,
+ std::string* error,
+ std::vector<InstallWarning>* warnings) {
+ std::set<ManifestHandler*> handlers;
+ for (ManifestHandlerMap::iterator iter = handlers_.begin();
+ iter != handlers_.end(); ++iter) {
+ ManifestHandler* handler = iter->second.get();
+ if (extension->manifest()->HasPath(iter->first) ||
+ handler->AlwaysValidateForType(extension->GetType())) {
+ handlers.insert(handler);
+ }
+ }
+ for (std::set<ManifestHandler*>::iterator iter = handlers.begin();
+ iter != handlers.end(); ++iter) {
+ if (!(*iter)->Validate(extension, error, warnings))
+ return false;
+ }
+ return true;
+}
+
+// static
+ManifestHandlerRegistry* ManifestHandlerRegistry::SetForTesting(
+ ManifestHandlerRegistry* new_registry) {
+ ManifestHandlerRegistry* old_registry = GetRegistry();
+ if (new_registry != g_registry.Pointer())
+ g_registry_override = new_registry;
+ else
+ g_registry_override = NULL;
+ return old_registry;
+}
+
+void ManifestHandlerRegistry::SortManifestHandlers() {
+ std::set<ManifestHandler*> unsorted_handlers;
+ for (ManifestHandlerMap::const_iterator iter = handlers_.begin();
+ iter != handlers_.end(); ++iter) {
+ unsorted_handlers.insert(iter->second.get());
+ }
+
+ int priority = 0;
+ while (true) {
+ std::set<ManifestHandler*> next_unsorted_handlers;
+ for (std::set<ManifestHandler*>::const_iterator iter =
+ unsorted_handlers.begin();
+ iter != unsorted_handlers.end(); ++iter) {
+ ManifestHandler* handler = *iter;
+ const std::vector<std::string>& prerequisites =
+ handler->PrerequisiteKeys();
+ int unsatisfied = prerequisites.size();
+ for (size_t i = 0; i < prerequisites.size(); ++i) {
+ ManifestHandlerMap::const_iterator prereq_iter =
+ handlers_.find(prerequisites[i]);
+ // If the prerequisite does not exist, crash.
+ CHECK(prereq_iter != handlers_.end())
+ << "Extension manifest handler depends on unrecognized key "
+ << prerequisites[i];
+ // Prerequisite is in our map.
+ if (ContainsKey(priority_map_, prereq_iter->second.get()))
+ unsatisfied--;
+ }
+ if (unsatisfied == 0) {
+ priority_map_[handler] = priority;
+ priority++;
+ } else {
+ // Put in the list for next time.
+ next_unsorted_handlers.insert(handler);
+ }
+ }
+ if (next_unsorted_handlers.size() == unsorted_handlers.size())
+ break;
+ unsorted_handlers.swap(next_unsorted_handlers);
+ }
+
+ // If there are any leftover unsorted handlers, they must have had
+ // circular dependencies.
+ CHECK(unsorted_handlers.size() == 0) << "Extension manifest handlers have "
+ << "circular dependencies!";
+}
+
+} // namespace extensions