Changeset 223001 in webkit


Ignore:
Timestamp:
Oct 6, 2017, 3:07:19 PM (8 years ago)
Author:
achristensen@apple.com
Message:

Source/WebCore:
Add more infrastructure to apply custom header fields to same-origin requests
https://bugs.webkit.org/show_bug.cgi?id=177629

Reviewed by Ryosuke Niwa.

Covered by new API tests.

  • loader/DocumentLoader.h:

(WebCore::DocumentLoader::customHeaderFields):

  • loader/HTTPHeaderField.cpp:

(WebCore::HTTPHeaderField::create):
(WebCore::HTTPHeaderField::HTTPHeaderField): Deleted.

  • loader/HTTPHeaderField.h:

(WebCore::HTTPHeaderField::encode const):
(WebCore::HTTPHeaderField::decode):

Change HTTPHeaderField from one String containing the name and value
to a string for the name and another for value. This matches HTTPHeaderMap
and NSURLRequest more closely where names and values are treated as separate Strings.

  • loader/cache/CachedResourceLoader.cpp:

(WebCore::CachedResourceLoader::requestResource):

If the DocumentLoader has custom header fields from the WebsitePolicies, apply them to any same-origin requests.

  • loader/cache/CachedResourceRequest.h:

(WebCore::CachedResourceRequest::resourceRequest):

  • platform/network/ResourceRequestBase.cpp:

(WebCore::ResourceRequestBase::setCachePolicy):
(WebCore::ResourceRequestBase::setTimeoutInterval):
(WebCore::ResourceRequestBase::setHTTPMethod):
(WebCore::ResourceRequestBase::setHTTPHeaderField):
(WebCore::ResourceRequestBase::clearHTTPAuthorization):
(WebCore::ResourceRequestBase::clearHTTPContentType):
(WebCore::ResourceRequestBase::clearHTTPReferrer):
(WebCore::ResourceRequestBase::clearHTTPOrigin):
(WebCore::ResourceRequestBase::clearHTTPUserAgent):
(WebCore::ResourceRequestBase::clearHTTPAccept):
(WebCore::ResourceRequestBase::clearHTTPAcceptEncoding):
(WebCore::ResourceRequestBase::setResponseContentDispositionEncodingFallbackArray):
(WebCore::ResourceRequestBase::setHTTPBody):
(WebCore::ResourceRequestBase::setAllowCookies):
(WebCore::ResourceRequestBase::setPriority):
(WebCore::ResourceRequestBase::addHTTPHeaderFieldIfNotPresent):
(WebCore::ResourceRequestBase::addHTTPHeaderField):
(WebCore::ResourceRequestBase::setHTTPHeaderFields):

non-HTTP/HTTPS ResourceRequests need to be updated, too, if header fields are added.
Skipping updating non-HTTP/HTTPS ResourceRequests is not a valid shortcut, and with the
growing importance of custom schemes with our new public API, we should update ResourceRequests
of custom schemes correctly.

Source/WebKit:
Add more infrastructure to apply custom headers to same-origin requests
https://bugs.webkit.org/show_bug.cgi?id=177629

Reviewed by Ryosuke Niwa.

  • UIProcess/API/C/WKWebsitePolicies.cpp:

(WKWebsitePoliciesCopyCustomHeaderFields):
(WKWebsitePoliciesSetCustomHeaderFields):

  • UIProcess/API/C/WKWebsitePolicies.h:
  • UIProcess/API/Cocoa/_WKWebsitePolicies.h:
  • UIProcess/API/Cocoa/_WKWebsitePolicies.mm:

(-[_WKWebsitePolicies customHeaderFields]):
(-[_WKWebsitePolicies setCustomHeaderFields:]):

Make the SPI for setting custom header fields take a dictionary<String, String>
instead of an array of Strings with colons. This matches NSURLRequest and other
APIs that deal with header fields.

Tools:
Add more infrastructure to apply custom header fields to same-origin requests
https://bugs.webkit.org/show_bug.cgi?id=177629

Reviewed by Ryosuke Niwa.

  • TestWebKitAPI/Tests/WebCore/HTTPHeaderField.cpp:

(canonicalizeHTTPHeader):
(shouldRemainUnchanged):
(shouldBeInvalid):
(shouldBecome):

  • TestWebKitAPI/Tests/WebKitCocoa/WebsitePolicies.mm:

(TEST):
(expectHeaders):
(-[CustomHeaderFieldsDelegate _webView:decidePolicyForNavigationAction:decisionHandler:]):
(-[CustomHeaderFieldsDelegate webView:startURLSchemeTask:]):
(-[CustomHeaderFieldsDelegate webView:stopURLSchemeTask:]):

Test main resource requests, subresource requests, and cross-origin requests.

Location:
trunk
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r222997 r223001  
     12017-10-06  Alex Christensen  <achristensen@webkit.org>
     2
     3        Add more infrastructure to apply custom header fields to same-origin requests
     4        https://bugs.webkit.org/show_bug.cgi?id=177629
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        Covered by new API tests.
     9
     10        * loader/DocumentLoader.h:
     11        (WebCore::DocumentLoader::customHeaderFields):
     12        * loader/HTTPHeaderField.cpp:
     13        (WebCore::HTTPHeaderField::create):
     14        (WebCore::HTTPHeaderField::HTTPHeaderField): Deleted.
     15        * loader/HTTPHeaderField.h:
     16        (WebCore::HTTPHeaderField::encode const):
     17        (WebCore::HTTPHeaderField::decode):
     18       
     19        Change HTTPHeaderField from one String containing the name and value
     20        to a string for the name and another for value.  This matches HTTPHeaderMap
     21        and NSURLRequest more closely where names and values are treated as separate Strings.
     22       
     23        * loader/cache/CachedResourceLoader.cpp:
     24        (WebCore::CachedResourceLoader::requestResource):
     25       
     26        If the DocumentLoader has custom header fields from the WebsitePolicies, apply them to any same-origin requests.
     27       
     28        * loader/cache/CachedResourceRequest.h:
     29        (WebCore::CachedResourceRequest::resourceRequest):
     30        * platform/network/ResourceRequestBase.cpp:
     31        (WebCore::ResourceRequestBase::setCachePolicy):
     32        (WebCore::ResourceRequestBase::setTimeoutInterval):
     33        (WebCore::ResourceRequestBase::setHTTPMethod):
     34        (WebCore::ResourceRequestBase::setHTTPHeaderField):
     35        (WebCore::ResourceRequestBase::clearHTTPAuthorization):
     36        (WebCore::ResourceRequestBase::clearHTTPContentType):
     37        (WebCore::ResourceRequestBase::clearHTTPReferrer):
     38        (WebCore::ResourceRequestBase::clearHTTPOrigin):
     39        (WebCore::ResourceRequestBase::clearHTTPUserAgent):
     40        (WebCore::ResourceRequestBase::clearHTTPAccept):
     41        (WebCore::ResourceRequestBase::clearHTTPAcceptEncoding):
     42        (WebCore::ResourceRequestBase::setResponseContentDispositionEncodingFallbackArray):
     43        (WebCore::ResourceRequestBase::setHTTPBody):
     44        (WebCore::ResourceRequestBase::setAllowCookies):
     45        (WebCore::ResourceRequestBase::setPriority):
     46        (WebCore::ResourceRequestBase::addHTTPHeaderFieldIfNotPresent):
     47        (WebCore::ResourceRequestBase::addHTTPHeaderField):
     48        (WebCore::ResourceRequestBase::setHTTPHeaderFields):
     49       
     50        non-HTTP/HTTPS ResourceRequests need to be updated, too, if header fields are added.
     51        Skipping updating non-HTTP/HTTPS ResourceRequests is not a valid shortcut, and with the
     52        growing importance of custom schemes with our new public API, we should update ResourceRequests
     53        of custom schemes correctly.
     54
    1552017-10-06  Sam Weinig  <sam@webkit.org>
    256
  • trunk/Source/WebCore/loader/DocumentLoader.h

    r222329 r223001  
    298298
    299299    WEBCORE_EXPORT void setCustomHeaderFields(Vector<HTTPHeaderField>&& fields);
     300    const Vector<HTTPHeaderField>& customHeaderFields() { return m_customHeaderFields; }
    300301   
    301302protected:
  • trunk/Source/WebCore/loader/HTTPHeaderField.cpp

    r222306 r223001  
    203203} // namespace RFC7230
    204204
    205 HTTPHeaderField::HTTPHeaderField(const String& field)
    206 {
    207     size_t colonLocation = field.find(':');
    208     if (colonLocation == notFound)
    209         return;
    210 
    211     StringView name = StringView(field).substring(0, colonLocation).stripLeadingAndTrailingMatchedCharacters(RFC7230::isWhitespace);
    212     StringView value = StringView(field).substring(colonLocation + 1).stripLeadingAndTrailingMatchedCharacters(RFC7230::isWhitespace);
    213     if (!RFC7230::isValidName(name) || !RFC7230::isValidValue(value))
    214         return;
    215 
    216     m_field = makeString(name, ':', ' ',  value);
    217 }
    218 
    219 }
     205std::optional<HTTPHeaderField> HTTPHeaderField::create(String&& unparsedName, String&& unparsedValue)
     206{
     207    StringView strippedName = StringView(unparsedName).stripLeadingAndTrailingMatchedCharacters(RFC7230::isWhitespace);
     208    StringView strippedValue = StringView(unparsedValue).stripLeadingAndTrailingMatchedCharacters(RFC7230::isWhitespace);
     209    if (!RFC7230::isValidName(strippedName) || !RFC7230::isValidValue(strippedValue))
     210        return std::nullopt;
     211
     212    String name = strippedName.length() == unparsedName.length() ? WTFMove(unparsedName) : strippedName.toString();
     213    String value = strippedValue.length() == unparsedValue.length() ? WTFMove(unparsedValue) : strippedValue.toString();
     214    return {{ WTFMove(name), WTFMove(value) }};
     215}
     216
     217}
  • trunk/Source/WebCore/loader/HTTPHeaderField.h

    r222306 r223001  
    3232class WEBCORE_EXPORT HTTPHeaderField {
    3333public:
    34     HTTPHeaderField(const String&);
    35    
    36     const String& field() const { return m_field; }
     34    static std::optional<HTTPHeaderField> create(String&& name, String&& value);
     35
     36    const String& name() const { return m_name; }
     37    const String& value() const { return m_value; }
    3738
    3839    template<class Encoder> void encode(Encoder&) const;
     
    4041
    4142private:
    42     String m_field;
     43    HTTPHeaderField(String&& name, String&& value)
     44        : m_name(WTFMove(name))
     45        , m_value(WTFMove(value))
     46    { }
     47    String m_name;
     48    String m_value;
    4349};
    4450
     
    4652void HTTPHeaderField::encode(Encoder& encoder) const
    4753{
    48     encoder << m_field;
     54    encoder << m_name;
     55    encoder << m_value;
    4956}
    5057
     
    5259std::optional<HTTPHeaderField> HTTPHeaderField::decode(Decoder& decoder)
    5360{
    54     std::optional<String> field;
    55     decoder >> field;
    56     if (!field)
     61    std::optional<String> name;
     62    decoder >> name;
     63    if (!name)
    5764        return std::nullopt;
    5865
    59     return {{ WTFMove(*field) }};
     66    std::optional<String> value;
     67    decoder >> value;
     68    if (!value)
     69        return std::nullopt;
     70
     71    return {{ WTFMove(*name), WTFMove(*value) }};
    6072}
    6173
  • trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp

    r222602 r223001  
    5252#include "HTMLElement.h"
    5353#include "HTMLFrameOwnerElement.h"
     54#include "HTTPHeaderField.h"
    5455#include "LoaderStrategy.h"
    5556#include "LocalizedStrings.h"
     
    751752#endif
    752753
     754    // FIXME: Add custom headers to first-party requests.
     755    // https://bugs.webkit.org/show_bug.cgi?id=177629
     756
    753757    LoadTiming loadTiming;
    754758    loadTiming.markStartTimeAndFetchStart();
  • trunk/Source/WebCore/loader/cache/CachedResourceRequest.h

    r222602 r223001  
    5353    ResourceRequest&& releaseResourceRequest() { return WTFMove(m_resourceRequest); }
    5454    const ResourceRequest& resourceRequest() const { return m_resourceRequest; }
     55    ResourceRequest& resourceRequest() { return m_resourceRequest; }
    5556    const String& charset() const { return m_charset; }
    5657    void setCharset(const String& charset) { m_charset = charset; }
  • trunk/Source/WebKit/ChangeLog

    r222991 r223001  
     12017-10-06  Alex Christensen  <achristensen@webkit.org>
     2
     3        Add more infrastructure to apply custom headers to same-origin requests
     4        https://bugs.webkit.org/show_bug.cgi?id=177629
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        * UIProcess/API/C/WKWebsitePolicies.cpp:
     9        (WKWebsitePoliciesCopyCustomHeaderFields):
     10        (WKWebsitePoliciesSetCustomHeaderFields):
     11        * UIProcess/API/C/WKWebsitePolicies.h:
     12        * UIProcess/API/Cocoa/_WKWebsitePolicies.h:
     13        * UIProcess/API/Cocoa/_WKWebsitePolicies.mm:
     14        (-[_WKWebsitePolicies customHeaderFields]):
     15        (-[_WKWebsitePolicies setCustomHeaderFields:]):
     16
     17        Make the SPI for setting custom header fields take a dictionary<String, String>
     18        instead of an array of Strings with colons. This matches NSURLRequest and other
     19        APIs that deal with header fields.
     20
    1212017-10-06  Wenson Hsieh  <wenson_hsieh@apple.com>
    222
  • trunk/Source/WebKit/UIProcess/API/C/WKWebsitePolicies.cpp

    r222306 r223001  
    2727#include "WKWebsitePolicies.h"
    2828
    29 #include "APIArray.h"
     29#include "APIDictionary.h"
    3030#include "APIWebsitePolicies.h"
    3131#include "WKAPICast.h"
    3232#include "WKArray.h"
     33#include "WKDictionary.h"
     34#include "WKRetainPtr.h"
    3335#include "WebsitePolicies.h"
    3436
     
    5557}
    5658
    57 WK_EXPORT WKArrayRef WKWebsitePoliciesCopyCustomHeaderFields(WKWebsitePoliciesRef websitePolicies)
     59WK_EXPORT WKDictionaryRef WKWebsitePoliciesCopyCustomHeaderFields(WKWebsitePoliciesRef websitePolicies)
    5860{
    59     const auto& fields = toImpl(websitePolicies)->customHeaderFields();
    60     Vector<RefPtr<API::Object>> strings;
    61     strings.reserveInitialCapacity(fields.size());
    62     for (const auto& field : fields)
    63         strings.uncheckedAppend(API::String::create(field.field()));
    64     return toAPI(API::Array::create(WTFMove(strings)).ptr());
     61    HashMap<WTF::String, RefPtr<API::Object>> fields;
     62    for (const auto& field : toImpl(websitePolicies)->customHeaderFields())
     63        fields.add(field.name(), API::String::create(field.value()));
     64    return toAPI(API::Dictionary::create(WTFMove(fields)).ptr());
    6565}
    6666
    67 WK_EXPORT void WKWebsitePoliciesSetCustomHeaderFields(WKWebsitePoliciesRef websitePolicies, WKArrayRef array)
     67WK_EXPORT void WKWebsitePoliciesSetCustomHeaderFields(WKWebsitePoliciesRef websitePolicies, WKDictionaryRef dictionary)
    6868{
    69     size_t length = WKArrayGetSize(array);
     69    auto keys = adoptWK(WKDictionaryCopyKeys(dictionary));
     70    size_t length = WKArrayGetSize(keys.get());
    7071    Vector<WebCore::HTTPHeaderField> fields;
    7172    fields.reserveInitialCapacity(length);
    7273    for (size_t i = 0; i < length; ++i) {
    73         WebCore::HTTPHeaderField parsedField(toImpl(static_cast<WKStringRef>(WKArrayGetItemAtIndex(array, i)))->string());
    74         if (!parsedField.field().isNull()
    75             && parsedField.field().startsWithIgnoringASCIICase("X-")) // Let's just pretend RFC6648 never happened.
    76             fields.uncheckedAppend(WTFMove(parsedField));
     74        WKStringRef name = static_cast<WKStringRef>(WKArrayGetItemAtIndex(keys.get(), i));
     75        auto field = WebCore::HTTPHeaderField::create(toImpl(name)->string(), toImpl(static_cast<WKStringRef>(WKDictionaryGetItemForKey(dictionary, name)))->string());
     76        if (field && field->name().startsWithIgnoringASCIICase("X-"))
     77            fields.uncheckedAppend(WTFMove(*field));
    7778    }
    7879    toImpl(websitePolicies)->setCustomHeaderFields(WTFMove(fields));
  • trunk/Source/WebKit/UIProcess/API/C/WKWebsitePolicies.h

    r222306 r223001  
    5252WK_EXPORT void WKWebsitePoliciesSetContentBlockersEnabled(WKWebsitePoliciesRef, bool);
    5353
    54 WK_EXPORT WKArrayRef WKWebsitePoliciesCopyCustomHeaderFields(WKWebsitePoliciesRef);
    55 WK_EXPORT void WKWebsitePoliciesSetCustomHeaderFields(WKWebsitePoliciesRef, WKArrayRef);
     54WK_EXPORT WKDictionaryRef WKWebsitePoliciesCopyCustomHeaderFields(WKWebsitePoliciesRef);
     55WK_EXPORT void WKWebsitePoliciesSetCustomHeaderFields(WKWebsitePoliciesRef, WKDictionaryRef);
    5656
    5757WK_EXPORT WKWebsiteAutoplayQuirk WKWebsitePoliciesGetAllowedAutoplayQuirks(WKWebsitePoliciesRef);
  • trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebsitePolicies.h

    r222306 r223001  
    4646@property (nonatomic) _WKWebsiteAutoplayQuirk allowedAutoplayQuirks WK_API_AVAILABLE(macosx(10.13), ios(11.0));
    4747@property (nonatomic) _WKWebsiteAutoplayPolicy autoplayPolicy WK_API_AVAILABLE(macosx(10.13), ios(11.0));
    48 @property (nonatomic, copy, setter=setCustomHeaderFields:) NSArray<NSString *> *customHeaderFields WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
     48@property (nonatomic, copy, setter=setCustomHeaderFields:) NSDictionary<NSString *, NSString *> *customHeaderFields WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
    4949
    5050@end
  • trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebsitePolicies.mm

    r222306 r223001  
    117117}
    118118
    119 - (NSArray<NSString *> *)customHeaderFields
     119- (NSDictionary<NSString *, NSString *> *)customHeaderFields
    120120{
    121121    const auto& fields = _websitePolicies->customHeaderFields();
    122     NSMutableArray *array = [[[NSMutableArray alloc] initWithCapacity:fields.size()] autorelease];
     122    NSMutableDictionary *dictionary = [[[NSMutableDictionary alloc] initWithCapacity:fields.size()] autorelease];
    123123    for (const auto& field : fields)
    124         [array addObject:field.field()];
    125     return array;
     124        [dictionary setObject:field.value() forKey:field.name()];
     125    return dictionary;
    126126}
    127127
    128 - (void)setCustomHeaderFields:(NSArray<NSString *> *)fields
     128- (void)setCustomHeaderFields:(NSDictionary<NSString *, NSString *> *)fields
    129129{
    130130    Vector<WebCore::HTTPHeaderField> parsedFields;
    131131    parsedFields.reserveInitialCapacity(fields.count);
    132     for (NSString *string in fields) {
    133         WebCore::HTTPHeaderField parsedField(string);
    134         if (!parsedField.field().isNull()
    135             && parsedField.field().startsWithIgnoringASCIICase("X-")) // Let's just pretend RFC6648 never happened.
    136             parsedFields.uncheckedAppend(WTFMove(parsedField));
     132   
     133    for (NSString* name in fields) {
     134        auto field = WebCore::HTTPHeaderField::create(name, [fields objectForKey:name]);
     135        if (field && field->name().startsWithIgnoringASCIICase("X-"))
     136            parsedFields.uncheckedAppend(WTFMove(*field));
    137137    }
    138138    _websitePolicies->setCustomHeaderFields(WTFMove(parsedFields));
  • trunk/Tools/ChangeLog

    r222991 r223001  
     12017-10-06  Alex Christensen  <achristensen@webkit.org>
     2
     3        Add more infrastructure to apply custom header fields to same-origin requests
     4        https://bugs.webkit.org/show_bug.cgi?id=177629
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        * TestWebKitAPI/Tests/WebCore/HTTPHeaderField.cpp:
     9        (canonicalizeHTTPHeader):
     10        (shouldRemainUnchanged):
     11        (shouldBeInvalid):
     12        (shouldBecome):
     13        * TestWebKitAPI/Tests/WebKitCocoa/WebsitePolicies.mm:
     14        (TEST):
     15        (expectHeaders):
     16        (-[CustomHeaderFieldsDelegate _webView:decidePolicyForNavigationAction:decisionHandler:]):
     17        (-[CustomHeaderFieldsDelegate webView:startURLSchemeTask:]):
     18        (-[CustomHeaderFieldsDelegate webView:stopURLSchemeTask:]):
     19
     20        Test main resource requests, subresource requests, and cross-origin requests.
     21
    1222017-10-06  Wenson Hsieh  <wenson_hsieh@apple.com>
    223
  • trunk/Tools/TestWebKitAPI/Tests/WebCore/HTTPHeaderField.cpp

    r222306 r223001  
    2929#include <WebCore/HTTPHeaderField.h>
    3030
     31static String canonicalizeHTTPHeader(const String& string)
     32{
     33    size_t colonLocation = string.find(':');
     34    if (colonLocation == notFound)
     35        return { };
     36    auto field = WebCore::HTTPHeaderField::create(string.substring(0, colonLocation), string.substring(colonLocation + 1));
     37    if (!field)
     38        return { };
     39    return makeString(field->name(), ": ", field->value());
     40}
     41
    3142static void shouldRemainUnchanged(Vector<String>&& strings)
    3243{
    3344    for (const auto& string : strings)
    34         EXPECT_TRUE(WebCore::HTTPHeaderField(string).field() == string);
     45        EXPECT_TRUE(canonicalizeHTTPHeader(string) == string);
    3546}
    3647
     
    3849{
    3950    for (const auto& string : strings)
    40         EXPECT_TRUE(WebCore::HTTPHeaderField(string).field() == String());
     51        EXPECT_TRUE(canonicalizeHTTPHeader(string) == String());
    4152}
    4253
     
    4455{
    4556    for (const auto& pair : pairs)
    46         EXPECT_TRUE(WebCore::HTTPHeaderField(pair.first).field() == pair.second);
     57        EXPECT_TRUE(canonicalizeHTTPHeader(pair.first) == pair.second);
    4758}
    4859
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebsitePolicies.mm

    r222306 r223001  
    2828#import "PlatformUtilities.h"
    2929#import "TestWKWebView.h"
     30#import <WebKit/WKNavigationDelegatePrivate.h>
    3031#import <WebKit/WKPagePrivate.h>
    3132#import <WebKit/WKPreferencesRefPrivate.h>
     
    628629{
    629630    auto websitePolicies = adoptNS([[_WKWebsitePolicies alloc] init]);
    630     [websitePolicies setCustomHeaderFields:@[@"invalidheader:", @"noncustom: header", @"X-custom: header", @"    x-Custom :  Needs Canonicalization\t "]];
    631     NSArray<NSString *> *canonicalized = [websitePolicies customHeaderFields];
     631    [websitePolicies setCustomHeaderFields:@{@"invalidheader" : @"", @"noncustom" : @"header", @"    x-Custom ":@"  Needs Canonicalization\t ", @"x-other" : @"other value"}];
     632    NSDictionary<NSString *, NSString *> *canonicalized = [websitePolicies customHeaderFields];
    632633    EXPECT_EQ(canonicalized.count, 2u);
    633     EXPECT_STREQ([canonicalized objectAtIndex:0].UTF8String, "X-custom: header");
    634     EXPECT_STREQ([canonicalized objectAtIndex:1].UTF8String, "x-Custom: Needs Canonicalization");
    635 }
    636 
    637 // FIXME: Apply the custom headers from the DocumentLoader to each request and test that they are sent on main resource and subresources.
     634    EXPECT_STREQ([canonicalized objectForKey:@"x-Custom"].UTF8String, "Needs Canonicalization");
     635    EXPECT_STREQ([canonicalized objectForKey:@"x-other"].UTF8String, "other value");
     636}
     637
     638static bool firstTestDone;
     639static bool secondTestDone;
     640static bool thirdTestDone;
     641
     642static void expectHeaders(id <WKURLSchemeTask> task, bool expected)
     643{
     644    NSURLRequest *request = task.request;
     645    if (expected) {
     646        // FIXME: Check that headers are on the request.
     647        // https://bugs.webkit.org/show_bug.cgi?id=177629
     648    } else {
     649        EXPECT_TRUE([request valueForHTTPHeaderField:@"X-key1"] == nil);
     650        EXPECT_TRUE([request valueForHTTPHeaderField:@"X-key2"] == nil);
     651    }
     652}
     653
     654static void respond(id <WKURLSchemeTask>task, NSString *html = nil)
     655{
     656    [task didReceiveResponse:[[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:html.length textEncodingName:nil] autorelease]];
     657    [task didReceiveData:[html dataUsingEncoding:NSUTF8StringEncoding]];
     658    [task didFinish];
     659}
     660
     661@interface CustomHeaderFieldsDelegate : NSObject <WKNavigationDelegatePrivate, WKURLSchemeHandler>
     662@end
     663
     664@implementation CustomHeaderFieldsDelegate
     665
     666- (void)_webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy, _WKWebsitePolicies *))decisionHandler
     667{
     668    _WKWebsitePolicies *websitePolicies = [[[_WKWebsitePolicies alloc] init] autorelease];
     669    [websitePolicies setCustomHeaderFields:@{@"X-key1": @"value1", @"X-key2": @"value2"}];
     670    decisionHandler(WKNavigationActionPolicyAllow, websitePolicies);
     671}
     672
     673- (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)urlSchemeTask
     674{
     675    NSString *path = urlSchemeTask.request.URL.path;
     676    if ([path isEqualToString:@"/mainresource"]) {
     677        expectHeaders(urlSchemeTask, true);
     678        respond(urlSchemeTask, @"<script>fetch('subresource').then(function(response){fetch('test://differentsecurityorigin/crossoriginsubresource',{mode:'no-cors'})})</script>");
     679    } else if ([path isEqualToString:@"/subresource"]) {
     680        expectHeaders(urlSchemeTask, true);
     681        respond(urlSchemeTask);
     682    } else if ([path isEqualToString:@"/crossoriginsubresource"]) {
     683        expectHeaders(urlSchemeTask, false);
     684        respond(urlSchemeTask);
     685        firstTestDone = true;
     686    } else if ([path isEqualToString:@"/mainresourcewithiframe"]) {
     687        expectHeaders(urlSchemeTask, true);
     688        respond(urlSchemeTask, @"<iframe src='test://iframeorigin/iframemainresource'></iframe>");
     689    } else if ([path isEqualToString:@"/iframemainresource"]) {
     690        expectHeaders(urlSchemeTask, false);
     691        respond(urlSchemeTask, @"<script>fetch('iframesubresource').then(function(response){fetch('test://mainframeorigin/originaloriginsubresource',{mode:'no-cors'})})</script>");
     692    } else if ([path isEqualToString:@"/iframesubresource"]) {
     693        expectHeaders(urlSchemeTask, false);
     694        respond(urlSchemeTask);
     695    } else if ([path isEqualToString:@"/originaloriginsubresource"]) {
     696        expectHeaders(urlSchemeTask, false);
     697        respond(urlSchemeTask);
     698        secondTestDone = true;
     699    } else if ([path isEqualToString:@"/nestedtop"]) {
     700        expectHeaders(urlSchemeTask, true);
     701        respond(urlSchemeTask, @"<iframe src='test://otherorigin/nestedmid'></iframe>");
     702    } else if ([path isEqualToString:@"/nestedmid"]) {
     703        expectHeaders(urlSchemeTask, false);
     704        respond(urlSchemeTask, @"<iframe src='test://toporigin/nestedbottom'></iframe>");
     705    } else if ([path isEqualToString:@"/nestedbottom"]) {
     706        expectHeaders(urlSchemeTask, true);
     707        respond(urlSchemeTask);
     708        thirdTestDone = true;
     709    } else
     710        EXPECT_TRUE(false);
     711}
     712
     713- (void)webView:(WKWebView *)webView stopURLSchemeTask:(id <WKURLSchemeTask>)urlSchemeTask
     714{
     715}
     716
     717@end
     718
     719TEST(WebKit, CustomHeaderFields)
     720{
     721    auto delegate = adoptNS([[CustomHeaderFieldsDelegate alloc] init]);
     722    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     723    [configuration setURLSchemeHandler:delegate.get() forURLScheme:@"test"];
     724    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
     725    [webView setNavigationDelegate:delegate.get()];
     726    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"test:///mainresource"]]];
     727    TestWebKitAPI::Util::run(&firstTestDone);
     728   
     729    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"test://mainframeorigin/mainresourcewithiframe"]]];
     730    TestWebKitAPI::Util::run(&secondTestDone);
     731
     732    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"test://toporigin/nestedtop"]]];
     733    TestWebKitAPI::Util::run(&thirdTestDone);
     734}
     735
    638736
    639737#endif // WK_API_ENABLED
Note: See TracChangeset for help on using the changeset viewer.