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
3// found in the LICENSE file.
4
5#ifndef EXTENSIONS_COMMON_MANIFEST_HANDLER_H_
6#define EXTENSIONS_COMMON_MANIFEST_HANDLER_H_
7
8#include <memory>
9#include <set>
10#include <string>
11#include <unordered_map>
12#include <vector>
13
14#include "base/containers/small_map.h"
15#include "base/containers/span.h"
16#include "base/gtest_prod_util.h"
17#include "base/lazy_instance.h"
18#include "base/strings/string16.h"
19#include "extensions/common/manifest.h"
20
21namespace extensions {
22class Extension;
23class ManifestPermission;
24class ManifestPermissionSet;
25
26// An interface for clients that recognize and parse keys in extension
27// manifests.
28class ManifestHandler {
29 public:
30 ManifestHandler();
31 virtual ~ManifestHandler();
32
33 // Attempts to parse the extension's manifest.
34 // Returns true on success or false on failure; if false, |error| will
35 // be set to a failure message.
36 // This does not perform any IO operations.
37 virtual bool Parse(Extension* extension, base::string16* error) = 0;
38
39 // Validate that files associated with this manifest key exist.
40 // Validation takes place after parsing. May also append a series of
41 // warning messages to |warnings|.
42 // This may perform IO operations.
43 //
44 // Otherwise, returns false, and a description of the error is
45 // returned in |error|.
46 // TODO(yoz): Change error to base::string16. See crbug.com/71980.
47 virtual bool Validate(const Extension* extension,
48 std::string* error,
49 std::vector<InstallWarning>* warnings) const;
50
51 // If false (the default), only parse the manifest if a registered
52 // key is present in the manifest. If true, always attempt to parse
53 // the manifest for this extension type, even if no registered keys
54 // are present. This allows specifying a default parsed value for
55 // extensions that don't declare our key in the manifest.
56 // TODO(yoz): Use Feature availability instead.
57 virtual bool AlwaysParseForType(Manifest::Type type) const;
58
59 // Same as AlwaysParseForType, but for Validate instead of Parse.
60 virtual bool AlwaysValidateForType(Manifest::Type type) const;
61
62 // The list of keys that, if present, should be parsed before calling our
63 // Parse (typically, because our Parse needs to read those keys).
64 // Defaults to empty.
65 virtual const std::vector<std::string> PrerequisiteKeys() const;
66
67 // Creates a |ManifestPermission| instance for the given manifest key |name|.
68 // The returned permission does not contain any permission data, so this
69 // method is usually used before calling |FromValue| or |Read|. Returns
70 // |NULL| if the manifest handler does not support custom permissions.
71 virtual ManifestPermission* CreatePermission();
72
73 // Creates a |ManifestPermission| instance containing the initial set of
74 // required manifest permissions for the given |extension|. Returns |NULL| if
75 // the manifest handler does not support custom permissions or if there was
76 // no manifest key in the extension manifest for this handler.
77 virtual ManifestPermission* CreateInitialRequiredPermission(
78 const Extension* extension);
79
80 // The keys this handler is responsible for.
81 virtual base::span<const char* const> Keys() const = 0;
82
83 // Calling FinalizeRegistration indicates that there are no more
84 // manifest handlers to be registered.
85 static void FinalizeRegistration();
86
87 static bool IsRegistrationFinalized();
88
89 // Call Parse on all registered manifest handlers that should parse
90 // this extension.
91 static bool ParseExtension(Extension* extension, base::string16* error);
92
93 // Call Validate on all registered manifest handlers for this extension. This
94 // may perform IO operations.
95 static bool ValidateExtension(const Extension* extension,
96 std::string* error,
97 std::vector<InstallWarning>* warnings);
98
99 // Calls |CreatePermission| on the manifest handler for |key|. Returns |NULL|
100 // if there is no manifest handler for |key| or if the manifest handler for
101 // |key| does not support custom permissions.
102 static ManifestPermission* CreatePermission(const std::string& key);
103
104 // Calls |CreateInitialRequiredPermission| on all registered manifest handlers
105 // and adds the returned permissions to |permission_set|. Note this should be
106 // called after all manifest data elements have been read, parsed and stored
107 // in the manifest data property of |extension|, as manifest handlers need
108 // access to their manifest data to initialize their required manifest
109 // permission.
110 static void AddExtensionInitialRequiredPermissions(
111 const Extension* extension, ManifestPermissionSet* permission_set);
112
113 protected:
114 // A convenience method for handlers that only register for 1 key,
115 // so that they can define keys() { return SingleKey(kKey); }
116 static const std::vector<std::string> SingleKey(const std::string& key);
117
118 private:
119 DISALLOW_COPY_AND_ASSIGN(ManifestHandler);
120};
121
122// The global registry for manifest handlers.
123class ManifestHandlerRegistry {
124 public:
125 // Get the one true instance.
126 static ManifestHandlerRegistry* Get();
127
128 // Registers a ManifestHandler, associating it with its keys. If there is
129 // already a handler registered for any key |handler| manages, this method
130 // will DCHECK.
131 void RegisterHandler(std::unique_ptr<ManifestHandler> handler);
132
133 private:
134 friend class ManifestHandler;
135 friend class ScopedTestingManifestHandlerRegistry;
136 friend struct base::LazyInstanceTraitsBase<ManifestHandlerRegistry>;
137 FRIEND_TEST_ALL_PREFIXES(ManifestHandlerPerfTest, MANUAL_CommonInitialize);
138 FRIEND_TEST_ALL_PREFIXES(ManifestHandlerPerfTest, MANUAL_LookupTest);
139 FRIEND_TEST_ALL_PREFIXES(ManifestHandlerPerfTest,
140 MANUAL_CommonMeasureFinalization);
141 FRIEND_TEST_ALL_PREFIXES(ChromeExtensionsClientTest,
142 CheckManifestHandlerRegistryForOverflow);
143
144 ManifestHandlerRegistry();
145 ~ManifestHandlerRegistry();
146
147 void Finalize();
148
149 bool ParseExtension(Extension* extension, base::string16* error);
150 bool ValidateExtension(const Extension* extension,
151 std::string* error,
152 std::vector<InstallWarning>* warnings);
153
154 ManifestPermission* CreatePermission(const std::string& key);
155
156 void AddExtensionInitialRequiredPermissions(
157 const Extension* extension,
158 ManifestPermissionSet* permission_set);
159
160 // Reset the one true instance.
161 static void ResetForTesting();
162
163 // Overrides the current global ManifestHandlerRegistry with
164 // |registry|, returning the current one.
165 static ManifestHandlerRegistry* SetForTesting(
166 ManifestHandlerRegistry* new_registry);
167
168 // The owned collection of manifest handlers. These are then referenced by
169 // raw pointer in maps for keys and priority.
170 std::vector<std::unique_ptr<ManifestHandler>> owned_manifest_handlers_;
171
172 // This number is derived from determining the total number of manifest
173 // handlers that are installed for all build configurations. It is
174 // checked through a unit test:
175 // ChromeExtensionsClientTest.CheckManifestHandlerRegistryForOverflow.
176 //
177 // Any new manifest handlers added may cause the small_map to overflow
178 // to the backup std::unordered_map, which we don't want, as that would
179 // defeat the optimization of using small_map.
180 static constexpr size_t kHandlerMax = 73;
181 using FallbackMap = std::unordered_map<std::string, ManifestHandler*>;
182 using ManifestHandlerMap = base::small_map<FallbackMap, kHandlerMax>;
183 using FallbackPriorityMap = std::unordered_map<ManifestHandler*, int>;
184 using ManifestHandlerPriorityMap =
185 base::small_map<FallbackPriorityMap, kHandlerMax>;
186
187 // Puts the manifest handlers in order such that each handler comes after
188 // any handlers for their PrerequisiteKeys. If there is no handler for
189 // a prerequisite key, that dependency is simply ignored.
190 // CHECKs that there are no manifest handlers with circular dependencies.
191 void SortManifestHandlers();
192
193 // All registered manifest handlers.
194 ManifestHandlerMap handlers_;
195
196 // The priority for each manifest handler. Handlers with lower priority
197 // values are evaluated first.
198 ManifestHandlerPriorityMap priority_map_;
199
200 bool is_finalized_;
201
202 DISALLOW_COPY_AND_ASSIGN(ManifestHandlerRegistry);
203};
204
205} // namespace extensions
206
207#endif // EXTENSIONS_COMMON_MANIFEST_HANDLER_H_
208