// Copyright (c) 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef EXTENSIONS_COMMON_MANIFEST_HANDLER_H_ #define EXTENSIONS_COMMON_MANIFEST_HANDLER_H_ #include #include #include #include #include #include "base/containers/small_map.h" #include "base/containers/span.h" #include "base/gtest_prod_util.h" #include "base/lazy_instance.h" #include "extensions/common/manifest.h" namespace extensions { class Extension; class ManifestPermission; class ManifestPermissionSet; // An interface for clients that recognize and parse keys in extension // manifests. class ManifestHandler { public: ManifestHandler(); ManifestHandler(const ManifestHandler&) = delete; ManifestHandler& operator=(const ManifestHandler&) = delete; virtual ~ManifestHandler(); // Attempts to parse the extension's manifest. // Returns true on success or false on failure; if false, |error| will // be set to a failure message. // This does not perform any IO operations. virtual bool Parse(Extension* extension, std::u16string* error) = 0; // Validate that files associated with this manifest key exist. // Validation takes place after parsing. May also append a series of // warning messages to |warnings|. // This may perform IO operations. // // Otherwise, returns false, and a description of the error is // returned in |error|. // TODO(yoz): Change error to std::u16string. See crbug.com/71980. virtual bool Validate(const Extension* extension, std::string* error, std::vector* warnings) const; // If false (the default), only parse the manifest if a registered // key is present in the manifest. If true, always attempt to parse // the manifest for this extension type, even if no registered keys // are present. This allows specifying a default parsed value for // extensions that don't declare our key in the manifest. // TODO(yoz): Use Feature availability instead. virtual bool AlwaysParseForType(Manifest::Type type) const; // Same as AlwaysParseForType, but for Validate instead of Parse. virtual bool AlwaysValidateForType(Manifest::Type type) const; // The list of keys that, if present, should be parsed before calling our // Parse (typically, because our Parse needs to read those keys). // Defaults to empty. virtual const std::vector PrerequisiteKeys() const; // Creates a |ManifestPermission| instance for the given manifest key |name|. // The returned permission does not contain any permission data, so this // method is usually used before calling |FromValue| or |Read|. Returns // |NULL| if the manifest handler does not support custom permissions. virtual ManifestPermission* CreatePermission(); // Creates a |ManifestPermission| instance containing the initial set of // required manifest permissions for the given |extension|. Returns |NULL| if // the manifest handler does not support custom permissions or if there was // no manifest key in the extension manifest for this handler. virtual ManifestPermission* CreateInitialRequiredPermission( const Extension* extension); // The keys this handler is responsible for. virtual base::span Keys() const = 0; // Calling FinalizeRegistration indicates that there are no more // manifest handlers to be registered. static void FinalizeRegistration(); static bool IsRegistrationFinalized(); // Call Parse on all registered manifest handlers that should parse // this extension. static bool ParseExtension(Extension* extension, std::u16string* error); // Call Validate on all registered manifest handlers for this extension. This // may perform IO operations. static bool ValidateExtension(const Extension* extension, std::string* error, std::vector* warnings); // Calls |CreatePermission| on the manifest handler for |key|. Returns |NULL| // if there is no manifest handler for |key| or if the manifest handler for // |key| does not support custom permissions. static ManifestPermission* CreatePermission(const std::string& key); // Calls |CreateInitialRequiredPermission| on all registered manifest handlers // and adds the returned permissions to |permission_set|. Note this should be // called after all manifest data elements have been read, parsed and stored // in the manifest data property of |extension|, as manifest handlers need // access to their manifest data to initialize their required manifest // permission. static void AddExtensionInitialRequiredPermissions( const Extension* extension, ManifestPermissionSet* permission_set); protected: // A convenience method for handlers that only register for 1 key, // so that they can define keys() { return SingleKey(kKey); } static const std::vector SingleKey(const std::string& key); }; // The global registry for manifest handlers. class ManifestHandlerRegistry { public: ManifestHandlerRegistry(const ManifestHandlerRegistry&) = delete; ManifestHandlerRegistry& operator=(const ManifestHandlerRegistry&) = delete; // Get the one true instance. static ManifestHandlerRegistry* Get(); // Registers a ManifestHandler, associating it with its keys. If there is // already a handler registered for any key |handler| manages, this method // will DCHECK. void RegisterHandler(std::unique_ptr handler); private: friend class ManifestHandler; friend class ScopedTestingManifestHandlerRegistry; friend struct base::LazyInstanceTraitsBase; FRIEND_TEST_ALL_PREFIXES(ManifestHandlerPerfTest, MANUAL_CommonInitialize); FRIEND_TEST_ALL_PREFIXES(ManifestHandlerPerfTest, MANUAL_LookupTest); FRIEND_TEST_ALL_PREFIXES(ManifestHandlerPerfTest, MANUAL_CommonMeasureFinalization); FRIEND_TEST_ALL_PREFIXES(ChromeExtensionsClientTest, CheckManifestHandlerRegistryForOverflow); ManifestHandlerRegistry(); ~ManifestHandlerRegistry(); void Finalize(); bool ParseExtension(Extension* extension, std::u16string* error); bool ValidateExtension(const Extension* extension, std::string* error, std::vector* warnings); ManifestPermission* CreatePermission(const std::string& key); void AddExtensionInitialRequiredPermissions( const Extension* extension, ManifestPermissionSet* permission_set); // Reset the one true instance. static void ResetForTesting(); // Overrides the current global ManifestHandlerRegistry with // |registry|, returning the current one. static ManifestHandlerRegistry* SetForTesting( ManifestHandlerRegistry* new_registry); // The owned collection of manifest handlers. These are then referenced by // raw pointer in maps for keys and priority. std::vector> owned_manifest_handlers_; // This number is derived from determining the total number of manifest // handlers that are installed for all build configurations. It is // checked through a unit test: // ChromeExtensionsClientTest.CheckManifestHandlerRegistryForOverflow. // // Any new manifest handlers added may cause the small_map to overflow // to the backup std::unordered_map, which we don't want, as that would // defeat the optimization of using small_map. static constexpr size_t kHandlerMax = 87; using FallbackMap = std::unordered_map; using ManifestHandlerMap = base::small_map; using FallbackPriorityMap = std::unordered_map; using ManifestHandlerPriorityMap = base::small_map; // Puts the manifest handlers in order such that each handler comes after // any handlers for their PrerequisiteKeys. If there is no handler for // a prerequisite key, that dependency is simply ignored. // CHECKs that there are no manifest handlers with circular dependencies. void SortManifestHandlers(); // All registered manifest handlers. ManifestHandlerMap handlers_; // The priority for each manifest handler. Handlers with lower priority // values are evaluated first. ManifestHandlerPriorityMap priority_map_; bool is_finalized_; }; } // namespace extensions #endif // EXTENSIONS_COMMON_MANIFEST_HANDLER_H_