Use NotificationImageRetainer pattern from //chrome

This commit is contained in:
Developer-Ecosystem-Engineering
2025-08-29 08:35:52 -07:00
committed by Keeley Hammond
parent ed27a77558
commit 1c6bb418bd
5 changed files with 75 additions and 25 deletions

View File

@@ -454,6 +454,7 @@ source_set("electron_lib") {
"//chrome:strings",
"//chrome/app:command_ids",
"//chrome/app/resources:platform_locale_settings",
"//chrome/common/notifications",
"//components/autofill/core/common:features",
"//components/certificate_transparency",
"//components/compose:buildflags",

View File

@@ -36,6 +36,7 @@ class CocoaNotification : public Notification {
private:
void LogAction(const char* action);
void ScheduleNotification(UNMutableNotificationContent* content);
UNNotificationRequest* __strong notification_request_;
};

View File

@@ -7,17 +7,22 @@
#include <string>
#include <utility>
#include "base/apple/foundation_util.h"
#include "base/logging.h"
#include "base/mac/mac_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/task/sequenced_task_runner.h"
#include "chrome/common/notifications/notification_image_retainer.h"
#include "grit/electron_resources.h"
#include "shell/browser/notifications/mac/notification_presenter_mac.h"
#include "shell/browser/notifications/notification_delegate.h"
#include "shell/browser/notifications/notification_presenter.h"
#include "skia/ext/skia_utils_mac.h"
#include "ui/base/l10n/l10n_util_mac.h"
#include "ui/gfx/image/image.h"
#import <AppKit/AppKit.h>
#import <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
namespace electron {
@@ -41,30 +46,6 @@ void CocoaNotification::Show(const NotificationOptions& options) {
content.subtitle = base::SysUTF16ToNSString(options.subtitle);
content.body = base::SysUTF16ToNSString(options.msg);
if (!options.icon.drawsNothing()) {
NSImage* image = skia::SkBitmapToNSImage(options.icon);
NSData* imageData =
[[NSBitmapImageRep imageRepWithData:[image TIFFRepresentation]]
representationUsingType:NSBitmapImageFileTypePNG
properties:@{}];
NSString* tempFilePath = [NSTemporaryDirectory()
stringByAppendingPathComponent:[NSString
stringWithFormat:@"%@_icon.png",
[[NSUUID UUID]
UUIDString]]];
if ([imageData writeToFile:tempFilePath atomically:YES]) {
NSError* error = nil;
UNNotificationAttachment* attachment = [UNNotificationAttachment
attachmentWithIdentifier:@"image"
URL:[NSURL fileURLWithPath:tempFilePath]
options:nil
error:&error];
if (attachment && !error) {
content.attachments = @[ attachment ];
}
}
}
if (options.silent) {
content.sound = nil;
} else if (options.sound.empty()) {
@@ -148,6 +129,52 @@ void CocoaNotification::Show(const NotificationOptions& options) {
content.categoryIdentifier = categoryIdentifier;
}
if (!options.icon.drawsNothing()) {
gfx::Image icon = gfx::Image::CreateFrom1xBitmap(options.icon);
auto* mac_presenter = static_cast<NotificationPresenterMac*>(presenter());
mac_presenter->image_task_runner()->PostTaskAndReplyWithResult(
FROM_HERE,
base::BindOnce(
[](NotificationPresenterMac* mac_presenter,
gfx::Image icon) -> UNNotificationAttachment* {
base::FilePath path =
mac_presenter->image_retainer()->RegisterTemporaryImage(
icon);
if (path.empty()) {
return nil;
}
NSURL* url = base::apple::FilePathToNSURL(path);
NSDictionary* attachment_options = @{
UNNotificationAttachmentOptionsTypeHintKey :
UTTypePNG.identifier
};
NSError* error = nil;
UNNotificationAttachment* attachment = [UNNotificationAttachment
attachmentWithIdentifier:[[NSUUID UUID] UUIDString]
URL:url
options:attachment_options
error:&error];
return (attachment && !error) ? attachment : nil;
},
mac_presenter, icon),
base::BindOnce(
[](base::WeakPtr<Notification> weak_self,
UNMutableNotificationContent* content,
UNNotificationAttachment* attachment) {
if (auto* notification = weak_self.get()) {
content.attachments = @[ attachment ];
auto* self = static_cast<CocoaNotification*>(notification);
self->ScheduleNotification(content);
}
},
GetWeakPtr(), content));
} else {
ScheduleNotification(content);
}
}
void CocoaNotification::ScheduleNotification(
UNMutableNotificationContent* content) {
NSString* identifier =
[NSString stringWithFormat:@"%@:notification:%@",
[[NSBundle mainBundle] bundleIdentifier],

View File

@@ -6,6 +6,7 @@
#ifndef ELECTRON_SHELL_BROWSER_NOTIFICATIONS_MAC_NOTIFICATION_PRESENTER_MAC_H_
#define ELECTRON_SHELL_BROWSER_NOTIFICATIONS_MAC_NOTIFICATION_PRESENTER_MAC_H_
#include "chrome/common/notifications/notification_image_retainer.h"
#include "shell/browser/notifications/mac/notification_center_delegate.h"
#include "shell/browser/notifications/notification_presenter.h"
@@ -23,12 +24,21 @@ class NotificationPresenterMac : public NotificationPresenter {
NotificationPresenterMac();
~NotificationPresenterMac() override;
NotificationImageRetainer* image_retainer() {
return image_retainer_.get();
}
scoped_refptr<base::SequencedTaskRunner> image_task_runner() {
return image_task_runner_;
}
private:
// NotificationPresenter
Notification* CreateNotificationObject(
NotificationDelegate* delegate) override;
NotificationCenterDelegate* __strong notification_center_delegate_;
std::unique_ptr<NotificationImageRetainer> image_retainer_;
scoped_refptr<base::SequencedTaskRunner> image_task_runner_;
};
} // namespace electron

View File

@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "base/logging.h"
#include "base/task/thread_pool.h"
#include "shell/browser/notifications/mac/notification_presenter_mac.h"
@@ -35,7 +36,16 @@ CocoaNotification* NotificationPresenterMac::GetNotification(
NotificationPresenterMac::NotificationPresenterMac()
: notification_center_delegate_(
[[NotificationCenterDelegate alloc] initWithPresenter:this]) {
[[NotificationCenterDelegate alloc] initWithPresenter:this]),
image_retainer_(std::make_unique<NotificationImageRetainer>()),
image_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
{base::MayBlock(), base::TaskPriority::USER_VISIBLE})) {
// Delete any remaining temp files in the image folder from the previous
// sessions.
DCHECK(image_task_runner_);
auto cleanup_task = image_retainer_->GetCleanupTask();
image_task_runner_->PostTask(FROM_HERE, std::move(cleanup_task));
UNUserNotificationCenter* center =
[UNUserNotificationCenter currentNotificationCenter];
@@ -62,6 +72,7 @@ NotificationPresenterMac::NotificationPresenterMac()
NotificationPresenterMac::~NotificationPresenterMac() {
UNUserNotificationCenter.currentNotificationCenter.delegate = nil;
image_task_runner_->DeleteSoon(FROM_HERE, image_retainer_.release());
}
Notification* NotificationPresenterMac::CreateNotificationObject(