Changeset 282026 in webkit


Ignore:
Timestamp:
Sep 3, 2021 2:48:54 PM (11 months ago)
Author:
Devin Rousso
Message:

[Web App Manifest] Always fetch the first manifest if provided
https://bugs.webkit.org/show_bug.cgi?id=229059
<rdar://problem/82148333>

Reviewed by Brent Fulgham.

Source/WebCore:

Before this patch, WebKit only fetched/parsed/applied/etc. the web app manifest when
-[WKWebView _getApplicationManifestWithCompletionHandler:] was called. This patch makes
WebKit do all that as soon as a <link rel="manifest"> (with a valid URL) is encountered.
This allows manifests that have specified a "theme_color" to actually have an effect.

Tests: ApplicationManifest.AlwaysFetch

ApplicationManifest.OnlyFirstManifest
ApplicationManifest.NoManifest
ApplicationManifest.MediaAttriute
ApplicationManifest.DoesNotExist
ApplicationManifest.Blocked

  • html/HTMLLinkElement.cpp:

(WebCore::HTMLLinkElement::process):

  • loader/DocumentLoader.h:
  • loader/DocumentLoader.cpp:

(WebCore::DocumentLoader::stopLoading):
(WebCore::DocumentLoader::loadApplicationManifest):
(WebCore::DocumentLoader::finishedLoadingApplicationManifest):
(WebCore::DocumentLoader::notifyFinishedLoadingApplicationManifest): Deleted.
Simplify the way that the UIProcess communicates with the WebProcess (and between WebKit and
WebCore). There's no need to have a HashMap of callbacks since each document can only have
at most one web app manifest. Furthermore, instead of having a HashMap in both WebKit and
WebCore, just pass along the CompletionHandler to the DocumentLoader for a single list
of completion callbacks (a list is needed because it's possible for a client to invoke
-[WKWebView _getApplicationManifestWithCompletionHandler:] multiple times).

Source/WebKit:

Before this patch, WebKit only fetched/parsed/applied/etc. the web app manifest when
-[WKWebView _getApplicationManifestWithCompletionHandler:] was called. This patch makes
WebKit do all that as soon as a <link rel="manifest"> (with a valid URL) is encountered.
This allows manifests that have specified a "theme_color" to actually have an effect.

  • WebProcess/WebCoreSupport/WebFrameLoaderClient.h:
  • WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:

(WebKit::WebFrameLoaderClient::finishedLoadingApplicationManifest): Deleted.

  • WebProcess/WebPage/WebPage.h:
  • WebProcess/WebPage/WebPage.cpp:

(WebKit::WebPage::~WebPage):
(WebKit::WebPage::getApplicationManifest):
(WebKit::WebPage::didFinishLoadingApplicationManifest):
Simplify the way that the UIProcess communicates with the WebProcess (and between WebKit and
WebCore). There's no need to have a HashMap of callbacks since each document can only have
at most one web app manifest. Furthermore, instead of having a HashMap in both WebKit and
WebCore, just pass along the CompletionHandler to the DocumentLoader for a single list
of completion callbacks (a list is needed because it's possible for a client to invoke
-[WKWebView _getApplicationManifestWithCompletionHandler:] multiple times).

Tools:

  • TestWebKitAPI/Tests/WebKitCocoa/ApplicationManifest.mm:

(TestWebKitAPI::TEST.ApplicationManifest.AlwaysFetch): Added.
(TestWebKitAPI::TEST.ApplicationManifest.OnlyFirstManifest): Added.
(TestWebKitAPI::TEST.ApplicationManifest.NoManifest): Added.
(TestWebKitAPI::TEST.ApplicationManifest.MediaAttriute): Added.
(TestWebKitAPI::TEST.ApplicationManifest.DoesNotExist): Added.
(TestWebKitAPI::TEST.ApplicationManifest.Blocked): Added.

LayoutTests:

  • applicationmanifest/multiple-links.html:
  • applicationmanifest/multiple-links-expected.txt:
  • http/tests/security/contentSecurityPolicy/manifest-src-blocked.html:
Location:
trunk
Files:
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r282025 r282026  
     12021-09-03  Devin Rousso  <drousso@apple.com>
     2
     3        [Web App Manifest] Always fetch the first manifest if provided
     4        https://bugs.webkit.org/show_bug.cgi?id=229059
     5        <rdar://problem/82148333>
     6
     7        Reviewed by Brent Fulgham.
     8
     9        * applicationmanifest/multiple-links.html:
     10        * applicationmanifest/multiple-links-expected.txt:
     11        * http/tests/security/contentSecurityPolicy/manifest-src-blocked.html:
     12
    1132021-09-03  Chris Dumez  <cdumez@apple.com>
    214
  • trunk/LayoutTests/applicationmanifest/multiple-links-expected.txt

    r225598 r282026  
     1urlscheme://2 - willSendRequest <NSURLRequest URL urlscheme://2, main document URL multiple-links.html, http method GET> redirectResponse (null)
    12multiple-links.html - didFinishLoading
    2 urlscheme://1 - willSendRequest <NSURLRequest URL urlscheme://1, main document URL multiple-links.html, http method GET> redirectResponse (null)
    3 urlscheme://1 - didFailLoadingWithError: <NSError domain NSURLErrorDomain, code -1002, failing URL "urlscheme://1">
     3urlscheme://2 - didFailLoadingWithError: <NSError domain NSURLErrorDomain, code -1002, failing URL "urlscheme://2">
    44
  • trunk/LayoutTests/applicationmanifest/multiple-links.html

    r225598 r282026  
    1 <link rel="manifest" href="urlscheme://1" media="print">
    2 <link rel="manifest" href="urlscheme://2">
    31<script>
    42if (window.testRunner) {
     
    64    testRunner.dumpAsText();
    75    testRunner.waitUntilDone();
     6}
     7</script>
     8<link rel="manifest" href="urlscheme://1" media="print">
     9<link rel="manifest" href="urlscheme://2">
     10<script>
     11if (window.testRunner) {
    812    testRunner.getApplicationManifestThen(function() {
    913        testRunner.notifyDone();
  • trunk/LayoutTests/http/tests/security/contentSecurityPolicy/manifest-src-blocked.html

    r225598 r282026  
    11<meta http-equiv="Content-Security-Policy" content="manifest-src 'none'">
    2 <link rel="manifest" href="manifest.test/manifest.json">
    32<script>
    43    if (window.testRunner) {
    54        testRunner.dumpAsText();
    65        testRunner.waitUntilDone();
     6    }
     7</script>
     8<link rel="manifest" href="manifest.test/manifest.json">
     9<script>
     10    if (window.testRunner) {
    711        testRunner.getApplicationManifestThen(function() {
    812            alert("Pass");
  • trunk/Source/WebCore/ChangeLog

    r282022 r282026  
     12021-09-03  Devin Rousso  <drousso@apple.com>
     2
     3        [Web App Manifest] Always fetch the first manifest if provided
     4        https://bugs.webkit.org/show_bug.cgi?id=229059
     5        <rdar://problem/82148333>
     6
     7        Reviewed by Brent Fulgham.
     8
     9        Before this patch, WebKit only fetched/parsed/applied/etc. the web app manifest when
     10        `-[WKWebView _getApplicationManifestWithCompletionHandler:]` was called. This patch makes
     11        WebKit do all that as soon as a `<link rel="manifest">` (with a valid URL) is encountered.
     12        This allows manifests that have specified a `"theme_color"` to actually have an effect.
     13
     14        Tests: ApplicationManifest.AlwaysFetch
     15               ApplicationManifest.OnlyFirstManifest
     16               ApplicationManifest.NoManifest
     17               ApplicationManifest.MediaAttriute
     18               ApplicationManifest.DoesNotExist
     19               ApplicationManifest.Blocked
     20
     21        * html/HTMLLinkElement.cpp:
     22        (WebCore::HTMLLinkElement::process):
     23
     24        * loader/DocumentLoader.h:
     25        * loader/DocumentLoader.cpp:
     26        (WebCore::DocumentLoader::stopLoading):
     27        (WebCore::DocumentLoader::loadApplicationManifest):
     28        (WebCore::DocumentLoader::finishedLoadingApplicationManifest):
     29        (WebCore::DocumentLoader::notifyFinishedLoadingApplicationManifest): Deleted.
     30        Simplify the way that the UIProcess communicates with the WebProcess (and between WebKit and
     31        WebCore). There's no need to have a `HashMap` of callbacks since each document can only have
     32        at most one web app manifest. Furthermore, instead of having a `HashMap` in both WebKit and
     33        WebCore, just pass along the `CompletionHandler` to the `DocumentLoader` for a single list
     34        of completion callbacks (a list is needed because it's possible for a client to invoke
     35        `-[WKWebView _getApplicationManifestWithCompletionHandler:]` multiple times).
     36
    1372021-09-03  Tim Nguyen  <ntim@apple.com>
    238
  • trunk/Source/WebCore/html/HTMLLinkElement.cpp

    r280479 r282026  
    3636#include "DefaultResourceLoadPriority.h"
    3737#include "Document.h"
     38#include "DocumentLoader.h"
    3839#include "Event.h"
    3940#include "EventNames.h"
     
    306307        m_loading = true;
    307308
    308         bool mediaQueryMatches = true;
    309         if (!m_media.isEmpty()) {
    310             std::optional<RenderStyle> documentStyle;
    311             if (document().hasLivingRenderTree())
    312                 documentStyle = Style::resolveForDocument(document());
    313             auto media = MediaQuerySet::create(m_media, MediaQueryParserContext(document()));
    314             LOG(MediaQueries, "HTMLLinkElement::process evaluating queries");
    315             mediaQueryMatches = MediaQueryEvaluator { document().frame()->view()->mediaType(), document(), documentStyle ? &*documentStyle : nullptr }.evaluate(media.get());
    316         }
    317 
    318309        // Don't hold up render tree construction and script execution on stylesheets
    319310        // that are not needed for the rendering at the moment.
    320         bool isActive = mediaQueryMatches && !isAlternate();
     311        bool isActive = mediaAttributeMatches() && !isAlternate();
    321312        addPendingSheet(isActive ? ActiveSheet : InactiveSheet);
    322313
     
    352343            notifyLoadedSheetAndAllCriticalSubresources(true);
    353344        }
    354     } else if (m_sheet) {
     345
     346        return;
     347    }
     348
     349    if (m_sheet) {
    355350        // we no longer contain a stylesheet, e.g. perhaps rel or type was changed
    356351        clearSheet();
    357352        m_styleScope->didChangeActiveStyleSheetCandidates();
    358     }
     353        return;
     354    }
     355
     356#if ENABLE(APPLICATION_MANIFEST)
     357    if (isApplicationManifest()) {
     358        if (RefPtr loader = document().loader())
     359            loader->loadApplicationManifest({ });
     360        return;
     361    }
     362#endif // ENABLE(APPLICATION_MANIFEST)
    359363}
    360364
     
    500504}
    501505
     506bool HTMLLinkElement::mediaAttributeMatches() const
     507{
     508    if (m_media.isEmpty())
     509        return true;
     510
     511    std::optional<RenderStyle> documentStyle;
     512    if (document().hasLivingRenderTree())
     513        documentStyle = Style::resolveForDocument(document());
     514    auto media = MediaQuerySet::create(m_media, MediaQueryParserContext(document()));
     515    LOG(MediaQueries, "HTMLLinkElement::mediaAttributeMatches");
     516    return MediaQueryEvaluator(document().frame()->view()->mediaType(), document(), documentStyle ? &*documentStyle : nullptr).evaluate(media.get());
     517}
     518
    502519void HTMLLinkElement::linkLoaded()
    503520{
  • trunk/Source/WebCore/html/HTMLLinkElement.h

    r280479 r282026  
    6565    bool isEnabledViaScript() const { return m_disabledState == EnabledViaScript; }
    6666    DOMTokenList& sizes();
     67
     68    bool mediaAttributeMatches() const;
    6769
    6870    WEBCORE_EXPORT void setCrossOrigin(const AtomString&);
  • trunk/Source/WebCore/loader/DocumentLoader.cpp

    r281941 r282026  
    9797#include <wtf/NeverDestroyed.h>
    9898#include <wtf/Ref.h>
     99#include <wtf/Scope.h>
    99100#include <wtf/text/CString.h>
    100101#include <wtf/text/WTFString.h>
     
    333334   
    334335#if ENABLE(APPLICATION_MANIFEST)
    335     for (auto callbackIdentifier : m_applicationManifestLoaders.values())
    336         notifyFinishedLoadingApplicationManifest(callbackIdentifier, std::nullopt);
    337     m_applicationManifestLoaders.clear();
     336    m_applicationManifestLoader = nullptr;
     337    m_finishedLoadingApplicationManifest = false;
     338    notifyFinishedLoadingApplicationManifest();
    338339#endif
    339340
     
    15541555
    15551556#if ENABLE(APPLICATION_MANIFEST)
    1556 uint64_t DocumentLoader::loadApplicationManifest()
    1557 {
    1558     static uint64_t nextCallbackID = 1;
     1557
     1558void DocumentLoader::loadApplicationManifest(CompletionHandler<void(const std::optional<ApplicationManifest>&)>&& completionHandler)
     1559{
     1560    if (completionHandler)
     1561        m_loadApplicationManifestCallbacks.append(WTFMove(completionHandler));
     1562
     1563    bool isLoading = !!m_applicationManifestLoader;
     1564    auto notifyIfUnableToLoad = makeScopeExit([&] {
     1565        if (!isLoading || m_finishedLoadingApplicationManifest)
     1566            notifyFinishedLoadingApplicationManifest();
     1567    });
     1568
     1569    if (isLoading)
     1570        return;
    15591571
    15601572    auto* document = this->document();
    15611573    if (!document)
    1562         return 0;
    1563 
    1564     if (!m_frame->isMainFrame())
    1565         return 0;
     1574        return;
     1575
     1576    if (!document->isTopDocument())
     1577        return;
    15661578
    15671579    if (document->url().isEmpty() || document->url().protocolIsAbout())
    1568         return 0;
     1580        return;
    15691581
    15701582    auto head = document->head();
    15711583    if (!head)
    1572         return 0;
     1584        return;
    15731585
    15741586    URL manifestURL;
    15751587    bool useCredentials = false;
    15761588    for (const auto& link : childrenOfType<HTMLLinkElement>(*head)) {
    1577         if (link.isApplicationManifest()) {
    1578             manifestURL = link.href();
    1579             useCredentials = equalIgnoringASCIICase(link.attributeWithoutSynchronization(HTMLNames::crossoriginAttr), "use-credentials");
    1580             break;
    1581         }
     1589        if (!link.isApplicationManifest())
     1590            continue;
     1591
     1592        auto href = link.href();
     1593        if (href.isEmpty() || !href.isValid())
     1594            continue;
     1595
     1596        if (!link.mediaAttributeMatches())
     1597            continue;
     1598
     1599        manifestURL = href;
     1600        useCredentials = equalIgnoringASCIICase(link.attributeWithoutSynchronization(HTMLNames::crossoriginAttr), "use-credentials");
     1601        break;
    15821602    }
    15831603
    15841604    if (manifestURL.isEmpty() || !manifestURL.isValid())
    1585         return 0;
    1586 
    1587     auto manifestLoader = makeUnique<ApplicationManifestLoader>(*this, manifestURL, useCredentials);
    1588     auto* rawManifestLoader = manifestLoader.get();
    1589     auto callbackID = nextCallbackID++;
    1590     m_applicationManifestLoaders.set(WTFMove(manifestLoader), callbackID);
    1591 
    1592     if (!rawManifestLoader->startLoading()) {
    1593         m_applicationManifestLoaders.remove(rawManifestLoader);
    1594         return 0;
    1595     }
    1596 
    1597     return callbackID;
     1605        return;
     1606
     1607    m_applicationManifestLoader = makeUnique<ApplicationManifestLoader>(*this, manifestURL, useCredentials);
     1608
     1609    isLoading = m_applicationManifestLoader->startLoading();
     1610    if (!isLoading)
     1611        m_finishedLoadingApplicationManifest = true;
    15981612}
    15991613
    16001614void DocumentLoader::finishedLoadingApplicationManifest(ApplicationManifestLoader& loader)
    16011615{
     1616    ASSERT_UNUSED(loader, &loader == m_applicationManifestLoader.get());
     1617
    16021618    // If the DocumentLoader has detached from its frame, all manifest loads should have already been canceled.
    16031619    ASSERT(m_frame);
    16041620
    1605     auto callbackIdentifier = m_applicationManifestLoaders.get(&loader);
    1606     notifyFinishedLoadingApplicationManifest(callbackIdentifier, loader.processManifest());
    1607     m_applicationManifestLoaders.remove(&loader);
    1608 }
    1609 
    1610 void DocumentLoader::notifyFinishedLoadingApplicationManifest(uint64_t callbackIdentifier, std::optional<ApplicationManifest> manifest)
    1611 {
    1612     RELEASE_ASSERT(callbackIdentifier);
    1613     RELEASE_ASSERT(m_frame);
    1614     m_frame->loader().client().finishedLoadingApplicationManifest(callbackIdentifier, manifest);
    1615 }
    1616 #endif
     1621    ASSERT(!m_finishedLoadingApplicationManifest);
     1622    m_finishedLoadingApplicationManifest = true;
     1623
     1624    notifyFinishedLoadingApplicationManifest();
     1625}
     1626
     1627void DocumentLoader::notifyFinishedLoadingApplicationManifest()
     1628{
     1629    std::optional<ApplicationManifest> manifest = m_applicationManifestLoader ? m_applicationManifestLoader->processManifest() : std::nullopt;
     1630    ASSERT_IMPLIES(manifest, m_finishedLoadingApplicationManifest);
     1631
     1632    for (auto& callback : std::exchange(m_loadApplicationManifestCallbacks, { }))
     1633        callback(manifest);
     1634}
     1635
     1636#endif // ENABLE(APPLICATION_MANIFEST)
    16171637
    16181638bool DocumentLoader::isLoadingInAPISense() const
  • trunk/Source/WebCore/loader/DocumentLoader.h

    r281941 r282026  
    394394
    395395#if ENABLE(APPLICATION_MANIFEST)
    396     WEBCORE_EXPORT uint64_t loadApplicationManifest();
     396    WEBCORE_EXPORT void loadApplicationManifest(CompletionHandler<void(const std::optional<ApplicationManifest>&)>&&);
    397397    void finishedLoadingApplicationManifest(ApplicationManifestLoader&);
    398398#endif
     
    517517
    518518#if ENABLE(APPLICATION_MANIFEST)
    519     void notifyFinishedLoadingApplicationManifest(uint64_t callbackIdentifier, std::optional<ApplicationManifest>);
     519    void notifyFinishedLoadingApplicationManifest();
    520520#endif
    521521
     
    622622
    623623#if ENABLE(APPLICATION_MANIFEST)
    624     HashMap<std::unique_ptr<ApplicationManifestLoader>, uint64_t> m_applicationManifestLoaders;
     624    std::unique_ptr<ApplicationManifestLoader> m_applicationManifestLoader;
     625    Vector<CompletionHandler<void(const std::optional<ApplicationManifest>&)>> m_loadApplicationManifestCallbacks;
     626    bool m_finishedLoadingApplicationManifest { false };
    625627#endif
    626628
  • trunk/Source/WebKit/ChangeLog

    r282013 r282026  
     12021-09-03  Devin Rousso  <drousso@apple.com>
     2
     3        [Web App Manifest] Always fetch the first manifest if provided
     4        https://bugs.webkit.org/show_bug.cgi?id=229059
     5        <rdar://problem/82148333>
     6
     7        Reviewed by Brent Fulgham.
     8
     9        Before this patch, WebKit only fetched/parsed/applied/etc. the web app manifest when
     10        `-[WKWebView _getApplicationManifestWithCompletionHandler:]` was called. This patch makes
     11        WebKit do all that as soon as a `<link rel="manifest">` (with a valid URL) is encountered.
     12        This allows manifests that have specified a `"theme_color"` to actually have an effect.
     13
     14        * WebProcess/WebCoreSupport/WebFrameLoaderClient.h:
     15        * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
     16        (WebKit::WebFrameLoaderClient::finishedLoadingApplicationManifest): Deleted.
     17        * WebProcess/WebPage/WebPage.h:
     18        * WebProcess/WebPage/WebPage.cpp:
     19        (WebKit::WebPage::~WebPage):
     20        (WebKit::WebPage::getApplicationManifest):
     21        (WebKit::WebPage::didFinishLoadingApplicationManifest):
     22        Simplify the way that the UIProcess communicates with the WebProcess (and between WebKit and
     23        WebCore). There's no need to have a `HashMap` of callbacks since each document can only have
     24        at most one web app manifest. Furthermore, instead of having a `HashMap` in both WebKit and
     25        WebCore, just pass along the `CompletionHandler` to the `DocumentLoader` for a single list
     26        of completion callbacks (a list is needed because it's possible for a client to invoke
     27        `-[WKWebView _getApplicationManifestWithCompletionHandler:]` multiple times).
     28
    1292021-09-03  Per Arne  <pvollan@apple.com>
    230
  • trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp

    r281832 r282026  
    19341934}
    19351935
    1936 #if ENABLE(APPLICATION_MANIFEST)
    1937 void WebFrameLoaderClient::finishedLoadingApplicationManifest(uint64_t callbackIdentifier, const std::optional<WebCore::ApplicationManifest>& manifest)
    1938 {
    1939     WebPage* webPage = m_frame->page();
    1940     if (!webPage)
    1941         return;
    1942 
    1943     webPage->didFinishLoadingApplicationManifest(callbackIdentifier, manifest);
    1944 }
    1945 #endif // ENABLE(APPLICATION_MANIFEST)
    1946 
    19471936#if ENABLE(APP_BOUND_DOMAINS)
    19481937bool WebFrameLoaderClient::shouldEnableInAppBrowserPrivacyProtections() const
  • trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.h

    r281832 r282026  
    271271    void didCreateWindow(WebCore::DOMWindow&) final;
    272272
    273 #if ENABLE(APPLICATION_MANIFEST)
    274     void finishedLoadingApplicationManifest(uint64_t, const std::optional<WebCore::ApplicationManifest>&) final;
    275 #endif
    276 
    277273    Ref<WebFrame> m_frame;
    278274    RefPtr<PluginView> m_pluginView;
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp

    r281980 r282026  
    10521052    for (auto& completionHandler : std::exchange(m_markLayersAsVolatileCompletionHandlers, { }))
    10531053        completionHandler(false);
    1054    
    1055 #if ENABLE(APPLICATION_MANIFEST)
    1056     for (auto& completionHandler : m_applicationManifestFetchCallbackMap.values()) {
    1057         if (completionHandler)
    1058             completionHandler(std::nullopt);
    1059     }
    1060 #endif
    10611054}
    10621055
     
    72097202
    72107203#if ENABLE(APPLICATION_MANIFEST)
     7204
    72117205void WebPage::getApplicationManifest(CompletionHandler<void(const std::optional<WebCore::ApplicationManifest>&)>&& completionHandler)
    72127206{
     
    72167210        return completionHandler(std::nullopt);
    72177211
    7218     auto coreCallbackID = loader->loadApplicationManifest();
    7219     if (!coreCallbackID)
    7220         return completionHandler(std::nullopt);
    7221 
    7222     m_applicationManifestFetchCallbackMap.add(coreCallbackID, WTFMove(completionHandler));
    7223 }
    7224 
    7225 void WebPage::didFinishLoadingApplicationManifest(uint64_t coreCallbackID, const std::optional<WebCore::ApplicationManifest>& manifest)
    7226 {
    7227     if (auto callback = m_applicationManifestFetchCallbackMap.take(coreCallbackID))
    7228         callback(manifest);
    7229 }
     7212    loader->loadApplicationManifest(WTFMove(completionHandler));
     7213}
     7214
    72307215#endif // ENABLE(APPLICATION_MANIFEST)
    72317216
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.h

    r281980 r282026  
    12971297#if ENABLE(APPLICATION_MANIFEST)
    12981298    void getApplicationManifest(CompletionHandler<void(const std::optional<WebCore::ApplicationManifest>&)>&&);
    1299     void didFinishLoadingApplicationManifest(uint64_t, const std::optional<WebCore::ApplicationManifest>&);
    13001299#endif
    13011300
     
    23122311    HashMap<uint64_t, Function<void(bool granted)>> m_storageAccessResponseCallbackMap;
    23132312
    2314 #if ENABLE(APPLICATION_MANIFEST)
    2315     HashMap<uint64_t, CompletionHandler<void(const std::optional<WebCore::ApplicationManifest>&)>> m_applicationManifestFetchCallbackMap;
    2316 #endif
    2317 
    23182313    OptionSet<LayerTreeFreezeReason> m_layerTreeFreezeReasons;
    23192314    bool m_isSuspended { false };
  • trunk/Tools/ChangeLog

    r282025 r282026  
     12021-09-03  Devin Rousso  <drousso@apple.com>
     2
     3        [Web App Manifest] Always fetch the first manifest if provided
     4        https://bugs.webkit.org/show_bug.cgi?id=229059
     5        <rdar://problem/82148333>
     6
     7        Reviewed by Brent Fulgham.
     8
     9        * TestWebKitAPI/Tests/WebKitCocoa/ApplicationManifest.mm:
     10        (TestWebKitAPI::TEST.ApplicationManifest.AlwaysFetch): Added.
     11        (TestWebKitAPI::TEST.ApplicationManifest.OnlyFirstManifest): Added.
     12        (TestWebKitAPI::TEST.ApplicationManifest.NoManifest): Added.
     13        (TestWebKitAPI::TEST.ApplicationManifest.MediaAttriute): Added.
     14        (TestWebKitAPI::TEST.ApplicationManifest.DoesNotExist): Added.
     15        (TestWebKitAPI::TEST.ApplicationManifest.Blocked): Added.
     16
    1172021-09-03  Chris Dumez  <cdumez@apple.com>
    218
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ApplicationManifest.mm

    r276333 r282026  
    4040constexpr CGFloat redColorComponents[4] = { 1, 0, 0, 1 };
    4141
    42 TEST(WebKit, ApplicationManifestCoding)
     42TEST(ApplicationManifest, Coding)
    4343{
    4444    auto jsonString = @"{ \"name\": \"TestName\", \"short_name\": \"TestShortName\", \"description\": \"TestDescription\", \"scope\": \"https://test.com/app\", \"start_url\": \"https://test.com/app/index.html\", \"display\": \"minimal-ui\", \"theme_color\": \"red\" }";
     
    6161}
    6262
    63 TEST(WebKit, ApplicationManifestBasic)
     63TEST(ApplicationManifest, Basic)
    6464{
    6565    static bool done = false;
     
    118118}
    119119
    120 TEST(WebKit, ApplicationManifestDisplayMode)
     120TEST(ApplicationManifest, DisplayMode)
    121121{
    122122    static bool done;
     
    150150}
    151151
     152TEST(ApplicationManifest, AlwaysFetch)
     153{
     154    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect]);
     155
     156    NSDictionary *manifestObject = @{ @"theme_color": @"red" };
     157    [webView synchronouslyLoadHTMLString:[NSString stringWithFormat:@"<link rel=\"manifest\" href=\"data:application/manifest+json;charset=utf-8;base64,%@\">", [[NSJSONSerialization dataWithJSONObject:manifestObject options:0 error:nil] base64EncodedStringWithOptions:0]]];
     158
     159    {
     160        auto sRGBColorSpace = adoptCF(CGColorSpaceCreateWithName(kCGColorSpaceSRGB));
     161        auto redColor = adoptCF(CGColorCreate(sRGBColorSpace.get(), redColorComponents));
     162        while (!CGColorEqualToColor([webView themeColor].CGColor, redColor.get()))
     163            Util::sleep(1);
     164    }
     165
     166    __block bool done = false;
     167    [webView _getApplicationManifestWithCompletionHandler:^(_WKApplicationManifest *manifest) {
     168        auto sRGBColorSpace = adoptCF(CGColorSpaceCreateWithName(kCGColorSpaceSRGB));
     169        auto redColor = adoptCF(CGColorCreate(sRGBColorSpace.get(), redColorComponents));
     170        EXPECT_TRUE(CGColorEqualToColor(manifest.themeColor.CGColor, redColor.get()));
     171
     172        done = true;
     173    }];
     174    Util::run(&done);
     175}
     176
     177TEST(ApplicationManifest, OnlyFirstManifest)
     178{
     179    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect]);
     180
     181    NSDictionary *manifestObject1 = @{ @"theme_color": @"red" };
     182    NSDictionary *manifestObject2 = @{ @"theme_color": @"blue" };
     183    [webView synchronouslyLoadHTMLString:[NSString stringWithFormat:@"<link rel=\"manifest\" href=\"data:application/manifest+json;charset=utf-8;base64,%@\"><link rel=\"manifest\" href=\"data:application/manifest+json;charset=utf-8;base64,%@\">", [[NSJSONSerialization dataWithJSONObject:manifestObject1 options:0 error:nil] base64EncodedStringWithOptions:0], [[NSJSONSerialization dataWithJSONObject:manifestObject2 options:0 error:nil] base64EncodedStringWithOptions:0]]];
     184
     185    {
     186        auto sRGBColorSpace = adoptCF(CGColorSpaceCreateWithName(kCGColorSpaceSRGB));
     187        auto redColor = adoptCF(CGColorCreate(sRGBColorSpace.get(), redColorComponents));
     188        while (!CGColorEqualToColor([webView themeColor].CGColor, redColor.get()))
     189            Util::sleep(1);
     190    }
     191
     192    __block bool done = false;
     193    [webView _getApplicationManifestWithCompletionHandler:^(_WKApplicationManifest *manifest) {
     194        auto sRGBColorSpace = adoptCF(CGColorSpaceCreateWithName(kCGColorSpaceSRGB));
     195        auto redColor = adoptCF(CGColorCreate(sRGBColorSpace.get(), redColorComponents));
     196        EXPECT_TRUE(CGColorEqualToColor(manifest.themeColor.CGColor, redColor.get()));
     197
     198        done = true;
     199    }];
     200    Util::run(&done);
     201}
     202
     203TEST(ApplicationManifest, NoManifest)
     204{
     205    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect]);
     206
     207    [webView synchronouslyLoadHTMLString:@"Hello World"];
     208
     209    EXPECT_NULL([webView themeColor]);
     210
     211    __block bool done = false;
     212    [webView _getApplicationManifestWithCompletionHandler:^(_WKApplicationManifest *manifest) {
     213        EXPECT_NULL(manifest);
     214
     215        done = true;
     216    }];
     217    Util::run(&done);
     218}
     219
     220TEST(ApplicationManifest, MediaAttriute)
     221{
     222    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect]);
     223
     224    NSDictionary *manifestObject1 = @{ @"theme_color": @"blue" };
     225    NSDictionary *manifestObject2 = @{ @"theme_color": @"red" };
     226    [webView synchronouslyLoadHTMLString:[NSString stringWithFormat:@"<link rel=\"manifest\" href=\"data:application/manifest+json;charset=utf-8;base64,%@\" media=\"invalid\"><link rel=\"manifest\" href=\"data:application/manifest+json;charset=utf-8;base64,%@\" media=\"screen\">", [[NSJSONSerialization dataWithJSONObject:manifestObject1 options:0 error:nil] base64EncodedStringWithOptions:0], [[NSJSONSerialization dataWithJSONObject:manifestObject2 options:0 error:nil] base64EncodedStringWithOptions:0]]];
     227
     228    {
     229        auto sRGBColorSpace = adoptCF(CGColorSpaceCreateWithName(kCGColorSpaceSRGB));
     230        auto redColor = adoptCF(CGColorCreate(sRGBColorSpace.get(), redColorComponents));
     231        while (!CGColorEqualToColor([webView themeColor].CGColor, redColor.get()))
     232            Util::sleep(1);
     233    }
     234
     235    __block bool done = false;
     236    [webView _getApplicationManifestWithCompletionHandler:^(_WKApplicationManifest *manifest) {
     237        auto sRGBColorSpace = adoptCF(CGColorSpaceCreateWithName(kCGColorSpaceSRGB));
     238        auto redColor = adoptCF(CGColorCreate(sRGBColorSpace.get(), redColorComponents));
     239        EXPECT_TRUE(CGColorEqualToColor(manifest.themeColor.CGColor, redColor.get()));
     240
     241        done = true;
     242    }];
     243    Util::run(&done);
     244}
     245
     246TEST(ApplicationManifest, DoesNotExist)
     247{
     248    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect]);
     249
     250    [webView synchronouslyLoadHTMLString:@"<link rel=\"manifest\" href=\"does not exist\">"];
     251
     252    EXPECT_NULL([webView themeColor]);
     253
     254    __block bool done = false;
     255    [webView _getApplicationManifestWithCompletionHandler:^(_WKApplicationManifest *manifest) {
     256        EXPECT_NULL(manifest);
     257
     258        done = true;
     259    }];
     260    Util::run(&done);
     261}
     262
     263TEST(ApplicationManifest, Blocked)
     264{
     265    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect]);
     266
     267    NSDictionary *manifestObject = @{ @"theme_color": @"red" };
     268    [webView synchronouslyLoadHTMLString:[NSString stringWithFormat:@"<meta http-equiv=\"Content-Security-Policy\" content=\"manifest-src 'none'\"><link rel=\"manifest\" href=\"data:application/manifest+json;charset=utf-8;base64,%@\">", [[NSJSONSerialization dataWithJSONObject:manifestObject options:0 error:nil] base64EncodedStringWithOptions:0]]];
     269
     270    EXPECT_NULL([webView themeColor]);
     271
     272    __block bool done = false;
     273    [webView _getApplicationManifestWithCompletionHandler:^(_WKApplicationManifest *manifest) {
     274        EXPECT_NULL(manifest);
     275
     276        done = true;
     277    }];
     278    Util::run(&done);
     279}
     280
    152281} // namespace TestWebKitAPI
    153282
Note: See TracChangeset for help on using the changeset viewer.