1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef EXTENSIONS_BROWSER_USER_SCRIPT_MANAGER_H_
#define EXTENSIONS_BROWSER_USER_SCRIPT_MANAGER_H_
#include <map>
#include <memory>
#include <optional>
#include <set>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "base/values.h"
#include "extensions/browser/embedder_user_script_loader.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_registry_observer.h"
#include "extensions/browser/extension_user_script_loader.h"
#include "extensions/browser/pref_types.h"
#include "extensions/common/extension.h"
#include "extensions/common/mojom/host_id.mojom.h"
#include "extensions/common/user_script.h"
namespace content {
class BrowserContext;
}
namespace extensions {
class UserScriptLoader;
// Manages user scripts for all extensions and webview scripts from embedder
// pages. Owns one UserScriptLoader for manifest extension scripts, and a map
// of mojom::HostID to UserScriptLoaders for declarative extension and embedder
// scripts. File loading and shared memory management operations are delegated
// to these UserScriptLoaders.
class UserScriptManager : public ExtensionRegistryObserver {
public:
explicit UserScriptManager(content::BrowserContext* browser_context);
~UserScriptManager() override;
UserScriptManager(const UserScriptManager& other) = delete;
UserScriptManager& operator=(const UserScriptManager& other) = delete;
// Key corresponding to whether the user has allowed user scripts to run for
// the extension.
static constexpr PrefMap kUserScriptsAllowedPref = {
"user_scripts_enabled", PrefType::kBool, PrefScope::kExtensionSpecific};
// Key corresponding to whether the migration from using the dev mode toggle
// to the per-extension toggle for enabling dynamic user scripts usage has
// completed.
static constexpr PrefMap kUserScriptsToggleMigratedPref = {
"migrated_user_scripts_toggle", PrefType::kBool, PrefScope::kProfile};
UserScriptLoader* GetUserScriptLoaderByID(const mojom::HostID& host_id);
ExtensionUserScriptLoader* GetUserScriptLoaderForExtension(
const ExtensionId& extension_id);
EmbedderUserScriptLoader* GetUserScriptLoaderForEmbedder(
const mojom::HostID& host_id);
// Sets whether scripts of the given `source` should be enabled for
// (all) extensions. Does not affect embedder script loaders.
void SetUserScriptSourceEnabledForExtensions(UserScript::Source source,
bool enabled);
// Returns true if the extension is allowed to use the userScripts API.
// Note: this may also seed feature availability state the first time it is
// called so that it is always accurate.
bool AreUserScriptsAllowed(const Extension& extension);
// Returns whether the extension has permission to run user scripts or can
// request permission to do so.
static bool IsUserScriptsAPIPermissionAvailable(const Extension& extension);
bool IsUserScriptPrefEnabledForTesting(
const ExtensionId& extension_id) const {
return IsUserScriptPrefEnabled(extension_id);
}
// Set extension preference for userScripts API being allowed.
void SetUserScriptPrefEnabled(const ExtensionId& extension_id, bool enabled);
private:
// ExtensionRegistryObserver implementation.
void OnExtensionWillBeInstalled(content::BrowserContext* browser_context,
const Extension* extension,
bool is_update,
const std::string& old_name) override;
void OnExtensionLoaded(content::BrowserContext* browser_context,
const Extension* extension) override;
void OnExtensionUnloaded(content::BrowserContext* browser_context,
const Extension* extension,
UnloadedExtensionReason reason) override;
// Called when `loader` has finished loading its initial set of scripts. This
// is only fired for extension script loaders.
void OnInitialExtensionLoadComplete(UserScriptLoader* loader,
const std::optional<std::string>& error);
// Removes the given ID from `pending_initial_extension_loads_` and if there
// are no more pending initial loads, signal to the UserScriptListener.
void RemovePendingExtensionLoadAndSignal(const ExtensionId& extension_id);
// Creates a ExtensionUserScriptLoader object.
ExtensionUserScriptLoader* CreateExtensionUserScriptLoader(
const Extension* extension);
// Creates a EmbedderUserScriptLoader object.
EmbedderUserScriptLoader* CreateEmbedderUserScriptLoader(
const mojom::HostID& host_id);
// Migrate an extension from dev mode toggle to per-extension toggle if not
// done, otherwise just set the allowed state from the current allowed
// preference.
void InitializeUserScriptState(const Extension& extension);
// Get extension preference for userScripts API being allowed.
bool IsUserScriptPrefEnabled(const ExtensionId& extension_id) const;
// Migrates an eligible extension to use the per-extension toggle.
void MigrateUserScriptExtension(const Extension& extension);
// Migrates all non-enabled extensions to use the per-extension toggle.
void MigrateUserScriptExtensions();
// A map of ExtensionUserScriptLoader for each extension host, with one loader
// per extension. Currently, each loader is lazily initialized and contains
// scripts from APIs webview tags.
std::map<ExtensionId, std::unique_ptr<ExtensionUserScriptLoader>>
extension_script_loaders_;
// A map of EmbedderUserScriptLoader for each embedder host, each loader
// contains webview content scripts for the corresponding embedder page and is
// lazily initialized.
std::map<mojom::HostID, std::unique_ptr<EmbedderUserScriptLoader>>
embedder_script_loaders_;
// Tracks the IDs of extensions with initial script loads (consisting of
// manifest and persistent dynamic scripts) in progress.
std::set<ExtensionId> pending_initial_extension_loads_;
const raw_ptr<content::BrowserContext> browser_context_;
base::ScopedObservation<ExtensionRegistry, ExtensionRegistryObserver>
extension_registry_observation_{this};
base::WeakPtrFactory<UserScriptManager> weak_factory_{this};
};
} // namespace extensions
#endif // EXTENSIONS_BROWSER_USER_SCRIPT_MANAGER_H_
|