Skip to content

Commit

Permalink
Add support for icon_variants in Web Extensions.
Browse files Browse the repository at this point in the history
https://webkit.org/b/278818
rdar://problem/134885372

Reviewed by NOBODY (OOPS!).

Add support for `icon_variants` manifest parsing under the `WK_WEB_EXTENSIONS_ICON_VARIANTS` flag,
with optimizations to ensure efficient icon loading.

This change introduces `icon_variants` manifest parsing, explicitly supporting different icon sets,
such as dark mode icons. To achieve this efficiently, icons are now cached by size, reducing disk
I/O by avoiding repeated loads when the browser frequently requests the same icon. The cache is
automatically invalidated when device scales change, such as when connecting or disconnecting a
display with a different scale factor.

Only the necessary icons are loaded based on the specific scale factor of all screens, halving the
image loads compared to previous behavior. This ensures that even as more extensions adopt dark
mode icons, typical image loads remain at two images (light and dark).

Proposal: https://github.com/w3c/webextensions/blob/main/proposals/dark_mode_extension_icons.md
WECG issue: w3c/webextensions#229

* Source/WTF/wtf/PlatformEnableCocoa.h: Added ENABLE_WK_WEB_EXTENSIONS_ICON_VARIANTS.
* Source/WebCore/en.lproj/Localizable.strings: Updated.
* Source/WebKit/Platform/cocoa/CocoaHelpers.h:
* Source/WebKit/Platform/cocoa/CocoaHelpers.mm:
(WebKit::availableScreenScales): Added.
(WebKit::largestDisplayScale): Added.
* Source/WebKit/Platform/spi/ios/UIKitSPI.h:
* Source/WebKit/UIProcess/Extensions/Cocoa/WebExtensionActionCocoa.mm:
(WebKit::WebExtensionAction::icon):
* Source/WebKit/UIProcess/Extensions/Cocoa/WebExtensionCocoa.mm:
(WebKit::WebExtension::icon):
(WebKit::WebExtension::actionIcon):
(WebKit::WebExtension::populateActionPropertiesIfNeeded):
(WebKit::WebExtension::populateSidebarActionProperties):
(WebKit::WebExtension::populateSidePanelProperties):
(WebKit::WebExtension::imageForPath):
(WebKit::WebExtension::bestSizeInIconsDictionary): Added.
(WebKit::WebExtension::pathForBestImageInIconsDictionary):
(WebKit::WebExtension::bestImageInIconsDictionary):
(WebKit::WebExtension::bestImageForIconsDictionaryManifestKey):
(WebKit::toColorSchemes): Added.
(WebKit::WebExtension::iconsDictionaryForBestIconVariant): Added.
(WebKit::WebExtension::bestImageForIconVariants): Added.
(WebKit::WebExtension::bestImageForIconVariantsManifestKey): Added.
* Source/WebKit/UIProcess/Extensions/Cocoa/WebExtensionMenuItemCocoa.mm:
(WebKit::WebExtensionMenuItem::icon const):
* Source/WebKit/UIProcess/Extensions/WebExtension.h:
* Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebExtension.mm:
(TestWebKitAPI::TEST(WKWebExtension, MultipleIconVariants)): Added.
(TestWebKitAPI::TEST(WKWebExtension, SingleIconVariant)): Added.
(TestWebKitAPI::TEST(WKWebExtension, AnySizeIconVariant)): Added.
(TestWebKitAPI::TEST(WKWebExtension, NoIconVariants)): Added.
(TestWebKitAPI::TEST(WKWebExtension, IconsAndIconVariantsSpecified)): Added.
(TestWebKitAPI::TEST(WKWebExtension, ActionIconVariantsMultiple)): Added.
(TestWebKitAPI::TEST(WKWebExtension, ActionIconSingleVariant)): Added.
(TestWebKitAPI::TEST(WKWebExtension, ActionIconAnySizeVariant)): Added.
(TestWebKitAPI::TEST(WKWebExtension, ActionNoIconVariants)): Added.
(TestWebKitAPI::TEST(WKWebExtension, ActionIconsAndIconVariantsSpecified)): Added.
* Tools/TestWebKitAPI/cocoa/WebExtensionUtilities.h:
* Tools/TestWebKitAPI/cocoa/WebExtensionUtilities.mm:
(TestWebKitAPI::Util::performWithAppearance): Added.
(TestWebKitAPI::Util::pixelColor): Added.
(TestWebKitAPI::Util::toSRGBColor): Added.
(TestWebKitAPI::Util::compareColors): Added.
  • Loading branch information
xeenon committed Aug 31, 2024
1 parent 4a952c1 commit 7418be7
Show file tree
Hide file tree
Showing 13 changed files with 841 additions and 97 deletions.
9 changes: 8 additions & 1 deletion Source/WTF/wtf/PlatformEnableCocoa.h
Original file line number Diff line number Diff line change
Expand Up @@ -1010,10 +1010,17 @@
#define ENABLE_WIRELESS_PLAYBACK_TARGET_AVAILABILITY_API 1
#endif

#if !defined(ENABLE_WK_WEB_EXTENSIONS) && (PLATFORM(MAC) || PLATFORM(MACCATALYST) || PLATFORM(IOS) || PLATFORM(IOS_SIMULATOR) || PLATFORM(VISION))
#if !defined(ENABLE_WK_WEB_EXTENSIONS) && (PLATFORM(MAC) || PLATFORM(MACCATALYST) || PLATFORM(IOS) || PLATFORM(VISION))
#define ENABLE_WK_WEB_EXTENSIONS 1
#endif

#if !defined(ENABLE_WK_WEB_EXTENSIONS_ICON_VARIANTS) \
&& ((PLATFORM(MAC) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 150500) \
|| ((PLATFORM(IOS) || PLATFORM(MACCATALYST)) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 180500) \
|| (PLATFORM(VISION) && __VISION_OS_VERSION_MAX_ALLOWED >= 20500))
#define ENABLE_WK_WEB_EXTENSIONS_ICON_VARIANTS ENABLE_WK_WEB_EXTENSIONS
#endif

#if !defined(ENABLE_WK_WEB_EXTENSIONS_SIDEBAR)
#define ENABLE_WK_WEB_EXTENSIONS_SIDEBAR 0 && ENABLE_WK_WEB_EXTENSIONS
#endif
Expand Down
6 changes: 6 additions & 0 deletions Source/WebCore/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,12 @@
/* WKWebExtensionErrorInvalidActionIcon description for failing to load images for browser_action or page_action */
"Failed to load images in `default_icon` for the `browser_action` or `page_action` manifest entry." = "Failed to load images in `default_icon` for the `browser_action` or `page_action` manifest entry.";

/* WKWebExtensionErrorInvalidActionIcon description for failing to load image variantss for action */
"Failed to load images in `icon_variants` for the `action` manifest entry." = "Failed to load images in `icon_variants` for the `action` manifest entry.";

/* WKWebExtensionErrorInvalidIcon description for failing to load image variants */
"Failed to load images in `icon_variants` manifest entry." = "Failed to load images in `icon_variants` manifest entry.";

/* WKWebExtensionErrorInvalidIcon description for failing to load images */
"Failed to load images in `icons` manifest entry." = "Failed to load images in `icons` manifest entry.";

Expand Down
3 changes: 3 additions & 0 deletions Source/WebKit/Platform/cocoa/CocoaHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ NSString *escapeCharactersInString(NSString *, NSString *charactersToEscape);

void callAfterRandomDelay(Function<void()>&&);

NSSet *availableScreenScales();
CGFloat largestDisplayScale();

NSDate *toAPI(const WallTime&);
WallTime toImpl(NSDate *);

Expand Down
38 changes: 38 additions & 0 deletions Source/WebKit/Platform/cocoa/CocoaHelpers.mm
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@
#import <wtf/BlockPtr.h>
#import <wtf/FileSystem.h>

#if PLATFORM(IOS_FAMILY)
#import <UIKit/UIKit.h>
#endif

namespace WebKit {

static NSString * const privacyPreservingDescriptionKey = @"privacyPreservingDescription";
Expand Down Expand Up @@ -440,6 +444,40 @@ void callAfterRandomDelay(Function<void()>&& completionHandler)
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delay.nanosecondsAs<int64_t>()), dispatch_get_main_queue(), makeBlockPtr(WTFMove(completionHandler)).get());
}

NSSet *availableScreenScales()
{
NSMutableSet *screenScales = [NSMutableSet set];

#if USE(APPKIT)
for (NSScreen *screen in NSScreen.screens)
[screenScales addObject:@(screen.backingScaleFactor)];
#else
ALLOW_DEPRECATED_DECLARATIONS_BEGIN
for (UIScreen *screen in UIScreen.screens)
[screenScales addObject:@(screen.scale)];
ALLOW_DEPRECATED_DECLARATIONS_END
#endif

if (screenScales.count)
return [screenScales copy];

// Assume 1x if we got no results. This can happen on headless devices (bots).
return [NSSet setWithObject:@1];
}

CGFloat largestDisplayScale()
{
auto largestDisplayScale = 1.0;

for (NSNumber *scale in availableScreenScales()) {
auto scaleValue = scale.doubleValue;
if (scaleValue > largestDisplayScale)
largestDisplayScale = scaleValue;
}

return largestDisplayScale;
}

NSDate *toAPI(const WallTime& time)
{
if (time.isNaN())
Expand Down
10 changes: 10 additions & 0 deletions Source/WebKit/Platform/spi/ios/UIKitSPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#import <UIKit/UIFont_Private.h>
#import <UIKit/UIGeometry_Private.h>
#import <UIKit/UIGestureRecognizer_Private.h>
#import <UIKit/UIImageAsset_Private.h>
#import <UIKit/UIImagePickerController_Private.h>
#import <UIKit/UIImage_Private.h>
#import <UIKit/UIInterface_Private.h>
Expand Down Expand Up @@ -338,13 +339,18 @@ typedef enum {
@property (nonatomic, setter=_setShowsFileSizePicker:) BOOL _showsFileSizePicker;
@end

@interface UIImageAsset ()
+ (instancetype)_dynamicAssetNamed:(NSString *)name generator:(UIImage *(^)(UIImageAsset *, UIImageConfiguration *, UIImage *))block;
@end

typedef struct CGSVGDocument *CGSVGDocumentRef;

@interface UIImage ()
- (id)initWithCGImage:(CGImageRef)CGImage imageOrientation:(UIImageOrientation)imageOrientation;
- (UIImage *)_flatImageWithColor:(UIColor *)color;
+ (UIImage *)_systemImageNamed:(NSString *)name;
+ (UIImage *)_imageWithCGSVGDocument:(CGSVGDocumentRef)cgSVGDocument;
+ (UIImage *)_imageWithCGSVGDocument:(CGSVGDocumentRef)cgSVGDocument scale:(CGFloat)scale orientation:(UIImageOrientation)orientation;
@end

@protocol UIKeyboardImplGeometryDelegate
Expand Down Expand Up @@ -1111,6 +1117,10 @@ typedef NS_ENUM(NSUInteger, _UIScrollDeviceCategory) {
+ (UIColor *)insertionPointColor;
@end

@interface UIImage ()
- (UIImage *)_rasterizedImage;
@end

@interface UIView (IPI)
- (UIScrollView *)_scroller;
- (CGPoint)accessibilityConvertPointFromSceneReferenceCoordinates:(CGPoint)point;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -646,11 +646,12 @@ - (void)_otherPopoverWillShow:(NSNotification *)notification
return nil;

if (m_customIcons) {
NSError *error;
if (CocoaImage *result = extensionContext()->extension().bestImageInIconsDictionary(m_customIcons.get(), idealSize.width > idealSize.height ? idealSize.width : idealSize.height, &error))
return result;
auto *result = extensionContext()->extension().bestImageInIconsDictionary(m_customIcons.get(), idealSize, [&](auto *error) {
extensionContext()->recordError(error);
});

extensionContext()->recordErrorIfNeeded(error);
if (result)
return result;

// If custom icons fail, fallback to the default icons.
}
Expand Down
Loading

0 comments on commit 7418be7

Please sign in to comment.