12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/manifest_handler.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <map>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/permissions/manifest_permission.h"
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/permissions/manifest_permission_set.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace extensions {
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static base::LazyInstance<ManifestHandlerRegistry> g_registry =
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LAZY_INSTANCE_INITIALIZER;
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static ManifestHandlerRegistry* g_registry_override = NULL;
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ManifestHandlerRegistry* GetRegistry() {
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!g_registry_override)
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return g_registry.Pointer();
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return g_registry_override;
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ManifestHandler::ManifestHandler() {
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ManifestHandler::~ManifestHandler() {
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool ManifestHandler::Validate(const Extension* extension,
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               std::string* error,
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               std::vector<InstallWarning>* warnings) const {
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool ManifestHandler::AlwaysParseForType(Manifest::Type type) const {
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return false;
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool ManifestHandler::AlwaysValidateForType(Manifest::Type type) const {
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return false;
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const std::vector<std::string> ManifestHandler::PrerequisiteKeys() const {
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return std::vector<std::string>();
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ManifestHandler::Register() {
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  linked_ptr<ManifestHandler> this_linked(this);
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::vector<std::string> keys = Keys();
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (size_t i = 0; i < keys.size(); ++i)
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    GetRegistry()->RegisterManifestHandler(keys[i], this_linked);
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ManifestPermission* ManifestHandler::CreatePermission() {
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return NULL;
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ManifestPermission* ManifestHandler::CreateInitialRequiredPermission(
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const Extension* extension) {
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return NULL;
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid ManifestHandler::FinalizeRegistration() {
737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  GetRegistry()->Finalize();
747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// static
777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool ManifestHandler::IsRegistrationFinalized() {
787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return GetRegistry()->is_finalized_;
797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// static
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ManifestHandler::ParseExtension(Extension* extension,
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     base::string16* error) {
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return GetRegistry()->ParseExtension(extension, error);
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool ManifestHandler::ValidateExtension(const Extension* extension,
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                        std::string* error,
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                        std::vector<InstallWarning>* warnings) {
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return GetRegistry()->ValidateExtension(extension, error, warnings);
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ManifestPermission* ManifestHandler::CreatePermission(const std::string& name) {
96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return GetRegistry()->CreatePermission(name);
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ManifestHandler::AddExtensionInitialRequiredPermissions(
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const Extension* extension, ManifestPermissionSet* permission_set) {
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return GetRegistry()->AddExtensionInitialRequiredPermissions(extension,
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                               permission_set);
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const std::vector<std::string> ManifestHandler::SingleKey(
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& key) {
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return std::vector<std::string>(1, key);
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochManifestHandlerRegistry::ManifestHandlerRegistry() : is_finalized_(false) {
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ManifestHandlerRegistry::~ManifestHandlerRegistry() {
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid ManifestHandlerRegistry::Finalize() {
1197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  CHECK(!is_finalized_);
1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  SortManifestHandlers();
1217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  is_finalized_ = true;
1227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ManifestHandlerRegistry::RegisterManifestHandler(
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& key, linked_ptr<ManifestHandler> handler) {
1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  CHECK(!is_finalized_);
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  handlers_[key] = handler;
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ManifestHandlerRegistry::ParseExtension(Extension* extension,
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             base::string16* error) {
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::map<int, ManifestHandler*> handlers_by_priority;
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (ManifestHandlerMap::iterator iter = handlers_.begin();
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != handlers_.end(); ++iter) {
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ManifestHandler* handler = iter->second.get();
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (extension->manifest()->HasPath(iter->first) ||
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        handler->AlwaysParseForType(extension->GetType())) {
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      handlers_by_priority[priority_map_[handler]] = handler;
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::map<int, ManifestHandler*>::iterator iter =
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           handlers_by_priority.begin();
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != handlers_by_priority.end(); ++iter) {
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!(iter->second)->Parse(extension, error))
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ManifestHandlerRegistry::ValidateExtension(
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const Extension* extension,
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string* error,
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::vector<InstallWarning>* warnings) {
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::set<ManifestHandler*> handlers;
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (ManifestHandlerMap::iterator iter = handlers_.begin();
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != handlers_.end(); ++iter) {
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ManifestHandler* handler = iter->second.get();
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (extension->manifest()->HasPath(iter->first) ||
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        handler->AlwaysValidateForType(extension->GetType())) {
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      handlers.insert(handler);
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::set<ManifestHandler*>::iterator iter = handlers.begin();
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != handlers.end(); ++iter) {
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!(*iter)->Validate(extension, error, warnings))
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ManifestPermission* ManifestHandlerRegistry::CreatePermission(
172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& name) {
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ManifestHandlerMap::const_iterator it = handlers_.find(name);
174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (it == handlers_.end())
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return NULL;
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return it->second->CreatePermission();
178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ManifestHandlerRegistry::AddExtensionInitialRequiredPermissions(
181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const Extension* extension, ManifestPermissionSet* permission_set) {
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (ManifestHandlerMap::const_iterator it = handlers_.begin();
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      it != handlers_.end(); ++it) {
184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ManifestPermission* permission =
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        it->second->CreateInitialRequiredPermission(extension);
186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (permission) {
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      permission_set->insert(permission);
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ManifestHandlerRegistry* ManifestHandlerRegistry::SetForTesting(
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ManifestHandlerRegistry* new_registry) {
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ManifestHandlerRegistry* old_registry = GetRegistry();
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (new_registry != g_registry.Pointer())
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    g_registry_override = new_registry;
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    g_registry_override = NULL;
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return old_registry;
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ManifestHandlerRegistry::SortManifestHandlers() {
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::set<ManifestHandler*> unsorted_handlers;
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (ManifestHandlerMap::const_iterator iter = handlers_.begin();
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != handlers_.end(); ++iter) {
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsorted_handlers.insert(iter->second.get());
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int priority = 0;
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (true) {
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::set<ManifestHandler*> next_unsorted_handlers;
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (std::set<ManifestHandler*>::const_iterator iter =
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             unsorted_handlers.begin();
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         iter != unsorted_handlers.end(); ++iter) {
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ManifestHandler* handler = *iter;
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const std::vector<std::string>& prerequisites =
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          handler->PrerequisiteKeys();
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int unsatisfied = prerequisites.size();
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for (size_t i = 0; i < prerequisites.size(); ++i) {
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ManifestHandlerMap::const_iterator prereq_iter =
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            handlers_.find(prerequisites[i]);
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // If the prerequisite does not exist, crash.
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        CHECK(prereq_iter != handlers_.end())
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            << "Extension manifest handler depends on unrecognized key "
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            << prerequisites[i];
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // Prerequisite is in our map.
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (ContainsKey(priority_map_, prereq_iter->second.get()))
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          unsatisfied--;
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (unsatisfied == 0) {
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        priority_map_[handler] = priority;
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        priority++;
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // Put in the list for next time.
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        next_unsorted_handlers.insert(handler);
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (next_unsorted_handlers.size() == unsorted_handlers.size())
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsorted_handlers.swap(next_unsorted_handlers);
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If there are any leftover unsorted handlers, they must have had
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // circular dependencies.
246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CHECK_EQ(unsorted_handlers.size(), std::set<ManifestHandler*>::size_type(0))
247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      << "Extension manifest handlers have circular dependencies!";
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace extensions
251