Diff
Modified: trunk/Source/WTF/ChangeLog (247460 => 247461)
--- trunk/Source/WTF/ChangeLog 2019-07-15 23:09:31 UTC (rev 247460)
+++ trunk/Source/WTF/ChangeLog 2019-07-15 23:45:07 UTC (rev 247461)
@@ -1,3 +1,16 @@
+2019-07-15 Brady Eidson <beid...@apple.com>
+
+ Make WKURLSchemeTask thread safe.
+ <rdar://problem/50471863> and https://bugs.webkit.org/show_bug.cgi?id=199764
+
+ Reviewed by Alex Christensen.
+
+ * wtf/MainThread.cpp:
+ (WTF::callOnMainAndWait):
+ (WTF::callOnMainRunLoopAndWait):
+ (WTF::callOnMainThreadAndWait):
+ * wtf/MainThread.h:
+
2019-07-15 Dean Jackson <d...@apple.com>
MacCatalyst asserts when command key is raised
Modified: trunk/Source/WTF/wtf/MainThread.cpp (247460 => 247461)
--- trunk/Source/WTF/wtf/MainThread.cpp 2019-07-15 23:09:31 UTC (rev 247460)
+++ trunk/Source/WTF/wtf/MainThread.cpp 2019-07-15 23:45:07 UTC (rev 247461)
@@ -174,9 +174,15 @@
return isMainThread();
}
-void callOnMainThreadAndWait(WTF::Function<void()>&& function)
+enum class MainStyle : bool {
+ Thread,
+ RunLoop
+};
+
+static void callOnMainAndWait(WTF::Function<void()>&& function, MainStyle mainStyle)
{
- if (isMainThread()) {
+
+ if (mainStyle == MainStyle::Thread ? isMainThread() : isMainRunLoop()) {
function();
return;
}
@@ -186,14 +192,22 @@
bool isFinished = false;
- callOnMainThread([&, function = WTFMove(function)] {
+ auto functionImpl = [&, function = WTFMove(function)] {
function();
std::lock_guard<Lock> lock(mutex);
isFinished = true;
conditionVariable.notifyOne();
- });
+ };
+ switch (mainStyle) {
+ case MainStyle::Thread:
+ callOnMainThread(WTFMove(functionImpl));
+ break;
+ case MainStyle::RunLoop:
+ callOnMainRunLoop(WTFMove(functionImpl));
+ };
+
std::unique_lock<Lock> lock(mutex);
conditionVariable.wait(lock, [&] {
return isFinished;
@@ -200,4 +214,14 @@
});
}
+void callOnMainRunLoopAndWait(WTF::Function<void()>&& function)
+{
+ callOnMainAndWait(WTFMove(function), MainStyle::RunLoop);
+}
+
+void callOnMainThreadAndWait(WTF::Function<void()>&& function)
+{
+ callOnMainAndWait(WTFMove(function), MainStyle::Thread);
+}
+
} // namespace WTF
Modified: trunk/Source/WTF/wtf/MainThread.h (247460 => 247461)
--- trunk/Source/WTF/wtf/MainThread.h 2019-07-15 23:09:31 UTC (rev 247460)
+++ trunk/Source/WTF/wtf/MainThread.h 2019-07-15 23:45:07 UTC (rev 247461)
@@ -59,6 +59,7 @@
WTF_EXPORT_PRIVATE bool isMainRunLoop();
WTF_EXPORT_PRIVATE void callOnMainRunLoop(Function<void()>&&);
+WTF_EXPORT_PRIVATE void callOnMainRunLoopAndWait(Function<void()>&&);
#if USE(WEB_THREAD)
WTF_EXPORT_PRIVATE bool isWebThread();
@@ -92,6 +93,8 @@
using WTF::callOnMainThread;
using WTF::callOnMainThreadAndWait;
+using WTF::callOnMainRunLoop;
+using WTF::callOnMainRunLoopAndWait;
using WTF::canAccessThreadLocalDataForThread;
using WTF::isMainThread;
using WTF::isMainThreadOrGCThread;
Modified: trunk/Source/WebKit/ChangeLog (247460 => 247461)
--- trunk/Source/WebKit/ChangeLog 2019-07-15 23:09:31 UTC (rev 247460)
+++ trunk/Source/WebKit/ChangeLog 2019-07-15 23:45:07 UTC (rev 247461)
@@ -1,3 +1,42 @@
+2019-07-15 Brady Eidson <beid...@apple.com>
+
+ Make WKURLSchemeTask thread safe.
+ <rdar://problem/50471863> and https://bugs.webkit.org/show_bug.cgi?id=199764
+
+ Reviewed by Alex Christensen.
+
+ Punt most of the WKURLSchemeTask operations back to the main thread.
+ Make accessing the NSURLRequest be thread safe with lock protection.
+
+ * UIProcess/API/Cocoa/WKURLSchemeTask.mm:
+ (getExceptionTypeFromMainRunLoop):
+ (-[WKURLSchemeTaskImpl dealloc]):
+ (-[WKURLSchemeTaskImpl request]):
+ (-[WKURLSchemeTaskImpl _requestOnlyIfCached]):
+ (-[WKURLSchemeTaskImpl didReceiveResponse:]):
+ (-[WKURLSchemeTaskImpl didReceiveData:]):
+ (-[WKURLSchemeTaskImpl didFinish]):
+ (-[WKURLSchemeTaskImpl didFailWithError:]):
+ (-[WKURLSchemeTaskImpl _didPerformRedirection:newRequest:]):
+
+ * UIProcess/WebURLSchemeTask.cpp:
+ (WebKit::WebURLSchemeTask::WebURLSchemeTask):
+ (WebKit::WebURLSchemeTask::~WebURLSchemeTask):
+ (WebKit::WebURLSchemeTask::didPerformRedirection):
+ (WebKit::WebURLSchemeTask::didReceiveResponse):
+ (WebKit::WebURLSchemeTask::didReceiveData):
+ (WebKit::WebURLSchemeTask::didComplete):
+ (WebKit::WebURLSchemeTask::pageDestroyed):
+ (WebKit::WebURLSchemeTask::stop):
+ (WebKit::WebURLSchemeTask::nsRequest const):
+
+ * UIProcess/WebURLSchemeTask.h:
+ (WebKit::WebURLSchemeTask::identifier const):
+ (WebKit::WebURLSchemeTask::pageID const):
+ (WebKit::WebURLSchemeTask::process):
+ (WebKit::WebURLSchemeTask::process const): Deleted.
+ (WebKit::WebURLSchemeTask::request const): Deleted.
+
2019-07-15 Wenson Hsieh <wenson_hs...@apple.com>
Followup to r247439
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKURLSchemeTask.mm (247460 => 247461)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKURLSchemeTask.mm 2019-07-15 23:09:31 UTC (rev 247460)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKURLSchemeTask.mm 2019-07-15 23:45:07 UTC (rev 247461)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,7 +32,21 @@
#import <WebCore/ResourceResponse.h>
#import <WebCore/SharedBuffer.h>
#import <wtf/BlockPtr.h>
+#import <wtf/MainThread.h>
+static WebKit::WebURLSchemeTask::ExceptionType getExceptionTypeFromMainRunLoop(Function<WebKit::WebURLSchemeTask::ExceptionType ()>&& function)
+{
+ if (RunLoop::isMain())
+ return function();
+
+ WebKit::WebURLSchemeTask::ExceptionType exceptionType;
+ callOnMainRunLoopAndWait([function = WTFMove(function), &exceptionType] {
+ exceptionType = function();
+ });
+
+ return exceptionType;
+}
+
static void raiseExceptionIfNecessary(WebKit::WebURLSchemeTask::ExceptionType exceptionType)
{
switch (exceptionType) {
@@ -60,48 +74,75 @@
- (void)dealloc
{
- _urlSchemeTask->API::URLSchemeTask::~URLSchemeTask();
+ auto func = [task = WTFMove(_urlSchemeTask)] () mutable {
+ task->API::URLSchemeTask::~URLSchemeTask();
+ };
+ if (RunLoop::isMain())
+ func();
+ else
+ callOnMainRunLoop(WTFMove(func));
+
[super dealloc];
}
- (NSURLRequest *)request
{
- return _urlSchemeTask->task().request().nsURLRequest(WebCore::HTTPBodyUpdatePolicy::UpdateHTTPBody);
+ return _urlSchemeTask->task().nsRequest();
}
- (BOOL)_requestOnlyIfCached
{
- return _urlSchemeTask->task().request().cachePolicy() == WebCore::ResourceRequestCachePolicy::ReturnCacheDataDontLoad;
+ return _urlSchemeTask->task().nsRequest().cachePolicy == NSURLRequestReturnCacheDataDontLoad;
}
- (void)didReceiveResponse:(NSURLResponse *)response
{
- auto result = _urlSchemeTask->task().didReceiveResponse(response);
+ auto function = [protectedSelf = retainPtr(self), self, protectedResponse = retainPtr(response), response] {
+ return _urlSchemeTask->task().didReceiveResponse(response);
+ };
+
+ auto result = getExceptionTypeFromMainRunLoop(WTFMove(function));
raiseExceptionIfNecessary(result);
}
- (void)didReceiveData:(NSData *)data
{
- auto result = _urlSchemeTask->task().didReceiveData(WebCore::SharedBuffer::create(data));
+ auto function = [protectedSelf = retainPtr(self), self, protectedData = retainPtr(data), data] () mutable {
+ return _urlSchemeTask->task().didReceiveData(WebCore::SharedBuffer::create(data));
+ };
+
+ auto result = getExceptionTypeFromMainRunLoop(WTFMove(function));
raiseExceptionIfNecessary(result);
}
- (void)didFinish
{
- auto result = _urlSchemeTask->task().didComplete({ });
+ auto function = [protectedSelf = retainPtr(self), self] {
+ return _urlSchemeTask->task().didComplete({ });
+ };
+
+ auto result = getExceptionTypeFromMainRunLoop(WTFMove(function));
raiseExceptionIfNecessary(result);
}
- (void)didFailWithError:(NSError *)error
{
- auto result = _urlSchemeTask->task().didComplete(error);
+ auto function = [protectedSelf = retainPtr(self), self, protectedError = retainPtr(error), error] {
+ return _urlSchemeTask->task().didComplete(error);
+ };
+
+ auto result = getExceptionTypeFromMainRunLoop(WTFMove(function));
raiseExceptionIfNecessary(result);
}
- (void)_didPerformRedirection:(NSURLResponse *)response newRequest:(NSURLRequest *)request
{
- auto result = _urlSchemeTask->task().didPerformRedirection(response, request);
+ auto function = [protectedSelf = retainPtr(self), self, protectedResponse = retainPtr(response), response, protectedRequest = retainPtr(request), request] {
+ return _urlSchemeTask->task().didPerformRedirection(response, request);
+ };
+
+ auto result = getExceptionTypeFromMainRunLoop(WTFMove(function));
raiseExceptionIfNecessary(result);
}
Modified: trunk/Source/WebKit/UIProcess/WebURLSchemeTask.cpp (247460 => 247461)
--- trunk/Source/WebKit/UIProcess/WebURLSchemeTask.cpp 2019-07-15 23:09:31 UTC (rev 247460)
+++ trunk/Source/WebKit/UIProcess/WebURLSchemeTask.cpp 2019-07-15 23:45:07 UTC (rev 247461)
@@ -50,10 +50,18 @@
, m_request(WTFMove(request))
, m_syncCompletionHandler(WTFMove(syncCompletionHandler))
{
+ ASSERT(RunLoop::isMain());
}
+WebURLSchemeTask::~WebURLSchemeTask()
+{
+ ASSERT(RunLoop::isMain());
+}
+
auto WebURLSchemeTask::didPerformRedirection(WebCore::ResourceResponse&& response, WebCore::ResourceRequest&& request) -> ExceptionType
{
+ ASSERT(RunLoop::isMain());
+
if (m_stopped)
return ExceptionType::TaskAlreadyStopped;
@@ -69,7 +77,11 @@
if (isSync())
m_syncResponse = response;
- m_request = request;
+ {
+ LockHolder locker(m_requestLock);
+ m_request = request;
+ }
+
m_process->send(Messages::WebPage::URLSchemeTaskDidPerformRedirection(m_urlSchemeHandler->identifier(), m_identifier, response, request), m_page->pageID());
return ExceptionType::None;
@@ -77,6 +89,8 @@
auto WebURLSchemeTask::didReceiveResponse(const ResourceResponse& response) -> ExceptionType
{
+ ASSERT(RunLoop::isMain());
+
if (m_stopped)
return ExceptionType::TaskAlreadyStopped;
@@ -99,6 +113,8 @@
auto WebURLSchemeTask::didReceiveData(Ref<SharedBuffer>&& buffer) -> ExceptionType
{
+ ASSERT(RunLoop::isMain());
+
if (m_stopped)
return ExceptionType::TaskAlreadyStopped;
@@ -124,6 +140,8 @@
auto WebURLSchemeTask::didComplete(const ResourceError& error) -> ExceptionType
{
+ ASSERT(RunLoop::isMain());
+
if (m_stopped)
return ExceptionType::TaskAlreadyStopped;
@@ -154,22 +172,38 @@
void WebURLSchemeTask::pageDestroyed()
{
+ ASSERT(RunLoop::isMain());
ASSERT(m_page);
+
m_page = nullptr;
m_process = nullptr;
m_stopped = true;
- if (isSync())
+ if (isSync()) {
+ LockHolder locker(m_requestLock);
m_syncCompletionHandler({ }, failedCustomProtocolSyncLoad(m_request), { });
+ }
}
void WebURLSchemeTask::stop()
{
+ ASSERT(RunLoop::isMain());
ASSERT(!m_stopped);
+
m_stopped = true;
- if (isSync())
+ if (isSync()) {
+ LockHolder locker(m_requestLock);
m_syncCompletionHandler({ }, failedCustomProtocolSyncLoad(m_request), { });
+ }
}
+#if PLATFORM(COCOA)
+NSURLRequest *WebURLSchemeTask::nsRequest() const
+{
+ LockHolder locker(m_requestLock);
+ return m_request.nsURLRequest(WebCore::HTTPBodyUpdatePolicy::UpdateHTTPBody);
+}
+#endif
+
} // namespace WebKit
Modified: trunk/Source/WebKit/UIProcess/WebURLSchemeTask.h (247460 => 247461)
--- trunk/Source/WebKit/UIProcess/WebURLSchemeTask.h 2019-07-15 23:09:31 UTC (rev 247460)
+++ trunk/Source/WebKit/UIProcess/WebURLSchemeTask.h 2019-07-15 23:45:07 UTC (rev 247461)
@@ -51,17 +51,22 @@
using SyncLoadCompletionHandler = CompletionHandler<void(const WebCore::ResourceResponse&, const WebCore::ResourceError&, const Vector<char>&)>;
-class WebURLSchemeTask : public RefCounted<WebURLSchemeTask>, public InstanceCounted<WebURLSchemeTask> {
+class WebURLSchemeTask : public ThreadSafeRefCounted<WebURLSchemeTask>, public InstanceCounted<WebURLSchemeTask> {
WTF_MAKE_NONCOPYABLE(WebURLSchemeTask);
public:
static Ref<WebURLSchemeTask> create(WebURLSchemeHandler&, WebPageProxy&, WebProcessProxy&, uint64_t identifier, WebCore::ResourceRequest&&, SyncLoadCompletionHandler&&);
- uint64_t identifier() const { return m_identifier; }
- WebCore::PageIdentifier pageID() const { return m_pageIdentifier; }
- WebProcessProxy* process() const { return m_process.get(); }
+ ~WebURLSchemeTask();
- const WebCore::ResourceRequest& request() const { return m_request; }
+ uint64_t identifier() const { ASSERT(RunLoop::isMain()); return m_identifier; }
+ WebCore::PageIdentifier pageID() const { ASSERT(RunLoop::isMain()); return m_pageIdentifier; }
+ WebProcessProxy* process() { ASSERT(RunLoop::isMain()); return m_process.get(); }
+
+#if PLATFORM(COCOA)
+ NSURLRequest *nsRequest() const;
+#endif
+
enum class ExceptionType {
DataAlreadySent,
CompleteAlreadyCalled,
@@ -89,6 +94,7 @@
uint64_t m_identifier;
WebCore::PageIdentifier m_pageIdentifier;
WebCore::ResourceRequest m_request;
+ mutable Lock m_requestLock;
bool m_stopped { false };
bool m_responseSent { false };
bool m_dataSent { false };
Modified: trunk/Tools/ChangeLog (247460 => 247461)
--- trunk/Tools/ChangeLog 2019-07-15 23:09:31 UTC (rev 247460)
+++ trunk/Tools/ChangeLog 2019-07-15 23:45:07 UTC (rev 247461)
@@ -1,3 +1,12 @@
+2019-07-15 Brady Eidson <beid...@apple.com>
+
+ Make WKURLSchemeTask thread safe.
+ <rdar://problem/50471863> and https://bugs.webkit.org/show_bug.cgi?id=199764
+
+ Reviewed by Alex Christensen.
+
+ * TestWebKitAPI/Tests/WebKitCocoa/WKURLSchemeHandler-1.mm:
+
2019-07-15 Jiewen Tan <jiewen_...@apple.com>
Unreviewed, a build fix after r247437
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKURLSchemeHandler-1.mm (247460 => 247461)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKURLSchemeHandler-1.mm 2019-07-15 23:09:31 UTC (rev 247460)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKURLSchemeHandler-1.mm 2019-07-15 23:45:07 UTC (rev 247461)
@@ -34,8 +34,11 @@
#import <WebKit/WKURLSchemeTaskPrivate.h>
#import <WebKit/WKWebViewConfigurationPrivate.h>
#import <WebKit/WebKit.h>
+#import <wtf/BlockPtr.h>
#import <wtf/HashMap.h>
#import <wtf/RetainPtr.h>
+#import <wtf/RunLoop.h>
+#import <wtf/Threading.h>
#import <wtf/Vector.h>
#import <wtf/text/StringHash.h>
#import <wtf/text/WTFString.h>
@@ -692,3 +695,41 @@
TestWebKitAPI::Util::run(&done);
}
+TEST(URLSchemeHandler, Threads)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ auto handler = adoptNS([[TestURLSchemeHandler alloc] init]);
+ auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+ [configuration setURLSchemeHandler:handler.get() forURLScheme:@"threads"];
+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
+
+ static bool done;
+ static id<WKURLSchemeTask> theTask;
+ static RefPtr<Thread> theThread;
+ [handler setStartURLSchemeTaskHandler:^(WKWebView *, id<WKURLSchemeTask> task) {
+ theTask = task;
+ [task retain];
+ theThread = Thread::create("A", [task] {
+ auto response = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil]);
+ [task didReceiveResponse:response.get()];
+ [task didFinish];
+ done = true;
+ });
+ }];
+
+ [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"threads://main.html"]]];
+
+ TestWebKitAPI::Util::run(&done);
+
+ handler = nil;
+ configuration = nil;
+ webView = nil;
+ theThread = nullptr;
+ [pool drain];
+
+ Thread::create("B", [] {
+ [theTask release];
+ theTask = nil;
+ })->waitForCompletion();
+}