mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
1 Commits
menu-item-
...
refactor/t
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b8f6459e44 |
@@ -15,7 +15,7 @@ runs:
|
||||
git config --global core.preloadindex true
|
||||
git config --global core.longpaths true
|
||||
fi
|
||||
export BUILD_TOOLS_SHA=1b7bd25dae4a780bb3170fff56c9327b53aaf7eb
|
||||
export BUILD_TOOLS_SHA=a0cc95a1884a631559bcca0c948465b725d9295a
|
||||
npm i -g @electron/build-tools
|
||||
# Update depot_tools to ensure python
|
||||
e d update_depot_tools
|
||||
@@ -29,4 +29,4 @@ runs:
|
||||
else
|
||||
echo "$HOME/.electron_build_tools/third_party/depot_tools" >> $GITHUB_PATH
|
||||
echo "$HOME/.electron_build_tools/third_party/depot_tools/python-bin" >> $GITHUB_PATH
|
||||
fi
|
||||
fi
|
||||
2
.github/workflows/pull-request-labeled.yml
vendored
2
.github/workflows/pull-request-labeled.yml
vendored
@@ -50,7 +50,7 @@ jobs:
|
||||
field-value: ✅ Reviewed
|
||||
pull-request-labeled-ai-pr:
|
||||
name: ai-pr label added
|
||||
if: github.event.label.name == 'ai-pr' && github.event.pull_request.state != 'closed'
|
||||
if: github.event.label.name == 'ai-pr'
|
||||
runs-on: ubuntu-latest
|
||||
permissions: {}
|
||||
steps:
|
||||
|
||||
@@ -63,17 +63,10 @@ See [`Menu`](menu.md) for examples.
|
||||
* `afterGroupContaining` string[] (optional) - Provides a means for a single context menu to declare
|
||||
the placement of their containing group after the containing group of the item
|
||||
with the specified id.
|
||||
* `badge` Object (optional) _macOS_ - Only available on macOS 14 and up.
|
||||
* `type` string (optional) - Can be one of `alerts`, `updates`, `new-items` or `none`. Default is `none`.
|
||||
* `count` number (optional) - The number of items the badge displays. Cannot be used with `type: 'none'`.
|
||||
* `content` string (optional) - A custom string to display in the badge. Only usable with `type: 'none'`.
|
||||
|
||||
> [!NOTE]
|
||||
> `acceleratorWorksWhenHidden` is specified as being macOS-only because accelerators always work when items are hidden on Windows and Linux. The option is exposed to users to give them the option to turn it off, as this is possible in native macOS development.
|
||||
|
||||
> [!NOTE]
|
||||
> If you use one of the predefined badge types on macOS (not 'none'), the system localizes and pluralizes the string for you. If you create your own custom badge string, you need to localize and pluralize that string yourself.
|
||||
|
||||
### Instance Properties
|
||||
|
||||
The following properties are available on instances of `MenuItem`:
|
||||
@@ -188,9 +181,3 @@ A `number` indicating an item's sequential unique id.
|
||||
#### `menuItem.menu`
|
||||
|
||||
A [`Menu`](menu.md) that the item is a part of.
|
||||
|
||||
#### `menuItem.badge` _macOS_
|
||||
|
||||
An [`MenuItemBadge`](structures/menu-item-badge.md) indicating the badge for the menu item.
|
||||
|
||||
This property can be dynamically changed. Only available on macOS 14 and up.
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# MenuItemBadge Object
|
||||
|
||||
* `type` string (optional) - Can be one of `alerts`, `updates`, `new-items` or `none`. Default is `none`.
|
||||
* `count` number (optional) - The number of items the badge displays. Cannot be used with `type: 'none'`.
|
||||
* `content` string (optional) - A custom string to display in the badge. Only usable with `type: 'none'`.
|
||||
@@ -111,7 +111,6 @@ auto_filenames = {
|
||||
"docs/api/structures/media-access-permission-request.md",
|
||||
"docs/api/structures/memory-info.md",
|
||||
"docs/api/structures/memory-usage-details.md",
|
||||
"docs/api/structures/menu-item-badge.md",
|
||||
"docs/api/structures/mime-typed-buffer.md",
|
||||
"docs/api/structures/mouse-input-event.md",
|
||||
"docs/api/structures/mouse-wheel-input-event.md",
|
||||
|
||||
@@ -38,24 +38,6 @@ const MenuItem = function (this: any, options: any) {
|
||||
this.overrideProperty('acceleratorWorksWhenHidden', true);
|
||||
this.overrideProperty('registerAccelerator', roles.shouldRegisterAccelerator(this.role));
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
let badgeValue = options.badge;
|
||||
Object.defineProperty(this, 'badge', {
|
||||
get: () => badgeValue,
|
||||
set: (newValue) => {
|
||||
badgeValue = newValue;
|
||||
// Update native badge if this item is already in a menu
|
||||
if (this.menu) {
|
||||
const index = this.menu.getIndexOfCommandId(this.commandId);
|
||||
if (index !== -1 && badgeValue) {
|
||||
this.menu.setBadge(index, badgeValue);
|
||||
}
|
||||
}
|
||||
},
|
||||
enumerable: true
|
||||
});
|
||||
}
|
||||
|
||||
if (!MenuItem.types.includes(this.type)) {
|
||||
throw new Error(`Unknown menu item type: ${this.type}`);
|
||||
}
|
||||
|
||||
@@ -176,9 +176,6 @@ Menu.prototype.insert = function (pos, item) {
|
||||
if (item.type === 'palette' || item.type === 'header') {
|
||||
this.setCustomType(pos, item.type);
|
||||
}
|
||||
if (process.platform === 'darwin' && item.badge) {
|
||||
this.setBadge(pos, item.badge);
|
||||
}
|
||||
|
||||
// Make menu accessible to items.
|
||||
item.overrideReadOnlyProperty('menu', this);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "shell/common/gin_converters/gurl_converter.h"
|
||||
#include "shell/common/gin_converters/image_converter.h"
|
||||
#include "shell/common/gin_converters/optional_converter.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "shell/common/gin_helper/object_template_builder.h"
|
||||
#include "shell/common/node_includes.h"
|
||||
#include "ui/base/models/image_model.h"
|
||||
@@ -27,7 +28,6 @@
|
||||
namespace gin {
|
||||
|
||||
using SharingItem = electron::ElectronMenuModel::SharingItem;
|
||||
using Badge = electron::ElectronMenuModel::Badge;
|
||||
|
||||
template <>
|
||||
struct Converter<SharingItem> {
|
||||
@@ -44,28 +44,6 @@ struct Converter<SharingItem> {
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<Badge> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
Badge* out) {
|
||||
gin_helper::Dictionary dict;
|
||||
if (!ConvertFromV8(isolate, val, &dict))
|
||||
return false;
|
||||
|
||||
std::string type_str;
|
||||
if (dict.Get("type", &type_str)) {
|
||||
out->type = base::UTF8ToUTF16(type_str);
|
||||
} else {
|
||||
out->type = u"none";
|
||||
}
|
||||
|
||||
dict.GetOptional("count", &(out->count));
|
||||
dict.GetOptional("content", &(out->content));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace gin
|
||||
|
||||
#endif
|
||||
@@ -274,21 +252,6 @@ void Menu::SetCustomType(int index, const std::u16string& customType) {
|
||||
model_->SetCustomType(index, customType);
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
void Menu::SetBadge(int index, const gin_helper::Dictionary& badge_dict) {
|
||||
ElectronMenuModel::Badge badge;
|
||||
std::string type_str;
|
||||
if (badge_dict.Get("type", &type_str)) {
|
||||
badge.type = base::UTF8ToUTF16(type_str);
|
||||
} else {
|
||||
badge.type = u"none";
|
||||
}
|
||||
badge_dict.GetOptional("count", &badge.count);
|
||||
badge_dict.GetOptional("content", &badge.content);
|
||||
model_->SetBadge(index, std::move(badge));
|
||||
}
|
||||
#endif
|
||||
|
||||
void Menu::Clear() {
|
||||
model_->Clear();
|
||||
}
|
||||
@@ -329,12 +292,8 @@ void Menu::FillObjectTemplate(v8::Isolate* isolate,
|
||||
.SetMethod("setToolTip", &Menu::SetToolTip)
|
||||
.SetMethod("setRole", &Menu::SetRole)
|
||||
.SetMethod("setCustomType", &Menu::SetCustomType)
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
.SetMethod("setBadge", &Menu::SetBadge)
|
||||
#endif
|
||||
.SetMethod("clear", &Menu::Clear)
|
||||
.SetMethod("getItemCount", &Menu::GetItemCount)
|
||||
.SetMethod("getIndexOfCommandId", &Menu::GetIndexOfCommandId)
|
||||
.SetMethod("popupAt", &Menu::PopupAt)
|
||||
.SetMethod("closePopupAt", &Menu::ClosePopupAt)
|
||||
.SetMethod("_getAcceleratorTextAt", &Menu::GetAcceleratorTextAtForTesting)
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "shell/browser/event_emitter_mixin.h"
|
||||
#include "shell/browser/ui/electron_menu_model.h"
|
||||
#include "shell/common/gin_helper/constructible.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "shell/common/gin_helper/self_keep_alive.h"
|
||||
#include "ui/base/mojom/menu_source_type.mojom-forward.h"
|
||||
|
||||
@@ -129,9 +128,6 @@ class Menu : public gin::Wrappable<Menu>,
|
||||
void SetToolTip(int index, const std::u16string& toolTip);
|
||||
void SetRole(int index, const std::u16string& role);
|
||||
void SetCustomType(int index, const std::u16string& customType);
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
void SetBadge(int index, const gin_helper::Dictionary& badge);
|
||||
#endif
|
||||
void Clear();
|
||||
int GetIndexOfCommandId(int command_id) const;
|
||||
int GetItemCount() const;
|
||||
|
||||
@@ -550,7 +550,8 @@ gin::WrapperInfo Session::kWrapperInfo = {{gin::kEmbedderNativeGin},
|
||||
Session::Session(v8::Isolate* isolate, ElectronBrowserContext* browser_context)
|
||||
: isolate_(isolate),
|
||||
network_emulation_token_(base::UnguessableToken::Create()),
|
||||
browser_context_{browser_context} {
|
||||
browser_context_{
|
||||
raw_ref<ElectronBrowserContext>::from_ptr(browser_context)} {
|
||||
gin::PerIsolateData* data = gin::PerIsolateData::From(isolate);
|
||||
data->AddDisposeObserver(this);
|
||||
// Observe DownloadManager to get download notifications.
|
||||
@@ -583,21 +584,16 @@ Session::~Session() {
|
||||
}
|
||||
|
||||
void Session::Dispose() {
|
||||
if (!keep_alive_)
|
||||
return;
|
||||
|
||||
ElectronBrowserContext* const browser_context = this->browser_context();
|
||||
if (!browser_context)
|
||||
return;
|
||||
|
||||
browser_context->GetDownloadManager()->RemoveObserver(this);
|
||||
if (keep_alive_) {
|
||||
browser_context()->GetDownloadManager()->RemoveObserver(this);
|
||||
|
||||
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
||||
if (auto* service =
|
||||
SpellcheckServiceFactory::GetForContext(browser_context)) {
|
||||
service->SetHunspellObserver(nullptr);
|
||||
}
|
||||
if (auto* service =
|
||||
SpellcheckServiceFactory::GetForContext(browser_context())) {
|
||||
service->SetHunspellObserver(nullptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void Session::OnDownloadCreated(content::DownloadManager* manager,
|
||||
@@ -1879,7 +1875,6 @@ void Session::OnBeforeMicrotasksRunnerDispose(v8::Isolate* isolate) {
|
||||
data->RemoveDisposeObserver(this);
|
||||
Dispose();
|
||||
weak_factory_.Invalidate();
|
||||
browser_context_ = nullptr;
|
||||
keep_alive_.Clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/raw_ref.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/values.h"
|
||||
#include "content/public/browser/download_manager.h"
|
||||
@@ -102,8 +103,8 @@ class Session final : public gin::Wrappable<Session>,
|
||||
Session(v8::Isolate* isolate, ElectronBrowserContext* browser_context);
|
||||
~Session() override;
|
||||
|
||||
[[nodiscard]] ElectronBrowserContext* browser_context() const {
|
||||
return browser_context_;
|
||||
ElectronBrowserContext* browser_context() const {
|
||||
return &browser_context_.get();
|
||||
}
|
||||
|
||||
// gin::Wrappable
|
||||
@@ -224,7 +225,7 @@ class Session final : public gin::Wrappable<Session>,
|
||||
// The client id to enable the network throttler.
|
||||
base::UnguessableToken network_emulation_token_;
|
||||
|
||||
raw_ptr<ElectronBrowserContext> browser_context_;
|
||||
const raw_ref<ElectronBrowserContext> browser_context_;
|
||||
|
||||
gin::WeakCellFactory<Session> weak_factory_{this};
|
||||
|
||||
|
||||
@@ -910,15 +910,14 @@ WebContents::WebContents(v8::Isolate* isolate,
|
||||
session = Session::FromPartition(isolate, "");
|
||||
}
|
||||
session_ = session;
|
||||
ElectronBrowserContext* const browser_context = session->browser_context();
|
||||
DCHECK(browser_context != nullptr);
|
||||
|
||||
std::unique_ptr<content::WebContents> web_contents;
|
||||
if (is_guest()) {
|
||||
scoped_refptr<content::SiteInstance> site_instance =
|
||||
content::SiteInstance::CreateForURL(browser_context,
|
||||
content::SiteInstance::CreateForURL(session->browser_context(),
|
||||
GURL("chrome-guest://fake-host"));
|
||||
content::WebContents::CreateParams params{browser_context, site_instance};
|
||||
content::WebContents::CreateParams params(session->browser_context(),
|
||||
site_instance);
|
||||
guest_delegate_ =
|
||||
std::make_unique<WebViewGuestDelegate>(embedder_->web_contents(), this);
|
||||
params.guest_delegate = guest_delegate_.get();
|
||||
@@ -946,7 +945,7 @@ WebContents::WebContents(v8::Isolate* isolate,
|
||||
SkColor bc = ParseCSSColor(background_color_str).value_or(SK_ColorWHITE);
|
||||
bool transparent = bc == SK_ColorTRANSPARENT;
|
||||
|
||||
content::WebContents::CreateParams params{browser_context};
|
||||
content::WebContents::CreateParams params(session->browser_context());
|
||||
auto* view = new OffScreenWebContentsView(
|
||||
transparent, offscreen_use_shared_texture_,
|
||||
offscreen_shared_texture_pixel_format_, offscreen_device_scale_factor_,
|
||||
@@ -957,13 +956,13 @@ WebContents::WebContents(v8::Isolate* isolate,
|
||||
web_contents = content::WebContents::Create(params);
|
||||
view->SetWebContents(web_contents.get());
|
||||
} else {
|
||||
content::WebContents::CreateParams params{browser_context};
|
||||
content::WebContents::CreateParams params(session->browser_context());
|
||||
params.initially_hidden = !initially_shown;
|
||||
web_contents = content::WebContents::Create(params);
|
||||
}
|
||||
|
||||
InitWithSessionAndOptions(isolate, std::move(web_contents), browser_context,
|
||||
options);
|
||||
InitWithSessionAndOptions(isolate, std::move(web_contents),
|
||||
session->browser_context(), options);
|
||||
}
|
||||
|
||||
void WebContents::InitZoomController(content::WebContents* web_contents,
|
||||
|
||||
@@ -626,9 +626,6 @@ void ElectronBrowserMainParts::PostMainMessageLoopRun() {
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
ui::OzonePlatform::GetInstance()->PostMainMessageLoopRun();
|
||||
#endif
|
||||
|
||||
browser_.reset();
|
||||
js_env_.reset();
|
||||
}
|
||||
|
||||
#if !BUILDFLAG(IS_MAC)
|
||||
|
||||
@@ -116,6 +116,10 @@ class FileSystemAccessPermissionContext
|
||||
content::GlobalRenderFrameHostId frame_id,
|
||||
EntriesAllowedByEnterprisePolicyCallback callback) override;
|
||||
|
||||
enum class Access { kRead, kWrite, kReadWrite };
|
||||
|
||||
enum class RequestType { kNewPermission, kRestorePermissions };
|
||||
|
||||
void RevokeActiveGrants(const url::Origin& origin,
|
||||
const base::FilePath& file_path = base::FilePath());
|
||||
|
||||
|
||||
@@ -117,30 +117,6 @@ NSArray* ConvertSharingItemToNS(const SharingItem& item) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Convert a Badge to an NSMenuItemBadge.
|
||||
NSMenuItemBadge* CreateBadge(const electron::ElectronMenuModel::Badge& badge)
|
||||
API_AVAILABLE(macos(14.0)) {
|
||||
NSString* badgeType = base::SysUTF16ToNSString(badge.type);
|
||||
|
||||
if ([badgeType isEqualToString:@"alerts"]) {
|
||||
if (badge.count.has_value())
|
||||
return [NSMenuItemBadge alertsWithCount:badge.count.value()];
|
||||
} else if ([badgeType isEqualToString:@"updates"]) {
|
||||
if (badge.count.has_value())
|
||||
return [NSMenuItemBadge updatesWithCount:badge.count.value()];
|
||||
} else if ([badgeType isEqualToString:@"new-items"]) {
|
||||
if (badge.count.has_value())
|
||||
return [NSMenuItemBadge newItemsWithCount:badge.count.value()];
|
||||
} else if ([badgeType isEqualToString:@"none"]) {
|
||||
if (badge.content.has_value()) {
|
||||
NSString* content = base::SysUTF8ToNSString(badge.content.value());
|
||||
return [[NSMenuItemBadge alloc] initWithString:content];
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// This class stores a base::WeakPtr<electron::ElectronMenuModel> as an
|
||||
@@ -365,12 +341,14 @@ NSMenuItemBadge* CreateBadge(const electron::ElectronMenuModel::Badge& badge)
|
||||
electron::ElectronMenuModel::ItemType type = model->GetTypeAt(index);
|
||||
std::u16string customType = model->GetCustomTypeAt(index);
|
||||
|
||||
// The sectionHeaderWithTitle menu item is only available in macOS 14.0+.
|
||||
if (@available(macOS 14, *)) {
|
||||
if (customType == u"header") {
|
||||
item = [NSMenuItem sectionHeaderWithTitle:label];
|
||||
}
|
||||
}
|
||||
|
||||
// If the menu item has an icon, set it.
|
||||
ui::ImageModel icon = model->GetIconAt(index);
|
||||
if (icon.IsImage())
|
||||
item.image = icon.GetImage().ToNSImage();
|
||||
@@ -378,15 +356,6 @@ NSMenuItemBadge* CreateBadge(const electron::ElectronMenuModel::Badge& badge)
|
||||
std::u16string toolTip = model->GetToolTipAt(index);
|
||||
item.toolTip = base::SysUTF16ToNSString(toolTip);
|
||||
|
||||
if (@available(macOS 14, *)) {
|
||||
electron::ElectronMenuModel::Badge badge;
|
||||
if (model->GetBadgeAt(index, &badge)) {
|
||||
NSMenuItemBadge* nsBadge = CreateBadge(badge);
|
||||
if (nsBadge)
|
||||
item.badge = nsBadge;
|
||||
}
|
||||
}
|
||||
|
||||
if (role == u"services") {
|
||||
std::u16string title = u"Services";
|
||||
NSString* sub_label = l10n_util::FixUpWindowsStyleLabel(title);
|
||||
@@ -548,15 +517,6 @@ NSMenuItemBadge* CreateBadge(const electron::ElectronMenuModel::Badge& badge)
|
||||
} else {
|
||||
item.image = nil;
|
||||
}
|
||||
|
||||
if (@available(macOS 14, *)) {
|
||||
electron::ElectronMenuModel::Badge badge;
|
||||
if (model->GetBadgeAt(index, &badge)) {
|
||||
item.badge = CreateBadge(badge);
|
||||
} else {
|
||||
item.badge = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)refreshMenuTree:(NSMenu*)menu {
|
||||
|
||||
@@ -12,15 +12,6 @@ namespace electron {
|
||||
ElectronMenuModel::SharingItem::SharingItem() = default;
|
||||
ElectronMenuModel::SharingItem::SharingItem(SharingItem&&) = default;
|
||||
ElectronMenuModel::SharingItem::~SharingItem() = default;
|
||||
|
||||
ElectronMenuModel::Badge::Badge() = default;
|
||||
ElectronMenuModel::Badge::Badge(Badge&&) = default;
|
||||
ElectronMenuModel::Badge::Badge(const Badge&) = default;
|
||||
ElectronMenuModel::Badge& ElectronMenuModel::Badge::operator=(const Badge&) =
|
||||
default;
|
||||
ElectronMenuModel::Badge& ElectronMenuModel::Badge::operator=(Badge&&) =
|
||||
default;
|
||||
ElectronMenuModel::Badge::~Badge() = default;
|
||||
#endif
|
||||
|
||||
bool ElectronMenuModel::Delegate::GetAcceleratorForCommandId(
|
||||
@@ -124,21 +115,6 @@ bool ElectronMenuModel::GetSharingItemAt(size_t index,
|
||||
void ElectronMenuModel::SetSharingItem(SharingItem item) {
|
||||
sharing_item_.emplace(std::move(item));
|
||||
}
|
||||
|
||||
void ElectronMenuModel::SetBadge(size_t index, Badge badge) {
|
||||
int command_id = GetCommandIdAt(index);
|
||||
badges_[command_id] = std::move(badge);
|
||||
}
|
||||
|
||||
bool ElectronMenuModel::GetBadgeAt(size_t index, Badge* badge) const {
|
||||
int command_id = GetCommandIdAt(index);
|
||||
const auto iter = badges_.find(command_id);
|
||||
if (iter != badges_.end()) {
|
||||
*badge = iter->second;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void ElectronMenuModel::MenuWillClose() {
|
||||
|
||||
@@ -33,19 +33,6 @@ class ElectronMenuModel : public ui::SimpleMenuModel {
|
||||
std::optional<std::vector<GURL>> urls;
|
||||
std::optional<std::vector<base::FilePath>> file_paths;
|
||||
};
|
||||
|
||||
struct Badge {
|
||||
Badge();
|
||||
Badge(Badge&&);
|
||||
Badge(const Badge&);
|
||||
Badge& operator=(const Badge&);
|
||||
Badge& operator=(Badge&&);
|
||||
~Badge();
|
||||
|
||||
std::u16string type; // "alerts", "updates", "new-items", or "none"
|
||||
std::optional<int> count;
|
||||
std::optional<std::string> content;
|
||||
};
|
||||
#endif
|
||||
|
||||
class Delegate : public ui::SimpleMenuModel::Delegate {
|
||||
@@ -118,9 +105,6 @@ class ElectronMenuModel : public ui::SimpleMenuModel {
|
||||
return sharing_item_;
|
||||
}
|
||||
|
||||
// Set/Get the Badge of a menu item.
|
||||
void SetBadge(size_t index, Badge badge);
|
||||
bool GetBadgeAt(size_t index, Badge* badge) const;
|
||||
#endif
|
||||
|
||||
// ui::SimpleMenuModel:
|
||||
@@ -139,7 +123,6 @@ class ElectronMenuModel : public ui::SimpleMenuModel {
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
std::optional<SharingItem> sharing_item_;
|
||||
base::flat_map<int, Badge> badges_; // command id -> badge
|
||||
#endif
|
||||
|
||||
base::flat_map<int, std::u16string> toolTips_; // command id -> tooltip
|
||||
|
||||
@@ -705,10 +705,8 @@ gin_helper::Handle<SimpleURLLoaderWrapper> SimpleURLLoaderWrapper::Create(
|
||||
else // default session
|
||||
session = Session::FromPartition(args->isolate(), "");
|
||||
}
|
||||
if (session) {
|
||||
if (session)
|
||||
browser_context = session->browser_context();
|
||||
DCHECK(browser_context != nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
auto ret = gin_helper::CreateHandle(
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include "shell/common/gin_helper/callback.h"
|
||||
|
||||
#include "gin/dictionary.h"
|
||||
#include "gin/arguments.h"
|
||||
#include "gin/persistent.h"
|
||||
#include "v8/include/cppgc/allocation.h"
|
||||
#include "v8/include/v8-cppgc.h"
|
||||
@@ -51,42 +51,28 @@ struct TranslatorHolder {
|
||||
delete data.GetParameter();
|
||||
}
|
||||
|
||||
static gin::DeprecatedWrapperInfo kWrapperInfo;
|
||||
|
||||
v8::Global<v8::External> handle;
|
||||
Translator translator;
|
||||
bool one_time = false;
|
||||
bool called = false;
|
||||
};
|
||||
|
||||
gin::DeprecatedWrapperInfo TranslatorHolder::kWrapperInfo = {
|
||||
gin::kEmbedderNativeGin};
|
||||
void CallTranslator(const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||
gin::Arguments args(info);
|
||||
auto* holder =
|
||||
static_cast<TranslatorHolder*>(info.Data().As<v8::External>()->Value(
|
||||
v8::kExternalPointerTypeTagDefault));
|
||||
|
||||
void CallTranslator(v8::Local<v8::External> external,
|
||||
v8::Local<v8::Object> state,
|
||||
gin::Arguments* args) {
|
||||
// Whether the callback should only be called once.
|
||||
v8::Isolate* isolate = args->isolate();
|
||||
auto context = isolate->GetCurrentContext();
|
||||
bool one_time =
|
||||
state->Has(context, gin::StringToSymbol(isolate, "oneTime")).ToChecked();
|
||||
|
||||
// Check if the callback has already been called.
|
||||
if (one_time) {
|
||||
auto called_symbol = gin::StringToSymbol(isolate, "called");
|
||||
if (state->Has(context, called_symbol).ToChecked()) {
|
||||
args->ThrowTypeError("One-time callback was called more than once");
|
||||
return;
|
||||
} else {
|
||||
state->Set(context, called_symbol, v8::True(isolate)).ToChecked();
|
||||
}
|
||||
if (holder->one_time && holder->called) {
|
||||
args.ThrowTypeError("One-time callback was called more than once");
|
||||
return;
|
||||
}
|
||||
holder->called = true;
|
||||
|
||||
auto* holder = static_cast<TranslatorHolder*>(
|
||||
external->Value(v8::kExternalPointerTypeTagDefault));
|
||||
holder->translator.Run(args);
|
||||
holder->translator.Run(&args);
|
||||
|
||||
// Free immediately for one-time callback.
|
||||
if (one_time)
|
||||
delete holder;
|
||||
if (holder->one_time)
|
||||
holder->translator.Reset();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -113,41 +99,11 @@ v8::Local<v8::Function> SafeV8Function::NewHandle(v8::Isolate* isolate) const {
|
||||
v8::Local<v8::Value> CreateFunctionFromTranslator(v8::Isolate* isolate,
|
||||
const Translator& translator,
|
||||
bool one_time) {
|
||||
gin::PerIsolateData* data = gin::PerIsolateData::From(isolate);
|
||||
auto* wrapper_info = &TranslatorHolder::kWrapperInfo;
|
||||
v8::Local<v8::FunctionTemplate> constructor =
|
||||
data->DeprecatedGetFunctionTemplate(wrapper_info);
|
||||
// The FunctionTemplate is cached.
|
||||
if (constructor.IsEmpty()) {
|
||||
constructor =
|
||||
CreateFunctionTemplate(isolate, base::BindRepeating(&CallTranslator));
|
||||
data->DeprecatedSetFunctionTemplate(wrapper_info, constructor);
|
||||
}
|
||||
|
||||
auto* holder = new TranslatorHolder(isolate);
|
||||
holder->translator = translator;
|
||||
auto state = gin::Dictionary::CreateEmpty(isolate);
|
||||
if (one_time)
|
||||
state.Set("oneTime", true);
|
||||
holder->one_time = one_time;
|
||||
auto context = isolate->GetCurrentContext();
|
||||
return BindFunctionWith(
|
||||
isolate, context, constructor->GetFunction(context).ToLocalChecked(),
|
||||
holder->handle.Get(isolate), gin::ConvertToV8(isolate, state));
|
||||
}
|
||||
|
||||
// func.bind(func, arg1).
|
||||
// NB(zcbenz): Using C++11 version crashes VS.
|
||||
v8::Local<v8::Value> BindFunctionWith(v8::Isolate* isolate,
|
||||
v8::Local<v8::Context> context,
|
||||
v8::Local<v8::Function> func,
|
||||
v8::Local<v8::Value> arg1,
|
||||
v8::Local<v8::Value> arg2) {
|
||||
v8::MaybeLocal<v8::Value> bind =
|
||||
func->Get(context, gin::StringToV8(isolate, "bind"));
|
||||
CHECK(!bind.IsEmpty());
|
||||
v8::Local<v8::Function> bind_func = bind.ToLocalChecked().As<v8::Function>();
|
||||
v8::Local<v8::Value> converted[] = {func, arg1, arg2};
|
||||
return bind_func->Call(context, func, std::size(converted), converted)
|
||||
return v8::Function::New(context, CallTranslator, holder->handle.Get(isolate))
|
||||
.ToLocalChecked();
|
||||
}
|
||||
|
||||
|
||||
@@ -118,11 +118,6 @@ using Translator = base::RepeatingCallback<void(gin::Arguments* args)>;
|
||||
v8::Local<v8::Value> CreateFunctionFromTranslator(v8::Isolate* isolate,
|
||||
const Translator& translator,
|
||||
bool one_time);
|
||||
v8::Local<v8::Value> BindFunctionWith(v8::Isolate* isolate,
|
||||
v8::Local<v8::Context> context,
|
||||
v8::Local<v8::Function> func,
|
||||
v8::Local<v8::Value> arg1,
|
||||
v8::Local<v8::Value> arg2);
|
||||
|
||||
// Calls callback with Arguments.
|
||||
template <typename Sig>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "base/containers/span.h"
|
||||
#include "base/memory/memory_pressure_listener_registry.h"
|
||||
#include "base/memory/memory_pressure_listener.h"
|
||||
#include "base/no_destructor.h"
|
||||
#include "base/strings/strcat.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
@@ -810,7 +810,7 @@ class WebFrameRenderer final
|
||||
|
||||
void ClearCache(v8::Isolate* isolate) {
|
||||
blink::WebCache::Clear();
|
||||
base::MemoryPressureListenerRegistry::NotifyMemoryPressure(
|
||||
base::MemoryPressureListener::NotifyMemoryPressure(
|
||||
base::MEMORY_PRESSURE_LEVEL_CRITICAL);
|
||||
}
|
||||
|
||||
|
||||
@@ -372,6 +372,33 @@ describe('contextBridge', () => {
|
||||
expect(result).to.equal(123);
|
||||
});
|
||||
|
||||
it('should proxy promises correctly when Function.prototype has been overridden in the main world', async () => {
|
||||
await makeBindingWindow(() => {
|
||||
contextBridge.exposeInMainWorld('example', {
|
||||
getPromise: () => Promise.resolve('proxied-ok')
|
||||
});
|
||||
});
|
||||
const result = await callWithBindings((root: any) => {
|
||||
return new Promise(resolve => {
|
||||
let observed = false;
|
||||
const original = Function.prototype.bind;
|
||||
// eslint-disable-next-line no-extend-native
|
||||
Function.prototype.bind = new Proxy(original, {
|
||||
apply (target, thisArg, args) {
|
||||
observed = true;
|
||||
return Reflect.apply(target, thisArg, args);
|
||||
}
|
||||
});
|
||||
root.example.getPromise().then((v: string) => {
|
||||
// eslint-disable-next-line no-extend-native
|
||||
Function.prototype.bind = original;
|
||||
resolve({ observed, value: v });
|
||||
});
|
||||
});
|
||||
});
|
||||
expect(result).to.deep.equal({ observed: false, value: 'proxied-ok' });
|
||||
});
|
||||
|
||||
it('should proxy methods', async () => {
|
||||
await makeBindingWindow(() => {
|
||||
contextBridge.exposeInMainWorld('example', {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { expect } from 'chai';
|
||||
|
||||
import { once } from 'node:events';
|
||||
import * as path from 'node:path';
|
||||
|
||||
import { ifdescribe, isTestingBindingAvailable, startRemoteControlApp } from './lib/spec-helpers';
|
||||
@@ -40,33 +39,6 @@ describe('cpp heap', () => {
|
||||
});
|
||||
|
||||
describe('session module', () => {
|
||||
it('does not crash on exit with live session wrappers', async () => {
|
||||
const rc = await startRemoteControlApp();
|
||||
await rc.remotely(async () => {
|
||||
const { app, session } = require('electron');
|
||||
|
||||
const sessions = [
|
||||
session.defaultSession,
|
||||
session.fromPartition('cppheap-exit'),
|
||||
session.fromPartition('persist:cppheap-exit-persist')
|
||||
];
|
||||
|
||||
// We want to test GC on shutdown, so add a global reference
|
||||
// to these sessions to prevent pre-shutdown GC.
|
||||
(globalThis as any).sessionRefs = sessions;
|
||||
|
||||
// We want to test CppGC-traced references during shutdown.
|
||||
// The CppGC-managed cookies will do that; but since they're
|
||||
// lazy-created, access them here to ensure they're live.
|
||||
sessions.forEach(ses => ses.cookies);
|
||||
|
||||
setTimeout(() => app.quit());
|
||||
});
|
||||
|
||||
const [code] = await once(rc.process, 'exit');
|
||||
expect(code).to.equal(0);
|
||||
});
|
||||
|
||||
it('should record as node in heap snapshot', async () => {
|
||||
const { remotely } = await startRemoteControlApp(['--expose-internals']);
|
||||
const result = await remotely(async (heap: string, snapshotHelper: string) => {
|
||||
|
||||
2
typings/internal-electron.d.ts
vendored
2
typings/internal-electron.d.ts
vendored
@@ -166,7 +166,6 @@ declare namespace Electron {
|
||||
commandsMap: Record<string, MenuItem>;
|
||||
groupsMap: Record<string, MenuItem[]>;
|
||||
getItemCount(): number;
|
||||
getIndexOfCommandId(commandId: number): number;
|
||||
popupAt(window: BaseWindow, frame: WebFrameMain | undefined, x: number, y: number, positioning: number, sourceType: Required<Electron.PopupOptions>['sourceType'], callback: () => void): void;
|
||||
closePopupAt(id: number): void;
|
||||
setSublabel(index: number, label: string): void;
|
||||
@@ -174,7 +173,6 @@ declare namespace Electron {
|
||||
setIcon(index: number, image: string | NativeImage): void;
|
||||
setRole(index: number, role: string): void;
|
||||
setCustomType(index: number, customType: string): void;
|
||||
setBadge(index: number, badge: MenuItemBadge): void;
|
||||
insertItem(index: number, commandId: number, label: string): void;
|
||||
insertCheckItem(index: number, commandId: number, label: string): void;
|
||||
insertRadioItem(index: number, commandId: number, label: string, groupId: number): void;
|
||||
|
||||
Reference in New Issue
Block a user