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

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: 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 // Manifest handlers with circular dependencies are unregistered.
Devlin 2013/02/02 21:41:38 nit: comment should be updated - while it's true t
Yoyo Zhou 2013/02/04 20:24:31 Done.
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 (prereq_iter == handlers_.end()) {
108 // Prerequisite does not exist.
109 LOG(FATAL) << "Extension manifest handler depends on "
110 << "unrecognized key " << prerequisites[i];
111 } else if (ContainsKey(priority_map_,
112 prereq_iter->second.get())) {
113 // Prerequisite is in our map.
114 unsatisfied--;
115 }
116 }
117 if (unsatisfied == 0) {
118 priority_map_[handler] = priority;
119 priority++;
120 } else {
121 // Put in the list for next time.
122 next_unsorted_handlers.insert(handler);
123 }
124 }
125 if (next_unsorted_handlers.size() == unsorted_handlers.size())
126 break;
127 unsorted_handlers.swap(next_unsorted_handlers);
128 }
129
130 // If there are any leftover unsorted handlers, they must have had
131 // circular dependencies.
132 CHECK(unsorted_handlers.size() == 0) << "Extension manifest handlers have "
133 << "circular dependencies!";
134
135 is_sorted_ = true;
136 }
137
58 static base::LazyInstance<ManifestHandlerRegistry> g_registry = 138 static base::LazyInstance<ManifestHandlerRegistry> g_registry =
59 LAZY_INSTANCE_INITIALIZER; 139 LAZY_INSTANCE_INITIALIZER;
60 140
141 static base::LazyInstance<std::vector<std::string> > g_empty_string_vector =
142 LAZY_INSTANCE_INITIALIZER;
143
61 } // namespace 144 } // namespace
62 145
63 ManifestHandler::ManifestHandler() { 146 ManifestHandler::ManifestHandler() {
64 } 147 }
65 148
66 ManifestHandler::~ManifestHandler() { 149 ManifestHandler::~ManifestHandler() {
67 } 150 }
68 151
69 bool ManifestHandler::AlwaysParseForType(Manifest::Type type) { 152 bool ManifestHandler::AlwaysParseForType(Manifest::Type type) {
70 return false; 153 return false;
71 } 154 }
72 155
156 const std::vector<std::string>& ManifestHandler::PrerequisiteKeys() {
157 return g_empty_string_vector.Get();
158 }
159
73 // static 160 // static
74 void ManifestHandler::Register(const std::string& key, 161 void ManifestHandler::Register(const std::string& key,
75 ManifestHandler* handler) { 162 linked_ptr<ManifestHandler> handler) {
76 g_registry.Get().RegisterManifestHandler(key, handler); 163 g_registry.Get().RegisterManifestHandler(key, handler);
77 } 164 }
78 165
79 // static 166 // static
80 bool ManifestHandler::ParseExtension(Extension* extension, string16* error) { 167 bool ManifestHandler::ParseExtension(Extension* extension, string16* error) {
81 return g_registry.Get().ParseExtension(extension, error); 168 return g_registry.Get().ParseExtension(extension, error);
82 } 169 }
83 170
171 // static
172 void ManifestHandler::ClearRegistryForTesting() {
173 g_registry.Get().ClearForTesting();
174 }
175
84 } // namespace extensions 176 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698