// 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 #include #include "base/logging.h" #include "base/stl_util.h" #include "extensions/common/extension.h" #include "extensions/common/permissions/manifest_permission.h" #include "extensions/common/permissions/manifest_permission_set.h" namespace extensions { namespace { static base::LazyInstance 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* 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 ManifestHandler::PrerequisiteKeys() const { return std::vector(); } void ManifestHandler::Register() { linked_ptr this_linked(this); const std::vector keys = Keys(); for (size_t i = 0; i < keys.size(); ++i) GetRegistry()->RegisterManifestHandler(keys[i], this_linked); } ManifestPermission* ManifestHandler::CreatePermission() { return NULL; } ManifestPermission* ManifestHandler::CreateInitialRequiredPermission( const Extension* extension) { return NULL; } // static void ManifestHandler::FinalizeRegistration() { GetRegistry()->Finalize(); } // static bool ManifestHandler::IsRegistrationFinalized() { return GetRegistry()->is_finalized_; } // static bool ManifestHandler::ParseExtension(Extension* extension, base::string16* error) { return GetRegistry()->ParseExtension(extension, error); } // static bool ManifestHandler::ValidateExtension(const Extension* extension, std::string* error, std::vector* warnings) { return GetRegistry()->ValidateExtension(extension, error, warnings); } // static ManifestPermission* ManifestHandler::CreatePermission(const std::string& name) { return GetRegistry()->CreatePermission(name); } // static void ManifestHandler::AddExtensionInitialRequiredPermissions( const Extension* extension, ManifestPermissionSet* permission_set) { return GetRegistry()->AddExtensionInitialRequiredPermissions(extension, permission_set); } // static const std::vector ManifestHandler::SingleKey( const std::string& key) { return std::vector(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 handler) { CHECK(!is_finalized_); handlers_[key] = handler; } bool ManifestHandlerRegistry::ParseExtension(Extension* extension, base::string16* error) { std::map 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::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* warnings) { std::set 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::iterator iter = handlers.begin(); iter != handlers.end(); ++iter) { if (!(*iter)->Validate(extension, error, warnings)) return false; } return true; } ManifestPermission* ManifestHandlerRegistry::CreatePermission( const std::string& name) { ManifestHandlerMap::const_iterator it = handlers_.find(name); if (it == handlers_.end()) return NULL; return it->second->CreatePermission(); } void ManifestHandlerRegistry::AddExtensionInitialRequiredPermissions( const Extension* extension, ManifestPermissionSet* permission_set) { for (ManifestHandlerMap::const_iterator it = handlers_.begin(); it != handlers_.end(); ++it) { ManifestPermission* permission = it->second->CreateInitialRequiredPermission(extension); if (permission) { permission_set->insert(permission); } } } // 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 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 next_unsorted_handlers; for (std::set::const_iterator iter = unsorted_handlers.begin(); iter != unsorted_handlers.end(); ++iter) { ManifestHandler* handler = *iter; const std::vector& 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_EQ(unsorted_handlers.size(), std::set::size_type(0)) << "Extension manifest handlers have circular dependencies!"; } } // namespace extensions