Compare commits

...

1 Commits

Author SHA1 Message Date
Samuel Maddock
f6452226d3 refactor: move ExtensionRegistrar up to ElectronExtensionSystem 2025-02-11 15:01:01 -05:00
7 changed files with 269 additions and 178 deletions

View File

@@ -763,6 +763,8 @@ filenames = {
"shell/browser/extensions/electron_extension_host_delegate.h",
"shell/browser/extensions/electron_extension_loader.cc",
"shell/browser/extensions/electron_extension_loader.h",
"shell/browser/extensions/electron_extension_registrar_delegate.cc",
"shell/browser/extensions/electron_extension_registrar_delegate.h",
"shell/browser/extensions/electron_extension_system_factory.cc",
"shell/browser/extensions/electron_extension_system_factory.h",
"shell/browser/extensions/electron_extension_system.cc",

View File

@@ -6,7 +6,6 @@
#include <utility>
#include "base/auto_reset.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
@@ -17,16 +16,14 @@
#include "base/time/time.h"
#include "extensions/browser/extension_file_task_runner.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/pref_names.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/file_util.h"
#include "extensions/common/manifest_constants.h"
#include "shell/browser/extensions/electron_extension_system.h"
namespace extensions {
using LoadErrorBehavior = ExtensionRegistrar::LoadErrorBehavior;
namespace {
std::pair<scoped_refptr<const Extension>, std::string> LoadUnpacked(
@@ -92,9 +89,9 @@ std::pair<scoped_refptr<const Extension>, std::string> LoadUnpacked(
} // namespace
ElectronExtensionLoader::ElectronExtensionLoader(
content::BrowserContext* browser_context)
: browser_context_(browser_context),
extension_registrar_(browser_context, this) {}
content::BrowserContext* browser_context,
ElectronExtensionSystem* extension_system)
: browser_context_(browser_context), extension_system_(extension_system) {}
ElectronExtensionLoader::~ElectronExtensionLoader() = default;
@@ -108,34 +105,12 @@ void ElectronExtensionLoader::LoadExtension(
weak_factory_.GetWeakPtr(), std::move(cb)));
}
void ElectronExtensionLoader::ReloadExtension(const ExtensionId& extension_id) {
const Extension* extension = ExtensionRegistry::Get(browser_context_)
->GetInstalledExtension(extension_id);
// We shouldn't be trying to reload extensions that haven't been added.
DCHECK(extension);
// This should always start false since it's only set here, or in
// LoadExtensionForReload() as a result of the call below.
DCHECK_EQ(false, did_schedule_reload_);
base::AutoReset<bool> reset_did_schedule_reload(&did_schedule_reload_, false);
extension_registrar_.ReloadExtension(extension_id, LoadErrorBehavior::kQuiet);
if (did_schedule_reload_)
return;
}
void ElectronExtensionLoader::UnloadExtension(
const ExtensionId& extension_id,
extensions::UnloadedExtensionReason reason) {
extension_registrar_.RemoveExtension(extension_id, reason);
}
void ElectronExtensionLoader::FinishExtensionLoad(
base::OnceCallback<void(const Extension*, const std::string&)> cb,
std::pair<scoped_refptr<const Extension>, std::string> result) {
scoped_refptr<const Extension> extension = result.first;
if (extension) {
extension_registrar_.AddExtension(extension);
extension_system_->AddExtension(extension.get());
// Write extension install time to ExtensionPrefs. This is required by
// WebRequestAPI which calls extensions::ExtensionPrefs::GetInstallTime.
@@ -158,90 +133,4 @@ void ElectronExtensionLoader::FinishExtensionLoad(
std::move(cb).Run(extension.get(), result.second);
}
void ElectronExtensionLoader::FinishExtensionReload(
const ExtensionId& old_extension_id,
std::pair<scoped_refptr<const Extension>, std::string> result) {
scoped_refptr<const Extension> extension = result.first;
if (extension) {
extension_registrar_.AddExtension(extension);
}
}
void ElectronExtensionLoader::PreAddExtension(const Extension* extension,
const Extension* old_extension) {
if (old_extension)
return;
// The extension might be disabled if a previous reload attempt failed. In
// that case, we want to remove that disable reason.
ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(browser_context_);
if (extension_prefs->IsExtensionDisabled(extension->id()) &&
extension_prefs->HasDisableReason(extension->id(),
disable_reason::DISABLE_RELOAD)) {
extension_prefs->RemoveDisableReason(extension->id(),
disable_reason::DISABLE_RELOAD);
// Only re-enable the extension if there are no other disable reasons.
if (extension_prefs->GetDisableReasons(extension->id()) ==
disable_reason::DISABLE_NONE) {
extension_prefs->SetExtensionEnabled(extension->id());
}
}
}
void ElectronExtensionLoader::PostActivateExtension(
scoped_refptr<const Extension> extension) {}
void ElectronExtensionLoader::PostDeactivateExtension(
scoped_refptr<const Extension> extension) {}
void ElectronExtensionLoader::PreUninstallExtension(
scoped_refptr<const Extension> extension) {}
void ElectronExtensionLoader::PostUninstallExtension(
scoped_refptr<const Extension> extension,
base::OnceClosure done_callback) {}
void ElectronExtensionLoader::PostNotifyUninstallExtension(
scoped_refptr<const Extension> extension) {}
void ElectronExtensionLoader::LoadExtensionForReload(
const ExtensionId& extension_id,
const base::FilePath& path,
LoadErrorBehavior load_error_behavior) {
CHECK(!path.empty());
// TODO(nornagon): we should save whether file access was granted
// when loading this extension and retain it here. As is, reloading an
// extension will cause the file access permission to be dropped.
int load_flags = Extension::FOLLOW_SYMLINKS_ANYWHERE;
GetExtensionFileTaskRunner()->PostTaskAndReplyWithResult(
FROM_HERE, base::BindOnce(&LoadUnpacked, path, load_flags),
base::BindOnce(&ElectronExtensionLoader::FinishExtensionReload,
weak_factory_.GetWeakPtr(), extension_id));
did_schedule_reload_ = true;
}
void ElectronExtensionLoader::ShowExtensionDisabledError(
const Extension* extension,
bool is_remote_install) {}
void ElectronExtensionLoader::FinishDelayedInstallationsIfAny() {}
bool ElectronExtensionLoader::CanAddExtension(const Extension* extension) {
return true;
}
bool ElectronExtensionLoader::CanEnableExtension(const Extension* extension) {
return true;
}
bool ElectronExtensionLoader::CanDisableExtension(const Extension* extension) {
// Extensions cannot be disabled by the user.
return false;
}
bool ElectronExtensionLoader::ShouldBlockExtension(const Extension* extension) {
return false;
}
} // namespace extensions

View File

@@ -11,7 +11,6 @@
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "extensions/browser/extension_registrar.h"
#include "extensions/common/extension_id.h"
namespace base {
@@ -25,12 +24,14 @@ class BrowserContext;
namespace extensions {
class Extension;
class ElectronExtensionSystem;
// Handles extension loading and reloading using ExtensionRegistrar.
class ElectronExtensionLoader : public ExtensionRegistrar::Delegate {
// Handles extension loading.
class ElectronExtensionLoader {
public:
explicit ElectronExtensionLoader(content::BrowserContext* browser_context);
~ElectronExtensionLoader() override;
explicit ElectronExtensionLoader(content::BrowserContext* browser_context,
ElectronExtensionSystem* extension_system);
~ElectronExtensionLoader();
// disable copy
ElectronExtensionLoader(const ElectronExtensionLoader&) = delete;
@@ -43,64 +44,13 @@ class ElectronExtensionLoader : public ExtensionRegistrar::Delegate {
base::OnceCallback<void(const Extension* extension,
const std::string&)> cb);
// Starts reloading the extension. A keep-alive is maintained until the
// reload succeeds/fails. If the extension is an app, it will be launched upon
// reloading.
// This may invalidate references to the old Extension object, so it takes the
// ID by value.
void ReloadExtension(const ExtensionId& extension_id);
void UnloadExtension(const ExtensionId& extension_id,
extensions::UnloadedExtensionReason reason);
ExtensionRegistrar* registrar() { return &extension_registrar_; }
private:
// If the extension loaded successfully, enables it. If it's an app, launches
// it. If the load failed, updates ShellKeepAliveRequester.
void FinishExtensionReload(
const ExtensionId& old_extension_id,
std::pair<scoped_refptr<const Extension>, std::string> result);
void FinishExtensionLoad(
base::OnceCallback<void(const Extension*, const std::string&)> cb,
std::pair<scoped_refptr<const Extension>, std::string> result);
// ExtensionRegistrar::Delegate:
void PreAddExtension(const Extension* extension,
const Extension* old_extension) override;
void PostActivateExtension(scoped_refptr<const Extension> extension) override;
void PostDeactivateExtension(
scoped_refptr<const Extension> extension) override;
void PreUninstallExtension(scoped_refptr<const Extension> extension) override;
void PostUninstallExtension(scoped_refptr<const Extension> extension,
base::OnceClosure done_callback) override;
void PostNotifyUninstallExtension(
scoped_refptr<const Extension> extension) override;
void LoadExtensionForReload(
const ExtensionId& extension_id,
const base::FilePath& path,
ExtensionRegistrar::LoadErrorBehavior load_error_behavior) override;
void ShowExtensionDisabledError(const Extension* extension,
bool is_remote_install) override;
void FinishDelayedInstallationsIfAny() override;
bool CanAddExtension(const Extension* extension) override;
bool CanEnableExtension(const Extension* extension) override;
bool CanDisableExtension(const Extension* extension) override;
bool ShouldBlockExtension(const Extension* extension) override;
raw_ptr<content::BrowserContext> browser_context_; // Not owned.
// Registers and unregisters extensions.
ExtensionRegistrar extension_registrar_;
// Holds keep-alives for relaunching apps.
// ShellKeepAliveRequester keep_alive_requester_;
// Indicates that we posted the (asynchronous) task to start reloading.
// Used by ReloadExtension() to check whether ExtensionRegistrar calls
// LoadExtensionForReload().
bool did_schedule_reload_ = false;
raw_ptr<content::BrowserContext> browser_context_; // Not owned.
raw_ptr<ElectronExtensionSystem> extension_system_; // Not owned.
base::WeakPtrFactory<ElectronExtensionLoader> weak_factory_{this};
};

View File

@@ -0,0 +1,127 @@
// Copyright 2018 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.
#include "shell/browser/extensions/electron_extension_registrar_delegate.h"
#include <utility>
#include "base/auto_reset.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/sequenced_task_runner.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "extensions/browser/extension_file_task_runner.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/pref_names.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/file_util.h"
#include "extensions/common/manifest_constants.h"
#include "shell/browser/extensions/electron_extension_system.h"
namespace extensions {
using LoadErrorBehavior = ExtensionRegistrar::LoadErrorBehavior;
ElectronExtensionRegistrarDelegate::ElectronExtensionRegistrarDelegate(
content::BrowserContext* browser_context,
ElectronExtensionSystem* extension_system)
: browser_context_(browser_context), extension_system_(extension_system) {}
ElectronExtensionRegistrarDelegate::~ElectronExtensionRegistrarDelegate() =
default;
void ElectronExtensionRegistrarDelegate::PreAddExtension(
const Extension* extension,
const Extension* old_extension) {
if (old_extension)
return;
// The extension might be disabled if a previous reload attempt failed. In
// that case, we want to remove that disable reason.
ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(browser_context_);
if (extension_prefs->IsExtensionDisabled(extension->id()) &&
extension_prefs->HasDisableReason(extension->id(),
disable_reason::DISABLE_RELOAD)) {
extension_prefs->RemoveDisableReason(extension->id(),
disable_reason::DISABLE_RELOAD);
// Only re-enable the extension if there are no other disable reasons.
if (extension_prefs->GetDisableReasons(extension->id()) ==
disable_reason::DISABLE_NONE) {
extension_prefs->SetExtensionEnabled(extension->id());
}
}
}
void ElectronExtensionRegistrarDelegate::PostActivateExtension(
scoped_refptr<const Extension> extension) {}
void ElectronExtensionRegistrarDelegate::PostDeactivateExtension(
scoped_refptr<const Extension> extension) {}
void ElectronExtensionRegistrarDelegate::PreUninstallExtension(
scoped_refptr<const Extension> extension) {}
void ElectronExtensionRegistrarDelegate::PostUninstallExtension(
scoped_refptr<const Extension> extension,
base::OnceClosure done_callback) {}
void ElectronExtensionRegistrarDelegate::PostNotifyUninstallExtension(
scoped_refptr<const Extension> extension) {}
void ElectronExtensionRegistrarDelegate::LoadExtensionForReload(
const ExtensionId& extension_id,
const base::FilePath& path,
LoadErrorBehavior load_error_behavior) {
CHECK(!path.empty());
// TODO(nornagon): we should save whether file access was granted
// when loading this extension and retain it here. As is, reloading an
// extension will cause the file access permission to be dropped.
int load_flags = Extension::FOLLOW_SYMLINKS_ANYWHERE;
extension_system_->LoadExtension(
path, load_flags,
base::BindOnce(&ElectronExtensionRegistrarDelegate::FinishExtensionReload,
weak_factory_.GetWeakPtr()));
}
void ElectronExtensionRegistrarDelegate::FinishExtensionReload(
const Extension* extension,
const ExtensionId& extension_id) {
if (extension) {
extension_system_->AddExtension(extension);
}
}
void ElectronExtensionRegistrarDelegate::ShowExtensionDisabledError(
const Extension* extension,
bool is_remote_install) {}
void ElectronExtensionRegistrarDelegate::FinishDelayedInstallationsIfAny() {}
bool ElectronExtensionRegistrarDelegate::CanAddExtension(
const Extension* extension) {
return true;
}
bool ElectronExtensionRegistrarDelegate::CanEnableExtension(
const Extension* extension) {
return true;
}
bool ElectronExtensionRegistrarDelegate::CanDisableExtension(
const Extension* extension) {
return true;
}
bool ElectronExtensionRegistrarDelegate::ShouldBlockExtension(
const Extension* extension) {
return false;
}
} // namespace extensions

View File

@@ -0,0 +1,86 @@
// Copyright 2018 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 ELECTRON_SHELL_BROWSER_EXTENSIONS_ELECTRON_EXTENSION_REGISTRAR_DELEGATE_H_
#define ELECTRON_SHELL_BROWSER_EXTENSIONS_ELECTRON_EXTENSION_REGISTRAR_DELEGATE_H_
#include <string>
#include <utility>
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "extensions/browser/extension_registrar.h"
#include "extensions/common/extension_id.h"
namespace base {
class FilePath;
}
namespace content {
class BrowserContext;
}
namespace extensions {
class Extension;
class ElectronExtensionSystem;
// Handles extension loading and reloading using ExtensionRegistrar.
class ElectronExtensionRegistrarDelegate : public ExtensionRegistrar::Delegate {
public:
explicit ElectronExtensionRegistrarDelegate(
content::BrowserContext* browser_context,
ElectronExtensionSystem* extension_system);
~ElectronExtensionRegistrarDelegate() override;
// disable copy
ElectronExtensionRegistrarDelegate(
const ElectronExtensionRegistrarDelegate&) = delete;
ElectronExtensionRegistrarDelegate& operator=(
const ElectronExtensionRegistrarDelegate&) = delete;
void set_extension_registrar(ExtensionRegistrar* registrar) {
extension_registrar_ = registrar;
}
private:
// ExtensionRegistrar::Delegate:
void PreAddExtension(const Extension* extension,
const Extension* old_extension) override;
void PostActivateExtension(scoped_refptr<const Extension> extension) override;
void PostDeactivateExtension(
scoped_refptr<const Extension> extension) override;
void PreUninstallExtension(scoped_refptr<const Extension> extension) override;
void PostUninstallExtension(scoped_refptr<const Extension> extension,
base::OnceClosure done_callback) override;
void PostNotifyUninstallExtension(
scoped_refptr<const Extension> extension) override;
void LoadExtensionForReload(
const ExtensionId& extension_id,
const base::FilePath& path,
ExtensionRegistrar::LoadErrorBehavior load_error_behavior) override;
void ShowExtensionDisabledError(const Extension* extension,
bool is_remote_install) override;
void FinishDelayedInstallationsIfAny() override;
bool CanAddExtension(const Extension* extension) override;
bool CanEnableExtension(const Extension* extension) override;
bool CanDisableExtension(const Extension* extension) override;
bool ShouldBlockExtension(const Extension* extension) override;
// If the extension loaded successfully, enables it. If it's an app, launches
// it. If the load failed, updates ShellKeepAliveRequester.
void FinishExtensionReload(const Extension* extension,
const ExtensionId& extension_id);
raw_ptr<content::BrowserContext> browser_context_; // Not owned.
raw_ptr<ElectronExtensionSystem> extension_system_; // Not owned.
raw_ptr<ExtensionRegistrar> extension_registrar_ = nullptr;
base::WeakPtrFactory<ElectronExtensionRegistrarDelegate> weak_factory_{this};
};
} // namespace extensions
#endif // ELECTRON_SHELL_BROWSER_EXTENSIONS_ELECTRON_EXTENSION_REGISTRAR_DELEGATE_H_

View File

@@ -29,6 +29,7 @@
#include "extensions/browser/user_script_manager.h"
#include "extensions/common/constants.h"
#include "shell/browser/extensions/electron_extension_loader.h"
#include "shell/browser/extensions/electron_extension_registrar_delegate.h"
#if BUILDFLAG(ENABLE_PDF_VIEWER)
#include "chrome/browser/pdf/pdf_extension_util.h" // nogncheck
@@ -39,6 +40,8 @@ using content::BrowserThread;
namespace extensions {
using LoadErrorBehavior = ExtensionRegistrar::LoadErrorBehavior;
ElectronExtensionSystem::ElectronExtensionSystem(
BrowserContext* browser_context)
: browser_context_(browser_context),
@@ -47,6 +50,10 @@ ElectronExtensionSystem::ElectronExtensionSystem(
ElectronExtensionSystem::~ElectronExtensionSystem() = default;
void ElectronExtensionSystem::AddExtension(const Extension* extension) {
extension_registrar_->AddExtension(extension);
}
void ElectronExtensionSystem::LoadExtension(
const base::FilePath& extension_dir,
int load_flags,
@@ -60,11 +67,17 @@ void ElectronExtensionSystem::FinishInitialization() {
}
void ElectronExtensionSystem::ReloadExtension(const ExtensionId& extension_id) {
extension_loader_->ReloadExtension(extension_id);
const Extension* extension = ExtensionRegistry::Get(browser_context_)
->GetInstalledExtension(extension_id);
// We shouldn't be trying to reload extensions that haven't been added.
DCHECK(extension);
extension_registrar_->ReloadExtension(extension_id,
LoadErrorBehavior::kQuiet);
}
void ElectronExtensionSystem::RemoveExtension(const ExtensionId& extension_id) {
extension_loader_->UnloadExtension(
extension_registrar_->RemoveExtension(
extension_id, extensions::UnloadedExtensionReason::UNINSTALL);
}
@@ -73,13 +86,21 @@ void ElectronExtensionSystem::Shutdown() {
}
void ElectronExtensionSystem::InitForRegularProfile(bool extensions_enabled) {
extension_registrar_delegate_ =
std::make_unique<ElectronExtensionRegistrarDelegate>(browser_context_,
this);
extension_registrar_ = std::make_unique<ExtensionRegistrar>(
browser_context_, extension_registrar_delegate_.get());
extension_registrar_delegate_->set_extension_registrar(
extension_registrar_.get());
service_worker_manager_ =
std::make_unique<ServiceWorkerManager>(browser_context_);
quota_service_ = std::make_unique<QuotaService>();
user_script_manager_ = std::make_unique<UserScriptManager>(browser_context_);
app_sorting_ = std::make_unique<NullAppSorting>();
extension_loader_ =
std::make_unique<ElectronExtensionLoader>(browser_context_);
std::make_unique<ElectronExtensionLoader>(browser_context_, this);
if (!browser_context_->IsOffTheRecord())
LoadComponentExtensions();
@@ -120,7 +141,7 @@ void ElectronExtensionSystem::LoadComponentExtensions() {
extensions::Extension::Create(
root_directory, extensions::mojom::ManifestLocation::kComponent,
*pdf_manifest, extensions::Extension::REQUIRE_KEY, &utf8_error);
extension_loader_->registrar()->AddExtension(pdf_extension);
AddExtension(pdf_extension.get());
}
#endif
}

View File

@@ -13,6 +13,7 @@
#include "base/one_shot_event.h"
#include "components/value_store/value_store_factory.h"
#include "components/value_store/value_store_factory_impl.h"
#include "extensions/browser/extension_registrar.h"
#include "extensions/browser/extension_system.h"
namespace base {
@@ -26,6 +27,7 @@ class BrowserContext;
namespace extensions {
class ElectronExtensionLoader;
class ElectronExtensionRegistrarDelegate;
class ValueStoreFactory;
// A simplified version of ExtensionSystem for app_shell. Allows
@@ -40,6 +42,10 @@ class ElectronExtensionSystem : public ExtensionSystem {
ElectronExtensionSystem(const ElectronExtensionSystem&) = delete;
ElectronExtensionSystem& operator=(const ElectronExtensionSystem&) = delete;
// Adds |extension| to this ExtensionService and notifies observers that the
// extension has been loaded.
void AddExtension(const Extension* extension);
// Loads an unpacked extension from a directory. Returns the extension on
// success, or nullptr otherwise.
void LoadExtension(
@@ -86,6 +92,10 @@ class ElectronExtensionSystem : public ExtensionSystem {
const std::string& extension_id,
const base::Value::Dict& attributes) override;
base::WeakPtr<ElectronExtensionSystem> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
private:
void OnExtensionRegisteredWithRequestContexts(
scoped_refptr<Extension> extension);
@@ -99,6 +109,12 @@ class ElectronExtensionSystem : public ExtensionSystem {
std::unique_ptr<AppSorting> app_sorting_;
std::unique_ptr<ManagementPolicy> management_policy_;
std::unique_ptr<ElectronExtensionRegistrarDelegate>
extension_registrar_delegate_;
// Helper to register and unregister extensions.
std::unique_ptr<ExtensionRegistrar> extension_registrar_;
std::unique_ptr<ElectronExtensionLoader> extension_loader_;
scoped_refptr<value_store::ValueStoreFactory> store_factory_;