Compare commits

..

7 Commits

Author SHA1 Message Date
Samuel Maddock
2551c8f89a add methods 2025-02-11 14:47:10 -05:00
Samuel Maddock
663fd64451 fix crash 2025-02-11 14:46:55 -05:00
Samuel Maddock
4d7cb66db4 add enabled property 2025-02-11 13:20:54 -05:00
Samuel Maddock
22d4e1f916 fix: build errors 2025-02-11 13:02:31 -05:00
Samuel Maddock
0c825b08b6 wip 2025-02-11 10:14:09 -05:00
Samuel Maddock
0da62a6dd5 refactor: move ExtensionRegistrar to ElectronExtensionSystem 2025-02-11 10:14:08 -05:00
Samuel Maddock
478b4a3c30 feat: session.enableExtension and session.disableExtension 2025-02-11 10:14:08 -05:00
9 changed files with 158 additions and 38 deletions

View File

@@ -1541,6 +1541,25 @@ Unloads an extension.
**Note:** This API cannot be called before the `ready` event of the `app` module
is emitted.
#### `ses.enableExtension(extensionId)`
* `extensionId` string - ID of extension to enable
Enables the extension and activates it for use by starting any background
workers. If the extension is disabled, marks it as enabled.
**Note:** This API cannot be called before the `ready` event of the `app` module
is emitted.
#### `ses.disableExtension(extensionId)`
* `extensionId` string - ID of extension to disable
Disables the extension and deactives it.
**Note:** This API cannot be called before the `ready` event of the `app` module
is emitted.
#### `ses.getExtension(extensionId)`
* `extensionId` string - ID of extension to query

View File

@@ -98,6 +98,7 @@
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
#include "extensions/browser/extension_registry.h"
#include "shell/browser/extensions/electron_extension_info.h"
#include "shell/browser/extensions/electron_extension_system.h"
#include "shell/common/gin_converters/extension_converter.h"
#endif
@@ -1309,7 +1310,8 @@ v8::Local<v8::Promise> Session::GetSharedDictionaryUsageInfo() {
v8::Local<v8::Promise> Session::LoadExtension(
const base::FilePath& extension_path,
gin::Arguments* args) {
gin_helper::Promise<const extensions::Extension*> promise(isolate_);
gin_helper::Promise<const extensions::ElectronExtensionInfo&> promise(
isolate_);
v8::Local<v8::Promise> handle = promise.GetHandle();
if (!extension_path.IsAbsolute()) {
@@ -1338,27 +1340,37 @@ v8::Local<v8::Promise> Session::LoadExtension(
extension_system->LoadExtension(
extension_path, load_flags,
base::BindOnce(
[](gin_helper::Promise<const extensions::Extension*> promise,
[](gin_helper::Promise<const extensions::ElectronExtensionInfo&>
promise,
base::WeakPtr<ElectronBrowserContext> browser_context,
const extensions::Extension* extension,
const std::string& error_msg) {
if (extension) {
if (extension && browser_context) {
if (!error_msg.empty())
util::EmitWarning(promise.isolate(), error_msg,
"ExtensionLoadWarning");
promise.Resolve(extension);
const auto& extension_info = extensions::ElectronExtensionInfo(
extension, browser_context.get());
promise.Resolve(extension_info);
} else {
promise.RejectWithErrorMessage(error_msg);
}
},
std::move(promise)));
std::move(promise), browser_context()->GetWeakPtr()));
return handle;
}
void Session::RemoveExtension(const std::string& extension_id) {
auto* extension_system = static_cast<extensions::ElectronExtensionSystem*>(
extensions::ExtensionSystem::Get(browser_context()));
extension_system->RemoveExtension(extension_id);
browser_context()->extension_system()->RemoveExtension(extension_id);
}
void Session::EnableExtension(const std::string& extension_id) {
browser_context()->extension_system()->EnableExtension(extension_id);
}
void Session::DisableExtension(const std::string& extension_id) {
browser_context()->extension_system()->DisableExtension(extension_id);
}
v8::Local<v8::Value> Session::GetExtension(const std::string& extension_id) {
@@ -1366,7 +1378,9 @@ v8::Local<v8::Value> Session::GetExtension(const std::string& extension_id) {
const extensions::Extension* extension =
registry->GetInstalledExtension(extension_id);
if (extension) {
return gin::ConvertToV8(isolate_, extension);
const auto& extension_info =
extensions::ElectronExtensionInfo(extension, browser_context());
return gin::ConvertToV8(isolate_, extension_info);
} else {
return v8::Null(isolate_);
}
@@ -1376,29 +1390,40 @@ v8::Local<v8::Value> Session::GetAllExtensions() {
auto* registry = extensions::ExtensionRegistry::Get(browser_context());
const extensions::ExtensionSet extensions =
registry->GenerateInstalledExtensionsSet();
std::vector<const extensions::Extension*> extensions_vector;
std::vector<extensions::ElectronExtensionInfo> extensions_vector;
for (const auto& extension : extensions) {
if (extension->location() !=
extensions::mojom::ManifestLocation::kComponent)
extensions_vector.emplace_back(extension.get());
extensions::mojom::ManifestLocation::kComponent) {
const auto& extension_info =
extensions::ElectronExtensionInfo(extension.get(), browser_context());
extensions_vector.emplace_back(extension_info);
}
}
return gin::ConvertToV8(isolate_, extensions_vector);
}
void Session::OnExtensionLoaded(content::BrowserContext* browser_context,
const extensions::Extension* extension) {
Emit("extension-loaded", extension);
void Session::OnExtensionLoaded(
content::BrowserContext* content_browser_context,
const extensions::Extension* extension) {
const auto& extension_info =
extensions::ElectronExtensionInfo(extension, browser_context());
Emit("extension-loaded", extension_info);
}
void Session::OnExtensionUnloaded(content::BrowserContext* browser_context,
const extensions::Extension* extension,
extensions::UnloadedExtensionReason reason) {
Emit("extension-unloaded", extension);
void Session::OnExtensionUnloaded(
content::BrowserContext* content_browser_context,
const extensions::Extension* extension,
extensions::UnloadedExtensionReason reason) {
const auto& extension_info =
extensions::ElectronExtensionInfo(extension, browser_context());
Emit("extension-unloaded", extension_info);
}
void Session::OnExtensionReady(content::BrowserContext* browser_context,
void Session::OnExtensionReady(content::BrowserContext* content_browser_context,
const extensions::Extension* extension) {
Emit("extension-ready", extension);
const auto& extension_info =
extensions::ElectronExtensionInfo(extension, browser_context());
Emit("extension-ready", extension_info);
}
#endif
@@ -1875,6 +1900,8 @@ void Session::FillObjectTemplate(v8::Isolate* isolate,
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
.SetMethod("loadExtension", &Session::LoadExtension)
.SetMethod("removeExtension", &Session::RemoveExtension)
.SetMethod("enableExtension", &Session::EnableExtension)
.SetMethod("disableExtension", &Session::DisableExtension)
.SetMethod("getExtension", &Session::GetExtension)
.SetMethod("getAllExtensions", &Session::GetAllExtensions)
#endif

View File

@@ -55,6 +55,12 @@ namespace net {
class ProxyConfig;
}
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
namespace extensions {
class ElectronExtensionSystem;
}
#endif
namespace electron {
class ElectronBrowserContext;
@@ -182,6 +188,8 @@ class Session final : public gin::Wrappable<Session>,
v8::Local<v8::Promise> LoadExtension(const base::FilePath& extension_path,
gin::Arguments* args);
void RemoveExtension(const std::string& extension_id);
void EnableExtension(const std::string& extension_id);
void DisableExtension(const std::string& extension_id);
v8::Local<v8::Value> GetExtension(const std::string& extension_id);
v8::Local<v8::Value> GetAllExtensions();

View File

@@ -155,10 +155,7 @@ class ElectronBrowserContext : public content::BrowserContext {
}
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
extensions::ElectronExtensionSystem* extension_system() {
// Guard usages of extension_system() with !IsOffTheRecord()
// There is no extension system for in-memory sessions
DCHECK(!IsOffTheRecord());
extensions::ElectronExtensionSystem* extension_system() const {
return extension_system_;
}
#endif

View File

@@ -0,0 +1,33 @@
// 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_INFO_H_
#define ELECTRON_SHELL_BROWSER_EXTENSIONS_ELECTRON_EXTENSION_INFO_H_
#include "base/memory/raw_ptr.h"
namespace electron {
class ElectronBrowserContext;
}
namespace extensions {
class Extension;
struct ElectronExtensionInfo {
explicit ElectronExtensionInfo(const Extension* extension_in,
const electron::ElectronBrowserContext* browser_context_in)
: extension(extension_in),
browser_context(browser_context_in) {
DCHECK(extension_in);
DCHECK(browser_context_in);
}
raw_ptr<const Extension> extension;
raw_ptr<const electron::ElectronBrowserContext> browser_context;
};
} // namespace extensions
#endif // ELECTRON_SHELL_BROWSER_EXTENSIONS_ELECTRON_EXTENSION_INFO_H_

View File

@@ -81,6 +81,22 @@ void ElectronExtensionSystem::RemoveExtension(const ExtensionId& extension_id) {
extension_id, extensions::UnloadedExtensionReason::UNINSTALL);
}
void ElectronExtensionSystem::EnableExtension(const std::string& extension_id) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
extension_registrar_->EnableExtension(extension_id);
}
void ElectronExtensionSystem::DisableExtension(
const ExtensionId& extension_id) {
extension_registrar_->DisableExtension(
extension_id, disable_reason::DisableReason::DISABLE_USER_ACTION);
}
bool ElectronExtensionSystem::IsExtensionEnabled(
const ExtensionId& extension_id) const {
return extension_registrar_->IsExtensionEnabled(extension_id);
}
void ElectronExtensionSystem::Shutdown() {
extension_loader_.reset();
}

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/disable_reason.h"
#include "extensions/browser/extension_registrar.h"
#include "extensions/browser/extension_system.h"
@@ -61,6 +62,17 @@ class ElectronExtensionSystem : public ExtensionSystem {
void RemoveExtension(const ExtensionId& extension_id);
// Enables the extension. If the extension is already enabled, does
// nothing.
void EnableExtension(const ExtensionId& extension_id);
// Disables the extension. If the extension is already disabled, just adds
// the incoming disable reason(s). If the extension cannot be disabled (due to
// policy), does nothing.
void DisableExtension(const ExtensionId& extension_id);
bool IsExtensionEnabled(const ExtensionId& extension_id) const;
// KeyedService implementation:
void Shutdown() override;

View File

@@ -6,6 +6,9 @@
#include "extensions/common/extension.h"
#include "gin/dictionary.h"
#include "shell/browser/electron_browser_context.h"
#include "shell/browser/extensions/electron_extension_info.h"
#include "shell/browser/extensions/electron_extension_system.h"
#include "shell/common/gin_converters/file_path_converter.h"
#include "shell/common/gin_converters/gurl_converter.h"
#include "shell/common/gin_converters/value_converter.h"
@@ -13,16 +16,20 @@
namespace gin {
// static
v8::Local<v8::Value> Converter<const extensions::Extension*>::ToV8(
v8::Local<v8::Value> Converter<extensions::ElectronExtensionInfo>::ToV8(
v8::Isolate* isolate,
const extensions::Extension* extension) {
const extensions::ElectronExtensionInfo& info) {
auto extension_id = info.extension->id();
auto dict = gin::Dictionary::CreateEmpty(isolate);
dict.Set("id", extension->id());
dict.Set("name", extension->name());
dict.Set("path", extension->path());
dict.Set("url", extension->url());
dict.Set("version", extension->VersionString());
dict.Set("manifest", *extension->manifest()->value());
dict.Set("id", extension_id);
dict.Set("name", info.extension->name());
dict.Set("path", info.extension->path());
dict.Set("url", info.extension->url());
dict.Set("version", info.extension->VersionString());
dict.Set("manifest", *info.extension->manifest()->value());
auto* ext_system = info.browser_context->extension_system();
dict.Set("enabled", ext_system->IsExtensionEnabled(extension_id));
return gin::ConvertToV8(isolate, dict);
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2019 Slack Technologies, Inc.
// Copyright (c) 2025 Salesforce, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
@@ -8,15 +8,16 @@
#include "gin/converter.h"
namespace extensions {
class Extension;
struct ElectronExtensionInfo;
}
namespace gin {
template <>
struct Converter<const extensions::Extension*> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const extensions::Extension* val);
struct Converter<extensions::ElectronExtensionInfo> {
static v8::Local<v8::Value> ToV8(
v8::Isolate* isolate,
const extensions::ElectronExtensionInfo& val);
};
} // namespace gin