[Mac] Wrap a resource and resource loader in a NSURLSession-like object for use by...
authorjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 3 Feb 2016 22:57:43 +0000 (22:57 +0000)
committerjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 3 Feb 2016 22:57:43 +0000 (22:57 +0000)
https://bugs.webkit.org/show_bug.cgi?id=153669

Reviewed by Alex Christensen.

Source/WebCore:

API Test: WebCore.WebCoreNSURLSession

Add a NSURLSession-like object, which wraps a CachedResourceLoader and CachedRawResource, which we can
hand to lower-level frameworks, so that network loads by those frameworks use WebKit's loader.

* platform/network/cocoa/WebCoreNSURLSession.h: Added.
* platform/network/cocoa/WebCoreNSURLSession.mm: Added.
(-[WebCoreNSURLSession initWithResourceLoader:delegate:delegateQueue:]):
(-[WebCoreNSURLSession dealloc]):
(-[WebCoreNSURLSession copyWithZone:]):
(-[WebCoreNSURLSession delegateQueue]):
(-[WebCoreNSURLSession configuration]):
(-[WebCoreNSURLSession loader]):
(-[WebCoreNSURLSession finishTasksAndInvalidate]):
(-[WebCoreNSURLSession invalidateAndCancel]):
(-[WebCoreNSURLSession resetWithCompletionHandler:]):
(-[WebCoreNSURLSession flushWithCompletionHandler:]):
(-[WebCoreNSURLSession getTasksWithCompletionHandler:]):
(-[WebCoreNSURLSession getAllTasksWithCompletionHandler:]):
(-[WebCoreNSURLSession dataTaskWithRequest:]):
(-[WebCoreNSURLSession dataTaskWithURL:]):
(-[WebCoreNSURLSession uploadTaskWithRequest:fromFile:]):
(-[WebCoreNSURLSession uploadTaskWithRequest:fromData:]):
(-[WebCoreNSURLSession uploadTaskWithStreamedRequest:]):
(-[WebCoreNSURLSession downloadTaskWithRequest:]):
(-[WebCoreNSURLSession downloadTaskWithURL:]):
(-[WebCoreNSURLSession downloadTaskWithResumeData:]):
(-[WebCoreNSURLSession streamTaskWithHostName:port:]):
(-[WebCoreNSURLSession streamTaskWithNetService:]):
(-[WebCoreNSURLSession isKindOfClass:]):

Add a C++ class which can act as a CachedRawResourceClient, passing the results back to a WebCoreNSURLSessionDataTask:

(WebCore::WebCoreNSURLSessionDataTaskClient::WebCoreNSURLSessionDataTaskClient):
(WebCore::WebCoreNSURLSessionDataTaskClient::dataSent):
(WebCore::WebCoreNSURLSessionDataTaskClient::responseReceived):
(WebCore::WebCoreNSURLSessionDataTaskClient::dataReceived):
(WebCore::WebCoreNSURLSessionDataTaskClient::redirectReceived):
(WebCore::WebCoreNSURLSessionDataTaskClient::notifyFinished):

Add a NSURLSessionDataTask-like object, which takes a request, then uses it to create and wrap a CachedRawResource.
Becase NSURSessionDataTask is intended to be used off-main-thread, care must be taken to dispatch back to the main-
(or web-) thread before calling CachedRawResource functions.

(-[WebCoreNSURLSessionDataTask initWithSession:identifier:URL:]):
(-[WebCoreNSURLSessionDataTask initWithSession:identifier:request:]):
(-[WebCoreNSURLSessionDataTask copyWithZone:]):
(-[WebCoreNSURLSessionDataTask _restart]):
(-[WebCoreNSURLSessionDataTask _cancel]):
(-[WebCoreNSURLSessionDataTask _finish]):
(-[WebCoreNSURLSessionDataTask _setDefersLoading:]):
(-[WebCoreNSURLSessionDataTask cancel]):
(-[WebCoreNSURLSessionDataTask suspend]):
(-[WebCoreNSURLSessionDataTask resume]):
(-[WebCoreNSURLSessionDataTask _timingData]):
(-[WebCoreNSURLSessionDataTask resource:sentBytes:totalBytesToBeSent:]):
(-[WebCoreNSURLSessionDataTask resource:receivedResponse:]):
(-[WebCoreNSURLSessionDataTask resource:receivedData:length:]):
(-[WebCoreNSURLSessionDataTask resource:receivedRedirect:request:]):
(-[WebCoreNSURLSessionDataTask resourceFinished:]):
* WebCore.xcodeproj/project.pbxproj: Add new files to project.

Tools:

Add an API test for WebCoreNSURLSession, testing that it behaves like a regulare NSURLSession, including
calling appropriate NSURLSessionDelegate callbacks.

Drive-by fix: Add a FeatureDefines.xcconfig to TestWebKitAPI.  Without this, the ENABLE macros in WebCore
header files will not match the one used when compiling WebCore, leading to strange crashes and weird
inconsistencies when calling, e.g., inline methods.

* TestWebKitAPI/Configurations/FeatureDefines.xcconfig: Added.
* TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebCore/WebCoreNSURLSession.mm: Added.
(-[TestNSURLSessionLoaderDelegate webView:didCommitLoadForFrame:]):
(-[TestNSURLSessionDataDelegate URLSession:task:didCompleteWithError:]):
(-[TestNSURLSessionDataDelegate URLSession:dataTask:didReceiveResponse:completionHandler:]):
(-[TestNSURLSessionDataDelegate URLSession:dataTask:didReceiveData:]):
(TestWebKitAPI::WebCoreNSURLSessionTest::SetUp):
(TestWebKitAPI::WebCoreNSURLSessionTest::TearDown):
(TestWebKitAPI::TEST_F):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@196082 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/platform/network/cocoa/WebCoreNSURLSession.h [new file with mode: 0644]
Source/WebCore/platform/network/cocoa/WebCoreNSURLSession.mm [new file with mode: 0644]
Tools/ChangeLog
Tools/TestWebKitAPI/Configurations/FeatureDefines.xcconfig [new file with mode: 0644]
Tools/TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WebCore/WebCoreNSURLSession.mm [new file with mode: 0644]

index 2c0b998..fceb434 100644 (file)
@@ -1,3 +1,72 @@
+2016-02-03  Jer Noble  <jer.noble@apple.com>
+
+        [Mac] Wrap a resource and resource loader in a NSURLSession-like object for use by lower level frameworks
+        https://bugs.webkit.org/show_bug.cgi?id=153669
+
+        Reviewed by Alex Christensen.
+
+        API Test: WebCore.WebCoreNSURLSession
+
+        Add a NSURLSession-like object, which wraps a CachedResourceLoader and CachedRawResource, which we can
+        hand to lower-level frameworks, so that network loads by those frameworks use WebKit's loader.
+
+        * platform/network/cocoa/WebCoreNSURLSession.h: Added.
+        * platform/network/cocoa/WebCoreNSURLSession.mm: Added.
+        (-[WebCoreNSURLSession initWithResourceLoader:delegate:delegateQueue:]):
+        (-[WebCoreNSURLSession dealloc]):
+        (-[WebCoreNSURLSession copyWithZone:]):
+        (-[WebCoreNSURLSession delegateQueue]):
+        (-[WebCoreNSURLSession configuration]):
+        (-[WebCoreNSURLSession loader]):
+        (-[WebCoreNSURLSession finishTasksAndInvalidate]):
+        (-[WebCoreNSURLSession invalidateAndCancel]):
+        (-[WebCoreNSURLSession resetWithCompletionHandler:]):
+        (-[WebCoreNSURLSession flushWithCompletionHandler:]):
+        (-[WebCoreNSURLSession getTasksWithCompletionHandler:]):
+        (-[WebCoreNSURLSession getAllTasksWithCompletionHandler:]):
+        (-[WebCoreNSURLSession dataTaskWithRequest:]):
+        (-[WebCoreNSURLSession dataTaskWithURL:]):
+        (-[WebCoreNSURLSession uploadTaskWithRequest:fromFile:]):
+        (-[WebCoreNSURLSession uploadTaskWithRequest:fromData:]):
+        (-[WebCoreNSURLSession uploadTaskWithStreamedRequest:]):
+        (-[WebCoreNSURLSession downloadTaskWithRequest:]):
+        (-[WebCoreNSURLSession downloadTaskWithURL:]):
+        (-[WebCoreNSURLSession downloadTaskWithResumeData:]):
+        (-[WebCoreNSURLSession streamTaskWithHostName:port:]):
+        (-[WebCoreNSURLSession streamTaskWithNetService:]):
+        (-[WebCoreNSURLSession isKindOfClass:]):
+
+        Add a C++ class which can act as a CachedRawResourceClient, passing the results back to a WebCoreNSURLSessionDataTask:
+
+        (WebCore::WebCoreNSURLSessionDataTaskClient::WebCoreNSURLSessionDataTaskClient):
+        (WebCore::WebCoreNSURLSessionDataTaskClient::dataSent):
+        (WebCore::WebCoreNSURLSessionDataTaskClient::responseReceived):
+        (WebCore::WebCoreNSURLSessionDataTaskClient::dataReceived):
+        (WebCore::WebCoreNSURLSessionDataTaskClient::redirectReceived):
+        (WebCore::WebCoreNSURLSessionDataTaskClient::notifyFinished):
+
+        Add a NSURLSessionDataTask-like object, which takes a request, then uses it to create and wrap a CachedRawResource.
+        Becase NSURSessionDataTask is intended to be used off-main-thread, care must be taken to dispatch back to the main-
+        (or web-) thread before calling CachedRawResource functions.
+
+        (-[WebCoreNSURLSessionDataTask initWithSession:identifier:URL:]):
+        (-[WebCoreNSURLSessionDataTask initWithSession:identifier:request:]):
+        (-[WebCoreNSURLSessionDataTask copyWithZone:]):
+        (-[WebCoreNSURLSessionDataTask _restart]):
+        (-[WebCoreNSURLSessionDataTask _cancel]):
+        (-[WebCoreNSURLSessionDataTask _finish]):
+        (-[WebCoreNSURLSessionDataTask _setDefersLoading:]):
+        (-[WebCoreNSURLSessionDataTask cancel]):
+        (-[WebCoreNSURLSessionDataTask suspend]):
+        (-[WebCoreNSURLSessionDataTask resume]):
+        (-[WebCoreNSURLSessionDataTask _timingData]):
+        (-[WebCoreNSURLSessionDataTask resource:sentBytes:totalBytesToBeSent:]):
+        (-[WebCoreNSURLSessionDataTask resource:receivedResponse:]):
+        (-[WebCoreNSURLSessionDataTask resource:receivedData:length:]):
+        (-[WebCoreNSURLSessionDataTask resource:receivedRedirect:request:]):
+        (-[WebCoreNSURLSessionDataTask resourceFinished:]):
+        * WebCore.xcodeproj/project.pbxproj: Add new files to project.
+
 2016-02-03  Darin Adler  <darin@apple.com>
 
         Convert another batch of String::lower callsites to something better, typically convertToASCIILowercase
index a5d14c1..b4c0dfb 100644 (file)
                CD19A2681A13E700008D650E /* DiagnosticLoggingClient.h in Headers */ = {isa = PBXBuildFile; fileRef = CD19A2671A13E700008D650E /* DiagnosticLoggingClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CD1B4A65160786AE00282DF9 /* MediaKeyNeededEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDA98DC216014EEE00FEA3B1 /* MediaKeyNeededEvent.cpp */; };
                CD1E7347167BC78E009A885D /* TextTrackRepresentation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD1E7346167BC78E009A885D /* TextTrackRepresentation.cpp */; };
+               CD225C0B1C46FBF400140761 /* WebCoreNSURLSession.mm in Sources */ = {isa = PBXBuildFile; fileRef = CD225C091C46FBF400140761 /* WebCoreNSURLSession.mm */; };
+               CD225C0C1C46FBF400140761 /* WebCoreNSURLSession.h in Headers */ = {isa = PBXBuildFile; fileRef = CD225C0A1C46FBF400140761 /* WebCoreNSURLSession.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CD27F6E51457685A0078207D /* JSMediaController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD27F6E2145767580078207D /* JSMediaController.cpp */; };
                CD27F6E7145770D30078207D /* MediaController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD27F6E6145770D30078207D /* MediaController.cpp */; };
                CD2F4A2318D89F700063746D /* AudioHardwareListener.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD2F4A2118D89F700063746D /* AudioHardwareListener.cpp */; };
                CD127DEB14F3097900E84779 /* WebCoreFullScreenWindow.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCoreFullScreenWindow.mm; sourceTree = "<group>"; };
                CD19A2671A13E700008D650E /* DiagnosticLoggingClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DiagnosticLoggingClient.h; sourceTree = "<group>"; };
                CD1E7346167BC78E009A885D /* TextTrackRepresentation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextTrackRepresentation.cpp; sourceTree = "<group>"; };
+               CD225C091C46FBF400140761 /* WebCoreNSURLSession.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCoreNSURLSession.mm; sourceTree = "<group>"; };
+               CD225C0A1C46FBF400140761 /* WebCoreNSURLSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebCoreNSURLSession.h; sourceTree = "<group>"; };
                CD27F6E014575C1B0078207D /* MediaController.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = MediaController.idl; sourceTree = "<group>"; };
                CD27F6E2145767580078207D /* JSMediaController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMediaController.cpp; sourceTree = "<group>"; };
                CD27F6E3145767580078207D /* JSMediaController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSMediaController.h; sourceTree = "<group>"; };
                                5C9B860B1C21E3C600110F36 /* ResourceLoadTiming.mm */,
                                7E7DE1FC195CEF260035363B /* ResourceRequestCocoa.mm */,
                                A1F78D0B1C25422C00245446 /* ResourceResponseCocoa.mm */,
+                               CD225C091C46FBF400140761 /* WebCoreNSURLSession.mm */,
+                               CD225C0A1C46FBF400140761 /* WebCoreNSURLSession.h */,
                        );
                        path = cocoa;
                        sourceTree = "<group>";
                                973E325710883B7C005BC493 /* ResourceLoadNotifier.h in Headers */,
                                E4295FA412B0614E00D1ACE0 /* ResourceLoadPriority.h in Headers */,
                                8A81BF8511DCFD9000DA2B98 /* ResourceLoadTiming.h in Headers */,
+                               CD225C0C1C46FBF400140761 /* WebCoreNSURLSession.h in Headers */,
                                7EE6846D12D26E3800E79415 /* ResourceRequest.h in Headers */,
                                514C767D0CE923A1007EF3CD /* ResourceRequestBase.h in Headers */,
                                7EE6846F12D26E3800E79415 /* ResourceRequestCFNet.h in Headers */,
                                FD315FFE12B0267600C1A359 /* ChannelMergerNode.cpp in Sources */,
                                FD31600112B0267600C1A359 /* ChannelSplitterNode.cpp in Sources */,
                                6550B69F099DF0270090D781 /* CharacterData.cpp in Sources */,
+                               CD225C0B1C46FBF400140761 /* WebCoreNSURLSession.mm in Sources */,
                                9326DC0C09DAD5D600AFC847 /* CharsetData.cpp in Sources */,
                                F55B3DB11251F12D003EF269 /* CheckboxInputType.cpp in Sources */,
                                93F925440F7EF5B8007E37C9 /* CheckedRadioButtons.cpp in Sources */,
diff --git a/Source/WebCore/platform/network/cocoa/WebCoreNSURLSession.h b/Source/WebCore/platform/network/cocoa/WebCoreNSURLSession.h
new file mode 100644 (file)
index 0000000..96f1813
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef WebCoreNSURLSession_h
+#define WebCoreNSURLSession_h
+
+#import "CachedRawResource.h"
+#import "CachedResourceHandle.h"
+#import <Foundation/NSURLSession.h>
+#import <wtf/HashSet.h>
+#import <wtf/RefPtr.h>
+#import <wtf/RetainPtr.h>
+
+@class NSNetService;
+@class NSOperationQueue;
+@class NSURL;
+@class NSURLRequest;
+@class NSURLResponse;
+@class WebCoreNSURLSessionDataTask;
+
+namespace WebCore {
+class CachedResourceLoader;
+class CachedResourceRequest;
+class WebCoreNSURLSessionDataTaskClient;
+}
+
+NS_ASSUME_NONNULL_BEGIN
+
+WEBCORE_EXPORT @interface WebCoreNSURLSession : NSObject {
+    RefPtr<WebCore::CachedResourceLoader> _loader;
+    RetainPtr<id<NSURLSessionDelegate>> _delegate;
+    RetainPtr<NSOperationQueue> _queue;
+    NSString *_sessionDescription;
+    HashSet<RetainPtr<WebCoreNSURLSessionDataTask>> _dataTasks;
+    BOOL _invalidated;
+    NSUInteger _nextTaskIdentifier;
+}
+- (id)initWithResourceLoader:(WebCore::CachedResourceLoader&)loader delegate:(id<NSURLSessionTaskDelegate>)delegate delegateQueue:(NSOperationQueue*)queue;
+@property (readonly, retain) NSOperationQueue *delegateQueue;
+@property (nullable, readonly, retain) id <NSURLSessionDelegate> delegate;
+@property (readonly, copy) NSURLSessionConfiguration *configuration;
+@property (copy) NSString *sessionDescription;
+- (void)finishTasksAndInvalidate;
+- (void)invalidateAndCancel;
+
+- (void)resetWithCompletionHandler:(void (^)(void))completionHandler;
+- (void)flushWithCompletionHandler:(void (^)(void))completionHandler;
+- (void)getTasksWithCompletionHandler:(void (^)(NSArray<NSURLSessionDataTask *> *dataTasks, NSArray<NSURLSessionUploadTask *> *uploadTasks, NSArray<NSURLSessionDownloadTask *> *downloadTasks))completionHandler;
+- (void)getAllTasksWithCompletionHandler:(void (^)(NSArray<__kindof NSURLSessionTask *> *tasks))completionHandler;
+
+- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request;
+- (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url;
+- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL;
+- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(NSData *)bodyData;
+- (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request;
+- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request;
+- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url;
+- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData;
+- (NSURLSessionStreamTask *)streamTaskWithHostName:(NSString *)hostname port:(NSInteger)port;
+- (NSURLSessionStreamTask *)streamTaskWithNetService:(NSNetService *)service;
+@end
+
+@interface WebCoreNSURLSession (NSURLSessionAsynchronousConvenience)
+- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSData * data, NSURLResponse * response, NSError * error))completionHandler;
+- (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSData * data, NSURLResponse * response, NSError * error))completionHandler;
+- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL completionHandler:(void (^)(NSData * data, NSURLResponse * response, NSError * error))completionHandler;
+- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(nullable NSData *)bodyData completionHandler:(void (^)(NSData * data, NSURLResponse * response, NSError * error))completionHandler;
+- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURL * location, NSURLResponse * response, NSError * error))completionHandler;
+- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSURL * location, NSURLResponse * response, NSError * error))completionHandler;
+- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData completionHandler:(void (^)(NSURL * location, NSURLResponse * response, NSError * error))completionHandler;
+@end
+
+@interface WebCoreNSURLSessionDataTask : NSObject {
+    WebCoreNSURLSession *_session;
+    std::unique_ptr<WebCore::CachedResourceRequest> _request;
+    std::unique_ptr<WebCore::WebCoreNSURLSessionDataTaskClient> _client;
+    WebCore::CachedResourceHandle<WebCore::CachedRawResource> _resource;
+    RetainPtr<NSURLResponse> _response;
+    NSUInteger _taskIdentifier;
+    NSURLRequest *_originalRequest;
+    NSURLRequest *_currentRequest;
+    int64_t _countOfBytesReceived;
+    int64_t _countOfBytesSent;
+    int64_t _countOfBytesExpectedToSend;
+    int64_t _countOfBytesExpectedToReceive;
+    NSURLSessionTaskState _state;
+    NSError *_error;
+    NSString *_taskDescription;
+    float _priority;
+}
+@property (readwrite) NSUInteger taskIdentifier;
+@property (readwrite, copy) NSURLRequest *originalRequest;
+@property (readwrite, copy) NSURLRequest *currentRequest;
+@property (readonly, copy) NSURLResponse *response;
+@property (readwrite) int64_t countOfBytesReceived;
+@property (readwrite) int64_t countOfBytesSent;
+@property (readwrite) int64_t countOfBytesExpectedToSend;
+@property (readwrite) int64_t countOfBytesExpectedToReceive;
+@property (readwrite) NSURLSessionTaskState state;
+@property (readwrite, copy) NSError *error;
+@property (copy) NSString *taskDescription;
+@property float priority;
+- (void)cancel;
+- (void)suspend;
+- (void)resume;
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif
diff --git a/Source/WebCore/platform/network/cocoa/WebCoreNSURLSession.mm b/Source/WebCore/platform/network/cocoa/WebCoreNSURLSession.mm
new file mode 100644 (file)
index 0000000..12ef7d1
--- /dev/null
@@ -0,0 +1,548 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#import "config.h"
+#import "WebCoreNSURLSession.h"
+
+#import "CachedRawResource.h"
+#import "CachedResourceLoader.h"
+#import "CachedResourceRequest.h"
+#import "SoftLinking.h"
+#import "SubresourceLoader.h"
+
+using namespace WebCore;
+
+#pragma mark - Soft linking
+
+// FIXME: Soft Linking is required for Yosemite; remove once Yosemite support is no longer needed.
+SOFT_LINK_FRAMEWORK(Foundation);
+SOFT_LINK_CONSTANT_MAY_FAIL(Foundation, NSURLSessionTaskPriorityDefault, float)
+#define NSURLSessionTaskPriorityDefault getNSURLSessionTaskPriorityDefault()
+
+#pragma mark - Private declarations
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface WebCoreNSURLSession ()
+@property (readonly) CachedResourceLoader& loader;
+@property (readwrite, retain) id<NSURLSessionTaskDelegate> delegate;
+- (void)taskCompleted:(WebCoreNSURLSessionDataTask *)task;
+@end
+
+@interface WebCoreNSURLSessionDataTask ()
+- (id)initWithSession:(WebCoreNSURLSession *)session identifier:(NSUInteger)identifier request:(NSURLRequest *)request;
+- (id)initWithSession:(WebCoreNSURLSession *)session identifier:(NSUInteger)identifier URL:(NSURL *)url;
+- (void)_restart;
+- (void)_cancel;
+- (void)_finish;
+- (void)_setDefersLoading:(BOOL)defers;
+@property (assign) WebCoreNSURLSession * _Nullable session;
+
+- (void)resource:(CachedResource*)resource sentBytes:(unsigned long long)bytesSent totalBytesToBeSent:(unsigned long long)totalBytesToBeSent;
+- (void)resource:(CachedResource*)resource receivedResponse:(const ResourceResponse&)response;
+- (void)resource:(CachedResource*)resource receivedData:(const char*)data length:(int)length;
+- (void)resource:(CachedResource*)resource receivedRedirect:(const ResourceResponse&)response request:(ResourceRequest&)request;
+- (void)resourceFinished:(CachedResource*)resource;
+@end
+
+NS_ASSUME_NONNULL_END
+
+#pragma mark - WebCoreNSURLSession
+
+@implementation WebCoreNSURLSession
+- (id)initWithResourceLoader:(CachedResourceLoader&)loader delegate:(id<NSURLSessionTaskDelegate>)inDelegate delegateQueue:(NSOperationQueue*)inQueue
+{
+    self = [super init];
+    if (!self)
+        return nil;
+
+    _loader = &loader;
+    self.delegate = inDelegate;
+    _queue = inQueue ? inQueue : [NSOperationQueue mainQueue];
+    _invalidated = NO;
+    return self;
+}
+
+- (void)dealloc
+{
+    for (auto& task : _dataTasks)
+        task.get().session = nil;
+    [super dealloc];
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    UNUSED_PARAM(zone);
+    return [self retain];
+}
+
+#pragma mark - Internal Methods
+
+- (void)taskCompleted:(WebCoreNSURLSessionDataTask *)task
+{
+    ASSERT(_dataTasks.contains(task));
+    _dataTasks.remove(task);
+    if (!_dataTasks.isEmpty() || !_invalidated)
+        return;
+
+    RetainPtr<WebCoreNSURLSession> strongSelf { self };
+    [self.delegateQueue addOperationWithBlock:[strongSelf] {
+        if ([strongSelf.get().delegate respondsToSelector:@selector(URLSession:didBecomeInvalidWithError:)])
+            [strongSelf.get().delegate URLSession:(NSURLSession *)strongSelf.get() didBecomeInvalidWithError:nil];
+    }];
+}
+
+#pragma mark - NSURLSession API
+@synthesize sessionDescription=_sessionDescription;
+@dynamic delegate;
+- (__nullable id<NSURLSessionDelegate>)delegate
+{
+    return _delegate.get();
+}
+
+- (void)setDelegate:(id<NSURLSessionDelegate>)delegate
+{
+    _delegate = delegate;
+}
+
+@dynamic delegateQueue;
+- (NSOperationQueue *)delegateQueue
+{
+    return _queue.get();
+}
+
+@dynamic configuration;
+- (NSURLSessionConfiguration *)configuration
+{
+    return nil;
+}
+
+@dynamic loader;
+- (CachedResourceLoader&)loader
+{
+    return *_loader;
+}
+
+- (void)finishTasksAndInvalidate
+{
+    _invalidated = YES;
+    if (!_dataTasks.isEmpty())
+        return;
+
+    RetainPtr<WebCoreNSURLSession> strongSelf { self };
+    [self.delegateQueue addOperationWithBlock:[strongSelf] {
+        if ([strongSelf.get().delegate respondsToSelector:@selector(URLSession:didBecomeInvalidWithError:)])
+            [strongSelf.get().delegate URLSession:(NSURLSession *)strongSelf.get() didBecomeInvalidWithError:nil];
+    }];
+}
+
+- (void)invalidateAndCancel
+{
+    for (auto& task : _dataTasks)
+        [task cancel];
+
+    [self finishTasksAndInvalidate];
+}
+
+- (void)resetWithCompletionHandler:(void (^)(void))completionHandler
+{
+    // FIXME: This cannot currently be implemented. We cannot guarantee that the next connection will happen on a new socket.
+    [self.delegateQueue addOperationWithBlock:completionHandler];
+}
+
+- (void)flushWithCompletionHandler:(void (^)(void))completionHandler
+{
+    // FIXME: This cannot currently be implemented. We cannot guarantee that the next connection will happen on a new socket.
+    [self.delegateQueue addOperationWithBlock:completionHandler];
+}
+
+- (void)getTasksWithCompletionHandler:(void (^)(NSArray<NSURLSessionDataTask *> *dataTasks, NSArray<NSURLSessionUploadTask *> *uploadTasks, NSArray<NSURLSessionDownloadTask *> *downloadTasks))completionHandler
+{
+    NSMutableArray *array = [NSMutableArray arrayWithCapacity:_dataTasks.size()];
+    for (auto& task : _dataTasks)
+        [array addObject:task.get()];
+    [self.delegateQueue addOperationWithBlock:^{
+        completionHandler(array, nil, nil);
+    }];
+}
+
+- (void)getAllTasksWithCompletionHandler:(void (^)(NSArray<__kindof NSURLSessionTask *> *tasks))completionHandler
+{
+    NSMutableArray *array = [NSMutableArray arrayWithCapacity:_dataTasks.size()];
+    for (auto& task : _dataTasks)
+        [array addObject:task.get()];
+    [self.delegateQueue addOperationWithBlock:^{
+        completionHandler(array);
+    }];
+}
+
+- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
+{
+    if (_invalidated)
+        return nil;
+
+    WebCoreNSURLSessionDataTask *task = [[WebCoreNSURLSessionDataTask alloc] initWithSession:self identifier:_nextTaskIdentifier++ request:request];
+    _dataTasks.add(task);
+    return (NSURLSessionDataTask *)[task autorelease];
+}
+
+- (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url
+{
+    if (_invalidated)
+        return nil;
+
+    WebCoreNSURLSessionDataTask *task = [[WebCoreNSURLSessionDataTask alloc] initWithSession:self identifier:_nextTaskIdentifier++ URL:url];
+    _dataTasks.add(task);
+    return (NSURLSessionDataTask *)[task autorelease];
+}
+
+- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL
+{
+    UNUSED_PARAM(request);
+    UNUSED_PARAM(fileURL);
+    return nil;
+}
+
+- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(NSData *)bodyData
+{
+    UNUSED_PARAM(request);
+    UNUSED_PARAM(bodyData);
+    return nil;
+}
+
+- (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request
+{
+    UNUSED_PARAM(request);
+    return nil;
+}
+
+- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request
+{
+    UNUSED_PARAM(request);
+    return nil;
+}
+
+- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url
+{
+    UNUSED_PARAM(url);
+    return nil;
+}
+
+- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData
+{
+    UNUSED_PARAM(resumeData);
+    return nil;
+}
+
+- (NSURLSessionStreamTask *)streamTaskWithHostName:(NSString *)hostname port:(NSInteger)port
+{
+    UNUSED_PARAM(hostname);
+    UNUSED_PARAM(port);
+    return nil;
+}
+
+- (NSURLSessionStreamTask *)streamTaskWithNetService:(NSNetService *)service
+{
+    UNUSED_PARAM(service);
+    return nil;
+}
+
+- (BOOL)isKindOfClass:(Class)aClass
+{
+    if (aClass == [NSURLSession class])
+        return YES;
+    return [super isKindOfClass:aClass];
+}
+@end
+
+#pragma mark - WebCoreNSURLSessionDataTaskClient
+
+namespace WebCore {
+
+class WebCoreNSURLSessionDataTaskClient : public CachedRawResourceClient {
+public:
+    WebCoreNSURLSessionDataTaskClient(WebCoreNSURLSessionDataTask *task)
+        : m_task(task)
+    {
+    }
+
+    void dataSent(CachedResource*, unsigned long long, unsigned long long) override;
+    void responseReceived(CachedResource*, const ResourceResponse&) override;
+    void dataReceived(CachedResource*, const char* /* data */, int /* length */) override;
+    void redirectReceived(CachedResource*, ResourceRequest&, const ResourceResponse&) override;
+    void notifyFinished(CachedResource*) override;
+
+private:
+    WebCoreNSURLSessionDataTask *m_task;
+};
+
+void WebCoreNSURLSessionDataTaskClient::dataSent(CachedResource* resource, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
+{
+    [m_task resource:resource sentBytes:bytesSent totalBytesToBeSent:totalBytesToBeSent];
+}
+
+void WebCoreNSURLSessionDataTaskClient::responseReceived(CachedResource* resource, const ResourceResponse& response)
+{
+    [m_task resource:resource receivedResponse:response];
+}
+
+void WebCoreNSURLSessionDataTaskClient::dataReceived(CachedResource* resource, const char* data, int length)
+{
+    [m_task resource:resource receivedData:data length:length];
+}
+
+void WebCoreNSURLSessionDataTaskClient::redirectReceived(CachedResource* resource, ResourceRequest& request, const ResourceResponse& response)
+{
+    [m_task resource:resource receivedRedirect:response request:request];
+}
+
+void WebCoreNSURLSessionDataTaskClient::notifyFinished(CachedResource* resource)
+{
+    [m_task resourceFinished:resource];
+}
+
+}
+
+#pragma mark - WebCoreNSURLSessionDataTask
+
+@implementation WebCoreNSURLSessionDataTask
+- (id)initWithSession:(WebCoreNSURLSession *)session identifier:(NSUInteger)identifier URL:(NSURL *)url
+{
+    self.taskIdentifier = identifier;
+    self.session = session;
+    self.state = NSURLSessionTaskStateSuspended;
+    self.priority = canLoadNSURLSessionTaskPriorityDefault() ? NSURLSessionTaskPriorityDefault : 0.5f;
+    self.originalRequest = self.currentRequest = [NSURLRequest requestWithURL:url];
+    _client = std::make_unique<WebCoreNSURLSessionDataTaskClient>(self);
+
+    return self;
+}
+
+- (id)initWithSession:(WebCoreNSURLSession *)session identifier:(NSUInteger)identifier request:(NSURLRequest *)request
+{
+    self.taskIdentifier = identifier;
+    self.session = session;
+    self.state = NSURLSessionTaskStateSuspended;
+    self.priority = canLoadNSURLSessionTaskPriorityDefault() ? NSURLSessionTaskPriorityDefault : 0.5f;
+    self.originalRequest = self.currentRequest = request;
+    _client = std::make_unique<WebCoreNSURLSessionDataTaskClient>(self);
+
+    return self;
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    UNUSED_PARAM(zone);
+    return [self retain];
+}
+
+#pragma mark - Internal methods
+
+- (void)_restart
+{
+    ASSERT(isMainThread());
+    [self _cancel];
+
+    _request = std::make_unique<CachedResourceRequest>(self.originalRequest, ResourceLoaderOptions(SendCallbacks, DoNotSniffContent, DoNotBufferData, DoNotAllowStoredCredentials, DoNotAskClientForCrossOriginCredentials, ClientDidNotRequestCredentials, DoSecurityCheck, UseDefaultOriginRestrictionsForType, DoNotIncludeCertificateInfo, ContentSecurityPolicyImposition::DoPolicyCheck, DefersLoadingPolicy::AllowDefersLoading, CachingPolicy::DisallowCaching));
+    _resource = self.session.loader.requestRawResource(*_request);
+    if (_resource)
+        _resource->addClient(_client.get());
+}
+
+- (void)_cancel
+{
+    ASSERT(isMainThread());
+    if (_resource) {
+        if (SubresourceLoader* loader = _resource->loader())
+            loader->cancel(ResourceError());
+        _resource->removeClient(_client.get());
+        _resource = nil;
+    }
+}
+
+- (void)_finish
+{
+    ASSERT(isMainThread());
+    if (_resource)
+        [self resourceFinished:_resource.get()];
+}
+
+- (void)_setDefersLoading:(BOOL)defers
+{
+    ASSERT(isMainThread());
+    if (_resource && _resource->loader())
+        _resource->loader()->setDefersLoading(defers);
+}
+
+#pragma mark - NSURLSession API
+@synthesize session=_session;
+@synthesize taskIdentifier=_taskIdentifier;
+@synthesize originalRequest=_originalRequest;
+@synthesize currentRequest=_currentRequest;
+@synthesize countOfBytesReceived=_countOfBytesReceived;
+@synthesize countOfBytesSent=_countOfBytesSent;
+@synthesize countOfBytesExpectedToSend=_countOfBytesExpectedToSend;
+@synthesize countOfBytesExpectedToReceive=_countOfBytesExpectedToReceive;
+@synthesize state=_state;
+@synthesize error=_error;
+@synthesize taskDescription=_taskDescription;
+@synthesize priority=_priority;
+@dynamic response;
+- (NSURLResponse *)response
+{
+    return _response.get();
+}
+
+- (void)cancel
+{
+    self.state = NSURLSessionTaskStateCanceling;
+    RetainPtr<WebCoreNSURLSessionDataTask> strongSelf { self };
+    callOnMainThread([strongSelf] {
+        [strongSelf _cancel];
+        [strongSelf _finish];
+    });
+}
+
+- (void)suspend
+{
+    RetainPtr<WebCoreNSURLSessionDataTask> strongSelf { self };
+    callOnMainThread([strongSelf] {
+        // NSURLSessionDataTasks must start over after suspending, so while
+        // we could defer loading at this point, instead cancel and restart
+        // upon resume so as to adhere to NSURLSessionDataTask semantics.
+        [strongSelf _cancel];
+        strongSelf.get().state = NSURLSessionTaskStateSuspended;
+    });
+}
+
+- (void)resume
+{
+    RetainPtr<WebCoreNSURLSessionDataTask> strongSelf { self };
+    callOnMainThread([strongSelf] {
+        if (strongSelf.get().state != NSURLSessionTaskStateSuspended)
+            return;
+
+        [strongSelf _restart];
+        strongSelf.get().state = NSURLSessionTaskStateRunning;
+    });
+}
+
+#pragma mark - NSURLSession SPI
+
+- (NSDictionary *)_timingData
+{
+    // FIXME: return a dictionary sourced from ResourceHandle::getConnectionTimingData().
+    return @{ };
+}
+
+#pragma mark - CachedRawResourceClient callbacks
+
+- (void)resource:(CachedResource*)resource sentBytes:(unsigned long long)bytesSent totalBytesToBeSent:(unsigned long long)totalBytesToBeSent
+{
+    ASSERT_UNUSED(resource, resource == _resource);
+    UNUSED_PARAM(bytesSent);
+    UNUSED_PARAM(totalBytesToBeSent);
+    // No-op.
+}
+
+- (void)resource:(CachedResource*)resource receivedResponse:(const ResourceResponse&)response
+{
+    ASSERT_UNUSED(resource, resource == _resource);
+    ASSERT(isMainThread());
+    _response = response.nsURLResponse();
+    self.countOfBytesExpectedToReceive = response.expectedContentLength();
+    [self _setDefersLoading:YES];
+    RetainPtr<WebCoreNSURLSessionDataTask> strongSelf { self };
+    [self.session.delegateQueue addOperationWithBlock:[strongSelf] {
+        id<NSURLSessionDataDelegate> dataDelegate = (id<NSURLSessionDataDelegate>)strongSelf.get().session.delegate;
+        if (![dataDelegate respondsToSelector:@selector(URLSession:dataTask:didReceiveResponse:completionHandler:)]) {
+            callOnMainThread([strongSelf] {
+                [strongSelf _setDefersLoading:NO];
+            });
+            return;
+        }
+
+        [dataDelegate URLSession:(NSURLSession *)strongSelf.get().session dataTask:(NSURLSessionDataTask *)strongSelf.get() didReceiveResponse:strongSelf.get().response completionHandler:[strongSelf] (NSURLSessionResponseDisposition disposition) {
+            if (disposition == NSURLSessionResponseCancel)
+                [strongSelf cancel];
+            else if (disposition == NSURLSessionResponseAllow)
+                [strongSelf resume];
+            else
+                ASSERT_NOT_REACHED();
+            callOnMainThread([strongSelf] {
+                [strongSelf _setDefersLoading:NO];
+            });
+        }];
+    }];
+}
+
+- (void)resource:(CachedResource*)resource receivedData:(const char*)data length:(int)length
+{
+    ASSERT_UNUSED(resource, resource == _resource);
+    UNUSED_PARAM(data);
+    UNUSED_PARAM(length);
+    // FIXME: try to avoid a copy, if possible.
+    // e.g., RetainPtr<CFDataRef> cfData = resource->resourceBuffer()->createCFData();
+
+    RetainPtr<NSData> nsData = adoptNS([[NSData alloc] initWithBytes:data length:length]);
+    RetainPtr<WebCoreNSURLSessionDataTask> strongSelf { self };
+    [self.session.delegateQueue addOperationWithBlock:[strongSelf, length, nsData] {
+        strongSelf.get().countOfBytesReceived += length;
+        id<NSURLSessionDataDelegate> dataDelegate = (id<NSURLSessionDataDelegate>)strongSelf.get().session.delegate;
+        if ([dataDelegate respondsToSelector:@selector(URLSession:dataTask:didReceiveData:)])
+            [dataDelegate URLSession:(NSURLSession *)strongSelf.get().session dataTask:(NSURLSessionDataTask *)strongSelf.get() didReceiveData:nsData.get()];
+    }];
+}
+
+- (void)resource:(CachedResource*)resource receivedRedirect:(const ResourceResponse&)response request:(ResourceRequest&)request
+{
+    ASSERT_UNUSED(resource, resource == _resource);
+    UNUSED_PARAM(response);
+    UNUSED_PARAM(request);
+    // FIXME: This cannot currently be implemented, as the callback is synchronous
+    // on the main thread, and the NSURLSession delegate must be called back on a
+    // background queue, and we do not want to block the main thread until the
+    // delegate handles the callback and responds via a completion handler. If, in
+    // the future, the ResourceLoader exposes a callback-based willSendResponse
+    // API, this can be implemented.
+}
+
+- (void)resourceFinished:(CachedResource*)resource
+{
+    ASSERT_UNUSED(resource, resource == _resource);
+    self.state = NSURLSessionTaskStateCompleted;
+
+    RetainPtr<WebCoreNSURLSessionDataTask> strongSelf { self };
+    [self.session.delegateQueue addOperationWithBlock:[strongSelf] {
+        id<NSURLSessionTaskDelegate> delegate = (id<NSURLSessionTaskDelegate>)strongSelf.get().session.delegate;
+        if ([delegate respondsToSelector:@selector(URLSession:task:didCompleteWithError:)])
+            [delegate URLSession:(NSURLSession *)strongSelf.get().session task:(NSURLSessionDataTask *)strongSelf.get() didCompleteWithError:nil];
+
+        callOnMainThread([strongSelf] {
+            [strongSelf.get().session taskCompleted:strongSelf.get()];
+        });
+    }];
+}
+@end
index a96bfdb..8949d63 100644 (file)
@@ -1,3 +1,29 @@
+2016-02-03  Jer Noble  <jer.noble@apple.com>
+
+        [Mac] Wrap a resource and resource loader in a NSURLSession-like object for use by lower level frameworks
+        https://bugs.webkit.org/show_bug.cgi?id=153669
+
+        Reviewed by Alex Christensen.
+
+        Add an API test for WebCoreNSURLSession, testing that it behaves like a regulare NSURLSession, including
+        calling appropriate NSURLSessionDelegate callbacks.
+
+        Drive-by fix: Add a FeatureDefines.xcconfig to TestWebKitAPI.  Without this, the ENABLE macros in WebCore
+        header files will not match the one used when compiling WebCore, leading to strange crashes and weird
+        inconsistencies when calling, e.g., inline methods.
+
+        * TestWebKitAPI/Configurations/FeatureDefines.xcconfig: Added.
+        * TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig:
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebCore/WebCoreNSURLSession.mm: Added.
+        (-[TestNSURLSessionLoaderDelegate webView:didCommitLoadForFrame:]):
+        (-[TestNSURLSessionDataDelegate URLSession:task:didCompleteWithError:]):
+        (-[TestNSURLSessionDataDelegate URLSession:dataTask:didReceiveResponse:completionHandler:]):
+        (-[TestNSURLSessionDataDelegate URLSession:dataTask:didReceiveData:]):
+        (TestWebKitAPI::WebCoreNSURLSessionTest::SetUp):
+        (TestWebKitAPI::WebCoreNSURLSessionTest::TearDown):
+        (TestWebKitAPI::TEST_F):
+
 2016-02-03  Konstantin Tokarev  <annulen@yandex.ru>
 
         [webkitdirs] Clarify logic behind is{PortName} functions.
diff --git a/Tools/TestWebKitAPI/Configurations/FeatureDefines.xcconfig b/Tools/TestWebKitAPI/Configurations/FeatureDefines.xcconfig
new file mode 100644 (file)
index 0000000..4927cea
--- /dev/null
@@ -0,0 +1,195 @@
+// Copyright (C) 2009, 2010, 2014, 2015 Apple Inc. All rights reserved.
+// Copyright (C) 2009 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The contents of this file must be kept in sync with FeatureDefines.xcconfig in JavaScriptCore,
+// WebCore, WebKit and WebKit2.  Also the default values of the ENABLE_FEATURE_NAME macros in
+// build-webkit should match the values below, but they do not need to be in the same order.
+
+// Keep this list of features (not enabled/disabled state) in sync with FeatureDefines.vsprops
+// and FeatureDefinesCairo.vsprops in WebKitLibraries/win/tools/vsprops.
+
+// Set any ENABLE_FEATURE_NAME macro to an empty string to disable that feature.
+
+ENABLE_3D_TRANSFORMS = ENABLE_3D_TRANSFORMS;
+ENABLE_ACCELERATED_2D_CANVAS = ;
+ENABLE_ACCELERATED_OVERFLOW_SCROLLING[sdk=iphone*] = ENABLE_ACCELERATED_OVERFLOW_SCROLLING;
+ENABLE_ATTACHMENT_ELEMENT = ENABLE_ATTACHMENT_ELEMENT;
+ENABLE_AVF_CAPTIONS = ENABLE_AVF_CAPTIONS;
+ENABLE_CACHE_PARTITIONING = ENABLE_CACHE_PARTITIONING;
+ENABLE_CANVAS_PATH = ENABLE_CANVAS_PATH;
+ENABLE_CANVAS_PROXY = ;
+ENABLE_CHANNEL_MESSAGING = ENABLE_CHANNEL_MESSAGING;
+ENABLE_ES6_ARROWFUNCTION_SYNTAX = ENABLE_ES6_ARROWFUNCTION_SYNTAX;
+ENABLE_ES6_CLASS_SYNTAX = ENABLE_ES6_CLASS_SYNTAX;
+ENABLE_ES6_GENERATORS = ENABLE_ES6_GENERATORS;
+ENABLE_ES6_MODULES = ;
+ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX = ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX;
+ENABLE_CONTENT_FILTERING = ENABLE_CONTENT_FILTERING;
+ENABLE_CSP_NEXT = ;
+ENABLE_CSS_ANIMATIONS_LEVEL_2 = ENABLE_CSS_ANIMATIONS_LEVEL_2;
+ENABLE_CSS_BOX_DECORATION_BREAK = ENABLE_CSS_BOX_DECORATION_BREAK;
+ENABLE_CSS_COMPOSITING = ENABLE_CSS_COMPOSITING;
+ENABLE_CSS_DEVICE_ADAPTATION = ;
+ENABLE_CSS_GRID_LAYOUT = ENABLE_CSS_GRID_LAYOUT;
+ENABLE_CSS_IMAGE_ORIENTATION = ;
+ENABLE_CSS_IMAGE_RESOLUTION = ;
+ENABLE_CSS_REGIONS = ENABLE_CSS_REGIONS;
+ENABLE_CSS_SELECTORS_LEVEL4 = ENABLE_CSS_SELECTORS_LEVEL4;
+ENABLE_CSS_SHAPES = ENABLE_CSS_SHAPES;
+ENABLE_CSS3_TEXT = ;
+ENABLE_CSS3_TEXT_LINE_BREAK = ;
+ENABLE_CURRENTSRC = ;
+ENABLE_CURSOR_VISIBILITY = ENABLE_CURSOR_VISIBILITY;
+ENABLE_CUSTOM_SCHEME_HANDLER = ;
+ENABLE_DASHBOARD_SUPPORT[sdk=macosx*] = ENABLE_DASHBOARD_SUPPORT;
+ENABLE_DATALIST_ELEMENT = ;
+ENABLE_DATA_TRANSFER_ITEMS = ;
+ENABLE_DETAILS_ELEMENT = ENABLE_DETAILS_ELEMENT;
+ENABLE_DEVICE_ORIENTATION[sdk=iphone*] = ENABLE_DEVICE_ORIENTATION;
+ENABLE_DOM4_EVENTS_CONSTRUCTOR = ENABLE_DOM4_EVENTS_CONSTRUCTOR;
+ENABLE_ENCRYPTED_MEDIA[sdk=macosx*] = ENABLE_ENCRYPTED_MEDIA;
+ENABLE_ENCRYPTED_MEDIA_V2[sdk=macosx*] = ENABLE_ENCRYPTED_MEDIA_V2;
+ENABLE_FETCH_API = ENABLE_FETCH_API;
+ENABLE_FILTERS_LEVEL_2 = ENABLE_FILTERS_LEVEL_2;
+ENABLE_FONT_LOAD_EVENTS = ;
+ENABLE_FULLSCREEN_API[sdk=macosx*] = ENABLE_FULLSCREEN_API;
+ENABLE_GAMEPAD[sdk=macosx*] = ENABLE_GAMEPAD;
+ENABLE_GAMEPAD_DEPRECATED = ;
+ENABLE_GEOLOCATION = ENABLE_GEOLOCATION;
+ENABLE_HIDDEN_PAGE_DOM_TIMER_THROTTLING[sdk=macosx*] = ENABLE_HIDDEN_PAGE_DOM_TIMER_THROTTLING;
+ENABLE_ICONDATABASE[sdk=macosx*] = ENABLE_ICONDATABASE;
+ENABLE_SERVICE_CONTROLS[sdk=macosx*] = ENABLE_SERVICE_CONTROLS;
+ENABLE_INDEXED_DATABASE = ENABLE_INDEXED_DATABASE;
+ENABLE_INDEXED_DATABASE_IN_WORKERS = ;
+ENABLE_INDIE_UI = ENABLE_INDIE_UI;
+ENABLE_INPUT_TYPE_COLOR[sdk=macosx*] = ENABLE_INPUT_TYPE_COLOR;
+ENABLE_INPUT_TYPE_COLOR_POPOVER[sdk=macosx*] = ENABLE_INPUT_TYPE_COLOR_POPOVER;
+ENABLE_INPUT_TYPE_DATE[sdk=iphone*] = ENABLE_INPUT_TYPE_DATE;
+ENABLE_INPUT_TYPE_DATETIME_INCOMPLETE = ;
+ENABLE_INPUT_TYPE_DATETIMELOCAL[sdk=iphone*] = ENABLE_INPUT_TYPE_DATETIMELOCAL;
+ENABLE_INPUT_TYPE_MONTH[sdk=iphone*] = ENABLE_INPUT_TYPE_MONTH;
+ENABLE_INPUT_TYPE_TIME[sdk=iphone*] = ENABLE_INPUT_TYPE_TIME;
+ENABLE_INPUT_TYPE_WEEK[sdk=iphone*] = ENABLE_INPUT_TYPE_WEEK;
+
+ENABLE_INSPECTOR_ALTERNATE_DISPATCHERS = ENABLE_INSPECTOR_ALTERNATE_DISPATCHERS;
+
+ENABLE_WIRELESS_PLAYBACK_TARGET[sdk=iphone*] = ENABLE_WIRELESS_PLAYBACK_TARGET;
+ENABLE_WIRELESS_PLAYBACK_TARGET[sdk=macosx*] = $(ENABLE_WIRELESS_PLAYBACK_TARGET_macosx_$(TARGET_MAC_OS_X_VERSION_MAJOR))
+ENABLE_WIRELESS_PLAYBACK_TARGET_macosx_101000 = ;
+ENABLE_WIRELESS_PLAYBACK_TARGET_macosx_101100 = ENABLE_WIRELESS_PLAYBACK_TARGET;
+ENABLE_WIRELESS_PLAYBACK_TARGET_macosx_101200 = ENABLE_WIRELESS_PLAYBACK_TARGET;
+
+ENABLE_INTL = ENABLE_INTL;
+
+ENABLE_IOS_GESTURE_EVENTS = ;
+ENABLE_IOS_GESTURE_EVENTS[sdk=iphone*] = $(ENABLE_IOS_GESTURE_EVENTS_ios_WITH_INTERNAL_SDK_$(USE_INTERNAL_SDK));
+ENABLE_IOS_GESTURE_EVENTS_ios_WITH_INTERNAL_SDK_YES = ENABLE_IOS_GESTURE_EVENTS;
+
+ENABLE_MAC_GESTURE_EVENTS = ;
+ENABLE_MAC_GESTURE_EVENTS[sdk=macosx*] = $(ENABLE_MAC_GESTURE_EVENTS_macosx_WITH_INTERNAL_SDK_$(USE_INTERNAL_SDK));
+ENABLE_MAC_GESTURE_EVENTS_macosx_WITH_INTERNAL_SDK_YES = ENABLE_MAC_GESTURE_EVENTS;
+
+ENABLE_IOS_TEXT_AUTOSIZING[sdk=iphone*] = ENABLE_IOS_TEXT_AUTOSIZING;
+
+ENABLE_IOS_TOUCH_EVENTS[sdk=iphone*] = $(ENABLE_IOS_TOUCH_EVENTS_ios_WITH_INTERNAL_SDK_$(USE_INTERNAL_SDK));
+ENABLE_IOS_TOUCH_EVENTS_ios_WITH_INTERNAL_SDK_YES = ENABLE_IOS_TOUCH_EVENTS;
+
+ENABLE_LEGACY_CSS_VENDOR_PREFIXES = ENABLE_LEGACY_CSS_VENDOR_PREFIXES;
+ENABLE_LEGACY_NOTIFICATIONS[sdk=macosx*] = ENABLE_LEGACY_NOTIFICATIONS;
+ENABLE_LEGACY_VENDOR_PREFIXES = ENABLE_LEGACY_VENDOR_PREFIXES;
+ENABLE_LEGACY_WEB_AUDIO = ENABLE_LEGACY_WEB_AUDIO;
+ENABLE_LETTERPRESS[sdk=iphone*] = ENABLE_LETTERPRESS;
+ENABLE_LINK_PREFETCH = ;
+ENABLE_MATHML = ENABLE_MATHML;
+ENABLE_MEDIA_CONTROLS_SCRIPT = ENABLE_MEDIA_CONTROLS_SCRIPT;
+ENABLE_MEDIA_SESSION = ;
+
+ENABLE_MEDIA_SOURCE[sdk=macosx*] = ENABLE_MEDIA_SOURCE;
+
+ENABLE_MEDIA_STATISTICS = ;
+ENABLE_MEDIA_STREAM = ENABLE_MEDIA_STREAM;
+ENABLE_METER_ELEMENT[sdk=macosx*] = ENABLE_METER_ELEMENT;
+ENABLE_MHTML = ;
+ENABLE_MOUSE_CURSOR_SCALE[sdk=macosx*] = ENABLE_MOUSE_CURSOR_SCALE;
+ENABLE_NAVIGATOR_CONTENT_UTILS = ;
+ENABLE_NAVIGATOR_HWCONCURRENCY = ENABLE_NAVIGATOR_HWCONCURRENCY;
+ENABLE_NOSNIFF = ;
+ENABLE_NOTIFICATIONS[sdk=macosx*] = ENABLE_NOTIFICATIONS;
+ENABLE_PDFKIT_PLUGIN[sdk=macosx*] = ENABLE_PDFKIT_PLUGIN;
+ENABLE_POINTER_LOCK = ;
+ENABLE_PROXIMITY_EVENTS = ;
+ENABLE_PUBLIC_SUFFIX_LIST = ENABLE_PUBLIC_SUFFIX_LIST;
+ENABLE_QUOTA = ;
+ENABLE_REQUEST_ANIMATION_FRAME = ENABLE_REQUEST_ANIMATION_FRAME;
+ENABLE_REQUEST_AUTOCOMPLETE = ;
+ENABLE_REMOTE_INSPECTOR = ENABLE_REMOTE_INSPECTOR;
+ENABLE_RESOLUTION_MEDIA_QUERY = ;
+ENABLE_RUBBER_BANDING[sdk=macosx*] = ENABLE_RUBBER_BANDING;
+ENABLE_CSS_SCROLL_SNAP = ENABLE_CSS_SCROLL_SNAP;
+ENABLE_SPEECH_SYNTHESIS = ENABLE_SPEECH_SYNTHESIS;
+ENABLE_STREAMS_API = ENABLE_STREAMS_API;
+ENABLE_SUBTLE_CRYPTO = ENABLE_SUBTLE_CRYPTO;
+ENABLE_SVG_FONTS = ENABLE_SVG_FONTS;
+ENABLE_SVG_OTF_CONVERTER = ENABLE_SVG_OTF_CONVERTER;
+
+ENABLE_TELEPHONE_NUMBER_DETECTION = ENABLE_TELEPHONE_NUMBER_DETECTION;
+
+ENABLE_TEMPLATE_ELEMENT = ENABLE_TEMPLATE_ELEMENT;
+ENABLE_TEXT_AUTOSIZING = ;
+
+ENABLE_CSS_TRAILING_WORD = ENABLE_CSS_TRAILING_WORD;
+
+// FIXME: Remove the USE_INTERNAL_SDK condition once we support touch events when building for iOS with
+// the public SDK. We will also need to update FeatureDefines.h.
+ENABLE_TOUCH_EVENTS[sdk=iphone*] = $(ENABLE_TOUCH_EVENTS_ios_WITH_INTERNAL_SDK_$(USE_INTERNAL_SDK));
+ENABLE_TOUCH_EVENTS_ios_WITH_INTERNAL_SDK_YES = ENABLE_TOUCH_EVENTS;
+
+ENABLE_TOUCH_ICON_LOADING = ;
+ENABLE_USERSELECT_ALL = ENABLE_USERSELECT_ALL;
+ENABLE_VIDEO = ENABLE_VIDEO;
+ENABLE_VIDEO_PRESENTATION_MODE[sdk=iphone*] = ENABLE_VIDEO_PRESENTATION_MODE;
+ENABLE_VIDEO_TRACK = ENABLE_VIDEO_TRACK;
+ENABLE_DATACUE_VALUE = ENABLE_DATACUE_VALUE;
+ENABLE_VIEW_MODE_CSS_MEDIA = ;
+ENABLE_WEBASSEMBLY = ;
+ENABLE_WEBGL = ENABLE_WEBGL;
+ENABLE_WEBGL2 = ;
+ENABLE_WEB_ANIMATIONS = ;
+ENABLE_WEB_AUDIO = ENABLE_WEB_AUDIO;
+ENABLE_WEB_REPLAY = $(ENABLE_WEB_REPLAY_$(PLATFORM_NAME)_$(CONFIGURATION));
+ENABLE_WEB_REPLAY_macosx_Debug = ENABLE_WEB_REPLAY;
+ENABLE_WEB_REPLAY_macosx_Release = ENABLE_WEB_REPLAY;
+ENABLE_WEB_SOCKETS = ENABLE_WEB_SOCKETS;
+
+ENABLE_WEB_TIMING = ENABLE_WEB_TIMING;
+
+ENABLE_XSLT = ENABLE_XSLT;
+
+ENABLE_FTL_JIT[sdk=macosx*] = ENABLE_FTL_JIT;
+ENABLE_FTL_JIT[sdk=iphoneos*] = ENABLE_FTL_JIT;
+
+ENABLE_SHADOW_DOM = ENABLE_SHADOW_DOM;
+ENABLE_CUSTOM_ELEMENTS = ENABLE_CUSTOM_ELEMENTS;
+
+FEATURE_DEFINES = $(ENABLE_3D_TRANSFORMS) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ACCELERATED_OVERFLOW_SCROLLING) $(ENABLE_AVF_CAPTIONS) $(ENABLE_ATTACHMENT_ELEMENT) $(ENABLE_CACHE_PARTITIONING) $(ENABLE_CANVAS_PATH) $(ENABLE_CANVAS_PROXY) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_ES6_ARROWFUNCTION_SYNTAX) $(ENABLE_ES6_CLASS_SYNTAX) $(ENABLE_ES6_GENERATORS) $(ENABLE_ES6_MODULES) $(ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX) $(ENABLE_CONTENT_FILTERING) $(ENABLE_CSP_NEXT) $(ENABLE_CSS_ANIMATIONS_LEVEL_2) $(ENABLE_CSS_BOX_DECORATION_BREAK) $(ENABLE_CSS_COMPOSITING) $(ENABLE_CSS_DEVICE_ADAPTATION) $(ENABLE_CSS_GRID_LAYOUT) $(ENABLE_CSS_IMAGE_ORIENTATION) $(ENABLE_CSS_IMAGE_RESOLUTION) $(ENABLE_CSS_REGIONS) $(ENABLE_CSS_SELECTORS_LEVEL4) $(ENABLE_CSS_SHAPES) $(ENABLE_CSS3_TEXT) $(ENABLE_CSS3_TEXT_LINE_BREAK) $(ENABLE_CURSOR_VISIBILITY) $(ENABLE_CUSTOM_SCHEME_HANDLER) $(ENABLE_DASHBOARD_SUPPORT) $(ENABLE_DATALIST_ELEMENT) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS_ELEMENT) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DOM4_EVENTS_CONSTRUCTOR) $(ENABLE_ENCRYPTED_MEDIA) $(ENABLE_ENCRYPTED_MEDIA_V2) $(ENABLE_FETCH_API) $(ENABLE_FILTERS_LEVEL_2) $(ENABLE_FONT_LOAD_EVENTS) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GAMEPAD_DEPRECATED) $(ENABLE_GEOLOCATION) $(ENABLE_HIDDEN_PAGE_DOM_TIMER_THROTTLING) $(ENABLE_ICONDATABASE) $(ENABLE_SERVICE_CONTROLS) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INDEXED_DATABASE_IN_WORKERS) $(ENABLE_INDIE_UI) $(ENABLE_INPUT_TYPE_COLOR) $(ENABLE_INPUT_TYPE_COLOR_POPOVER) $(ENABLE_INPUT_TYPE_DATE) $(ENABLE_INPUT_TYPE_DATETIME_INCOMPLETE) $(ENABLE_INPUT_TYPE_DATETIMELOCAL) $(ENABLE_INPUT_TYPE_MONTH) $(ENABLE_INPUT_TYPE_TIME) $(ENABLE_INPUT_TYPE_WEEK) $(ENABLE_WIRELESS_PLAYBACK_TARGET) $(ENABLE_INTL) $(ENABLE_IOS_GESTURE_EVENTS) $(ENABLE_IOS_TEXT_AUTOSIZING) $(ENABLE_IOS_TOUCH_EVENTS) $(ENABLE_LEGACY_CSS_VENDOR_PREFIXES) $(ENABLE_LEGACY_NOTIFICATIONS) $(ENABLE_LEGACY_VENDOR_PREFIXES) $(ENABLE_LEGACY_WEB_AUDIO) $(ENABLE_LETTERPRESS) $(ENABLE_LINK_PREFETCH) $(ENABLE_MAC_GESTURE_EVENTS) $(ENABLE_MATHML) $(ENABLE_MEDIA_CONTROLS_SCRIPT) $(ENABLE_MEDIA_SESSION) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_MEDIA_STREAM) $(ENABLE_METER_ELEMENT) $(ENABLE_MHTML) $(ENABLE_MOUSE_CURSOR_SCALE) $(ENABLE_NAVIGATOR_CONTENT_UTILS) $(ENABLE_NAVIGATOR_HWCONCURRENCY) $(ENABLE_NOTIFICATIONS) $(ENABLE_PDFKIT_PLUGIN) $(ENABLE_CURRENTSRC) $(ENABLE_POINTER_LOCK) $(ENABLE_PROXIMITY_EVENTS) $(ENABLE_PUBLIC_SUFFIX_LIST) $(ENABLE_QUOTA) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_REQUEST_AUTOCOMPLETE) $(ENABLE_REMOTE_INSPECTOR) $(ENABLE_RESOLUTION_MEDIA_QUERY) $(ENABLE_RUBBER_BANDING) $(ENABLE_CSS_SCROLL_SNAP) $(ENABLE_SPEECH_SYNTHESIS) $(ENABLE_STREAMS_API) $(ENABLE_SUBTLE_CRYPTO) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_OTF_CONVERTER) $(ENABLE_TELEPHONE_NUMBER_DETECTION) $(ENABLE_TEMPLATE_ELEMENT) $(ENABLE_TEXT_AUTOSIZING) $(ENABLE_TOUCH_EVENTS) $(ENABLE_TOUCH_ICON_LOADING) $(ENABLE_CSS_TRAILING_WORD) $(ENABLE_USERSELECT_ALL) $(ENABLE_VIDEO) $(ENABLE_VIDEO_TRACK) $(ENABLE_DATACUE_VALUE) $(ENABLE_VIEW_MODE_CSS_MEDIA) $(ENABLE_WEBASSEMBLY) $(ENABLE_WEBGL) $(ENABLE_WEBGL2) $(ENABLE_WEB_ANIMATIONS) $(ENABLE_WEB_AUDIO) $(ENABLE_WEB_REPLAY) $(ENABLE_WEB_SOCKETS) $(ENABLE_WEB_TIMING) $(ENABLE_XSLT) $(ENABLE_FTL_JIT) $(ENABLE_JIT) $(ENABLE_SHADOW_DOM) $(ENABLE_CUSTOM_ELEMENTS) $(ENABLE_VIDEO_PRESENTATION_MODE);
index 0c5a3f9..741d033 100644 (file)
@@ -21,6 +21,8 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 
+#include "FeatureDefines.xcconfig"
+
 PRODUCT_NAME = TestWebKitAPI;
 GCC_ENABLE_OBJC_EXCEPTIONS = YES;
 
index 07c0832..1264c1e 100644 (file)
                CD225C081C45A69200140761 /* ParsedContentRange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD225C071C45A69200140761 /* ParsedContentRange.cpp */; };
                CD59F53419E9110D00CF1835 /* file-with-mse.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = CD59F53219E910AA00CF1835 /* file-with-mse.html */; };
                CD59F53519E9110D00CF1835 /* test-mse.mp4 in Copy Resources */ = {isa = PBXBuildFile; fileRef = CD59F53319E910BC00CF1835 /* test-mse.mp4 */; };
+               CD89D03A1C4EDB2A00040A04 /* WebCoreNSURLSession.mm in Sources */ = {isa = PBXBuildFile; fileRef = CD89D0381C4EDB2A00040A04 /* WebCoreNSURLSession.mm */; };
                CDBFCC451A9FF45300A7B691 /* FullscreenZoomInitialFrame.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDBFCC431A9FF44800A7B691 /* FullscreenZoomInitialFrame.mm */; };
                CDBFCC461A9FF49E00A7B691 /* FullscreenZoomInitialFrame.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = CDBFCC421A9FF44800A7B691 /* FullscreenZoomInitialFrame.html */; };
                CDC8E48D1BC5CB4500594FEC /* AudioSessionCategoryIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDC8E4851BC5B19400594FEC /* AudioSessionCategoryIOS.mm */; };
                CD5497B315857F0C00B5BC30 /* MediaTime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaTime.cpp; sourceTree = "<group>"; };
                CD59F53219E910AA00CF1835 /* file-with-mse.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "file-with-mse.html"; sourceTree = "<group>"; };
                CD59F53319E910BC00CF1835 /* test-mse.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = "test-mse.mp4"; sourceTree = "<group>"; };
+               CD773F711C5057DB0002257C /* FeatureDefines.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = FeatureDefines.xcconfig; sourceTree = "<group>"; };
+               CD89D0381C4EDB2A00040A04 /* WebCoreNSURLSession.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCoreNSURLSession.mm; sourceTree = "<group>"; };
                CDBFCC421A9FF44800A7B691 /* FullscreenZoomInitialFrame.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = FullscreenZoomInitialFrame.html; sourceTree = "<group>"; };
                CDBFCC431A9FF44800A7B691 /* FullscreenZoomInitialFrame.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FullscreenZoomInitialFrame.mm; sourceTree = "<group>"; };
                CDC2C7141797089D00E627FB /* TimeRanges.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TimeRanges.cpp; sourceTree = "<group>"; };
                440A1D3614A01000008A66F2 /* WebCore */ = {
                        isa = PBXGroup;
                        children = (
+                               CD89D0371C4EDB1300040A04 /* cocoa */,
                                93A720E518F1A0E800A848E1 /* CalculationValue.cpp */,
                                7CB184C41AA3F2100066EDFD /* ContentExtensions.cpp */,
                                CD5451E919E41F9D0016936F /* CSSParser.cpp */,
                        children = (
                                BC90957E12554CF900083756 /* Base.xcconfig */,
                                BC90957F12554CF900083756 /* DebugRelease.xcconfig */,
+                               CD773F711C5057DB0002257C /* FeatureDefines.xcconfig */,
                                BC575AE2126E88B1006F0F12 /* InjectedBundle.xcconfig */,
                                BC90958012554CF900083756 /* TestWebKitAPI.xcconfig */,
                                7CCE7EA31A4115CB00447C4C /* TestWebKitAPILibrary.xcconfig */,
                        path = mac;
                        sourceTree = "<group>";
                };
+               CD89D0371C4EDB1300040A04 /* cocoa */ = {
+                       isa = PBXGroup;
+                       children = (
+                               CD89D0381C4EDB2A00040A04 /* WebCoreNSURLSession.mm */,
+                       );
+                       name = cocoa;
+                       sourceTree = "<group>";
+               };
                CDC8E4981BC728AE00594FEC /* WebKit */ = {
                        isa = PBXGroup;
                        children = (
                                7AA6A1521AAC0B31002B2ED3 /* WorkQueue.cpp in Sources */,
                                2E7765CF16C4D81100BA2BB1 /* mainMac.mm in Sources */,
                                41973B5B1AF2286A006C7B36 /* FileSystem.cpp in Sources */,
+                               CD89D03A1C4EDB2A00040A04 /* WebCoreNSURLSession.mm in Sources */,
                                A1C4FB6E1BACCE50003742D0 /* QuickLook.mm in Sources */,
                                7A5623111AD5AF3E0096B920 /* MenuTypesForMouseEvents.cpp in Sources */,
                                9B0786A31C58830F00D159E3 /* InjectedBundleMakeAllShadowRootsOpen.cpp in Sources */,
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/WebCoreNSURLSession.mm b/Tools/TestWebKitAPI/Tests/WebCore/WebCoreNSURLSession.mm
new file mode 100644 (file)
index 0000000..930a449
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#import "config.h"
+#import "PlatformUtilities.h"
+#import <WebKit/WebView.h>
+#import <WebCore/FrameLoadRequest.h>
+#import <WebCore/MainFrame.h>
+#import <WebCore/Page.h>
+#import <WebCore/PageConfiguration.h>
+#import <WebCore/Document.h>
+#import <WebCore/DocumentLoader.h>
+#import <WebCore/Settings.h>
+#import <WebCore/SubresourceLoader.h>
+#import <WebCore/WebCoreNSURLSession.h>
+#import <WebCore/ResourceLoader.h>
+#import <wtf/SchedulePair.h>
+
+static bool didLoadMainResource;
+static bool didRecieveResponse;
+static bool didRecieveData;
+static bool didComplete;
+static bool didInvalidate;
+
+static NSURL *documentURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
+static NSURL *resourceURL = [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"mp4" subdirectory:@"TestWebKitAPI.resources"];
+
+@interface TestNSURLSessionLoaderDelegate : NSObject<WebFrameLoadDelegate>
+@end
+
+@implementation TestNSURLSessionLoaderDelegate
+- (void)webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame
+{
+    UNUSED_PARAM(sender);
+    UNUSED_PARAM(frame);
+    didLoadMainResource = true;
+}
+@end
+
+@interface TestNSURLSessionDataDelegate : NSObject<NSURLSessionDataDelegate>
+@end
+
+@implementation TestNSURLSessionDataDelegate
+- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error
+{
+    didComplete = true;
+}
+
+- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
+{
+    didRecieveResponse = true;
+    completionHandler(NSURLSessionResponseAllow);
+}
+
+- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
+{
+    didRecieveData = true;
+
+    NSData* directData = [NSData dataWithContentsOfURL:dataTask.originalRequest.URL];
+    NSData* directSubdata = [directData subdataWithRange:NSMakeRange(dataTask.countOfBytesReceived - data.length, data.length)];
+    ASSERT_TRUE([data isEqualToData:directSubdata]);
+}
+
+- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(nullable NSError *)error
+{
+    didInvalidate = true;
+}
+@end
+
+using namespace WebCore;
+
+@interface WebView (WebViewInternalForTesting)
+- (WebCore::Frame*)_mainCoreFrame;
+@end
+
+namespace TestWebKitAPI {
+
+class WebCoreNSURLSessionTest : public testing::Test {
+public:
+    WebView *view { nil };
+    Frame* frame { nullptr };
+    TestNSURLSessionDataDelegate *delegate { nil };
+
+    virtual void SetUp()
+    {
+        view = [[WebView alloc] initWithFrame:NSZeroRect];
+        view.frameLoadDelegate = [[[TestNSURLSessionLoaderDelegate alloc] init] autorelease];
+
+        didLoadMainResource = false;
+        view.mainFrameURL = documentURL.absoluteString;
+        TestWebKitAPI::Util::run(&didLoadMainResource);
+
+        delegate = [[TestNSURLSessionDataDelegate alloc] init];
+        frame = [view _mainCoreFrame];
+    }
+
+    virtual void TearDown()
+    {
+        [view release];
+        [delegate release];
+    }
+};
+
+TEST_F(WebCoreNSURLSessionTest, BasicOperation)
+{
+    WebCoreNSURLSession* session = [[WebCoreNSURLSession alloc] initWithResourceLoader:frame->document()->loader()->cachedResourceLoader() delegate:delegate delegateQueue:[NSOperationQueue mainQueue]];
+    didRecieveResponse = false;
+    didRecieveData = false;
+    didComplete = false;
+
+    NSURLSessionDataTask *task = [session dataTaskWithURL:resourceURL];
+    [task resume];
+
+    TestWebKitAPI::Util::run(&didRecieveResponse);
+    TestWebKitAPI::Util::run(&didRecieveData);
+    TestWebKitAPI::Util::run(&didComplete);
+
+    didInvalidate = false;
+
+    task = [session dataTaskWithURL:resourceURL];
+    [task resume];
+    [session finishTasksAndInvalidate];
+
+    TestWebKitAPI::Util::run(&didInvalidate);
+
+    [session release];
+}
+
+TEST_F(WebCoreNSURLSessionTest, InvalidateEmpty)
+{
+    WebCoreNSURLSession* session = [[WebCoreNSURLSession alloc] initWithResourceLoader:frame->document()->loader()->cachedResourceLoader() delegate:delegate delegateQueue:[NSOperationQueue mainQueue]];
+    didInvalidate = false;
+    [session finishTasksAndInvalidate];
+    TestWebKitAPI::Util::run(&didInvalidate);
+    [session release];
+}
+
+
+}