[go: nahoru, domu]

blob: bbba24718a9a05090ee58647e1ad46ba917e8cc0 [file] [log] [blame]
rdevlin.cronin@chromium.org7eeab9e2013-01-15 04:08:331// Copyright (c) 2013 The Chromium Authors. All rights reserved.
yoz@chromium.orgd356c982012-12-12 19:32:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
yoz@chromium.org582d12b2013-11-06 18:42:335#include "extensions/common/manifest_handler.h"
yoz@chromium.orgd356c982012-12-12 19:32:556
avi2d124c02015-12-23 06:36:427#include <stddef.h>
8
yoz@chromium.orgd356c982012-12-12 19:32:559#include <map>
David Bertoni88a71c182018-09-05 01:35:5510#include <vector>
yoz@chromium.orgd356c982012-12-12 19:32:5511
Hans Wennborg09979592020-04-27 12:34:3012#include "base/check.h"
yoz@chromium.org03e07532013-02-05 00:26:2413#include "base/stl_util.h"
yoz@chromium.orge4452d32013-11-15 23:07:4114#include "extensions/common/extension.h"
rpaquay@chromium.orge737c442013-11-15 15:55:2415#include "extensions/common/permissions/manifest_permission.h"
16#include "extensions/common/permissions/manifest_permission_set.h"
yoz@chromium.orgd356c982012-12-12 19:32:5517
18namespace extensions {
19
20namespace {
21
scottmg5e65e3a2017-03-08 08:48:4622static base::LazyInstance<ManifestHandlerRegistry>::DestructorAtExit
23 g_registry = LAZY_INSTANCE_INITIALIZER;
yoz@chromium.orgd1972842013-05-01 17:07:3224static ManifestHandlerRegistry* g_registry_override = NULL;
yoz@chromium.org03e07532013-02-05 00:26:2425
yoz@chromium.orgd1972842013-05-01 17:07:3226} // namespace
yoz@chromium.orgd356c982012-12-12 19:32:5527
yoz@chromium.orgd1972842013-05-01 17:07:3228ManifestHandler::ManifestHandler() {
29}
yoz@chromium.orgd356c982012-12-12 19:32:5530
yoz@chromium.orgd1972842013-05-01 17:07:3231ManifestHandler::~ManifestHandler() {
32}
yoz@chromium.org03e07532013-02-05 00:26:2433
yoz@chromium.orgd1972842013-05-01 17:07:3234bool ManifestHandler::Validate(const Extension* extension,
35 std::string* error,
36 std::vector<InstallWarning>* warnings) const {
37 return true;
38}
yoz@chromium.org03e07532013-02-05 00:26:2439
yoz@chromium.orgd1972842013-05-01 17:07:3240bool ManifestHandler::AlwaysParseForType(Manifest::Type type) const {
41 return false;
42}
43
44bool ManifestHandler::AlwaysValidateForType(Manifest::Type type) const {
45 return false;
46}
47
48const std::vector<std::string> ManifestHandler::PrerequisiteKeys() const {
49 return std::vector<std::string>();
50}
51
rpaquay@chromium.orge737c442013-11-15 15:55:2452ManifestPermission* ManifestHandler::CreatePermission() {
53 return NULL;
54}
55
56ManifestPermission* ManifestHandler::CreateInitialRequiredPermission(
57 const Extension* extension) {
58 return NULL;
59}
60
yoz@chromium.orgd1972842013-05-01 17:07:3261// static
yoz@chromium.orga31c3982013-07-13 04:33:3162void ManifestHandler::FinalizeRegistration() {
David Bertonic0416892018-08-15 00:07:2063 ManifestHandlerRegistry::Get()->Finalize();
yoz@chromium.orga31c3982013-07-13 04:33:3164}
65
66// static
67bool ManifestHandler::IsRegistrationFinalized() {
David Bertonic0416892018-08-15 00:07:2068 return ManifestHandlerRegistry::Get()->is_finalized_;
yoz@chromium.orga31c3982013-07-13 04:33:3169}
70
71// static
dbeam@chromium.org0d163dc2013-12-20 23:48:3672bool ManifestHandler::ParseExtension(Extension* extension,
Jan Wilken Dörrie85285b02021-03-11 23:38:4773 std::u16string* error) {
David Bertonic0416892018-08-15 00:07:2074 return ManifestHandlerRegistry::Get()->ParseExtension(extension, error);
yoz@chromium.orgd1972842013-05-01 17:07:3275}
76
77// static
78bool ManifestHandler::ValidateExtension(const Extension* extension,
79 std::string* error,
80 std::vector<InstallWarning>* warnings) {
David Bertonic0416892018-08-15 00:07:2081 return ManifestHandlerRegistry::Get()->ValidateExtension(extension, error,
82 warnings);
yoz@chromium.orgd1972842013-05-01 17:07:3283}
84
85// static
rpaquay@chromium.orge737c442013-11-15 15:55:2486ManifestPermission* ManifestHandler::CreatePermission(const std::string& name) {
David Bertonic0416892018-08-15 00:07:2087 return ManifestHandlerRegistry::Get()->CreatePermission(name);
rpaquay@chromium.orge737c442013-11-15 15:55:2488}
89
90// static
91void ManifestHandler::AddExtensionInitialRequiredPermissions(
92 const Extension* extension, ManifestPermissionSet* permission_set) {
David Bertonic0416892018-08-15 00:07:2093 return ManifestHandlerRegistry::Get()->AddExtensionInitialRequiredPermissions(
94 extension, permission_set);
rpaquay@chromium.orge737c442013-11-15 15:55:2495}
96
97// static
yoz@chromium.orgd1972842013-05-01 17:07:3298const std::vector<std::string> ManifestHandler::SingleKey(
99 const std::string& key) {
100 return std::vector<std::string>(1, key);
101}
102
David Bertonic0416892018-08-15 00:07:20103// static
104const size_t ManifestHandlerRegistry::kHandlerMax;
105
yoz@chromium.orga31c3982013-07-13 04:33:31106ManifestHandlerRegistry::ManifestHandlerRegistry() : is_finalized_(false) {
yoz@chromium.orgd1972842013-05-01 17:07:32107}
108
109ManifestHandlerRegistry::~ManifestHandlerRegistry() {
110}
yoz@chromium.orgd356c982012-12-12 19:32:55111
yoz@chromium.orga31c3982013-07-13 04:33:31112void ManifestHandlerRegistry::Finalize() {
113 CHECK(!is_finalized_);
114 SortManifestHandlers();
115 is_finalized_ = true;
116}
117
Devlin Cronin2033d602018-12-14 23:54:49118void ManifestHandlerRegistry::RegisterHandler(
119 std::unique_ptr<ManifestHandler> handler) {
yoz@chromium.orga31c3982013-07-13 04:33:31120 CHECK(!is_finalized_);
Devlin Cronincd24bd82018-12-14 03:36:08121
Devlin Cronin2033d602018-12-14 23:54:49122 ManifestHandler* raw_handler = handler.get();
123 owned_manifest_handlers_.push_back(std::move(handler));
124
125 for (const char* key : raw_handler->Keys()) {
126 auto insertion = handlers_.emplace(key, raw_handler);
127 DCHECK(insertion.second)
128 << "A ManifestHandler was already registered for key: " << key;
129 }
yoz@chromium.orgd356c982012-12-12 19:32:55130}
131
yoz@chromium.orgce613ba2013-01-30 00:01:18132bool ManifestHandlerRegistry::ParseExtension(Extension* extension,
Jan Wilken Dörrie85285b02021-03-11 23:38:47133 std::u16string* error) {
yoz@chromium.org03e07532013-02-05 00:26:24134 std::map<int, ManifestHandler*> handlers_by_priority;
yoz@chromium.orgd356c982012-12-12 19:32:55135 for (ManifestHandlerMap::iterator iter = handlers_.begin();
136 iter != handlers_.end(); ++iter) {
Devlin Cronin2033d602018-12-14 23:54:49137 ManifestHandler* handler = iter->second;
yoz@chromium.orgce613ba2013-01-30 00:01:18138 if (extension->manifest()->HasPath(iter->first) ||
yoz@chromium.org03e07532013-02-05 00:26:24139 handler->AlwaysParseForType(extension->GetType())) {
140 handlers_by_priority[priority_map_[handler]] = handler;
141 }
yoz@chromium.orgd356c982012-12-12 19:32:55142 }
jdoerriea1e1598b2018-10-10 09:10:37143 for (auto iter = handlers_by_priority.begin();
yoz@chromium.org03e07532013-02-05 00:26:24144 iter != handlers_by_priority.end(); ++iter) {
145 if (!(iter->second)->Parse(extension, error))
yoz@chromium.orgce613ba2013-01-30 00:01:18146 return false;
147 }
148 return true;
yoz@chromium.orgd356c982012-12-12 19:32:55149}
150
yoz@chromium.org989ae862013-03-13 04:22:58151bool ManifestHandlerRegistry::ValidateExtension(
152 const Extension* extension,
153 std::string* error,
154 std::vector<InstallWarning>* warnings) {
155 std::set<ManifestHandler*> handlers;
156 for (ManifestHandlerMap::iterator iter = handlers_.begin();
157 iter != handlers_.end(); ++iter) {
Devlin Cronin2033d602018-12-14 23:54:49158 ManifestHandler* handler = iter->second;
yoz@chromium.org989ae862013-03-13 04:22:58159 if (extension->manifest()->HasPath(iter->first) ||
160 handler->AlwaysValidateForType(extension->GetType())) {
161 handlers.insert(handler);
162 }
163 }
jdoerriea1e1598b2018-10-10 09:10:37164 for (auto iter = handlers.begin(); iter != handlers.end(); ++iter) {
yoz@chromium.org989ae862013-03-13 04:22:58165 if (!(*iter)->Validate(extension, error, warnings))
166 return false;
167 }
168 return true;
169}
170
rpaquay@chromium.orge737c442013-11-15 15:55:24171ManifestPermission* ManifestHandlerRegistry::CreatePermission(
172 const std::string& name) {
173 ManifestHandlerMap::const_iterator it = handlers_.find(name);
174 if (it == handlers_.end())
175 return NULL;
176
177 return it->second->CreatePermission();
178}
179
180void ManifestHandlerRegistry::AddExtensionInitialRequiredPermissions(
181 const Extension* extension, ManifestPermissionSet* permission_set) {
182 for (ManifestHandlerMap::const_iterator it = handlers_.begin();
183 it != handlers_.end(); ++it) {
Devlin Cronin033021e62018-11-27 18:21:45184 std::unique_ptr<ManifestPermission> permission(
185 it->second->CreateInitialRequiredPermission(extension));
rpaquay@chromium.orge737c442013-11-15 15:55:24186 if (permission) {
Devlin Cronin033021e62018-11-27 18:21:45187 permission_set->insert(std::move(permission));
rpaquay@chromium.orge737c442013-11-15 15:55:24188 }
189 }
190}
191
yoz@chromium.orgd1972842013-05-01 17:07:32192// static
David Bertonic0416892018-08-15 00:07:20193ManifestHandlerRegistry* ManifestHandlerRegistry::Get() {
194 if (!g_registry_override)
195 return g_registry.Pointer();
196 return g_registry_override;
197}
198
199// static
yoz@chromium.orgd1972842013-05-01 17:07:32200ManifestHandlerRegistry* ManifestHandlerRegistry::SetForTesting(
201 ManifestHandlerRegistry* new_registry) {
David Bertonic0416892018-08-15 00:07:20202 ManifestHandlerRegistry* old_registry = ManifestHandlerRegistry::Get();
yoz@chromium.orgd1972842013-05-01 17:07:32203 if (new_registry != g_registry.Pointer())
204 g_registry_override = new_registry;
205 else
206 g_registry_override = NULL;
207 return old_registry;
208}
209
David Bertonic0416892018-08-15 00:07:20210// static
211void ManifestHandlerRegistry::ResetForTesting() {
212 ManifestHandlerRegistry* registry = Get();
213 registry->priority_map_.clear();
214 registry->handlers_.clear();
215 registry->is_finalized_ = false;
216}
217
yoz@chromium.org03e07532013-02-05 00:26:24218void ManifestHandlerRegistry::SortManifestHandlers() {
David Bertoni88a71c182018-09-05 01:35:55219 std::vector<ManifestHandler*> unsorted_handlers;
220 unsorted_handlers.reserve(handlers_.size());
221 for (const auto& key_value : handlers_) {
Devlin Cronin2033d602018-12-14 23:54:49222 unsorted_handlers.push_back(key_value.second);
yoz@chromium.org03e07532013-02-05 00:26:24223 }
224
225 int priority = 0;
226 while (true) {
David Bertoni88a71c182018-09-05 01:35:55227 std::vector<ManifestHandler*> next_unsorted_handlers;
228 next_unsorted_handlers.reserve(unsorted_handlers.size());
229 for (ManifestHandler* handler : unsorted_handlers) {
yoz@chromium.org03e07532013-02-05 00:26:24230 const std::vector<std::string>& prerequisites =
231 handler->PrerequisiteKeys();
232 int unsatisfied = prerequisites.size();
David Bertoni88a71c182018-09-05 01:35:55233 for (const std::string& key : prerequisites) {
234 ManifestHandlerMap::const_iterator prereq_iter = handlers_.find(key);
yoz@chromium.org03e07532013-02-05 00:26:24235 // If the prerequisite does not exist, crash.
236 CHECK(prereq_iter != handlers_.end())
David Bertoni88a71c182018-09-05 01:35:55237 << "Extension manifest handler depends on unrecognized key " << key;
yoz@chromium.org03e07532013-02-05 00:26:24238 // Prerequisite is in our map.
Jan Wilken Dörrie0fd53a22019-06-07 09:55:46239 if (base::Contains(priority_map_, prereq_iter->second))
yoz@chromium.org03e07532013-02-05 00:26:24240 unsatisfied--;
241 }
242 if (unsatisfied == 0) {
243 priority_map_[handler] = priority;
244 priority++;
245 } else {
246 // Put in the list for next time.
David Bertoni88a71c182018-09-05 01:35:55247 next_unsorted_handlers.push_back(handler);
yoz@chromium.org03e07532013-02-05 00:26:24248 }
249 }
250 if (next_unsorted_handlers.size() == unsorted_handlers.size())
251 break;
252 unsorted_handlers.swap(next_unsorted_handlers);
253 }
254
255 // If there are any leftover unsorted handlers, they must have had
256 // circular dependencies.
David Bertoni88a71c182018-09-05 01:35:55257 CHECK(unsorted_handlers.empty())
lauren.yeun.kim@gmail.com1b92809452014-05-29 20:20:27258 << "Extension manifest handlers have circular dependencies!";
yoz@chromium.org03e07532013-02-05 00:26:24259}
260
yoz@chromium.orgd356c982012-12-12 19:32:55261} // namespace extensions