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 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
|
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_EXTENSIONS_UNPACKED_INSTALLER_H_
#define CHROME_BROWSER_EXTENSIONS_UNPACKED_INSTALLER_H_
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "base/callback_list.h"
#include "base/files/file_path.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/scoped_observation.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile_observer.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/browser/preload_check.h"
#include "extensions/buildflags/buildflags.h"
#include "extensions/common/manifest.h"
static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE));
class Profile;
namespace content {
class BrowserContext;
}
namespace extensions {
class Extension;
class ExtensionService;
class PreloadCheckGroup;
// Installs and loads an unpacked extension. Because internal state needs to be
// held about the installation process, only one call to Load*() should be made
// per UnpackedInstaller.
// TODO(erikkay): It might be useful to be able to load a packed extension
// (presumably into memory) without installing it.
class UnpackedInstaller : public base::RefCountedThreadSafe<
UnpackedInstaller,
content::BrowserThread::DeleteOnUIThread>,
public ProfileObserver {
public:
// Manifest settings override types.
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
//
// LINT.IfChange(ManifestSettingsOverrideType)
enum ManifestSettingsOverrideType {
// No overrides.
kNoOverride = 0,
// Overrides the default search engine.
kSearchEngine = 1,
// Overrides the new tab page.
kNewTabPage = 2,
// Overrides the default search engine and new tab page.
kSearchEngineAndNewTabPage = 3,
kMaxValue = kSearchEngineAndNewTabPage,
};
// LINT.ThenChange(/tools/metrics/histograms/metadata/extensions/enums.xml:ManifestSettingsOverrideType)
using CompletionCallback = base::OnceCallback<void(const Extension* extension,
const base::FilePath&,
const std::string&)>;
UnpackedInstaller(const UnpackedInstaller&) = delete;
UnpackedInstaller& operator=(const UnpackedInstaller&) = delete;
static scoped_refptr<UnpackedInstaller> Create(
content::BrowserContext* context);
// Loads the extension from the directory `extension_path`, which is
// the top directory of a specific extension where its manifest file lives.
// Errors are reported through LoadErrorReporter. On success,
// ExtensionService::AddExtension() is called.
void Load(const base::FilePath& extension_path);
// Loads the extension from the directory `extension_path`;
// for use with command line switch --load-extension=path or
// --load-and-launch-app=path.
// This is equivalent to Load, except that it reads the extension from
// `extension_path` synchronously.
// The return value indicates whether the installation has begun successfully.
// The id of the extension being loaded is returned in `extension_id`.
// `only_allow_apps` is used to avoid side-loading of non-app extensions.
bool LoadFromCommandLine(const base::FilePath& extension_path,
std::string* extension_id,
bool only_allow_apps);
// Allows overriding of whether modern manifest versions are required;
// intended for testing.
bool require_modern_manifest_version() const {
return require_modern_manifest_version_;
}
void set_require_modern_manifest_version(bool val) {
require_modern_manifest_version_ = val;
}
void set_be_noisy_on_failure(bool be_noisy_on_failure) {
be_noisy_on_failure_ = be_noisy_on_failure;
}
void set_completion_callback(CompletionCallback callback) {
callback_ = std::move(callback);
}
void set_allow_file_access(bool allow) { allow_file_access_ = allow; }
void set_allow_incognito_access(bool allow) {
allow_incognito_access_ = allow;
}
void set_install_param(const std::string& param) { install_param_ = param; }
private:
friend struct content::BrowserThread::DeleteOnThread<
content::BrowserThread::UI>;
friend class base::DeleteHelper<UnpackedInstaller>;
explicit UnpackedInstaller(content::BrowserContext* context);
~UnpackedInstaller() override;
// Must be called from the UI thread. Begin management policy and requirements
// checks.
void StartInstallChecks();
// Callback from PreloadCheckGroup.
void OnInstallChecksComplete(const PreloadCheck::Errors& errors);
// Verifies if loading unpacked extensions is allowed.
bool IsLoadingUnpackedAllowed() const;
// We change the input extension path to an absolute path, on the file thread.
// Then we need to check the file access preference, which needs
// to happen back on the UI thread, so it posts CheckExtensionFileAccess on
// the UI thread. In turn, once that gets the pref, it goes back to the
// file thread with LoadWithFileAccess.
// TODO(yoz): It would be nice to remove this ping-pong, but we need to know
// what file access flags to pass to file_util::LoadExtension.
void GetAbsolutePathOnFileThread();
void CheckExtensionFileAccess();
void LoadWithFileAccessOnFileThread(int flags);
// Notify the frontend that an attempt to retry will not be necessary.
void UnregisterLoadRetryListener();
// Notify the frontend that there was an error loading an extension.
void ReportExtensionLoadError(const std::string& error);
// Passes the extension onto extension service.
void InstallExtension();
// Helper to get the Extension::CreateFlags for the installing extension.
int GetFlags();
// Helper to load an extension. Should be called on a sequence where file IO
// is allowed. Loads the extension, validates extension locales and persists
// the ruleset for the Declarative Net Request API, if needed. In case of an
// error, returns false and populates `error`.
bool LoadExtension(mojom::ManifestLocation location,
int flags,
std::string* error);
// Reads the Declarative Net Request JSON rulesets for the extension, if it
// provided any, and persists the indexed rulesets. Returns false and
// populates `error` in case of an error. Should be called on a sequence where
// file IO is allowed.
bool IndexAndPersistRulesIfNeeded(std::string* error);
// Records command-line extension metrics, emitted when a command line
// extension is installed.
void RecordCommandLineMetrics();
// ProfileObserver
void OnProfileWillBeDestroyed(Profile* profile) override;
// Called when the browser is terminating.
void OnBrowserTerminating();
const Extension* extension() { return extension_.get(); }
// The service we will report results back to.
raw_ptr<ExtensionService> service_ = nullptr;
// The Profile the extension is being installed in.
raw_ptr<Profile, DanglingUntriaged> profile_;
// Observes profile destruction.
base::ScopedObservation<Profile, ProfileObserver> profile_observation_{this};
// The pathname of the directory to load from, which is an absolute path
// after GetAbsolutePath has been called.
base::FilePath extension_path_;
// The extension being installed.
scoped_refptr<Extension> extension_;
// Whether to require the extension installed to have a modern manifest
// version.
bool require_modern_manifest_version_;
// Whether or not to be noisy (show a dialog) on failure. Defaults to true.
bool be_noisy_on_failure_;
// Checks to run before the extension can be installed.
std::unique_ptr<PreloadCheck> policy_check_;
std::unique_ptr<PreloadCheck> requirements_check_;
// Runs the above checks.
std::unique_ptr<PreloadCheckGroup> check_group_;
// Install prefs needed for the Declarative Net Request API.
base::Value::Dict ruleset_install_prefs_;
CompletionCallback callback_;
// Override default file access.
std::optional<bool> allow_file_access_;
// Override default incognito access.
std::optional<bool> allow_incognito_access_;
// Specify an install param.
std::optional<std::string> install_param_;
// True if the browser is terminating.
bool browser_terminating_ = false;
// Subscription to browser termination.
base::CallbackListSubscription on_browser_terminating_subscription_;
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_UNPACKED_INSTALLER_H_
|