Changeset 243682 in webkit


Ignore:
Timestamp:
Mar 31, 2019 10:37:45 AM (5 years ago)
Author:
aestes@apple.com
Message:

[iOS] WebKit should consult the navigation response policy delegate before previewing a QuickLook document
https://bugs.webkit.org/show_bug.cgi?id=196433
<rdar://problem/49293305>

Reviewed by Tim Horton.

Source/WebCore:

When ResourceLoader would encounter a response with a MIME type that QuickLook supports, the
response would be implicitly allowed and a QuickLook preview would be generated. After
generating, the client's navigation response policy delegate would be notified of the
preview response, but not the underlying response. Notably, the preview response has a URL
scheme of "x-apple-ql-id", does not include any underlying HTTP headers, and usually has a
MIME type of "text/html" or "application/pdf" rather than the underlying response MIME type.

To allow clients to make better navigation response policy decisions, this patch changes the
above behavior for WKWebView clients that have linked against a version of WebKit that
includes this change. Rather than notifying the client's navigation response policy delegate
of the preview response, we notify the client of the underlying response. Only if the client
responds with a policy of "allow" will the QuickLook preview response be loaded (without
another call to the navigation response policy delegate).

Non-WKWebView clients and clients that have linked against a version of WebKit that does not
include this change will retain the original behavior.

Covered by existing layout tests and new and existing API tests.

  • WebCore.xcodeproj/project.pbxproj:
  • loader/SubresourceLoader.cpp:

(WebCore::SubresourceLoader::shouldCreatePreviewLoaderForResponse const):
(WebCore::SubresourceLoader::didReceiveResponse):

  • loader/ios/PreviewLoader.h:
  • loader/ios/PreviewLoader.mm:

(-[WebPreviewLoader initWithResourceLoader:resourceResponse:]):
(-[WebPreviewLoader _loadPreviewIfNeeded]):
(-[WebPreviewLoader connection:didReceiveData:lengthReceived:]):
(-[WebPreviewLoader connectionDidFinishLoading:]):
(-[WebPreviewLoader connection:didFailWithError:]):
(WebCore::PreviewLoader::create):
(WebCore::PreviewLoader::didReceiveResponse):
(-[WebPreviewLoader _sendDidReceiveResponseIfNecessary]): Deleted.
(WebCore::PreviewLoader::shouldCreateForMIMEType): Deleted.

  • page/Settings.yaml:
  • platform/MIMETypeRegistry.cpp:

(WebCore::MIMETypeRegistry::canShowMIMEType):

  • platform/network/ios/PreviewConverter.h:
  • platform/network/ios/PreviewConverter.mm:

(WebCore::PreviewConverter::supportsMIMEType):

Source/WebKit:

Added WKWebViewConfiguration SPI for setting the QuickLook navigation response policy
decision behavior. The configuration setting defaults to YES for clients linked on or after
this WebKit change and NO otherwise.

  • NetworkProcess/NetworkResourceLoader.cpp:

(WebKit::NetworkResourceLoader::shouldInterruptLoadForCSPFrameAncestorsOrXFrameOptions):

  • Shared/WebPreferences.yaml:
  • Shared/ios/QuickLookDocumentData.cpp:

(WebKit::QuickLookDocumentData::isEmpty const):

  • Shared/ios/QuickLookDocumentData.h:
  • UIProcess/API/Cocoa/WKWebView.mm:

(-[WKWebView _initializeWithConfiguration:]):

  • UIProcess/API/Cocoa/WKWebViewConfiguration.mm:

(defaultShouldDecidePolicyBeforeLoadingQuickLookPreview):
(-[WKWebViewConfiguration init]):
(-[WKWebViewConfiguration encodeWithCoder:]):
(-[WKWebViewConfiguration initWithCoder:]):
(-[WKWebViewConfiguration copyWithZone:]):
(-[WKWebViewConfiguration _shouldDecidePolicyBeforeLoadingQuickLookPreview]):
(-[WKWebViewConfiguration _setShouldDecidePolicyBeforeLoadingQuickLookPreview:]):

  • UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h:
  • UIProcess/Cocoa/VersionChecks.h:
  • WebProcess/WebCoreSupport/ios/WebPreviewLoaderClient.cpp:

(WebKit::WebPreviewLoaderClient::didReceiveDataArray):

Source/WTF:

  • wtf/NeverDestroyed.h:

(WTF::NeverDestroyed::operator->):
(WTF::NeverDestroyed::operator-> const):

Tools:

Enhanced API test coverage to include all navigation response policy decisions in both
linked-before and linked-on-or-after modes. Also added new expectations for all tests.

  • TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
  • TestWebKitAPI/Tests/WebCore/ios/PreviewConverter.cpp: Renamed from Tools/TestWebKitAPI/Tests/WebCore/ios/PreviewLoader.cpp.

(TestWebKitAPI::TEST):

  • TestWebKitAPI/Tests/WebKitCocoa/QuickLook.mm:

(readFile):
(-[QuickLookDelegate initWithExpectedFileURL:responsePolicy:]):
(-[QuickLookDelegate initWithExpectedFileURL:previewMIMEType:responsePolicy:]):
(-[QuickLookDelegate webView:decidePolicyForNavigationResponse:decisionHandler:]):
(-[QuickLookDelegate _webView:didStartLoadForQuickLookDocumentInMainFrameWithFileName:uti:]):
(-[QuickLookDelegate _webView:didFinishLoadForQuickLookDocumentInMainFrame:]):
(-[QuickLookDelegate webView:didFailProvisionalNavigation:withError:]):
(-[QuickLookDelegate _webViewWebProcessDidCrash:]):
(-[QuickLookDelegate _downloadDidStart:]):
(-[QuickLookDelegate _download:didReceiveResponse:]):
(-[QuickLookDelegate _download:didReceiveData:]):
(-[QuickLookDelegate _download:decideDestinationWithSuggestedFilename:completionHandler:]):
(-[QuickLookDelegate _downloadDidFinish:]):
(-[QuickLookDelegate _download:didFailWithError:]):
(-[QuickLookDelegate _downloadDidCancel:]):
(-[QuickLookDelegate verifyDownload]):
(runTest):
(runTestDecideBeforeLoading):
(runTestDecideAfterLoading):
(TEST):
(-[QuickLookAsyncDelegate webView:decidePolicyForNavigationResponse:decisionHandler:]):
(-[QuickLookPasswordDelegate _webViewDidRequestPasswordForQuickLookDocument:]):
(-[QuickLookFrameLoadDelegate webView:didFinishLoadForFrame:]):
(-[QuickLookNavigationDelegate _webView:didStartLoadForQuickLookDocumentInMainFrameWithFileName:uti:]): Deleted.
(-[QuickLookNavigationDelegate _webView:didFinishLoadForQuickLookDocumentInMainFrame:]): Deleted.
(-[QuickLookNavigationDelegate webView:didFinishNavigation:]): Deleted.
(-[QuickLookAsyncNavigationDelegate webView:decidePolicyForNavigationResponse:decisionHandler:]): Deleted.
(-[QuickLookAsyncNavigationDelegate _webView:didStartLoadForQuickLookDocumentInMainFrameWithFileName:uti:]): Deleted.
(-[QuickLookAsyncNavigationDelegate _webView:didFinishLoadForQuickLookDocumentInMainFrame:]): Deleted.
(-[QuickLookAsyncNavigationDelegate webView:didFinishNavigation:]): Deleted.
(-[QuickLookDecidePolicyDelegate webView:decidePolicyForNavigationResponse:decisionHandler:]): Deleted.
(-[QuickLookDecidePolicyDelegate webView:didFailProvisionalNavigation:withError:]): Deleted.
(-[QuickLookDecidePolicyDelegate _webViewWebProcessDidCrash:]): Deleted.
(-[QuickLookPasswordNavigationDelegate _webViewDidRequestPasswordForQuickLookDocument:]): Deleted.

Location:
trunk
Files:
24 edited
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r243641 r243682  
     12019-03-31  Andy Estes  <aestes@apple.com>
     2
     3        [iOS] WebKit should consult the navigation response policy delegate before previewing a QuickLook document
     4        https://bugs.webkit.org/show_bug.cgi?id=196433
     5        <rdar://problem/49293305>
     6
     7        Reviewed by Tim Horton.
     8
     9        * wtf/NeverDestroyed.h:
     10        (WTF::NeverDestroyed::operator->):
     11        (WTF::NeverDestroyed::operator-> const):
     12
    1132019-03-28  Fujii Hironori  <Hironori.Fujii@sony.com>
    214
  • trunk/Source/WTF/wtf/NeverDestroyed.h

    r242116 r243682  
    11/*
    2  * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    6161    T& get() { return *storagePointer(); }
    6262
     63    T* operator->() { return storagePointer(); }
     64
    6365    operator const T&() const { return *storagePointer(); }
    6466    const T& get() const { return *storagePointer(); }
     67
     68    const T* operator->() const { return storagePointer(); }
    6569
    6670private:
  • trunk/Source/WebCore/ChangeLog

    r243681 r243682  
     12019-03-31  Andy Estes  <aestes@apple.com>
     2
     3        [iOS] WebKit should consult the navigation response policy delegate before previewing a QuickLook document
     4        https://bugs.webkit.org/show_bug.cgi?id=196433
     5        <rdar://problem/49293305>
     6
     7        Reviewed by Tim Horton.
     8
     9        When ResourceLoader would encounter a response with a MIME type that QuickLook supports, the
     10        response would be implicitly allowed and a QuickLook preview would be generated. After
     11        generating, the client's navigation response policy delegate would be notified of the
     12        preview response, but not the underlying response. Notably, the preview response has a URL
     13        scheme of "x-apple-ql-id", does not include any underlying HTTP headers, and usually has a
     14        MIME type of "text/html" or "application/pdf" rather than the underlying response MIME type.
     15
     16        To allow clients to make better navigation response policy decisions, this patch changes the
     17        above behavior for WKWebView clients that have linked against a version of WebKit that
     18        includes this change. Rather than notifying the client's navigation response policy delegate
     19        of the preview response, we notify the client of the underlying response. Only if the client
     20        responds with a policy of "allow" will the QuickLook preview response be loaded (without
     21        another call to the navigation response policy delegate).
     22
     23        Non-WKWebView clients and clients that have linked against a version of WebKit that does not
     24        include this change will retain the original behavior.
     25
     26        Covered by existing layout tests and new and existing API tests.
     27
     28        * WebCore.xcodeproj/project.pbxproj:
     29        * loader/SubresourceLoader.cpp:
     30        (WebCore::SubresourceLoader::shouldCreatePreviewLoaderForResponse const):
     31        (WebCore::SubresourceLoader::didReceiveResponse):
     32        * loader/ios/PreviewLoader.h:
     33        * loader/ios/PreviewLoader.mm:
     34        (-[WebPreviewLoader initWithResourceLoader:resourceResponse:]):
     35        (-[WebPreviewLoader _loadPreviewIfNeeded]):
     36        (-[WebPreviewLoader connection:didReceiveData:lengthReceived:]):
     37        (-[WebPreviewLoader connectionDidFinishLoading:]):
     38        (-[WebPreviewLoader connection:didFailWithError:]):
     39        (WebCore::PreviewLoader::create):
     40        (WebCore::PreviewLoader::didReceiveResponse):
     41        (-[WebPreviewLoader _sendDidReceiveResponseIfNecessary]): Deleted.
     42        (WebCore::PreviewLoader::shouldCreateForMIMEType): Deleted.
     43        * page/Settings.yaml:
     44        * platform/MIMETypeRegistry.cpp:
     45        (WebCore::MIMETypeRegistry::canShowMIMEType):
     46        * platform/network/ios/PreviewConverter.h:
     47        * platform/network/ios/PreviewConverter.mm:
     48        (WebCore::PreviewConverter::supportsMIMEType):
     49
    1502019-03-29  Dean Jackson  <dino@apple.com>
    251
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r243666 r243682  
    30093009                A1BF6B821AA96C7D00AF4A8A /* MockContentFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1BF6B801AA96C7D00AF4A8A /* MockContentFilter.cpp */; };
    30103010                A1BF6B831AA96C7D00AF4A8A /* MockContentFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = A1BF6B811AA96C7D00AF4A8A /* MockContentFilter.h */; };
    3011                 A1C1507A1E3F2B3E0032C98C /* PreviewConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = A1C150781E3F2B3E0032C98C /* PreviewConverter.h */; };
     3011                A1C1507A1E3F2B3E0032C98C /* PreviewConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = A1C150781E3F2B3E0032C98C /* PreviewConverter.h */; settings = {ATTRIBUTES = (Private, ); }; };
    30123012                A1CBEF641F9F11290028DE7C /* MockPaymentMethod.h in Headers */ = {isa = PBXBuildFile; fileRef = A1CBEF631F9F11290028DE7C /* MockPaymentMethod.h */; };
    30133013                A1CC56671F46147A00A4555B /* JSPaymentAddress.h in Headers */ = {isa = PBXBuildFile; fileRef = A1CC56651F46146800A4555B /* JSPaymentAddress.h */; };
  • trunk/Source/WebCore/loader/SubresourceLoader.cpp

    r239749 r243682  
    11/*
    2  * Copyright (C) 2006-2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2006-2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    6464
    6565#if USE(QUICK_LOOK)
     66#include "PreviewConverter.h"
    6667#include "PreviewLoader.h"
    6768#endif
     
    305306        return false;
    306307
    307     return PreviewLoader::shouldCreateForMIMEType(response.mimeType());
     308    return PreviewConverter::supportsMIMEType(response.mimeType());
    308309}
    309310
     
    320321    if (shouldCreatePreviewLoaderForResponse(response)) {
    321322        m_previewLoader = PreviewLoader::create(*this, response);
    322         return;
     323        if (m_previewLoader->didReceiveResponse(response))
     324            return;
    323325    }
    324326#endif
  • trunk/Source/WebCore/loader/ios/PreviewLoader.h

    r220722 r243682  
    11/*
    2  * Copyright (C) 2009-2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2009-2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    4242    WTF_MAKE_NONCOPYABLE(PreviewLoader);
    4343public:
    44     WEBCORE_EXPORT static bool shouldCreateForMIMEType(const String&);
    4544    static std::unique_ptr<PreviewLoader> create(ResourceLoader&, const ResourceResponse&);
    4645    ~PreviewLoader();
    4746
     47    bool didReceiveResponse(const ResourceResponse&);
    4848    bool didReceiveData(const char* data, unsigned length);
    4949    bool didReceiveBuffer(const SharedBuffer&);
  • trunk/Source/WebCore/loader/ios/PreviewLoader.mm

    r243471 r243682  
    11/*
    2  * Copyright (C) 2009-2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2009-2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3030
    3131#import "DocumentLoader.h"
     32#import "Frame.h"
    3233#import "FrameLoader.h"
    3334#import "FrameLoaderClient.h"
     
    3738#import "QuickLook.h"
    3839#import "ResourceLoader.h"
     40#import "Settings.h"
    3941#import <pal/spi/ios/QuickLookSPI.h>
    4042#import <wtf/NeverDestroyed.h>
     
    4850    std::unique_ptr<PreviewConverter> _converter;
    4951    RetainPtr<NSMutableArray> _bufferedDataArray;
    50     BOOL _hasSentDidReceiveResponse;
     52    BOOL _hasLoadedPreview;
    5153    BOOL _hasProcessedResponse;
    5254    RefPtr<SharedBuffer> _bufferedData;
     
    6062- (void)failed;
    6163
     64@property (nonatomic, readonly) BOOL shouldDecidePolicyBeforeLoading;
     65
    6266@end
    6367
     
    7882- (instancetype)initWithResourceLoader:(ResourceLoader&)resourceLoader resourceResponse:(const ResourceResponse&)resourceResponse
    7983{
    80     self = [super init];
    81     if (!self)
     84    if (!(self = [super init]))
    8285        return nil;
    8386
     
    8689    _converter = std::make_unique<PreviewConverter>(self, _response);
    8790    _bufferedDataArray = adoptNS([[NSMutableArray alloc] init]);
     91    _shouldDecidePolicyBeforeLoading = resourceLoader.frame()->settings().shouldDecidePolicyBeforeLoadingQuickLookPreview();
    8892
    8993    if (testingClient())
     
    120124}
    121125
    122 - (void)_sendDidReceiveResponseIfNecessary
     126- (void)_loadPreviewIfNeeded
    123127{
    124128    if (!_resourceLoader)
     
    126130
    127131    ASSERT(!_resourceLoader->reachedTerminalState());
    128     if (_hasSentDidReceiveResponse)
    129         return;
    130 
     132    if (_hasLoadedPreview)
     133        return;
     134
     135    _hasLoadedPreview = YES;
    131136    [_bufferedDataArray removeAllObjects];
    132137
     
    137142    _resourceLoader->documentLoader()->setPreviewConverter(WTFMove(_converter));
    138143
    139     _hasSentDidReceiveResponse = YES;
     144    if (_shouldDecidePolicyBeforeLoading) {
     145        _hasProcessedResponse = YES;
     146        _resourceLoader->documentLoader()->setResponse(response);
     147        return;
     148    }
     149
    140150    _hasProcessedResponse = NO;
    141151    _resourceLoader->didReceiveResponse(response, [self, retainedSelf = retainPtr(self)] {
     
    171181    if (_resourceLoader->reachedTerminalState())
    172182        return;
    173    
    174     [self _sendDidReceiveResponseIfNecessary];
     183
     184    [self _loadPreviewIfNeeded];
    175185
    176186    auto dataLength = data.length;
     
    202212        return;
    203213   
    204     ASSERT(_hasSentDidReceiveResponse);
     214    ASSERT(_hasLoadedPreview);
    205215
    206216    if (!_hasProcessedResponse) {
     
    227237
    228238    if (!isQuickLookPasswordError(error)) {
    229         [self _sendDidReceiveResponseIfNecessary];
    230239        _resourceLoader->didFail(error);
    231240        return;
     
    257266}
    258267
    259 bool PreviewLoader::shouldCreateForMIMEType(const String& mimeType)
    260 {
    261     if (equalLettersIgnoringASCIICase(mimeType, "text/html") || equalLettersIgnoringASCIICase(mimeType, "text/plain"))
    262         return false;
    263 
    264     static std::once_flag onceFlag;
    265     static NeverDestroyed<HashSet<String, ASCIICaseInsensitiveHash>> supportedMIMETypes;
    266     std::call_once(onceFlag, [] {
    267         for (NSString *mimeType in QLPreviewGetSupportedMIMETypesSet())
    268             supportedMIMETypes.get().add(mimeType);
    269     });
    270 
    271     if (mimeType.isNull())
    272         return false;
    273 
    274     return supportedMIMETypes.get().contains(mimeType);
    275 }
    276 
    277268std::unique_ptr<PreviewLoader> PreviewLoader::create(ResourceLoader& loader, const ResourceResponse& response)
    278269{
    279     ASSERT(shouldCreateForMIMEType(response.mimeType()));
     270    ASSERT(PreviewConverter::supportsMIMEType(response.mimeType()));
    280271    return std::make_unique<PreviewLoader>(loader, response);
     272}
     273
     274bool PreviewLoader::didReceiveResponse(const ResourceResponse&)
     275{
     276    return ![m_previewLoader shouldDecidePolicyBeforeLoading];
    281277}
    282278
  • trunk/Source/WebCore/page/Settings.yaml

    r243643 r243682  
    828828  initial: true
    829829
     830shouldDecidePolicyBeforeLoadingQuickLookPreview:
     831  initial: false
     832
    830833# Deprecated
    831834
  • trunk/Source/WebCore/platform/MIMETypeRegistry.cpp

    r240428 r243682  
    11/*
    2  * Copyright (C) 2006-2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2006-2019 Apple Inc. All rights reserved.
    33 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
    44 *
     
    5252#include "ContentType.h"
    5353#include "ImageDecoderAVFObjC.h"
     54#endif
     55
     56#if USE(QUICK_LOOK)
     57#include "PreviewConverter.h"
    5458#endif
    5559
     
    643647    if (isSupportedJavaScriptMIMEType(mimeType) || isSupportedJSONMIMEType(mimeType))
    644648        return true;
     649
     650#if USE(QUICK_LOOK)
     651    if (PreviewConverter::supportsMIMEType(mimeType))
     652        return true;
     653#endif
    645654
    646655    if (startsWithLettersIgnoringASCIICase(mimeType, "text/"))
  • trunk/Source/WebCore/platform/network/ios/PreviewConverter.h

    r211398 r243682  
    4242    PreviewConverter(NSData *, const String& uti, const String& password = { });
    4343
     44    WEBCORE_EXPORT static bool supportsMIMEType(const String& mimeType);
     45
    4446    QLPreviewConverter *platformConverter() const { return m_platformConverter.get(); }
    4547    ResourceRequest safeRequest(const ResourceRequest&) const;
  • trunk/Source/WebCore/platform/network/ios/PreviewConverter.mm

    r240272 r243682  
    11/*
    2  * Copyright (C) 2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2929#if USE(QUICK_LOOK)
    3030
     31#import "QuickLook.h"
    3132#import "ResourceRequest.h"
    3233#import "ResourceResponse.h"
     
    5253    : m_platformConverter { adoptNS([PAL::allocQLPreviewConverterInstance() initWithData:data name:nil uti:uti options:optionsWithPassword(password)]) }
    5354{
     55}
     56
     57bool PreviewConverter::supportsMIMEType(const String& mimeType)
     58{
     59    if (equalLettersIgnoringASCIICase(mimeType, "text/html") || equalLettersIgnoringASCIICase(mimeType, "text/plain"))
     60        return false;
     61
     62    static std::once_flag onceFlag;
     63    static NeverDestroyed<HashSet<String, ASCIICaseInsensitiveHash>> supportedMIMETypes;
     64    std::call_once(onceFlag, [] {
     65        for (NSString *mimeType in QLPreviewGetSupportedMIMETypesSet())
     66            supportedMIMETypes->add(mimeType);
     67    });
     68
     69    if (mimeType.isNull())
     70        return false;
     71
     72    return supportedMIMETypes->contains(mimeType);
    5473}
    5574
  • trunk/Source/WebKit/ChangeLog

    r243677 r243682  
     12019-03-31  Andy Estes  <aestes@apple.com>
     2
     3        [iOS] WebKit should consult the navigation response policy delegate before previewing a QuickLook document
     4        https://bugs.webkit.org/show_bug.cgi?id=196433
     5        <rdar://problem/49293305>
     6
     7        Reviewed by Tim Horton.
     8
     9        Added WKWebViewConfiguration SPI for setting the QuickLook navigation response policy
     10        decision behavior. The configuration setting defaults to YES for clients linked on or after
     11        this WebKit change and NO otherwise.
     12
     13        * NetworkProcess/NetworkResourceLoader.cpp:
     14        (WebKit::NetworkResourceLoader::shouldInterruptLoadForCSPFrameAncestorsOrXFrameOptions):
     15        * Shared/WebPreferences.yaml:
     16        * Shared/ios/QuickLookDocumentData.cpp:
     17        (WebKit::QuickLookDocumentData::isEmpty const):
     18        * Shared/ios/QuickLookDocumentData.h:
     19        * UIProcess/API/Cocoa/WKWebView.mm:
     20        (-[WKWebView _initializeWithConfiguration:]):
     21        * UIProcess/API/Cocoa/WKWebViewConfiguration.mm:
     22        (defaultShouldDecidePolicyBeforeLoadingQuickLookPreview):
     23        (-[WKWebViewConfiguration init]):
     24        (-[WKWebViewConfiguration encodeWithCoder:]):
     25        (-[WKWebViewConfiguration initWithCoder:]):
     26        (-[WKWebViewConfiguration copyWithZone:]):
     27        (-[WKWebViewConfiguration _shouldDecidePolicyBeforeLoadingQuickLookPreview]):
     28        (-[WKWebViewConfiguration _setShouldDecidePolicyBeforeLoadingQuickLookPreview:]):
     29        * UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h:
     30        * UIProcess/Cocoa/VersionChecks.h:
     31        * WebProcess/WebCoreSupport/ios/WebPreviewLoaderClient.cpp:
     32        (WebKit::WebPreviewLoaderClient::didReceiveDataArray):
     33
    1342019-03-30  Zalan Bujtas  <zalan@apple.com>
    235
  • trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp

    r242056 r243682  
    5656
    5757#if USE(QUICK_LOOK)
    58 #include <WebCore/PreviewLoader.h>
     58#include <WebCore/PreviewConverter.h>
    5959#endif
    6060
     
    387387
    388388#if USE(QUICK_LOOK)
    389     if (PreviewLoader::shouldCreateForMIMEType(response.mimeType()))
     389    if (PreviewConverter::supportsMIMEType(response.mimeType()))
    390390        return false;
    391391#endif
  • trunk/Source/WebKit/Shared/WebPreferences.yaml

    r243666 r243682  
    11931193  defaultValue: false
    11941194
     1195ShouldDecidePolicyBeforeLoadingQuickLookPreview:
     1196  defaultValue: false
     1197  type: bool
     1198
    11951199# For experimental features:
    11961200# The type should be boolean.
  • trunk/Source/WebKit/Shared/ios/QuickLookDocumentData.cpp

    r204668 r243682  
    4747}
    4848
     49bool QuickLookDocumentData::isEmpty() const
     50{
     51    return m_data.isEmpty();
     52}
     53
    4954void QuickLookDocumentData::clear()
    5055{
  • trunk/Source/WebKit/Shared/ios/QuickLookDocumentData.h

    r204668 r243682  
    4141    void append(CFDataRef);
    4242    CFDataRef decodedData() const;
     43    bool isEmpty() const;
    4344    void clear();
    4445    void encode(IPC::Encoder&) const;
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm

    r243630 r243682  
    627627    pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::systemLayoutDirectionKey(), WebKit::WebPreferencesStore::Value(static_cast<uint32_t>(WebCore::TextDirection::LTR)));
    628628    pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::allowSettingAnyXHRHeaderFromFileURLsKey(), WebKit::WebPreferencesStore::Value(shouldAllowSettingAnyXHRHeaderFromFileURLs()));
     629    pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::shouldDecidePolicyBeforeLoadingQuickLookPreviewKey(), WebKit::WebPreferencesStore::Value(!![_configuration _shouldDecidePolicyBeforeLoadingQuickLookPreview]));
    629630#if USE(SYSTEM_PREVIEW)
    630631    pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::systemPreviewEnabledKey(), WebKit::WebPreferencesStore::Value(!![_configuration _systemPreviewEnabled]));
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfiguration.mm

    r243324 r243682  
    100100}
    101101
     102static bool defaultShouldDecidePolicyBeforeLoadingQuickLookPreview()
     103{
     104#if USE(QUICK_LOOK)
     105    static bool shouldDecide = linkedOnOrAfter(WebKit::SDKVersion::FirstThatDecidesPolicyBeforeLoadingQuickLookPreview);
     106    return shouldDecide;
     107#else
     108    return false;
     109#endif
     110}
     111
    102112#endif
    103113
     
    130140    BOOL _longPressActionsEnabled;
    131141    BOOL _systemPreviewEnabled;
     142    BOOL _shouldDecidePolicyBeforeLoadingQuickLookPreview;
    132143#endif
    133144
     
    237248#endif
    238249    _systemPreviewEnabled = NO;
     250    _shouldDecidePolicyBeforeLoadingQuickLookPreview = defaultShouldDecidePolicyBeforeLoadingQuickLookPreview();
    239251#endif // PLATFORM(IOS_FAMILY)
    240252
     
    292304    [coder encodeBool:self._longPressActionsEnabled forKey:@"longPressActionsEnabled"];
    293305    [coder encodeBool:self._systemPreviewEnabled forKey:@"systemPreviewEnabled"];
     306    [coder encodeBool:self._shouldDecidePolicyBeforeLoadingQuickLookPreview forKey:@"shouldDecidePolicyBeforeLoadingQuickLookPreview"];
    294307#else
    295308    [coder encodeInteger:self.userInterfaceDirectionPolicy forKey:@"userInterfaceDirectionPolicy"];
     
    326339    self._longPressActionsEnabled = [coder decodeBoolForKey:@"longPressActionsEnabled"];
    327340    self._systemPreviewEnabled = [coder decodeBoolForKey:@"systemPreviewEnabled"];
     341    self._shouldDecidePolicyBeforeLoadingQuickLookPreview = [coder decodeBoolForKey:@"shouldDecidePolicyBeforeLoadingQuickLookPreview"];
    328342#else
    329343    auto userInterfaceDirectionPolicyCandidate = static_cast<WKUserInterfaceDirectionPolicy>([coder decodeIntegerForKey:@"userInterfaceDirectionPolicy"]);
     
    382396    configuration->_longPressActionsEnabled = self->_longPressActionsEnabled;
    383397    configuration->_systemPreviewEnabled = self->_systemPreviewEnabled;
     398    configuration->_shouldDecidePolicyBeforeLoadingQuickLookPreview = self->_shouldDecidePolicyBeforeLoadingQuickLookPreview;
    384399#endif
    385400#if PLATFORM(MAC)
     
    733748}
    734749
     750- (BOOL)_shouldDecidePolicyBeforeLoadingQuickLookPreview
     751{
     752    return _shouldDecidePolicyBeforeLoadingQuickLookPreview;
     753}
     754
     755- (void)_setShouldDecidePolicyBeforeLoadingQuickLookPreview:(BOOL)shouldDecide
     756{
     757    _shouldDecidePolicyBeforeLoadingQuickLookPreview = shouldDecide;
     758}
     759
    735760#endif // PLATFORM(IOS_FAMILY)
    736761
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h

    r243376 r243682  
    8383@property (nonatomic, setter=_setLongPressActionsEnabled:) BOOL _longPressActionsEnabled WK_API_AVAILABLE(ios(12.0));
    8484@property (nonatomic, setter=_setSystemPreviewEnabled:) BOOL _systemPreviewEnabled WK_API_AVAILABLE(ios(12.0));
     85@property (nonatomic, setter=_setShouldDecidePolicyBeforeLoadingQuickLookPreview:) BOOL _shouldDecidePolicyBeforeLoadingQuickLookPreview WK_API_AVAILABLE(ios(WK_IOS_TBA));
    8586#else
    8687@property (nonatomic, setter=_setShowsURLsInToolTips:) BOOL _showsURLsInToolTips WK_API_AVAILABLE(macos(10.12));
  • trunk/Source/WebKit/UIProcess/Cocoa/VersionChecks.h

    r242664 r243682  
    3535#define DYLD_IOS_VERSION_FIRST_WITH_SNAPSHOT_AFTER_SCREEN_UPDATES 0
    3636#define DYLD_IOS_VERSION_FIRST_WHERE_DOWNLOAD_ATTRIBUTE_DOES_NOT_OVERRIDE_NAVIGATION_DELEGATE 0
     37#define DYLD_IOS_VERSION_FIRST_THAT_DECIDES_POLICY_BEFORE_LOADING_QUICK_LOOK_PREVIEW 0
    3738#define DYLD_MACOS_VERSION_FIRST_WITH_SNAPSHOT_AFTER_SCREEN_UPDATES 0
    3839#define DYLD_MACOS_VERSION_FIRST_WHERE_DOWNLOAD_ATTRIBUTE_DOES_NOT_OVERRIDE_NAVIGATION_DELEGATE 0
     
    6263    FirstWhereDownloadAttributeDoesNotOverrideNavigationDelegate = DYLD_IOS_VERSION_FIRST_WHERE_DOWNLOAD_ATTRIBUTE_DOES_NOT_OVERRIDE_NAVIGATION_DELEGATE,
    6364    FirstWithDeviceOrientationAndMotionPermissionAPI = DYLD_IOS_VERSION_FIRST_WITH_DEVICE_ORIENTATION_AND_MOTION_PERMISSION_API,
     65    FirstThatDecidesPolicyBeforeLoadingQuickLookPreview = DYLD_IOS_VERSION_FIRST_THAT_DECIDES_POLICY_BEFORE_LOADING_QUICK_LOOK_PREVIEW,
    6466#elif PLATFORM(MAC)
    6567    FirstWithNetworkCache = DYLD_MACOSX_VERSION_10_11,
  • trunk/Source/WebKit/WebProcess/WebCoreSupport/ios/WebPreviewLoaderClient.cpp

    r214266 r243682  
    5050    , m_pageID { pageID }
    5151{
    52     WebProcess::singleton().send(Messages::WebPageProxy::DidStartLoadForQuickLookDocumentInMainFrame(m_fileName, m_uti), m_pageID);
    5352}
    5453
     
    6059void WebPreviewLoaderClient::didReceiveDataArray(CFArrayRef dataArray)
    6160{
     61    if (m_data.isEmpty())
     62        WebProcess::singleton().send(Messages::WebPageProxy::DidStartLoadForQuickLookDocumentInMainFrame(m_fileName, m_uti), m_pageID);
     63
    6264    CFArrayApplyFunction(dataArray, CFRangeMake(0, CFArrayGetCount(dataArray)), [](const void* value, void* context) {
    6365        ASSERT(CFGetTypeID(value) == CFDataGetTypeID());
  • trunk/Tools/ChangeLog

    r243676 r243682  
     12019-03-31  Andy Estes  <aestes@apple.com>
     2
     3        [iOS] WebKit should consult the navigation response policy delegate before previewing a QuickLook document
     4        https://bugs.webkit.org/show_bug.cgi?id=196433
     5        <rdar://problem/49293305>
     6
     7        Reviewed by Tim Horton.
     8
     9        Enhanced API test coverage to include all navigation response policy decisions in both
     10        linked-before and linked-on-or-after modes. Also added new expectations for all tests.
     11
     12        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
     13        * TestWebKitAPI/Tests/WebCore/ios/PreviewConverter.cpp: Renamed from Tools/TestWebKitAPI/Tests/WebCore/ios/PreviewLoader.cpp.
     14        (TestWebKitAPI::TEST):
     15        * TestWebKitAPI/Tests/WebKitCocoa/QuickLook.mm:
     16        (readFile):
     17        (-[QuickLookDelegate initWithExpectedFileURL:responsePolicy:]):
     18        (-[QuickLookDelegate initWithExpectedFileURL:previewMIMEType:responsePolicy:]):
     19        (-[QuickLookDelegate webView:decidePolicyForNavigationResponse:decisionHandler:]):
     20        (-[QuickLookDelegate _webView:didStartLoadForQuickLookDocumentInMainFrameWithFileName:uti:]):
     21        (-[QuickLookDelegate _webView:didFinishLoadForQuickLookDocumentInMainFrame:]):
     22        (-[QuickLookDelegate webView:didFailProvisionalNavigation:withError:]):
     23        (-[QuickLookDelegate _webViewWebProcessDidCrash:]):
     24        (-[QuickLookDelegate _downloadDidStart:]):
     25        (-[QuickLookDelegate _download:didReceiveResponse:]):
     26        (-[QuickLookDelegate _download:didReceiveData:]):
     27        (-[QuickLookDelegate _download:decideDestinationWithSuggestedFilename:completionHandler:]):
     28        (-[QuickLookDelegate _downloadDidFinish:]):
     29        (-[QuickLookDelegate _download:didFailWithError:]):
     30        (-[QuickLookDelegate _downloadDidCancel:]):
     31        (-[QuickLookDelegate verifyDownload]):
     32        (runTest):
     33        (runTestDecideBeforeLoading):
     34        (runTestDecideAfterLoading):
     35        (TEST):
     36        (-[QuickLookAsyncDelegate webView:decidePolicyForNavigationResponse:decisionHandler:]):
     37        (-[QuickLookPasswordDelegate _webViewDidRequestPasswordForQuickLookDocument:]):
     38        (-[QuickLookFrameLoadDelegate webView:didFinishLoadForFrame:]):
     39        (-[QuickLookNavigationDelegate _webView:didStartLoadForQuickLookDocumentInMainFrameWithFileName:uti:]): Deleted.
     40        (-[QuickLookNavigationDelegate _webView:didFinishLoadForQuickLookDocumentInMainFrame:]): Deleted.
     41        (-[QuickLookNavigationDelegate webView:didFinishNavigation:]): Deleted.
     42        (-[QuickLookAsyncNavigationDelegate webView:decidePolicyForNavigationResponse:decisionHandler:]): Deleted.
     43        (-[QuickLookAsyncNavigationDelegate _webView:didStartLoadForQuickLookDocumentInMainFrameWithFileName:uti:]): Deleted.
     44        (-[QuickLookAsyncNavigationDelegate _webView:didFinishLoadForQuickLookDocumentInMainFrame:]): Deleted.
     45        (-[QuickLookAsyncNavigationDelegate webView:didFinishNavigation:]): Deleted.
     46        (-[QuickLookDecidePolicyDelegate webView:decidePolicyForNavigationResponse:decisionHandler:]): Deleted.
     47        (-[QuickLookDecidePolicyDelegate webView:didFailProvisionalNavigation:withError:]): Deleted.
     48        (-[QuickLookDecidePolicyDelegate _webViewWebProcessDidCrash:]): Deleted.
     49        (-[QuickLookPasswordNavigationDelegate _webViewDidRequestPasswordForQuickLookDocument:]): Deleted.
     50
    1512019-03-30  Dominik Infuehr  <dinfuehr@igalia.com>
    252
  • trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj

    r243666 r243682  
    713713                A1C4FB731BACD1CA003742D0 /* pages.pages in Copy Resources */ = {isa = PBXBuildFile; fileRef = A1C4FB721BACD1B7003742D0 /* pages.pages */; };
    714714                A1DF74321C41B65800A2F4D0 /* AlwaysRevalidatedURLSchemes.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1DF74301C41B65800A2F4D0 /* AlwaysRevalidatedURLSchemes.mm */; };
    715                 A1EC11881F42541200D0146E /* PreviewLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1EC11871F42541200D0146E /* PreviewLoader.cpp */; };
     715                A1EC11881F42541200D0146E /* PreviewConverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1EC11871F42541200D0146E /* PreviewConverter.cpp */; };
    716716                A310827221F296FF00C28B97 /* FileSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A310827121F296EC00C28B97 /* FileSystem.cpp */; };
    717717                A57A34F216AF6B2B00C2501F /* PageVisibilityStateWithWindowChanges.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = A57A34F116AF69E200C2501F /* PageVisibilityStateWithWindowChanges.html */; };
     
    19791979                A1C4FB721BACD1B7003742D0 /* pages.pages */ = {isa = PBXFileReference; lastKnownFileType = file; name = pages.pages; path = ios/pages.pages; sourceTree = SOURCE_ROOT; };
    19801980                A1DF74301C41B65800A2F4D0 /* AlwaysRevalidatedURLSchemes.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AlwaysRevalidatedURLSchemes.mm; sourceTree = "<group>"; };
    1981                 A1EC11871F42541200D0146E /* PreviewLoader.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PreviewLoader.cpp; sourceTree = "<group>"; };
     1981                A1EC11871F42541200D0146E /* PreviewConverter.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PreviewConverter.cpp; sourceTree = "<group>"; };
    19821982                A1FDFD2E19C288BB005148A4 /* WKImageCreateCGImageCrash.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKImageCreateCGImageCrash.cpp; sourceTree = "<group>"; };
    19831983                A310827121F296EC00C28B97 /* FileSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileSystem.cpp; sourceTree = "<group>"; };
     
    30643064                        isa = PBXGroup;
    30653065                        children = (
    3066                                 A1EC11871F42541200D0146E /* PreviewLoader.cpp */,
     3066                                A1EC11871F42541200D0146E /* PreviewConverter.cpp */,
    30673067                        );
    30683068                        path = ios;
     
    42474247                                7CCE7F0B1A411AE600447C4C /* PreventEmptyUserAgent.cpp in Sources */,
    42484248                                7CCE7F2C1A411B1000447C4C /* PreventImageLoadWithAutoResizing.mm in Sources */,
    4249                                 A1EC11881F42541200D0146E /* PreviewLoader.cpp in Sources */,
     4249                                A1EC11881F42541200D0146E /* PreviewConverter.cpp in Sources */,
    42504250                                7CCE7F0C1A411AE600447C4C /* PrivateBrowsingPushStateNoHistoryCallback.cpp in Sources */,
    42514251                                4647B1261EBA3B850041D7EF /* ProcessDidTerminate.cpp in Sources */,
  • trunk/Tools/TestWebKitAPI/Tests/WebCore/ios/PreviewConverter.cpp

    r243681 r243682  
    11/*
    2  * Copyright (C) 2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2828#if PLATFORM(IOS_FAMILY) && USE(QUICK_LOOK)
    2929
    30 #include <WebCore/PreviewLoader.h>
     30#include <WebCore/PreviewConverter.h>
    3131#include <wtf/text/WTFString.h>
    3232
     
    3535namespace TestWebKitAPI {
    3636
    37 TEST(QuickLook, ShouldCreateForMIMEType)
     37TEST(QuickLook, SupportsMIMEType)
    3838{
    3939    // FIXME: Expand this to cover all the MIME types we expect to support.
    40     EXPECT_FALSE(PreviewLoader::shouldCreateForMIMEType(String()));
    41     EXPECT_FALSE(PreviewLoader::shouldCreateForMIMEType(emptyString()));
    42     EXPECT_TRUE(PreviewLoader::shouldCreateForMIMEType("application/vnd.ms-excel.sheet.macroEnabled.12"_s));
     40    EXPECT_FALSE(PreviewConverter::supportsMIMEType(String()));
     41    EXPECT_FALSE(PreviewConverter::supportsMIMEType(emptyString()));
     42    EXPECT_FALSE(PreviewConverter::supportsMIMEType("text/html"_s));
     43    EXPECT_FALSE(PreviewConverter::supportsMIMEType("text/plain"_s));
     44    EXPECT_TRUE(PreviewConverter::supportsMIMEType("application/vnd.ms-excel.sheet.macroEnabled.12"_s));
    4345}
    4446
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/QuickLook.mm

    r237266 r243682  
    11/*
    2  * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2015-2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3030#import "PlatformUtilities.h"
    3131#import "Test.h"
     32#import <CoreServices/CoreServices.h>
    3233#import <WebCore/WebCoreThread.h>
    3334#import <WebKit/WKNavigationDelegatePrivate.h>
     35#import <WebKit/WKProcessPoolPrivate.h>
     36#import <WebKit/WKWebViewConfigurationPrivate.h>
    3437#import <WebKit/WebDataSourcePrivate.h>
    3538#import <WebKit/WebKit.h>
     
    3740#import <WebKit/WebUIKitSupport.h>
    3841#import <WebKit/WebViewPrivate.h>
     42#import <WebKit/_WKDownload.h>
     43#import <WebKit/_WKDownloadDelegate.h>
    3944#import <wtf/RetainPtr.h>
    4045
     
    4247
    4348static bool isDone;
    44 static bool didStartQuickLookLoad;
    45 static bool didFinishQuickLookLoad;
    46 
    47 static const NSUInteger expectedFileSize = 274143;
    48 static NSString * const expectedFileName = @"pages.pages";
    49 static NSString * const expectedUTI = @"com.apple.iwork.pages.sffpages";
    50 static NSURLRequest * const pagesDocumentRequest = [[NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"pages" withExtension:@"pages" subdirectory:@"TestWebKitAPI.resources"]] retain];
    51 
    52 @interface QuickLookNavigationDelegate : NSObject <WKNavigationDelegatePrivate>
    53 @end
    54 
    55 @implementation QuickLookNavigationDelegate
     49static bool downloadIsDone;
     50
     51static NSString * const pagesDocumentPreviewMIMEType = @"application/pdf";
     52static NSURL * const pagesDocumentURL = [[NSBundle.mainBundle URLForResource:@"pages" withExtension:@"pages" subdirectory:@"TestWebKitAPI.resources"] retain];
     53
     54@interface QuickLookDelegate : NSObject <WKNavigationDelegatePrivate, _WKDownloadDelegate>
     55- (instancetype)init NS_UNAVAILABLE;
     56- (instancetype)initWithExpectedFileURL:(NSURL *)fileURL responsePolicy:(WKNavigationResponsePolicy)responsePolicy;
     57- (instancetype)initWithExpectedFileURL:(NSURL *)fileURL previewMIMEType:(NSString *)mimeType responsePolicy:(WKNavigationResponsePolicy)responsePolicy;
     58- (void)verifyDownload;
     59
     60@property (nonatomic) BOOL didStartQuickLookLoad;
     61@property (nonatomic) BOOL didFinishQuickLookLoad;
     62
     63@end
     64
     65@implementation QuickLookDelegate {
     66@protected
     67    NSUInteger _downloadFileSize;
     68    NSUInteger _expectedFileSize;
     69    RetainPtr<NSString> _expectedFileName;
     70    RetainPtr<NSString> _expectedFileType;
     71    RetainPtr<NSString> _expectedMIMEType;
     72    RetainPtr<NSURL> _downloadDestinationURL;
     73    WKNavigationResponsePolicy _responsePolicy;
     74}
     75
     76static void readFile(NSURL *fileURL, NSUInteger& fileSize, RetainPtr<NSString>& fileName, RetainPtr<NSString>& fileType, RetainPtr<NSString>& mimeType)
     77{
     78    if (NSDictionary *attributes = [NSFileManager.defaultManager attributesOfItemAtPath:fileURL.path error:nil])
     79        fileSize = [attributes[NSFileSize] unsignedIntegerValue];
     80
     81    fileName = fileURL.lastPathComponent;
     82
     83    NSString *typeIdentifier = nil;
     84    if ([fileURL getResourceValue:&typeIdentifier forKey:NSURLTypeIdentifierKey error:nil])
     85        fileType = typeIdentifier;
     86
     87    mimeType = adoptCF(UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)typeIdentifier, kUTTagClassMIMEType));
     88}
     89
     90- (instancetype)initWithExpectedFileURL:(NSURL *)fileURL responsePolicy:(WKNavigationResponsePolicy)responsePolicy
     91{
     92    if (!(self = [super init]))
     93        return nil;
     94
     95    readFile(fileURL, _expectedFileSize, _expectedFileName, _expectedFileType, _expectedMIMEType);
     96
     97    _responsePolicy = responsePolicy;
     98    return self;
     99}
     100
     101- (instancetype)initWithExpectedFileURL:(NSURL *)fileURL previewMIMEType:(NSString *)mimeType responsePolicy:(WKNavigationResponsePolicy)responsePolicy
     102{
     103    if (!(self = [self initWithExpectedFileURL:fileURL responsePolicy:responsePolicy]))
     104        return nil;
     105   
     106    _expectedMIMEType = mimeType;
     107    return self;
     108}
     109
     110- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
     111{
     112    EXPECT_TRUE(navigationResponse.canShowMIMEType);
     113    EXPECT_WK_STREQ(_expectedFileName.get(), navigationResponse.response.URL.lastPathComponent);
     114    EXPECT_WK_STREQ(_expectedMIMEType.get(), navigationResponse.response.MIMEType);
     115    decisionHandler(_responsePolicy);
     116}
    56117
    57118- (void)_webView:(WKWebView *)webView didStartLoadForQuickLookDocumentInMainFrameWithFileName:(NSString *)fileName uti:(NSString *)uti
    58119{
    59     EXPECT_WK_STREQ(expectedFileName, fileName);
    60     EXPECT_WK_STREQ(expectedUTI, uti);
    61     didStartQuickLookLoad = true;
     120    EXPECT_FALSE(_didFinishQuickLookLoad);
     121    EXPECT_FALSE(_didStartQuickLookLoad);
     122    EXPECT_WK_STREQ(_expectedFileName.get(), fileName);
     123    EXPECT_WK_STREQ(_expectedFileType.get(), uti);
     124    _didStartQuickLookLoad = YES;
    62125}
    63126
    64127- (void)_webView:(WKWebView *)webView didFinishLoadForQuickLookDocumentInMainFrame:(NSData *)documentData
    65128{
    66     EXPECT_EQ(expectedFileSize, documentData.length);
    67     didFinishQuickLookLoad = true;
     129    EXPECT_EQ(_expectedFileSize, documentData.length);
     130    EXPECT_FALSE(_didFinishQuickLookLoad);
     131    EXPECT_TRUE(_didStartQuickLookLoad);
     132    _didFinishQuickLookLoad = YES;
    68133}
    69134
     
    73138}
    74139
    75 @end
    76 
    77 @interface QuickLookAsyncNavigationDelegate : NSObject <WKNavigationDelegatePrivate>
    78 @end
    79 
    80 @implementation QuickLookAsyncNavigationDelegate
     140- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error
     141{
     142    isDone = true;
     143}
     144
     145- (void)_webViewWebProcessDidCrash:(WKWebView *)webView
     146{
     147    RELEASE_ASSERT_NOT_REACHED();
     148}
     149
     150- (void)_downloadDidStart:(_WKDownload *)download
     151{
     152    EXPECT_WK_STREQ(_expectedFileName.get(), download.request.URL.lastPathComponent);
     153}
     154
     155- (void)_download:(_WKDownload *)download didReceiveResponse:(NSURLResponse *)response
     156{
     157    EXPECT_WK_STREQ(_expectedFileName.get(), response.URL.lastPathComponent);
     158    EXPECT_WK_STREQ(_expectedMIMEType.get(), response.MIMEType);
     159}
     160
     161- (void)_download:(_WKDownload *)download didReceiveData:(uint64_t)length
     162{
     163    _downloadFileSize += length;
     164}
     165
     166- (void)_download:(_WKDownload *)download decideDestinationWithSuggestedFilename:(NSString *)filename completionHandler:(void (^)(BOOL, NSString *))completionHandler
     167{
     168    EXPECT_WK_STREQ(_expectedFileName.get(), filename);
     169   
     170    NSURL *tempDirectoryURL = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES];
     171    _downloadDestinationURL = [NSURL fileURLWithPath:filename relativeToURL:tempDirectoryURL];
     172    completionHandler(YES, [_downloadDestinationURL path]);
     173}
     174
     175- (void)_downloadDidFinish:(_WKDownload *)download
     176{
     177    EXPECT_EQ(_expectedFileSize, _downloadFileSize);
     178    downloadIsDone = true;
     179}
     180
     181- (void)_download:(_WKDownload *)download didFailWithError:(NSError *)error
     182{
     183    RELEASE_ASSERT_NOT_REACHED();
     184}
     185
     186- (void)_downloadDidCancel:(_WKDownload *)download
     187{
     188    RELEASE_ASSERT_NOT_REACHED();
     189}
     190
     191- (void)verifyDownload
     192{
     193    EXPECT_TRUE([NSFileManager.defaultManager fileExistsAtPath:[_downloadDestinationURL path]]);
     194
     195    NSUInteger downloadFileSize;
     196    RetainPtr<NSString> downloadFileName;
     197    RetainPtr<NSString> downloadFileType;
     198    RetainPtr<NSString> downloadMIMEType;
     199    readFile(_downloadDestinationURL.get(), downloadFileSize, downloadFileName, downloadFileType, downloadMIMEType);
     200
     201    EXPECT_EQ(_expectedFileSize, downloadFileSize);
     202    EXPECT_WK_STREQ(_expectedFileName.get(), downloadFileName.get());
     203    EXPECT_WK_STREQ(_expectedFileType.get(), downloadFileType.get());
     204    EXPECT_WK_STREQ(_expectedMIMEType.get(), downloadMIMEType.get());
     205}
     206
     207@end
     208
     209static void runTest(QuickLookDelegate *delegate, NSURLRequest *request, BOOL shouldDecidePolicyBeforeLoading)
     210{
     211    auto processPool = adoptNS([[WKProcessPool alloc] init]);
     212    [processPool _setDownloadDelegate:delegate];
     213
     214    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     215    [configuration _setShouldDecidePolicyBeforeLoadingQuickLookPreview:shouldDecidePolicyBeforeLoading];
     216    [configuration setProcessPool:processPool.get()];
     217
     218    auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration.get()]);
     219    [webView setNavigationDelegate:delegate];
     220    [webView loadRequest:request];
     221
     222    isDone = false;
     223    Util::run(&isDone);
     224}
     225
     226static void runTestDecideBeforeLoading(QuickLookDelegate *delegate, NSURLRequest *request)
     227{
     228    runTest(delegate, request, YES);
     229}
     230
     231static void runTestDecideAfterLoading(QuickLookDelegate *delegate, NSURLRequest *request)
     232{
     233    runTest(delegate, request, NO);
     234}
     235
     236TEST(QuickLook, AllowResponseBeforeLoadingPreview)
     237{
     238    auto delegate = adoptNS([[QuickLookDelegate alloc] initWithExpectedFileURL:pagesDocumentURL responsePolicy:WKNavigationResponsePolicyAllow]);
     239    runTestDecideBeforeLoading(delegate.get(), [NSURLRequest requestWithURL:pagesDocumentURL]);
     240    EXPECT_TRUE([delegate didStartQuickLookLoad]);
     241    EXPECT_TRUE([delegate didFinishQuickLookLoad]);
     242}
     243
     244TEST(QuickLook, AllowResponseAfterLoadingPreview)
     245{
     246    auto delegate = adoptNS([[QuickLookDelegate alloc] initWithExpectedFileURL:pagesDocumentURL previewMIMEType:pagesDocumentPreviewMIMEType responsePolicy:WKNavigationResponsePolicyAllow]);
     247    runTestDecideAfterLoading(delegate.get(), [NSURLRequest requestWithURL:pagesDocumentURL]);
     248    EXPECT_TRUE([delegate didStartQuickLookLoad]);
     249    EXPECT_TRUE([delegate didFinishQuickLookLoad]);
     250}
     251
     252@interface QuickLookAsyncDelegate : QuickLookDelegate
     253@end
     254
     255@implementation QuickLookAsyncDelegate
    81256
    82257- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
     
    86261
    87262    dispatch_after(when, dispatch_get_main_queue(), ^{
    88         decisionHandler(WKNavigationResponsePolicyAllow);
     263        decisionHandler(_responsePolicy);
    89264    });
    90265}
    91266
    92 - (void)_webView:(WKWebView *)webView didStartLoadForQuickLookDocumentInMainFrameWithFileName:(NSString *)fileName uti:(NSString *)uti
    93 {
    94     EXPECT_WK_STREQ(expectedFileName, fileName);
    95     EXPECT_WK_STREQ(expectedUTI, uti);
    96     didStartQuickLookLoad = true;
    97 }
    98 
    99 - (void)_webView:(WKWebView *)webView didFinishLoadForQuickLookDocumentInMainFrame:(NSData *)documentData
    100 {
    101     EXPECT_EQ(expectedFileSize, documentData.length);
    102     didFinishQuickLookLoad = true;
    103 }
    104 
    105 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
    106 {
     267@end
     268
     269TEST(QuickLook, AsyncAllowResponseBeforeLoadingPreview)
     270{
     271    auto delegate = adoptNS([[QuickLookAsyncDelegate alloc] initWithExpectedFileURL:pagesDocumentURL responsePolicy:WKNavigationResponsePolicyAllow]);
     272    runTestDecideBeforeLoading(delegate.get(), [NSURLRequest requestWithURL:pagesDocumentURL]);
     273    EXPECT_TRUE([delegate didStartQuickLookLoad]);
     274    EXPECT_TRUE([delegate didFinishQuickLookLoad]);
     275}
     276
     277TEST(QuickLook, AsyncAllowResponseAfterLoadingPreview)
     278{
     279    auto delegate = adoptNS([[QuickLookAsyncDelegate alloc] initWithExpectedFileURL:pagesDocumentURL previewMIMEType:pagesDocumentPreviewMIMEType responsePolicy:WKNavigationResponsePolicyAllow]);
     280    runTestDecideAfterLoading(delegate.get(), [NSURLRequest requestWithURL:pagesDocumentURL]);
     281    EXPECT_TRUE([delegate didStartQuickLookLoad]);
     282    EXPECT_TRUE([delegate didFinishQuickLookLoad]);
     283}
     284
     285TEST(QuickLook, CancelResponseBeforeLoadingPreview)
     286{
     287    auto delegate = adoptNS([[QuickLookDelegate alloc] initWithExpectedFileURL:pagesDocumentURL responsePolicy:WKNavigationResponsePolicyCancel]);
     288    runTestDecideBeforeLoading(delegate.get(), [NSURLRequest requestWithURL:pagesDocumentURL]);
     289    EXPECT_FALSE([delegate didStartQuickLookLoad]);
     290    EXPECT_FALSE([delegate didFinishQuickLookLoad]);
     291}
     292
     293TEST(QuickLook, CancelResponseAfterLoadingPreview)
     294{
     295    auto delegate = adoptNS([[QuickLookDelegate alloc] initWithExpectedFileURL:pagesDocumentURL previewMIMEType:pagesDocumentPreviewMIMEType responsePolicy:WKNavigationResponsePolicyCancel]);
     296    runTestDecideAfterLoading(delegate.get(), [NSURLRequest requestWithURL:pagesDocumentURL]);
     297    EXPECT_TRUE([delegate didStartQuickLookLoad]);
     298    EXPECT_TRUE([delegate didFinishQuickLookLoad]);
     299}
     300
     301TEST(QuickLook, DownloadResponseBeforeLoadingPreview)
     302{
     303    auto delegate = adoptNS([[QuickLookDelegate alloc] initWithExpectedFileURL:pagesDocumentURL responsePolicy:_WKNavigationResponsePolicyBecomeDownload]);
     304    runTestDecideBeforeLoading(delegate.get(), [NSURLRequest requestWithURL:pagesDocumentURL]);
     305    EXPECT_FALSE([delegate didStartQuickLookLoad]);
     306    EXPECT_FALSE([delegate didFinishQuickLookLoad]);
     307
     308    Util::run(&downloadIsDone);
     309    [delegate verifyDownload];
     310}
     311
     312TEST(QuickLook, DownloadResponseAfterLoadingPreview)
     313{
     314    auto delegate = adoptNS([[QuickLookDelegate alloc] initWithExpectedFileURL:pagesDocumentURL previewMIMEType:pagesDocumentPreviewMIMEType responsePolicy:_WKNavigationResponsePolicyBecomeDownload]);
     315    runTestDecideAfterLoading(delegate.get(), [NSURLRequest requestWithURL:pagesDocumentURL]);
     316    EXPECT_TRUE([delegate didStartQuickLookLoad]);
     317    EXPECT_TRUE([delegate didFinishQuickLookLoad]);
     318}
     319
     320@interface QuickLookPasswordDelegate : QuickLookDelegate
     321@property (nonatomic) BOOL didRequestPassword;
     322@end
     323
     324@implementation QuickLookPasswordDelegate
     325
     326- (void)_webViewDidRequestPasswordForQuickLookDocument:(WKWebView *)webView
     327{
     328    _didRequestPassword = YES;
    107329    isDone = true;
    108330}
     
    110332@end
    111333
    112 static void runTest(Class navigationDelegateClass, NSURLRequest *request)
    113 {
    114     auto webView = adoptNS([[WKWebView alloc] init]);
    115     auto navigationDelegate = adoptNS([[navigationDelegateClass alloc] init]);
    116     [webView setNavigationDelegate:navigationDelegate.get()];
    117     [webView loadRequest:request];
    118 
    119     isDone = false;
    120     Util::run(&isDone);
    121 }
    122 
    123 TEST(QuickLook, NavigationDelegate)
    124 {
    125     runTest([QuickLookNavigationDelegate class], pagesDocumentRequest);
    126     EXPECT_TRUE(didStartQuickLookLoad);
    127     EXPECT_TRUE(didFinishQuickLookLoad);
    128 }
    129 
    130 TEST(QuickLook, AsyncNavigationDelegate)
    131 {
    132     runTest([QuickLookAsyncNavigationDelegate class], pagesDocumentRequest);
    133     EXPECT_TRUE(didStartQuickLookLoad);
    134     EXPECT_TRUE(didFinishQuickLookLoad);
    135 }
    136 
    137 @interface QuickLookDecidePolicyDelegate : NSObject <WKNavigationDelegate>
    138 @end
    139 
    140 @implementation QuickLookDecidePolicyDelegate
    141 
    142 - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
    143 {
    144     decisionHandler(WKNavigationResponsePolicyCancel);
    145 }
    146 
    147 - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error
     334TEST(QuickLook, RequestPasswordBeforeLoadingPreview)
     335{
     336    NSURL *passwordProtectedDocumentURL = [NSBundle.mainBundle URLForResource:@"password-protected" withExtension:@"pages" subdirectory:@"TestWebKitAPI.resources"];
     337    auto delegate = adoptNS([[QuickLookPasswordDelegate alloc] initWithExpectedFileURL:passwordProtectedDocumentURL responsePolicy:WKNavigationResponsePolicyAllow]);
     338    runTestDecideBeforeLoading(delegate.get(), [NSURLRequest requestWithURL:passwordProtectedDocumentURL]);
     339    EXPECT_TRUE([delegate didRequestPassword]);
     340}
     341
     342TEST(QuickLook, RequestPasswordAfterLoadingPreview)
     343{
     344    NSURL *passwordProtectedDocumentURL = [NSBundle.mainBundle URLForResource:@"password-protected" withExtension:@"pages" subdirectory:@"TestWebKitAPI.resources"];
     345    auto delegate = adoptNS([[QuickLookPasswordDelegate alloc] initWithExpectedFileURL:passwordProtectedDocumentURL previewMIMEType:pagesDocumentPreviewMIMEType responsePolicy:WKNavigationResponsePolicyAllow]);
     346    runTestDecideAfterLoading(delegate.get(), [NSURLRequest requestWithURL:passwordProtectedDocumentURL]);
     347    EXPECT_TRUE([delegate didRequestPassword]);
     348}
     349
     350@interface QuickLookFrameLoadDelegate : NSObject <WebFrameLoadDelegate>
     351@end
     352
     353@implementation QuickLookFrameLoadDelegate
     354
     355- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame
    148356{
    149357    isDone = true;
    150358}
    151359
    152 - (void)_webViewWebProcessDidCrash:(WKWebView *)webView
    153 {
    154     RELEASE_ASSERT_NOT_REACHED();
    155 }
    156 
    157 @end
    158 
    159 @interface QuickLookFrameLoadDelegate : NSObject <WebFrameLoadDelegate>
    160 @end
    161 
    162 @implementation QuickLookFrameLoadDelegate
    163 
    164 - (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame
    165 {
    166     isDone = true;
    167 }
    168 
    169 @end
    170 
    171 TEST(QuickLook, CancelNavigationAfterResponse)
    172 {
    173     runTest([QuickLookDecidePolicyDelegate class], pagesDocumentRequest);
    174 }
    175 
    176 @interface QuickLookPasswordNavigationDelegate : NSObject <WKNavigationDelegatePrivate>
    177 @end
    178 
    179 @implementation QuickLookPasswordNavigationDelegate
    180 
    181 - (void)_webViewDidRequestPasswordForQuickLookDocument:(WKWebView *)webView
    182 {
    183     isDone = true;
    184 }
    185 
    186 @end
    187 
    188 #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000
    189 
    190 TEST(QuickLook, DidRequestPasswordNavigationDelegate)
    191 {
    192     NSURLRequest *passwordProtectedDocumentRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"password-protected" withExtension:@"pages" subdirectory:@"TestWebKitAPI.resources"]];
    193     runTest([QuickLookPasswordNavigationDelegate class], passwordProtectedDocumentRequest);
    194 }
    195 
    196 #endif
     360@end
    197361
    198362TEST(QuickLook, LegacyQuickLookContent)
     
    212376    WebFrame *mainFrame = [webView mainFrame];
    213377
    214     isDone = false;
    215     [mainFrame loadRequest:pagesDocumentRequest];
     378    [mainFrame loadRequest:[NSURLRequest requestWithURL:pagesDocumentURL]];
    216379    Util::run(&isDone);
    217380    WebThreadLock();
    218381
     382    NSUInteger expectedFileSize;
     383    RetainPtr<NSString> expectedFileName;
     384    RetainPtr<NSString> expectedFileType;
     385    RetainPtr<NSString> expectedMIMEType;
     386    readFile(pagesDocumentURL, expectedFileSize, expectedFileName, expectedFileType, expectedMIMEType);
     387
    219388    NSDictionary *quickLookContent = mainFrame.dataSource._quickLookContent;
    220389    NSString *filePath = quickLookContent[WebQuickLookFileNameKey];
    221     EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:filePath]);
    222     EXPECT_WK_STREQ(expectedFileName, filePath.lastPathComponent);
    223     EXPECT_WK_STREQ(expectedUTI, quickLookContent[WebQuickLookUTIKey]);
    224 
    225     NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil];
     390    EXPECT_TRUE([NSFileManager.defaultManager fileExistsAtPath:filePath]);
     391    EXPECT_WK_STREQ(expectedFileName.get(), filePath.lastPathComponent);
     392    EXPECT_WK_STREQ(expectedFileType.get(), quickLookContent[WebQuickLookUTIKey]);
     393
     394    NSDictionary *fileAttributes = [NSFileManager.defaultManager attributesOfItemAtPath:filePath error:nil];
    226395    EXPECT_EQ(expectedFileSize, [fileAttributes[NSFileSize] unsignedIntegerValue]);
    227396
Note: See TracChangeset for help on using the changeset viewer.