Changeset 218750 in webkit


Ignore:
Timestamp:
Jun 23, 2017 10:25:43 AM (7 years ago)
Author:
achristensen@apple.com
Message:

Add SPI to WKURLSchemeTask for redirection
https://bugs.webkit.org/show_bug.cgi?id=173730

Reviewed by Brady Eidson.

Source/WebCore:

  • platform/network/CacheValidation.cpp:

(WebCore::computeFreshnessLifetimeForHTTPFamily):
Asserting that redirects are always http/https URLs is no longer valid.
If there's a custom scheme redirect, give it no freshness lifetime in the cache.

Source/WebKit2:

This is needed for testing an upcoming fix for redirect callbacks, and it might be
necessary for loading with custom schemes in general. Right now just responding with

an HTTP 301/302/307/308 response code doesn't work because there is nothing that

synthesizes an NSURLRequest from the Location header like we do in
SynchronousResourceHandleCFURLConnectionDelegate::willSendRequest et al. for HSTS,
and that would require using an NSHTTPURLResponse for non-HTTP responses, which is
conceptually wrong. Instead of waiting for a completion handler in the API, we are
following the pattern of WKNavigationDelegate.didReceiveServerRedirectForProvisionalNavigation
and allowing the SPI to indicate that a redirect has happened to update the state of
WebKit, but not allowing the SPI to wait for a processed request and slow down loading.

This adds WKURLSchemeTaskPrivate._didPerformRedirection which is covered by new API tests.

  • UIProcess/API/Cocoa/WKURLSchemeTask.mm:

(raiseExceptionIfNecessary):
(-[WKURLSchemeTaskImpl _didPerformRedirection:newRequest:completionHandler:]):

  • UIProcess/API/Cocoa/WKURLSchemeTaskInternal.h:
  • UIProcess/API/Cocoa/WKURLSchemeTaskPrivate.h: Added.
  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::startURLSchemeTask):
(WebKit::WebPageProxy::stopURLSchemeTask):

  • UIProcess/WebPageProxy.h:
  • UIProcess/WebPageProxy.messages.in:
  • UIProcess/WebURLSchemeHandler.cpp:

(WebKit::WebURLSchemeHandler::startTask):
(WebKit::WebURLSchemeHandler::stopTask):

  • UIProcess/WebURLSchemeHandler.h:
  • UIProcess/WebURLSchemeTask.cpp:

(WebKit::WebURLSchemeTask::didReceiveResponse): Deleted.
(WebKit::WebURLSchemeTask::didReceiveData): Deleted.
(WebKit::WebURLSchemeTask::didComplete): Deleted.

  • UIProcess/WebURLSchemeTask.h:
  • WebKit2.xcodeproj/project.pbxproj:
  • WebProcess/WebPage/WebPage.cpp:

(WebKit::WebPage::urlSchemeTaskDidPerformRedirection):

  • WebProcess/WebPage/WebPage.h:
  • WebProcess/WebPage/WebPage.messages.in:
  • WebProcess/WebPage/WebURLSchemeHandlerProxy.cpp:

(WebKit::WebURLSchemeHandlerProxy::taskDidPerformRedirection):

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

(WebKit::WebURLSchemeTaskProxy::didPerformRedirection):

  • WebProcess/WebPage/WebURLSchemeTaskProxy.h:

Tools:

  • TestWebKitAPI/Tests/WebKit2Cocoa/WKURLSchemeHandler-1.mm:

(-[SchemeHandler webView:startURLSchemeTask:]):
(-[SchemeHandler webView:stopURLSchemeTask:]):
(TEST):
(-[RedirectSchemeHandler webView:startURLSchemeTask:]):
(-[RedirectSchemeHandler webView:stopURLSchemeTask:]):
(-[RedirectSchemeHandler webView:didReceiveServerRedirectForProvisionalNavigation:]):
(-[RedirectSchemeHandler webView:decidePolicyForNavigationResponse:decisionHandler:]):
(-[RedirectSchemeHandler userContentController:didReceiveScriptMessage:]):

Location:
trunk
Files:
1 added
22 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r218748 r218750  
     12017-06-23  Alex Christensen  <achristensen@webkit.org>
     2
     3        Add SPI to WKURLSchemeTask for redirection
     4        https://bugs.webkit.org/show_bug.cgi?id=173730
     5
     6        Reviewed by Brady Eidson.
     7
     8        * platform/network/CacheValidation.cpp:
     9        (WebCore::computeFreshnessLifetimeForHTTPFamily):
     10        Asserting that redirects are always http/https URLs is no longer valid.
     11        If there's a custom scheme redirect, give it no freshness lifetime in the cache.
     12
    1132017-06-23  Konstantin Tokarev  <annulen@yandex.ru>
    214
  • trunk/Source/WebCore/platform/network/CacheValidation.cpp

    r217860 r218750  
    119119    using namespace std::chrono;
    120120
    121     ASSERT(response.url().protocolIsInHTTPFamily());
     121    if (!response.url().protocolIsInHTTPFamily())
     122        return 0us;
    122123
    123124    // Freshness Lifetime:
  • trunk/Source/WebKit2/ChangeLog

    r218749 r218750  
     12017-06-23  Alex Christensen  <achristensen@webkit.org>
     2
     3        Add SPI to WKURLSchemeTask for redirection
     4        https://bugs.webkit.org/show_bug.cgi?id=173730
     5
     6        Reviewed by Brady Eidson.
     7
     8        This is needed for testing an upcoming fix for redirect callbacks, and it might be
     9        necessary for loading with custom schemes in general. Right now just responding with
     10         an HTTP 301/302/307/308 response code doesn't work because there is nothing that
     11        synthesizes an NSURLRequest from the Location header like we do in
     12        SynchronousResourceHandleCFURLConnectionDelegate::willSendRequest et al. for HSTS,
     13        and that would require using an NSHTTPURLResponse for non-HTTP responses, which is
     14        conceptually wrong.  Instead of waiting for a completion handler in the API, we are
     15        following the pattern of WKNavigationDelegate.didReceiveServerRedirectForProvisionalNavigation
     16        and allowing the SPI to indicate that a redirect has happened to update the state of
     17        WebKit, but not allowing the SPI to wait for a processed request and slow down loading.
     18
     19        This adds WKURLSchemeTaskPrivate._didPerformRedirection which is covered by new API tests.
     20
     21        * UIProcess/API/Cocoa/WKURLSchemeTask.mm:
     22        (raiseExceptionIfNecessary):
     23        (-[WKURLSchemeTaskImpl _didPerformRedirection:newRequest:completionHandler:]):
     24        * UIProcess/API/Cocoa/WKURLSchemeTaskInternal.h:
     25        * UIProcess/API/Cocoa/WKURLSchemeTaskPrivate.h: Added.
     26        * UIProcess/WebPageProxy.cpp:
     27        (WebKit::WebPageProxy::startURLSchemeTask):
     28        (WebKit::WebPageProxy::stopURLSchemeTask):
     29        * UIProcess/WebPageProxy.h:
     30        * UIProcess/WebPageProxy.messages.in:
     31        * UIProcess/WebURLSchemeHandler.cpp:
     32        (WebKit::WebURLSchemeHandler::startTask):
     33        (WebKit::WebURLSchemeHandler::stopTask):
     34        * UIProcess/WebURLSchemeHandler.h:
     35        * UIProcess/WebURLSchemeTask.cpp:
     36        (WebKit::WebURLSchemeTask::didReceiveResponse): Deleted.
     37        (WebKit::WebURLSchemeTask::didReceiveData): Deleted.
     38        (WebKit::WebURLSchemeTask::didComplete): Deleted.
     39        * UIProcess/WebURLSchemeTask.h:
     40        * WebKit2.xcodeproj/project.pbxproj:
     41        * WebProcess/WebPage/WebPage.cpp:
     42        (WebKit::WebPage::urlSchemeTaskDidPerformRedirection):
     43        * WebProcess/WebPage/WebPage.h:
     44        * WebProcess/WebPage/WebPage.messages.in:
     45        * WebProcess/WebPage/WebURLSchemeHandlerProxy.cpp:
     46        (WebKit::WebURLSchemeHandlerProxy::taskDidPerformRedirection):
     47        * WebProcess/WebPage/WebURLSchemeHandlerProxy.h:
     48        * WebProcess/WebPage/WebURLSchemeTaskProxy.cpp:
     49        (WebKit::WebURLSchemeTaskProxy::didPerformRedirection):
     50        * WebProcess/WebPage/WebURLSchemeTaskProxy.h:
     51
    1522017-06-23  Brent Fulgham  <bfulgham@apple.com>
    253
  • trunk/Source/WebKit2/UIProcess/API/Cocoa/WKURLSchemeTask.mm

    r216037 r218750  
    2929#if WK_API_ENABLED
    3030
    31 #include "WebURLSchemeTask.h"
    32 #include <WebCore/ResourceError.h>
    33 #include <WebCore/ResourceResponse.h>
    34 #include <WebCore/SharedBuffer.h>
     31#import "WebURLSchemeTask.h"
     32#import <WebCore/ResourceError.h>
     33#import <WebCore/ResourceResponse.h>
     34#import <WebCore/SharedBuffer.h>
     35#import <wtf/BlockPtr.h>
    3536
    3637using namespace WebCore;
     
    5253    case WebKit::WebURLSchemeTask::ExceptionType::NoResponseSent:
    5354        [NSException raise:NSInternalInconsistencyException format:@"No response has been sent for this task"];
     55        break;
     56    case WebKit::WebURLSchemeTask::ExceptionType::RedirectAfterResponse:
     57        [NSException raise:NSInternalInconsistencyException format:@"No redirects are allowed after the response"];
    5458        break;
    5559    }
     
    8791}
    8892
     93- (void)_didPerformRedirection:(NSURLResponse *)response newRequest:(NSURLRequest *)request
     94{
     95    auto result = _urlSchemeTask->task().didPerformRedirection(response, request);
     96    raiseExceptionIfNecessary(result);
     97}
     98
    8999#pragma mark WKObject protocol implementation
    90100
  • trunk/Source/WebKit2/UIProcess/API/Cocoa/WKURLSchemeTaskInternal.h

    r216037 r218750  
    2424 */
    2525
    26 #import "WKURLSchemeTask.h"
     26#import "WKURLSchemeTaskPrivate.h"
    2727
    2828#if WK_API_ENABLED
     
    3131#import "WKObject.h"
    3232
    33 @interface WKURLSchemeTaskImpl : NSObject <WKURLSchemeTask>
     33@interface WKURLSchemeTaskImpl : NSObject <WKURLSchemeTaskPrivate>
    3434@end
    3535
  • trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp

    r218632 r218750  
    68806880}
    68816881
    6882 void WebPageProxy::startURLSchemeTask(uint64_t handlerIdentifier, uint64_t resourceIdentifier, const WebCore::ResourceRequest& request)
     6882void WebPageProxy::startURLSchemeTask(uint64_t handlerIdentifier, uint64_t taskIdentifier, const WebCore::ResourceRequest& request)
    68836883{
    68846884    auto iterator = m_urlSchemeHandlersByIdentifier.find(handlerIdentifier);
    68856885    ASSERT(iterator != m_urlSchemeHandlersByIdentifier.end());
    68866886
    6887     iterator->value->startTask(*this, resourceIdentifier, request);
    6888 }
    6889 
    6890 void WebPageProxy::stopURLSchemeTask(uint64_t handlerIdentifier, uint64_t resourceIdentifier)
     6887    iterator->value->startTask(*this, taskIdentifier, request);
     6888}
     6889
     6890void WebPageProxy::stopURLSchemeTask(uint64_t handlerIdentifier, uint64_t taskIdentifier)
    68916891{
    68926892    auto iterator = m_urlSchemeHandlersByIdentifier.find(handlerIdentifier);
    68936893    ASSERT(iterator != m_urlSchemeHandlersByIdentifier.end());
    68946894
    6895     iterator->value->stopTask(*this, resourceIdentifier);
     6895    iterator->value->stopTask(*this, taskIdentifier);
    68966896}
    68976897
  • trunk/Source/WebKit2/UIProcess/WebPageProxy.h

    r218740 r218750  
    16081608#endif
    16091609
    1610     void startURLSchemeTask(uint64_t handlerIdentifier, uint64_t resourceIdentifier, const WebCore::ResourceRequest&);
    1611     void stopURLSchemeTask(uint64_t handlerIdentifier, uint64_t resourceIdentifier);
     1610    void startURLSchemeTask(uint64_t handlerIdentifier, uint64_t taskIdentifier, const WebCore::ResourceRequest&);
     1611    void stopURLSchemeTask(uint64_t handlerIdentifier, uint64_t taskIdentifier);
    16121612
    16131613    void handleAutoFillButtonClick(const UserData&);
  • trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in

    r218295 r218750  
    496496    SetIsUsingHighPerformanceWebGL(bool isUsingHighPerformanceWebGL)
    497497
    498     StartURLSchemeTask(uint64_t loaderIdentifier, uint64_t resourceIdentifier, WebCore::ResourceRequest request)
    499     StopURLSchemeTask(uint64_t loaderIdentifier, uint64_t resourceIdentifier)
     498    StartURLSchemeTask(uint64_t handlerIdentifier, uint64_t taskIdentifier, WebCore::ResourceRequest request)
     499    StopURLSchemeTask(uint64_t handlerIdentifier, uint64_t taskIdentifier)
    500500}
  • trunk/Source/WebKit2/UIProcess/WebURLSchemeHandler.cpp

    r216037 r218750  
    4949}
    5050
    51 void WebURLSchemeHandler::startTask(WebPageProxy& page, uint64_t resourceIdentifier, const ResourceRequest& request)
     51void WebURLSchemeHandler::startTask(WebPageProxy& page, uint64_t taskIdentifier, const ResourceRequest& request)
    5252{
    53     auto result = m_tasks.add(resourceIdentifier, WebURLSchemeTask::create(*this, page, resourceIdentifier, request));
     53    auto result = m_tasks.add(taskIdentifier, WebURLSchemeTask::create(*this, page, taskIdentifier, request));
    5454    ASSERT(result.isNewEntry);
    5555
     
    5757}
    5858
    59 void WebURLSchemeHandler::stopTask(WebPageProxy& page, uint64_t resourceIdentifier)
     59void WebURLSchemeHandler::stopTask(WebPageProxy& page, uint64_t taskIdentifier)
    6060{
    61     auto iterator = m_tasks.find(resourceIdentifier);
     61    auto iterator = m_tasks.find(taskIdentifier);
    6262    if (iterator == m_tasks.end())
    6363        return;
  • trunk/Source/WebKit2/UIProcess/WebURLSchemeHandler.h

    r216037 r218750  
    4646    uint64_t identifier() const { return m_identifier; }
    4747
    48     void startTask(WebPageProxy&, uint64_t resourceIdentifier, const WebCore::ResourceRequest&);
    49     void stopTask(WebPageProxy&, uint64_t resourceIdentifier);
     48    void startTask(WebPageProxy&, uint64_t taskIdentifier, const WebCore::ResourceRequest&);
     49    void stopTask(WebPageProxy&, uint64_t taskIdentifier);
    5050
    5151protected:
  • trunk/Source/WebKit2/UIProcess/WebURLSchemeTask.cpp

    r216037 r218750  
    4949}
    5050
    51 WebURLSchemeTask::ExceptionType WebURLSchemeTask::didReceiveResponse(const ResourceResponse& response)
     51auto WebURLSchemeTask::didPerformRedirection(WebCore::ResourceResponse&& response, WebCore::ResourceRequest&& request) -> ExceptionType
    5252{
    5353    if (m_stopped)
    54         return WebURLSchemeTask::ExceptionType::TaskAlreadyStopped;
     54        return ExceptionType::TaskAlreadyStopped;
     55   
     56    if (m_completed)
     57        return ExceptionType::CompleteAlreadyCalled;
     58   
     59    if (m_dataSent)
     60        return ExceptionType::DataAlreadySent;
     61   
     62    if (m_responseSent)
     63        return ExceptionType::RedirectAfterResponse;
     64   
     65    m_request = request;
     66    m_page->send(Messages::WebPage::URLSchemeTaskDidPerformRedirection(m_urlSchemeHandler->identifier(), m_identifier, response, request));
     67
     68    return ExceptionType::None;
     69}
     70
     71auto WebURLSchemeTask::didReceiveResponse(const ResourceResponse& response) -> ExceptionType
     72{
     73    if (m_stopped)
     74        return ExceptionType::TaskAlreadyStopped;
    5575
    5676    if (m_completed)
    57         return WebURLSchemeTask::ExceptionType::CompleteAlreadyCalled;
     77        return ExceptionType::CompleteAlreadyCalled;
    5878
    5979    if (m_dataSent)
    60         return WebURLSchemeTask::ExceptionType::DataAlreadySent;
     80        return ExceptionType::DataAlreadySent;
    6181
    6282    m_responseSent = true;
     
    6484    response.includeCertificateInfo();
    6585    m_page->send(Messages::WebPage::URLSchemeTaskDidReceiveResponse(m_urlSchemeHandler->identifier(), m_identifier, response));
    66     return WebURLSchemeTask::ExceptionType::None;
     86    return ExceptionType::None;
    6787}
    6888
    69 WebURLSchemeTask::ExceptionType WebURLSchemeTask::didReceiveData(Ref<SharedBuffer> buffer)
     89auto WebURLSchemeTask::didReceiveData(Ref<SharedBuffer> buffer) -> ExceptionType
    7090{
    7191    if (m_stopped)
    72         return WebURLSchemeTask::ExceptionType::TaskAlreadyStopped;
     92        return ExceptionType::TaskAlreadyStopped;
    7393
    7494    if (m_completed)
    75         return WebURLSchemeTask::ExceptionType::CompleteAlreadyCalled;
     95        return ExceptionType::CompleteAlreadyCalled;
    7696
    7797    if (!m_responseSent)
    78         return WebURLSchemeTask::ExceptionType::NoResponseSent;
     98        return ExceptionType::NoResponseSent;
    7999
    80100    m_dataSent = true;
    81101    m_page->send(Messages::WebPage::URLSchemeTaskDidReceiveData(m_urlSchemeHandler->identifier(), m_identifier, IPC::SharedBufferDataReference(buffer.ptr())));
    82     return WebURLSchemeTask::ExceptionType::None;
     102    return ExceptionType::None;
    83103}
    84104
    85 WebURLSchemeTask::ExceptionType WebURLSchemeTask::didComplete(const ResourceError& error)
     105auto WebURLSchemeTask::didComplete(const ResourceError& error) -> ExceptionType
    86106{
    87107    if (m_stopped)
    88         return WebURLSchemeTask::ExceptionType::TaskAlreadyStopped;
     108        return ExceptionType::TaskAlreadyStopped;
    89109
    90110    if (m_completed)
    91         return WebURLSchemeTask::ExceptionType::CompleteAlreadyCalled;
     111        return ExceptionType::CompleteAlreadyCalled;
    92112
    93113    if (!m_responseSent && error.isNull())
    94         return WebURLSchemeTask::ExceptionType::NoResponseSent;
     114        return ExceptionType::NoResponseSent;
    95115
    96116    m_completed = true;
    97117    m_page->send(Messages::WebPage::URLSchemeTaskDidComplete(m_urlSchemeHandler->identifier(), m_identifier, error));
    98     return WebURLSchemeTask::ExceptionType::None;
     118    return ExceptionType::None;
    99119}
    100120
  • trunk/Source/WebKit2/UIProcess/WebURLSchemeTask.h

    r216037 r218750  
    5353        DataAlreadySent,
    5454        CompleteAlreadyCalled,
     55        RedirectAfterResponse,
    5556        TaskAlreadyStopped,
    5657        NoResponseSent,
    5758        None,
    5859    };
     60    ExceptionType didPerformRedirection(WebCore::ResourceResponse&&, WebCore::ResourceRequest&&);
    5961    ExceptionType didReceiveResponse(const WebCore::ResourceResponse&);
    6062    ExceptionType didReceiveData(Ref<WebCore::SharedBuffer>);
  • trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj

    r218321 r218750  
    11611161                5C20CBA01BB1ECD800895BB1 /* NetworkSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C20CB9E1BB0DD1800895BB1 /* NetworkSession.h */; };
    11621162                5C298DA01C3DF02100470AFE /* PendingDownload.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C298D9E1C3DEF2900470AFE /* PendingDownload.h */; };
     1163                5C62FDF91EFC271C00CE072E /* WKURLSchemeTaskPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C62FDF81EFC263C00CE072E /* WKURLSchemeTaskPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
    11631164                5C7706741D1138380012700F /* WebSocketProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C7706731D111D8B0012700F /* WebSocketProvider.cpp */; };
    11641165                5C85C7881C3F23CE0061A4FA /* PendingDownload.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C85C7861C3F23C50061A4FA /* PendingDownload.cpp */; };
     
    34443445                5C20CB9E1BB0DD1800895BB1 /* NetworkSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NetworkSession.h; path = NetworkProcess/NetworkSession.h; sourceTree = "<group>"; };
    34453446                5C298D9E1C3DEF2900470AFE /* PendingDownload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PendingDownload.h; path = NetworkProcess/Downloads/PendingDownload.h; sourceTree = "<group>"; };
     3447                5C62FDF81EFC263C00CE072E /* WKURLSchemeTaskPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WKURLSchemeTaskPrivate.h; sourceTree = "<group>"; };
    34463448                5C7706731D111D8B0012700F /* WebSocketProvider.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebSocketProvider.cpp; path = Network/WebSocketProvider.cpp; sourceTree = "<group>"; };
    34473449                5C7C88DC1D0F41A0009D2F6D /* WebSocketProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebSocketProvider.h; path = Network/WebSocketProvider.h; sourceTree = "<group>"; };
     
    57195721                                51D124301E6DDDD7002B2820 /* WKURLSchemeTask.mm */,
    57205722                                51D124371E6DFD2A002B2820 /* WKURLSchemeTaskInternal.h */,
     5723                                5C62FDF81EFC263C00CE072E /* WKURLSchemeTaskPrivate.h */,
    57215724                                1AFA3AC718E61C61003CCBAE /* WKUserContentController.h */,
    57225725                                1AFA3AC618E61C61003CCBAE /* WKUserContentController.mm */,
     
    89458948                                C54256B518BEC18C00DE4179 /* WKFormInputControl.h in Headers */,
    89468949                                C54256B718BEC18C00DE4179 /* WKFormPeripheral.h in Headers */,
     8950                                5C62FDF91EFC271C00CE072E /* WKURLSchemeTaskPrivate.h in Headers */,
    89478951                                C54256B818BEC18C00DE4179 /* WKFormPopover.h in Headers */,
    89488952                                C54256BA18BEC18C00DE4179 /* WKFormSelectControl.h in Headers */,
  • trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp

    r218713 r218750  
    59065906void WebPage::registerURLSchemeHandler(uint64_t handlerIdentifier, const String& scheme)
    59075907{
    5908     auto schemeResult = m_schemeToURLSchemeHandlerProxyMap.add(scheme, std::make_unique<WebURLSchemeHandlerProxy>(*this, handlerIdentifier));
     5908    auto schemeResult = m_schemeToURLSchemeHandlerProxyMap.add(scheme, WebURLSchemeHandlerProxy::create(*this, handlerIdentifier));
    59095909    ASSERT(schemeResult.isNewEntry);
    59105910
     
    59135913}
    59145914
    5915 void WebPage::urlSchemeTaskDidReceiveResponse(uint64_t handlerIdentifier, uint64_t taskIdentifier, const ResourceResponse& response)
     5915void WebPage::urlSchemeTaskDidPerformRedirection(uint64_t handlerIdentifier, uint64_t taskIdentifier, ResourceResponse&& response, ResourceRequest&& request)
    59165916{
    59175917    auto* handler = m_identifierToURLSchemeHandlerProxyMap.get(handlerIdentifier);
    59185918    ASSERT(handler);
    5919 
    5920     handler->taskDidReceiveResponse(taskIdentifier, response);
    5921 }
    5922 
    5923 void WebPage::urlSchemeTaskDidReceiveData(uint64_t handlerIdentifier, uint64_t taskIdentifier, const IPC::DataReference& data)
     5919   
     5920    handler->taskDidPerformRedirection(taskIdentifier, WTFMove(response), WTFMove(request));
     5921}
     5922   
     5923void WebPage::urlSchemeTaskDidReceiveResponse(uint64_t handlerIdentifier, uint64_t taskIdentifier, const ResourceResponse& response)
    59245924{
    59255925    auto* handler = m_identifierToURLSchemeHandlerProxyMap.get(handlerIdentifier);
    59265926    ASSERT(handler);
    59275927
    5928     handler->taskDidReceiveData(taskIdentifier, data.size(), data.data());
    5929 }
    5930 
    5931 void WebPage::urlSchemeTaskDidComplete(uint64_t handlerIdentifier, uint64_t taskIdentifier, const ResourceError& error)
     5928    handler->taskDidReceiveResponse(taskIdentifier, response);
     5929}
     5930
     5931void WebPage::urlSchemeTaskDidReceiveData(uint64_t handlerIdentifier, uint64_t taskIdentifier, const IPC::DataReference& data)
    59325932{
    59335933    auto* handler = m_identifierToURLSchemeHandlerProxyMap.get(handlerIdentifier);
    59345934    ASSERT(handler);
    59355935
     5936    handler->taskDidReceiveData(taskIdentifier, data.size(), data.data());
     5937}
     5938
     5939void WebPage::urlSchemeTaskDidComplete(uint64_t handlerIdentifier, uint64_t taskIdentifier, const ResourceError& error)
     5940{
     5941    auto* handler = m_identifierToURLSchemeHandlerProxyMap.get(handlerIdentifier);
     5942    ASSERT(handler);
     5943
    59365944    handler->taskDidComplete(taskIdentifier, error);
    59375945}
  • trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h

    r218457 r218750  
    12771277    void registerURLSchemeHandler(uint64_t identifier, const String& scheme);
    12781278
     1279    void urlSchemeTaskDidPerformRedirection(uint64_t handlerIdentifier, uint64_t taskIdentifier, WebCore::ResourceResponse&&, WebCore::ResourceRequest&&);
    12791280    void urlSchemeTaskDidReceiveResponse(uint64_t handlerIdentifier, uint64_t taskIdentifier, const WebCore::ResourceResponse&);
    12801281    void urlSchemeTaskDidReceiveData(uint64_t handlerIdentifier, uint64_t taskIdentifier, const IPC::DataReference&);
     
    15691570    const std::optional<double> m_cpuLimit;
    15701571
    1571     HashMap<String, std::unique_ptr<WebURLSchemeHandlerProxy>> m_schemeToURLSchemeHandlerProxyMap;
     1572    HashMap<String, RefPtr<WebURLSchemeHandlerProxy>> m_schemeToURLSchemeHandlerProxyMap;
    15721573    HashMap<uint64_t, WebURLSchemeHandlerProxy*> m_identifierToURLSchemeHandlerProxyMap;
    15731574};
  • trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in

    r217725 r218750  
    476476    RegisterURLSchemeHandler(uint64_t identifier, String scheme)
    477477
    478     URLSchemeTaskDidReceiveResponse(uint64_t providerIdentifier, uint64_t taskIdentifier, WebCore::ResourceResponse response)
    479     URLSchemeTaskDidReceiveData(uint64_t providerIdentifier, uint64_t taskIdentifier, IPC::DataReference data)
    480     URLSchemeTaskDidComplete(uint64_t providerIdentifier, uint64_t taskIdentifier, WebCore::ResourceError error)
     478    URLSchemeTaskDidPerformRedirection(uint64_t handlerIdentifier, uint64_t taskIdentifier, WebCore::ResourceResponse response, WebCore::ResourceRequest request)
     479    URLSchemeTaskDidReceiveResponse(uint64_t handlerIdentifier, uint64_t taskIdentifier, WebCore::ResourceResponse response)
     480    URLSchemeTaskDidReceiveData(uint64_t handlerIdentifier, uint64_t taskIdentifier, IPC::DataReference data)
     481    URLSchemeTaskDidComplete(uint64_t handlerIdentifier, uint64_t taskIdentifier, WebCore::ResourceError error)
    481482}
  • trunk/Source/WebKit2/WebProcess/WebPage/WebURLSchemeHandlerProxy.cpp

    r216037 r218750  
    4949void WebURLSchemeHandlerProxy::startNewTask(ResourceLoader& loader)
    5050{
    51     auto result = m_tasks.add(loader.identifier(), std::make_unique<WebURLSchemeTaskProxy>(*this, loader));
     51    auto result = m_tasks.add(loader.identifier(), WebURLSchemeTaskProxy::create(*this, loader));
    5252    ASSERT(result.isNewEntry);
    5353
     
    5656}
    5757
     58void WebURLSchemeHandlerProxy::taskDidPerformRedirection(uint64_t taskIdentifier, WebCore::ResourceResponse&& redirectResponse, WebCore::ResourceRequest&& newRequest)
     59{
     60    auto* task = m_tasks.get(taskIdentifier);
     61    if (!task)
     62        return;
     63   
     64    task->didPerformRedirection(WTFMove(redirectResponse), WTFMove(newRequest));
     65}
    5866
    5967void WebURLSchemeHandlerProxy::taskDidReceiveResponse(uint64_t taskIdentifier, const ResourceResponse& response)
  • trunk/Source/WebKit2/WebProcess/WebPage/WebURLSchemeHandlerProxy.h

    r216037 r218750  
    2828#include "WebURLSchemeTaskProxy.h"
    2929#include <wtf/HashMap.h>
     30#include <wtf/RefCounted.h>
    3031
    3132namespace WebCore {
     
    3334class ResourceLoader;
    3435class ResourceResponse;
     36class ResourceRequest;
    3537}
    3638
     
    3941class WebPage;
    4042
    41 class WebURLSchemeHandlerProxy {
    42     WTF_MAKE_NONCOPYABLE(WebURLSchemeHandlerProxy);
     43class WebURLSchemeHandlerProxy : public RefCounted<WebURLSchemeHandlerProxy> {
    4344public:
    44     WebURLSchemeHandlerProxy(WebPage&, uint64_t identifier);
     45    static Ref<WebURLSchemeHandlerProxy> create(WebPage& page, uint64_t identifier)
     46    {
     47        return adoptRef(*new WebURLSchemeHandlerProxy(page, identifier));
     48    }
    4549    ~WebURLSchemeHandlerProxy();
    4650
     
    5054    WebPage& page() { return m_webPage; }
    5155
     56    void taskDidPerformRedirection(uint64_t taskIdentifier, WebCore::ResourceResponse&&, WebCore::ResourceRequest&&);
    5257    void taskDidReceiveResponse(uint64_t taskIdentifier, const WebCore::ResourceResponse&);
    5358    void taskDidReceiveData(uint64_t taskIdentifier, size_t, const uint8_t* data);
     
    5661
    5762private:
     63    WebURLSchemeHandlerProxy(WebPage&, uint64_t identifier);
    5864    WebPage& m_webPage;
    5965    uint64_t m_identifier { 0 };
    6066
    61     HashMap<unsigned long, std::unique_ptr<WebURLSchemeTaskProxy>> m_tasks;
     67    HashMap<uint64_t, RefPtr<WebURLSchemeTaskProxy>> m_tasks;
    6268}; // class WebURLSchemeHandlerProxy
    6369
  • trunk/Source/WebKit2/WebProcess/WebPage/WebURLSchemeTaskProxy.cpp

    r217041 r218750  
    6363    m_urlSchemeHandler.taskDidStopLoading(*this);
    6464}
     65   
     66void WebURLSchemeTaskProxy::didPerformRedirection(WebCore::ResourceResponse&& redirectResponse, WebCore::ResourceRequest&& request)
     67{
     68    if (!hasLoader())
     69        return;
     70   
     71    auto completionHandler = [this, protectedThis = makeRef(*this), originalRequest = request] (ResourceRequest&& request) {
     72        m_waitingForRedirectCompletionHandler = false;
     73        // We do not inform the UIProcess of WebKit's new request with the given suggested request.
     74        // We do want to know if WebKit would have generated a request that differs from the suggested request, though.
     75        if (request.url() != originalRequest.url())
     76            WTFLogAlways("Redirected scheme task would have been sent to a different URL.");
     77    };
     78   
     79    if (m_waitingForRedirectCompletionHandler)
     80        WTFLogAlways("Received redirect during previous redirect processing.");
     81    m_waitingForRedirectCompletionHandler = true;
     82
     83    m_coreLoader->willSendRequest(WTFMove(request), redirectResponse, WTFMove(completionHandler));
     84}
    6585
    6686void WebURLSchemeTaskProxy::didReceiveResponse(const ResourceResponse& response)
    6787{
     88    if (m_waitingForRedirectCompletionHandler)
     89        WTFLogAlways("Received response during redirect processing.");
     90   
    6891    if (!hasLoader())
    6992        return;
  • trunk/Source/WebKit2/WebProcess/WebPage/WebURLSchemeTaskProxy.h

    r216037 r218750  
    2727
    2828#include <WebCore/ResourceRequest.h>
     29#include <wtf/RefCounted.h>
    2930
    3031namespace WebCore {
     
    3839class WebURLSchemeHandlerProxy;
    3940
    40 class WebURLSchemeTaskProxy {
    41     WTF_MAKE_NONCOPYABLE(WebURLSchemeTaskProxy);
     41class WebURLSchemeTaskProxy : public RefCounted<WebURLSchemeTaskProxy> {
    4242public:
    43     WebURLSchemeTaskProxy(WebURLSchemeHandlerProxy&, WebCore::ResourceLoader&);
    44 
     43    static Ref<WebURLSchemeTaskProxy> create(WebURLSchemeHandlerProxy& handler, WebCore::ResourceLoader& loader)
     44    {
     45        return adoptRef(*new WebURLSchemeTaskProxy(handler, loader));
     46    }
     47   
    4548    const WebCore::ResourceRequest& request() const { return m_request; }
    4649
     
    4851    void stopLoading();
    4952
     53    void didPerformRedirection(WebCore::ResourceResponse&&, WebCore::ResourceRequest&&);
    5054    void didReceiveResponse(const WebCore::ResourceResponse&);
    5155    void didReceiveData(size_t, const uint8_t* data);
     
    5559
    5660private:
     61    WebURLSchemeTaskProxy(WebURLSchemeHandlerProxy&, WebCore::ResourceLoader&);
    5762    bool hasLoader();
    5863
     
    6166    WebCore::ResourceRequest m_request;
    6267    unsigned long m_identifier;
     68    bool m_waitingForRedirectCompletionHandler { };
    6369};
    6470
  • trunk/Tools/ChangeLog

    r218743 r218750  
     12017-06-23  Alex Christensen  <achristensen@webkit.org>
     2
     3        Add SPI to WKURLSchemeTask for redirection
     4        https://bugs.webkit.org/show_bug.cgi?id=173730
     5
     6        Reviewed by Brady Eidson.
     7
     8        * TestWebKitAPI/Tests/WebKit2Cocoa/WKURLSchemeHandler-1.mm:
     9        (-[SchemeHandler webView:startURLSchemeTask:]):
     10        (-[SchemeHandler webView:stopURLSchemeTask:]):
     11        (TEST):
     12        (-[RedirectSchemeHandler webView:startURLSchemeTask:]):
     13        (-[RedirectSchemeHandler webView:stopURLSchemeTask:]):
     14        (-[RedirectSchemeHandler webView:didReceiveServerRedirectForProvisionalNavigation:]):
     15        (-[RedirectSchemeHandler webView:decidePolicyForNavigationResponse:decisionHandler:]):
     16        (-[RedirectSchemeHandler userContentController:didReceiveScriptMessage:]):
     17
    1182017-06-23  Carlos Garcia Campos  <cgarcia@igalia.com>
    219
  • trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WKURLSchemeHandler-1.mm

    r218694 r218750  
    2929#import "Test.h"
    3030#import <WebKit/WKURLSchemeHandler.h>
    31 #import <WebKit/WKURLSchemeTask.h>
     31#import <WebKit/WKURLSchemeTaskPrivate.h>
    3232#import <WebKit/WKWebViewConfigurationPrivate.h>
    3333#import <WebKit/WebKit.h>
    3434#import <wtf/RetainPtr.h>
     35#import <wtf/Vector.h>
    3536
    3637#if WK_API_ENABLED
    3738
    38 static bool receivedScriptMessage;
     39static bool done;
    3940
    4041@interface SchemeHandler : NSObject <WKURLSchemeHandler>
     
    7778    if ([task.request.URL.absoluteString isEqualToString:@"testing:image"]) {
    7879        [task didFailWithError:[NSError errorWithDomain:@"TestWebKitAPI" code:1 userInfo:nil]];
    79         receivedScriptMessage = true;
     80        done = true;
    8081        return;
    8182    }
     
    9192    [_stoppedURLs addObject:task.request.URL];
    9293
    93     receivedScriptMessage = true;
     94    done = true;
    9495}
    9596
     
    103104TEST(URLSchemeHandler, Basic)
    104105{
    105     receivedScriptMessage = false;
     106    done = false;
    106107
    107108    RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     
    115116    [webView loadRequest:request];
    116117
    117     TestWebKitAPI::Util::run(&receivedScriptMessage);
     118    TestWebKitAPI::Util::run(&done);
    118119
    119120    EXPECT_EQ([handler.get().startedURLs count], 2u);
     
    128129    // This test makes sure that is communicated back to the URLSchemeHandler.
    129130
    130     receivedScriptMessage = false;
     131    done = false;
    131132
    132133    RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     
    140141    [webView loadRequest:request];
    141142
    142     TestWebKitAPI::Util::run(&receivedScriptMessage);
     143    TestWebKitAPI::Util::run(&done);
    143144
    144145    EXPECT_EQ([handler.get().startedURLs count], 1u);
     
    192193}
    193194
     195static bool receivedRedirect;
     196static bool responsePolicyDecided;
     197
     198@interface RedirectSchemeHandler : NSObject <WKURLSchemeHandler, WKNavigationDelegate, WKScriptMessageHandler>
     199@end
     200
     201@implementation RedirectSchemeHandler { }
     202
     203- (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)task
     204{
     205    ASSERT_STREQ(task.request.URL.absoluteString.UTF8String, "testing:///initial");
     206    NSURLResponse *response = [[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:nil expectedContentLength:0 textEncodingName:nil] autorelease];
     207    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"testing:///redirected"]];
     208    [(id<WKURLSchemeTaskPrivate>)task _didPerformRedirection:response newRequest:request];
     209    ASSERT_FALSE(receivedRedirect);
     210    ASSERT_STREQ(task.request.URL.absoluteString.UTF8String, "testing:///redirected");
     211    NSString *html = @"<script>window.webkit.messageHandlers.testHandler.postMessage('Document URL: ' + document.URL);</script>";
     212    [task didReceiveResponse:[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:html.length textEncodingName:nil]];
     213    [task didReceiveData:[html dataUsingEncoding:NSUTF8StringEncoding]];
     214    [task didFinish];
     215}
     216
     217- (void)webView:(WKWebView *)webView stopURLSchemeTask:(id <WKURLSchemeTask>)task
     218{
     219    ASSERT_TRUE(false);
     220}
     221
     222- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation
     223{
     224    ASSERT_FALSE(receivedRedirect);
     225    receivedRedirect = true;
     226}
     227
     228- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
     229{
     230    ASSERT_TRUE(receivedRedirect);
     231    ASSERT_STREQ(navigationResponse.response.URL.absoluteString.UTF8String, "testing:///redirected");
     232    ASSERT_FALSE(responsePolicyDecided);
     233    responsePolicyDecided = true;
     234    decisionHandler(WKNavigationResponsePolicyAllow);
     235}
     236
     237- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
     238{
     239    EXPECT_WK_STREQ(@"Document URL: testing:///redirected", [message body]);
     240    done = true;
     241}
     242@end
     243
     244TEST(URLSchemeHandler, Redirection)
     245{
     246    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     247    auto handler = adoptNS([[RedirectSchemeHandler alloc] init]);
     248    [configuration setURLSchemeHandler:handler.get() forURLScheme:@"testing"];
     249    [[configuration userContentController] addScriptMessageHandler:handler.get() name:@"testHandler"];
     250    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
     251    [webView setNavigationDelegate:handler.get()];
     252   
     253    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"testing:///initial"]];
     254    [webView loadRequest:request];
     255   
     256    TestWebKitAPI::Util::run(&done);
     257   
     258    EXPECT_TRUE(responsePolicyDecided);
     259    EXPECT_STREQ(webView.get().URL.absoluteString.UTF8String, "testing:///redirected");
     260}
     261
     262enum class Command {
     263    Redirect,
     264    Response,
     265    Data,
     266    Finish,
     267    Error,
     268};
     269
     270@interface TaskSchemeHandler : NSObject <WKURLSchemeHandler>
     271- (instancetype)initWithCommands:(Vector<Command>&&)commandVector expectedException:(bool)expected;
     272@end
     273
     274@implementation TaskSchemeHandler {
     275    Vector<Command> commands;
     276    bool expectedException;
     277}
     278
     279- (instancetype)initWithCommands:(Vector<Command>&&)commandVector expectedException:(bool)expected
     280{
     281    self = [super init];
     282    if (!self)
     283        return nil;
     284   
     285    self->commands = WTFMove(commandVector);
     286    self->expectedException = expected;
     287   
     288    return self;
     289}
     290
     291- (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)task
     292{
     293    bool caughtException = false;
     294    @try {
     295        for (auto command : commands) {
     296            switch (command) {
     297            case Command::Redirect:
     298                [(id<WKURLSchemeTaskPrivate>)task _didPerformRedirection:[[[NSURLResponse alloc] init] autorelease] newRequest:[[[NSURLRequest alloc] init] autorelease]];
     299                break;
     300            case Command::Response:
     301                [task didReceiveResponse:[[[NSURLResponse alloc] init] autorelease]];
     302                break;
     303            case Command::Data:
     304                [task didReceiveData:[[[NSData alloc] init] autorelease]];
     305                break;
     306            case Command::Finish:
     307                [task didFinish];
     308                break;
     309            case Command::Error:
     310                [task didFailWithError:[[[NSError alloc] init] autorelease]];
     311                break;
     312            }
     313        }
     314    }
     315    @catch(NSException *exception)
     316    {
     317        caughtException = true;
     318    }
     319    ASSERT_EQ(caughtException, expectedException);
     320    done = true;
     321}
     322
     323- (void)webView:(WKWebView *)webView stopURLSchemeTask:(id <WKURLSchemeTask>)task
     324{
     325}
     326@end
     327
     328enum class ShouldRaiseException { No, Yes };
     329
     330static void checkCallSequence(Vector<Command>&& commands, ShouldRaiseException shouldRaiseException)
     331{
     332    done = false;
     333    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     334    auto handler = adoptNS([[TaskSchemeHandler alloc] initWithCommands:WTFMove(commands) expectedException:shouldRaiseException == ShouldRaiseException::Yes]);
     335    [configuration setURLSchemeHandler:handler.get() forURLScheme:@"testing"];
     336    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
     337    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"testing:///initial"]]];
     338    TestWebKitAPI::Util::run(&done);
     339}
     340
     341TEST(URLSchemeHandler, Exceptions)
     342{
     343    checkCallSequence({Command::Response, Command::Data, Command::Finish}, ShouldRaiseException::No);
     344    checkCallSequence({Command::Response, Command::Redirect}, ShouldRaiseException::Yes);
     345    checkCallSequence({Command::Redirect, Command::Response}, ShouldRaiseException::No);
     346    checkCallSequence({Command::Data, Command::Finish}, ShouldRaiseException::Yes);
     347    checkCallSequence({Command::Error}, ShouldRaiseException::No);
     348    checkCallSequence({Command::Error, Command::Error}, ShouldRaiseException::Yes);
     349    checkCallSequence({Command::Error, Command::Data}, ShouldRaiseException::Yes);
     350    checkCallSequence({Command::Response, Command::Finish, Command::Data}, ShouldRaiseException::Yes);
     351    checkCallSequence({Command::Response, Command::Finish, Command::Redirect}, ShouldRaiseException::Yes);
     352    checkCallSequence({Command::Response, Command::Finish, Command::Response}, ShouldRaiseException::Yes);
     353    checkCallSequence({Command::Response, Command::Finish, Command::Finish}, ShouldRaiseException::Yes);
     354    checkCallSequence({Command::Response, Command::Finish, Command::Error}, ShouldRaiseException::Yes);
     355}
    194356
    195357#endif
Note: See TracChangeset for help on using the changeset viewer.