Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(461)

Side by Side Diff: chrome/common/extensions/manifest_handler.cc

Issue 12091115: Allow manifest handlers to declare keys they depend on that must be parsed before them. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: dcronin Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/common/extensions/manifest_handler.h" 5 #include "chrome/common/extensions/manifest_handler.h"
6 6
7 #include <map> 7 #include <map>
8 8
9 #include "base/lazy_instance.h" 9 #include "base/lazy_instance.h"
10 #include "base/memory/linked_ptr.h" 10 #include "base/logging.h"
11 #include "base/stl_util.h"
11 #include "chrome/common/extensions/manifest.h" 12 #include "chrome/common/extensions/manifest.h"
12 13
13 namespace extensions { 14 namespace extensions {
14 15
15 namespace { 16 namespace {
16 17
17 class ManifestHandlerRegistry { 18 class ManifestHandlerRegistry {
18 public: 19 public:
20 ManifestHandlerRegistry() : is_sorted_(false) {
21 }
22
19 void RegisterManifestHandler(const std::string& key, 23 void RegisterManifestHandler(const std::string& key,
20 ManifestHandler* handler); 24 linked_ptr<ManifestHandler> handler);
21 bool ParseExtension(Extension* extension, string16* error); 25 bool ParseExtension(Extension* extension, string16* error);
26 void ClearForTesting();
22 27
23 private: 28 private:
24 friend struct base::DefaultLazyInstanceTraits<ManifestHandlerRegistry>; 29 friend struct base::DefaultLazyInstanceTraits<ManifestHandlerRegistry>;
25 typedef std::map<std::string, linked_ptr<ManifestHandler> > 30 typedef std::map<std::string, linked_ptr<ManifestHandler> >
26 ManifestHandlerMap; 31 ManifestHandlerMap;
32 typedef std::map<ManifestHandler*, int> ManifestHandlerPriorityMap;
27 33
34 // Puts the manifest handlers in order such that each handler comes after
35 // any handlers for their PrerequisiteKeys. If there is no handler for
36 // a prerequisite key, that dependency is simply ignored.
37 // CHECKs that there are no manifest handlers with circular dependencies.
38 void SortManifestHandlers();
39
40 // All registered manifest handlers.
28 ManifestHandlerMap handlers_; 41 ManifestHandlerMap handlers_;
42
43 // The priority for each manifest handler. Handlers with lower priority
44 // values are evaluated first.
45 ManifestHandlerPriorityMap priority_map_;
46 bool is_sorted_;
29 }; 47 };
30 48
31 void ManifestHandlerRegistry::RegisterManifestHandler( 49 void ManifestHandlerRegistry::RegisterManifestHandler(
32 const std::string& key, ManifestHandler* handler) { 50 const std::string& key, linked_ptr<ManifestHandler> handler) {
33 handlers_[key] = make_linked_ptr(handler); 51 handlers_[key] = handler;
52 is_sorted_ = false;
34 } 53 }
35 54
36 bool ManifestHandlerRegistry::ParseExtension(Extension* extension, 55 bool ManifestHandlerRegistry::ParseExtension(Extension* extension,
37 string16* error) { 56 string16* error) {
38 std::set<ManifestHandler*> handler_set; 57 SortManifestHandlers();
58 std::map<int, ManifestHandler*> handlers_by_priority;
39 for (ManifestHandlerMap::iterator iter = handlers_.begin(); 59 for (ManifestHandlerMap::iterator iter = handlers_.begin();
40 iter != handlers_.end(); ++iter) { 60 iter != handlers_.end(); ++iter) {
41 ManifestHandler* handler = iter->second.get(); 61 ManifestHandler* handler = iter->second.get();
42 if (extension->manifest()->HasPath(iter->first) || 62 if (extension->manifest()->HasPath(iter->first) ||
43 handler->AlwaysParseForType(extension->GetType())) 63 handler->AlwaysParseForType(extension->GetType())) {
44 handler_set.insert(handler); 64 handlers_by_priority[priority_map_[handler]] = handler;
65 }
45 } 66 }
46 67 for (std::map<int, ManifestHandler*>::iterator iter =
47 // TODO(yoz): Some handlers may depend on other handlers having already 68 handlers_by_priority.begin();
48 // parsed their keys. Reorder the handlers so that handlers needed earlier 69 iter != handlers_by_priority.end(); ++iter) {
49 // come first in the returned container. 70 if (!(iter->second)->Parse(extension, error))
50 for (std::set<ManifestHandler*>::iterator iter = handler_set.begin();
51 iter != handler_set.end(); ++iter) {
52 if (!(*iter)->Parse(extension, error))
53 return false; 71 return false;
54 } 72 }
55 return true; 73 return true;
56 } 74 }
57 75
76 void ManifestHandlerRegistry::ClearForTesting() {
77 priority_map_.clear();
78 handlers_.clear();
79 is_sorted_ = false;
80 }
81
82 void ManifestHandlerRegistry::SortManifestHandlers() {
83 if (is_sorted_)
84 return;
85
86 // Forget our existing sort order.
87 priority_map_.clear();
88 std::set<ManifestHandler*> unsorted_handlers;
89 for (ManifestHandlerMap::const_iterator iter = handlers_.begin();
90 iter != handlers_.end(); ++iter) {
91 unsorted_handlers.insert(iter->second.get());
92 }
93
94 int priority = 0;
95 while (true) {
96 std::set<ManifestHandler*> next_unsorted_handlers;
97 for (std::set<ManifestHandler*>::const_iterator iter =
98 unsorted_handlers.begin();
99 iter != unsorted_handlers.end(); ++iter) {
100 ManifestHandler* handler = *iter;
101 const std::vector<std::string>& prerequisites =
102 handler->PrerequisiteKeys();
103 int unsatisfied = prerequisites.size();
104 for (size_t i = 0; i < prerequisites.size(); ++i) {
105 ManifestHandlerMap::const_iterator prereq_iter =
106 handlers_.find(prerequisites[i]);
107 // If the prerequisite does not exist, crash.
108 CHECK(prereq_iter != handlers_.end())
109 << "Extension manifest handler depends on unrecognized key "
110 << prerequisites[i];
111 // Prerequisite is in our map.
112 if (ContainsKey(priority_map_, prereq_iter->second.get()))
113 unsatisfied--;
114 }
115 if (unsatisfied == 0) {
116 priority_map_[handler] = priority;
117 priority++;
118 } else {
119 // Put in the list for next time.
120 next_unsorted_handlers.insert(handler);
121 }
122 }
123 if (next_unsorted_handlers.size() == unsorted_handlers.size())
124 break;
125 unsorted_handlers.swap(next_unsorted_handlers);
126 }
127
128 // If there are any leftover unsorted handlers, they must have had
129 // circular dependencies.
130 CHECK(unsorted_handlers.size() == 0) << "Extension manifest handlers have "
131 << "circular dependencies!";
132
133 is_sorted_ = true;
134 }
135
58 static base::LazyInstance<ManifestHandlerRegistry> g_registry = 136 static base::LazyInstance<ManifestHandlerRegistry> g_registry =
59 LAZY_INSTANCE_INITIALIZER; 137 LAZY_INSTANCE_INITIALIZER;
60 138
139 static base::LazyInstance<std::vector<std::string> > g_empty_string_vector =
140 LAZY_INSTANCE_INITIALIZER;
141
61 } // namespace 142 } // namespace
62 143
63 ManifestHandler::ManifestHandler() { 144 ManifestHandler::ManifestHandler() {
64 } 145 }
65 146
66 ManifestHandler::~ManifestHandler() { 147 ManifestHandler::~ManifestHandler() {
67 } 148 }
68 149
69 bool ManifestHandler::AlwaysParseForType(Manifest::Type type) { 150 bool ManifestHandler::AlwaysParseForType(Manifest::Type type) {
70 return false; 151 return false;
71 } 152 }
72 153
154 const std::vector<std::string>& ManifestHandler::PrerequisiteKeys() {
155 return g_empty_string_vector.Get();
156 }
157
73 // static 158 // static
74 void ManifestHandler::Register(const std::string& key, 159 void ManifestHandler::Register(const std::string& key,
75 ManifestHandler* handler) { 160 linked_ptr<ManifestHandler> handler) {
76 g_registry.Get().RegisterManifestHandler(key, handler); 161 g_registry.Get().RegisterManifestHandler(key, handler);
77 } 162 }
78 163
79 // static 164 // static
80 bool ManifestHandler::ParseExtension(Extension* extension, string16* error) { 165 bool ManifestHandler::ParseExtension(Extension* extension, string16* error) {
81 return g_registry.Get().ParseExtension(extension, error); 166 return g_registry.Get().ParseExtension(extension, error);
82 } 167 }
83 168
169 // static
170 void ManifestHandler::ClearRegistryForTesting() {
171 g_registry.Get().ClearForTesting();
172 }
173
84 } // namespace extensions 174 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/common/extensions/manifest_handler.h ('k') | chrome/common/extensions/manifest_handler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698