⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 286073 in webkit


Ignore:
Timestamp:
Nov 19, 2021, 1:20:53 PM (5 years ago)
Author:
Brent Fulgham
Message:

Add support for web app manifest icons in WebKit/UI Process layer
https://bugs.webkit.org/show_bug.cgi?id=233350
<rdar://problem/84311569>

Reviewed by Chris Dumez.

Source/WebCore:

This patch builds on the work in Bug 231339 and threads the new icons
feature through the WebKit layer.

This change modifies the parser to represent the 'sizes' member of the
icon as an array of strings, rather than a single string containing the
sizes as a set of space-separated items. This more closesly matches the
behavior of the WebKit API layer.

Tested by TestWebKitAPI.

  • Modules/applicationmanifest/ApplicationManifest.h:
  • Modules/applicationmanifest/ApplicationManifestParser.cpp:

(WebCore::ApplicationManifestParser::parseIcons):

Source/WebKit:

This patch builds on the work in Bug 231339 and threads the new icons
feature through the WebKit layer.

Note: This change also moves the implementation of _WKApplicationManifestIcon
earlier in the file since the implementation is needed for proper serialization
of the _WKApplicationManifest.

Tested by TestWebKitAPI (ApplicationManifest.Icons) test.

  • UIProcess/API/Cocoa/_WKApplicationManifest.h:
  • UIProcess/API/Cocoa/_WKApplicationManifest.mm:

(fromPurposes): New helper function.
(makeVectorElement): Ditto.
(-[_WKApplicationManifestIcon initWithCoder:]): Updated to call proper
serialization methods.
(-[_WKApplicationManifestIcon initWithCoreIcon:]): Added.
(-[_WKApplicationManifest initWithCoder:]): Updated to properly handle
serializing the object.
(-[_WKApplicationManifest icons]): Added.

Tools:

Add a new API test to exercise the _WKApplicationManifestIcon API.

  • TestWebKitAPI/Tests/WebCore/ApplicationManifestParser.cpp:

(ApplicationManifestParserTest::testIconsSizes):
(TEST_F):

  • TestWebKitAPI/Tests/WebKitCocoa/ApplicationManifest.mm:

(TestWebKitAPI::TEST):

Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r286068 r286073  
     12021-11-19  Brent Fulgham  <bfulgham@apple.com>
     2
     3        Add support for web app manifest icons in WebKit/UI Process layer
     4        https://bugs.webkit.org/show_bug.cgi?id=233350
     5        <rdar://problem/84311569>
     6
     7        Reviewed by Chris Dumez.
     8
     9        This patch builds on the work in Bug 231339 and threads the new icons
     10        feature through the WebKit layer.
     11
     12        This change modifies the parser to represent the 'sizes' member of the
     13        icon as an array of strings, rather than a single string containing the
     14        sizes as a set of space-separated items. This more closesly matches the
     15        behavior of the WebKit API layer.
     16
     17        Tested by TestWebKitAPI.
     18
     19        * Modules/applicationmanifest/ApplicationManifest.h:
     20        * Modules/applicationmanifest/ApplicationManifestParser.cpp:
     21        (WebCore::ApplicationManifestParser::parseIcons):
     22
    1232021-11-19  Antoine Quint  <graouts@webkit.org>
    224
  • trunk/Source/WebCore/Modules/applicationmanifest/ApplicationManifest.h

    r285645 r286073  
    11/*
    2  * Copyright (C) 2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    5151
    5252        URL src;
    53         String sizes;
     53        Vector<String> sizes;
    5454        String type;
    5555        OptionSet<Purpose> purposes;
  • trunk/Source/WebCore/Modules/applicationmanifest/ApplicationManifestParser.cpp

    r285645 r286073  
    11/*
    2  * Copyright (C) 2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    214214        currentIcon.src = srcURL;
    215215
    216         currentIcon.sizes = parseGenericString(iconJSON, "sizes"_s);
     216        currentIcon.sizes = parseGenericString(iconJSON, "sizes"_s).split(' ');
    217217
    218218        currentIcon.type = parseGenericString(iconJSON, "type"_s);
  • trunk/Source/WebKit/ChangeLog

    r286071 r286073  
     12021-11-19  Brent Fulgham  <bfulgham@apple.com>
     2
     3        Add support for web app manifest icons in WebKit/UI Process layer
     4        https://bugs.webkit.org/show_bug.cgi?id=233350
     5        <rdar://problem/84311569>
     6
     7        Reviewed by Chris Dumez.
     8
     9        This patch builds on the work in Bug 231339 and threads the new icons
     10        feature through the WebKit layer.
     11
     12        Note: This change also moves the implementation of _WKApplicationManifestIcon
     13        earlier in the file since the implementation is needed for proper serialization
     14        of the _WKApplicationManifest.
     15
     16        Tested by TestWebKitAPI (ApplicationManifest.Icons) test.
     17
     18        * UIProcess/API/Cocoa/_WKApplicationManifest.h:
     19        * UIProcess/API/Cocoa/_WKApplicationManifest.mm:
     20        (fromPurposes): New helper function.
     21        (makeVectorElement): Ditto.
     22        (-[_WKApplicationManifestIcon initWithCoder:]): Updated to call proper
     23        serialization methods.
     24        (-[_WKApplicationManifestIcon initWithCoreIcon:]): Added.
     25        (-[_WKApplicationManifest initWithCoder:]): Updated to properly handle
     26        serializing the object.
     27        (-[_WKApplicationManifest icons]): Added.
     28
    1292021-11-19  Per Arne  <pvollan@apple.com>
    230
  • trunk/Source/WebKit/UIProcess/API/Cocoa/_WKApplicationManifest.h

    r285645 r286073  
    11/*
    2  * Copyright (C) 2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    5858@property (nonatomic, readonly, copy) NSURL *startURL;
    5959@property (nonatomic, readonly) _WKApplicationManifestDisplayMode displayMode;
    60 @property (nonatomic, readonly) NSArray<_WKApplicationManifestIcon *> *icons WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
     60@property (nonatomic, readonly, copy) NSArray<_WKApplicationManifestIcon *> *icons WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
    6161
    6262#if TARGET_OS_IPHONE
     
    7272WK_CLASS_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA))
    7373@interface _WKApplicationManifestIcon : NSObject <NSSecureCoding>
    74 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=232959
     74
     75@property (nonatomic, readonly, copy) NSURL *src;
     76@property (nonatomic, readonly, copy) NSArray<NSString *> *sizes;
     77@property (nonatomic, readonly, copy) NSString *type;
     78@property (nonatomic, readonly) NSArray<NSNumber *> *purposes;
     79
    7580@end
    7681
  • trunk/Source/WebKit/UIProcess/API/Cocoa/_WKApplicationManifest.mm

    r285645 r286073  
    11/*
    2  * Copyright (C) 2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3333#import <WebCore/ColorCocoa.h>
    3434#import <WebCore/WebCoreObjCExtras.h>
     35#import <wtf/cocoa/VectorCocoa.h>
    3536
    3637#if PLATFORM(IOS_FAMILY)
     
    4243#endif
    4344
     45static OptionSet<WebCore::ApplicationManifest::Icon::Purpose> fromPurposes(NSArray<NSNumber *> *purposes)
     46{
     47    OptionSet<WebCore::ApplicationManifest::Icon::Purpose> purposeSet;
     48    for (NSNumber *purposeNumber in purposes) {
     49        auto purpose = static_cast<WebCore::ApplicationManifest::Icon::Purpose>(purposeNumber.integerValue);
     50        purposeSet.add(purpose);
     51    }
     52
     53    return purposeSet;
     54}
     55
     56static RetainPtr<NSArray<NSNumber *>> fromPurposes(OptionSet<WebCore::ApplicationManifest::Icon::Purpose> purposes)
     57{
     58    auto purposeArray = adoptNS([[NSMutableArray alloc] init]);
     59    for (auto purpose : purposes)
     60        [purposeArray addObject:[NSNumber numberWithUnsignedChar:static_cast<std::underlying_type<WebCore::ApplicationManifest::Icon::Purpose>::type>(purpose)]];
     61    return purposeArray;
     62}
     63
    4464static std::optional<WebCore::ApplicationManifest::Icon> makeVectorElement(const WebCore::ApplicationManifest::Icon*, id arrayElement)
    4565{
    46 
    4766    if (![arrayElement isKindOfClass: _WKApplicationManifestIcon.class])
    4867        return std::nullopt;
    4968
     69    auto icon = dynamic_objc_cast<_WKApplicationManifestIcon>(arrayElement);
     70    if (!icon)
     71        return std::nullopt;
     72
    5073    return WebCore::ApplicationManifest::Icon {
    51         // FIXME: https://bugs.webkit.org/show_bug.cgi?id=232959
     74        icon.src,
     75        makeVector<String>(icon.sizes),
     76        icon.type,
     77        fromPurposes(icon.purposes)
    5278    };
    5379}
    5480
     81@implementation _WKApplicationManifestIcon
     82
     83+ (BOOL)supportsSecureCoding
     84{
     85    return YES;
     86}
     87
     88- (instancetype)initWithCoder:(NSCoder *)coder
     89{
     90    if (!(self = [self init]))
     91        return nil;
     92
     93    _src = [[coder decodeObjectOfClass:[NSString class] forKey:@"src"] copy];
     94    _sizes = [[coder decodeObjectOfClasses:[NSSet setWithArray:@[[NSArray class], [NSString class]]] forKey:@"sizes"] copy];
     95    _type = [[coder decodeObjectOfClass:[NSString class] forKey:@"type"] copy];
     96    _purposes = [[coder decodeObjectOfClasses:[NSSet setWithArray:@[[NSArray class], [NSString class]]] forKey:@"purposes"] copy];
     97
     98    return self;
     99}
     100
     101- (instancetype)initWithCoreIcon:(const WebCore::ApplicationManifest::Icon *)icon
     102{
     103    if (!(self = [[_WKApplicationManifestIcon alloc] init]))
     104        return nil;
     105
     106    if (icon) {
     107        _src = [icon->src copy];
     108        _sizes = createNSArray(icon->sizes, [] (auto& size) -> NSString * {
     109            return size;
     110        }).leakRef();
     111        _type = [icon->type copy];
     112        _purposes = fromPurposes(icon->purposes).leakRef();
     113    }
     114
     115    return self;
     116}
     117
     118- (void)encodeWithCoder:(NSCoder *)coder
     119{
     120    [coder encodeObject:_src forKey:@"src"];
     121    [coder encodeObject:_sizes forKey:@"sizes"];
     122    [coder encodeObject:_type forKey:@"type"];
     123    [coder encodeObject:_purposes forKey:@"purposes"];
     124}
     125
     126- (void)dealloc
     127{
     128    if (WebCoreObjCScheduleDeallocateOnMainRunLoop(_WKApplicationManifestIcon.class, self))
     129        return;
     130
     131    [_src release];
     132    [_sizes release];
     133    [_type release];
     134    [_purposes release];
     135
     136    [super dealloc];
     137}
     138
     139@end
     140
     141   
    55142@implementation _WKApplicationManifest
    56143
     
    64151- (instancetype)initWithCoder:(NSCoder *)aDecoder
    65152{
    66     NSString *name = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"name"];
    67     NSString *shortName = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"short_name"];
    68     NSString *description = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"description"];
    69     NSURL *scopeURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:@"scope"];
     153    String name = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"name"];
     154    String shortName = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"short_name"];
     155    String description = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"description"];
     156    URL scopeURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:@"scope"];
    70157    NSInteger display = [aDecoder decodeIntegerForKey:@"display"];
    71     NSURL *startURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:@"start_url"];
     158    URL startURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:@"start_url"];
    72159    CocoaColor *themeColor = [aDecoder decodeObjectOfClass:[CocoaColor class] forKey:@"theme_color"];
    73160    NSArray<_WKApplicationManifestIcon *> *icons = [aDecoder decodeObjectOfClasses:[NSSet setWithArray:@[[NSArray class], [_WKApplicationManifestIcon class]]] forKey:@"icons"];
    74161
    75162    WebCore::ApplicationManifest coreApplicationManifest {
    76         WTF::String(name),
    77         WTF::String(shortName),
    78         WTF::String(description),
    79         URL(scopeURL),
     163        WTFMove(name),
     164        WTFMove(shortName),
     165        WTFMove(description),
     166        WTFMove(scopeURL),
    80167        static_cast<WebCore::ApplicationManifest::Display>(display),
    81         URL(startURL),
     168        WTFMove(startURL),
    82169        WebCore::roundAndClampToSRGBALossy(themeColor.CGColor),
    83         Vector<WebCore::ApplicationManifest::Icon>(makeVector<WebCore::ApplicationManifest::Icon>(icons)),
     170        makeVector<WebCore::ApplicationManifest::Icon>(icons),
    84171    };
    85172
     
    175262- (NSArray<_WKApplicationManifestIcon *> *)icons
    176263{
    177     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=232959
    178     return nil;
     264    return createNSArray(_applicationManifest->applicationManifest().icons, [] (auto& coreIcon) -> id {
     265        return adoptNS([[_WKApplicationManifestIcon alloc] initWithCoreIcon:&coreIcon]).autorelease();
     266    }).autorelease();
    179267}
    180268
     
    244332
    245333@end
    246 
    247 @implementation _WKApplicationManifestIcon
    248 
    249 + (BOOL)supportsSecureCoding
    250 {
    251     return YES;
    252 }
    253 
    254 - (instancetype)initWithCoder:(NSCoder *)aDecoder
    255 {
    256     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=232959
    257     UNUSED_PARAM(aDecoder);
    258     [self release];
    259     return nil;
    260 }
    261 
    262 - (void)encodeWithCoder:(NSCoder *)aCoder
    263 {
    264     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=232959
    265     UNUSED_PARAM(aCoder);
    266 }
    267 
    268 - (void)dealloc
    269 {
    270     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=232959
    271     if (WebCoreObjCScheduleDeallocateOnMainRunLoop(_WKApplicationManifestIcon.class, self))
    272         return;
    273     [super dealloc];
    274 }
    275 
    276 @end
  • trunk/Tools/ChangeLog

    r286072 r286073  
     12021-11-19  Brent Fulgham  <bfulgham@apple.com>
     2
     3        Add support for web app manifest icons in WebKit/UI Process layer
     4        https://bugs.webkit.org/show_bug.cgi?id=233350
     5        <rdar://problem/84311569>
     6
     7        Reviewed by Chris Dumez.
     8
     9        Add a new API test to exercise the _WKApplicationManifestIcon API.
     10
     11        * TestWebKitAPI/Tests/WebCore/ApplicationManifestParser.cpp:
     12        (ApplicationManifestParserTest::testIconsSizes):
     13        (TEST_F):
     14        * TestWebKitAPI/Tests/WebKitCocoa/ApplicationManifest.mm:
     15        (TestWebKitAPI::TEST):
     16
    1172021-11-19  Robert Jenner  <Jenner@apple.com>
    218
  • trunk/Tools/TestWebKitAPI/Tests/WebCore/ApplicationManifestParser.cpp

    r285645 r286073  
    11/*
    2  * Copyright (C) 2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    161161    }
    162162
    163     void testIconsSizes(const String &rawJSON, const String& expectedValue)
     163    void testIconsSizes(const String &rawJSON, size_t expectedCount, size_t testIndex, const String& expectedValue)
    164164    {
    165165        auto manifest = parseIconFirstTopLevelProperty("sizes", rawJSON);
    166166        auto value = manifest.icons[0].sizes;
    167         EXPECT_STREQ(expectedValue.utf8().data(), value.utf8().data());
     167        EXPECT_EQ(expectedCount, value.size());
     168        EXPECT_TRUE(testIndex < value.size());
     169        EXPECT_STREQ(expectedValue.utf8().data(), value[testIndex].utf8().data());
    168170    }
    169171
     
    369371    testIconsSrc("\"icon.jpg\"", srcURL);
    370372    testIconsType("\"image/webp\"", "image/webp");
    371     testIconsSizes("\"256x256\"", "256x256");
    372     testIconsSizes("\"72x72 96x96\"", "72x72 96x96");
     373    testIconsSizes("\"256x256\"", 1, 0, "256x256");
     374    testIconsSizes("\"72x72 96x96\"", 2, 0, "72x72");
     375    testIconsSizes("\"72x72 96x96\"", 2, 1, "96x96");
    373376
    374377    OptionSet<ApplicationManifest::Icon::Purpose> purposeAny { ApplicationManifest::Icon::Purpose::Any };
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ApplicationManifest.mm

    r282026 r286073  
    11/*
    2  * Copyright (C) 2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    279279}
    280280
     281TEST(ApplicationManifest, Icons)
     282{
     283    static bool done = false;
     284
     285    NSArray *expectedIcons = @[ @{
     286        @"src": @"https://example.com/images/touch/homescreen32.png",
     287        @"sizes": @"32x32",
     288        @"type": @"image/png"
     289    }, @{
     290        @"src": @"https://example.com/images/touch/homescreen48.png",
     291        @"sizes": @"48x48",
     292        @"type": @"image/png",
     293        @"purpose": @"monochrome maskable"
     294    }, @{
     295        @"src": @"https://example.com/images/touch/homescreen128.jpg",
     296        @"sizes": @"96x96 128x128",
     297        @"type": @"image/jpg",
     298        @"purpose": @"monochrome"
     299    }];
     300
     301    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect]);
     302    NSDictionary *manifestObject = @{
     303        @"name": @"A Web Application",
     304        @"short_name": @"WebApp",
     305        @"description": @"Hello.",
     306        @"start_url": @"http://example.com/app/start",
     307        @"scope": @"http://example.com/app",
     308        @"theme_color": @"red",
     309        @"icons": expectedIcons
     310    };
     311    NSString *htmlString = [NSString stringWithFormat:@"<link rel=\"manifest\" href=\"data:text/plain;charset=utf-8;base64,%@\">", [[NSJSONSerialization dataWithJSONObject:manifestObject options:0 error:nil] base64EncodedStringWithOptions:0]];
     312    [webView loadHTMLString:htmlString baseURL:[NSURL URLWithString:@"http://example.com/app/index"]];
     313    [webView _test_waitForDidFinishNavigation];
     314    [webView _getApplicationManifestWithCompletionHandler:^(_WKApplicationManifest *manifest) {
     315        EXPECT_TRUE([manifest.name isEqualToString:@"A Web Application"]);
     316        EXPECT_TRUE([manifest.shortName isEqualToString:@"WebApp"]);
     317        EXPECT_TRUE([manifest.applicationDescription isEqualToString:@"Hello."]);
     318        EXPECT_TRUE([manifest.startURL isEqual:[NSURL URLWithString:@"http://example.com/app/start"]]);
     319        EXPECT_TRUE([manifest.scope isEqual:[NSURL URLWithString:@"http://example.com/app"]]);
     320
     321        auto sRGBColorSpace = adoptCF(CGColorSpaceCreateWithName(kCGColorSpaceSRGB));
     322        auto redColor = adoptCF(CGColorCreate(sRGBColorSpace.get(), redColorComponents));
     323        EXPECT_TRUE(CGColorEqualToColor(manifest.themeColor.CGColor, redColor.get()));
     324
     325        size_t iconIndex = 0;
     326        for (_WKApplicationManifestIcon *icon in manifest.icons) {
     327            NSDictionary *expectedIcon = expectedIcons[iconIndex];
     328            NSString *expectedURLString = [expectedIcon objectForKey:@"src"];
     329            EXPECT_TRUE([icon.src isEqual:[NSURL URLWithString:expectedURLString]]);
     330            EXPECT_TRUE([icon.type isEqual:[expectedIcon objectForKey:@"type"]]);
     331
     332            switch (iconIndex) {
     333            case 0:
     334                EXPECT_EQ(icon.sizes.count, 1ul);
     335                EXPECT_TRUE([icon.sizes[0] isEqual:[expectedIcon objectForKey:@"sizes"]]);
     336                EXPECT_EQ(icon.purposes.count, 1ul);
     337                EXPECT_EQ(icon.purposes[0].unsignedLongValue, 1ul);
     338                break;
     339
     340            case 1:
     341                EXPECT_EQ(icon.sizes.count, 1ul);
     342                EXPECT_TRUE([icon.sizes[0] isEqual:[expectedIcon objectForKey:@"sizes"]]);
     343                EXPECT_EQ(icon.purposes.count, 2ul);
     344                EXPECT_EQ(icon.purposes[0].unsignedLongValue, 2ul);
     345                EXPECT_EQ(icon.purposes[1].unsignedLongValue, 4ul);
     346                break;
     347
     348            case 2:
     349                EXPECT_EQ(icon.sizes.count, 2ul);
     350                EXPECT_TRUE([icon.sizes[0] isEqual:@"96x96"]);
     351                EXPECT_TRUE([icon.sizes[1] isEqual:@"128x128"]);
     352                EXPECT_EQ(icon.purposes.count, 1ul);
     353                EXPECT_EQ(icon.purposes[0].unsignedLongValue, 2ul);
     354                break;
     355            }
     356
     357            ++iconIndex;
     358        }
     359        done = true;
     360    }];
     361    Util::run(&done);
     362}
     363
    281364} // namespace TestWebKitAPI
    282365
Note: See TracChangeset for help on using the changeset viewer.