Diff
Modified: trunk/Source/WebKit/ChangeLog (243109 => 243110)
--- trunk/Source/WebKit/ChangeLog 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/ChangeLog 2019-03-18 22:38:55 UTC (rev 243110)
@@ -1,3 +1,111 @@
+2019-03-18 Alex Christensen <[email protected]>
+
+ Implement DownloadMonitor to prevent long-running slow downloads from background apps
+ https://bugs.webkit.org/show_bug.cgi?id=195785
+
+ Reviewed by Geoffrey Garen.
+
+ This is similar to what was updated in <rdar://problem/42677685> but for WebKit Downloads.
+ To test it I implemented a throttled TCP server, SPI to speed up DownloadMonitor's timer,
+ and SPI to synthesize the application going into the background and foreground, which
+ NSNotificationCenter does on iOS.
+
+ * NetworkProcess/Downloads/Download.cpp:
+ (WebKit::Download::didReceiveData):
+ (WebKit::Download::didFinish):
+ (WebKit::Download::didFail):
+ (WebKit::Download::didCancel):
+ * NetworkProcess/Downloads/Download.h:
+ (WebKit::Download::applicationEnteredBackground):
+ (WebKit::Download::applicationEnteredForeground):
+ (WebKit::Download::manager const):
+ * NetworkProcess/Downloads/DownloadManager.cpp:
+ (WebKit::DownloadManager::downloadFinished):
+ (WebKit::DownloadManager::applicationDidEnterBackground):
+ (WebKit::DownloadManager::applicationWillEnterForeground):
+ * NetworkProcess/Downloads/DownloadManager.h:
+ * NetworkProcess/Downloads/DownloadMap.cpp:
+ (WebKit::DownloadMap::values):
+ * NetworkProcess/Downloads/DownloadMap.h:
+ * NetworkProcess/Downloads/DownloadMonitor.cpp: Added.
+ (WebKit::operator _kbps):
+ (WebKit::timeUntilNextInterval):
+ (WebKit::DownloadMonitor::DownloadMonitor):
+ (WebKit::DownloadMonitor::measuredThroughputRate const):
+ (WebKit::DownloadMonitor::downloadReceivedBytes):
+ (WebKit::DownloadMonitor::applicationEnteredForeground):
+ (WebKit::DownloadMonitor::applicationEnteredBackground):
+ (WebKit::DownloadMonitor::speedMultiplier const):
+ (WebKit::DownloadMonitor::timerFired):
+ * NetworkProcess/Downloads/DownloadMonitor.h: Added.
+ * NetworkProcess/NetworkProcess.cpp:
+ (WebKit::NetworkProcess::initializeNetworkProcess):
+ (WebKit::NetworkProcess::applicationDidEnterBackground):
+ (WebKit::NetworkProcess::applicationWillEnterForeground):
+ * NetworkProcess/NetworkProcess.h:
+ * NetworkProcess/NetworkProcess.messages.in:
+ * NetworkProcess/NetworkProcessCreationParameters.cpp:
+ (WebKit::NetworkProcessCreationParameters::encode const):
+ (WebKit::NetworkProcessCreationParameters::decode):
+ * NetworkProcess/NetworkProcessCreationParameters.h:
+ * Sources.txt:
+ * SourcesCocoa.txt:
+ * UIProcess/API/APIProcessPoolConfiguration.cpp:
+ (API::ProcessPoolConfiguration::copy):
+ * UIProcess/API/APIProcessPoolConfiguration.h:
+ * UIProcess/API/C/WKContext.cpp:
+ (WKContextDownloadURLRequest):
+ (WKContextResumeDownload):
+ * UIProcess/API/Cocoa/WKProcessPool.mm:
+ (-[WKProcessPool _synthesizeAppIsBackground:]):
+ (-[WKProcessPool _downloadURLRequest:originatingWebView:]):
+ * UIProcess/API/Cocoa/WKProcessPoolPrivate.h:
+ * UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h:
+ * UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm:
+ (-[_WKProcessPoolConfiguration downloadMonitorSpeedMultiplier]):
+ (-[_WKProcessPoolConfiguration setDownloadMonitorSpeedMultiplier:]):
+ * UIProcess/Cocoa/DownloadProxyMapCocoa.mm: Added.
+ (WebKit::DownloadProxyMap::platformCreate):
+ (WebKit::DownloadProxyMap::platformDestroy):
+ * UIProcess/Cocoa/WebProcessPoolCocoa.mm:
+ (WebKit::WebProcessPool::platformInitializeNetworkProcess):
+ * UIProcess/Downloads/DownloadProxy.cpp:
+ (WebKit::DownloadProxy::didFinish):
+ (WebKit::DownloadProxy::didFail):
+ (WebKit::DownloadProxy::didCancel):
+ * UIProcess/Downloads/DownloadProxyMap.cpp:
+ (WebKit::DownloadProxyMap::DownloadProxyMap):
+ (WebKit::DownloadProxyMap::~DownloadProxyMap):
+ (WebKit::DownloadProxyMap::platformCreate):
+ (WebKit::DownloadProxyMap::platformDestroy):
+ (WebKit::DownloadProxyMap::applicationDidEnterBackground):
+ (WebKit::DownloadProxyMap::applicationWillEnterForeground):
+ (WebKit::DownloadProxyMap::createDownloadProxy):
+ (WebKit::DownloadProxyMap::downloadFinished):
+ * UIProcess/Downloads/DownloadProxyMap.h:
+ * UIProcess/Network/NetworkProcessProxy.cpp:
+ (WebKit::NetworkProcessProxy::synthesizeAppIsBackground):
+ (WebKit::NetworkProcessProxy::createDownloadProxy):
+ * UIProcess/Network/NetworkProcessProxy.h:
+ * UIProcess/PageClient.h:
+ * UIProcess/WebPageProxy.cpp:
+ (WebKit::WebPageProxy::receivedPolicyDecision):
+ (WebKit::WebPageProxy::handleDownloadRequest):
+ * UIProcess/WebPageProxy.h:
+ * UIProcess/WebProcessPool.cpp:
+ (WebKit::WebProcessPool::download):
+ (WebKit::WebProcessPool::resumeDownload):
+ (WebKit::WebProcessPool::createDownloadProxy):
+ (WebKit::WebProcessPool::synthesizeAppIsBackground):
+ * UIProcess/WebProcessPool.h:
+ * UIProcess/ios/PageClientImplIOS.h:
+ * UIProcess/ios/PageClientImplIOS.mm:
+ (WebKit::PageClientImpl::handleDownloadRequest):
+ * UIProcess/mac/PageClientImplMac.h:
+ * UIProcess/mac/PageClientImplMac.mm:
+ (WebKit::PageClientImpl::handleDownloadRequest):
+ * WebKit.xcodeproj/project.pbxproj:
+
2019-03-18 Wenson Hsieh <[email protected]>
[iOS] Native selection views sometimes appear in hidden editable areas after losing focus
Modified: trunk/Source/WebKit/NetworkProcess/Downloads/Download.cpp (243109 => 243110)
--- trunk/Source/WebKit/NetworkProcess/Downloads/Download.cpp 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/NetworkProcess/Downloads/Download.cpp 2019-03-18 22:38:55 UTC (rev 243110)
@@ -31,6 +31,7 @@
#include "Connection.h"
#include "DataReference.h"
#include "DownloadManager.h"
+#include "DownloadMonitor.h"
#include "DownloadProxyMessages.h"
#include "Logging.h"
#include "NetworkDataTask.h"
@@ -114,6 +115,8 @@
RELEASE_LOG_IF_ALLOWED("didReceiveData: Started receiving data (id = %" PRIu64 ")", downloadID().downloadID());
m_hasReceivedData = true;
}
+
+ m_monitor.downloadReceivedBytes(length);
send(Messages::DownloadProxy::DidReceiveData(length));
}
@@ -129,7 +132,7 @@
m_sandboxExtension = nullptr;
}
- m_downloadManager.downloadFinished(this);
+ m_downloadManager.downloadFinished(*this);
}
void Download::didFail(const ResourceError& error, const IPC::DataReference& resumeData)
@@ -143,7 +146,7 @@
m_sandboxExtension->revoke();
m_sandboxExtension = nullptr;
}
- m_downloadManager.downloadFinished(this);
+ m_downloadManager.downloadFinished(*this);
}
void Download::didCancel(const IPC::DataReference& resumeData)
@@ -156,7 +159,7 @@
m_sandboxExtension->revoke();
m_sandboxExtension = nullptr;
}
- m_downloadManager.downloadFinished(this);
+ m_downloadManager.downloadFinished(*this);
}
IPC::Connection* Download::messageSenderConnection() const
Modified: trunk/Source/WebKit/NetworkProcess/Downloads/Download.h (243109 => 243110)
--- trunk/Source/WebKit/NetworkProcess/Downloads/Download.h 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/NetworkProcess/Downloads/Download.h 2019-03-18 22:38:55 UTC (rev 243110)
@@ -27,6 +27,7 @@
#include "DownloadID.h"
#include "DownloadManager.h"
+#include "DownloadMonitor.h"
#include "MessageSender.h"
#include "NetworkDataTask.h"
#include "SandboxExtension.h"
@@ -58,6 +59,7 @@
namespace WebKit {
+class DownloadMonitor;
class NetworkDataTask;
class NetworkSession;
class WebPage;
@@ -89,6 +91,12 @@
void didFail(const WebCore::ResourceError&, const IPC::DataReference& resumeData);
void didCancel(const IPC::DataReference& resumeData);
+ bool isAlwaysOnLoggingAllowed() const;
+
+ void applicationDidEnterBackground() { m_monitor.applicationDidEnterBackground(); }
+ void applicationWillEnterForeground() { m_monitor.applicationWillEnterForeground(); }
+ DownloadManager& manager() const { return m_downloadManager; }
+
private:
// IPC::MessageSender
IPC::Connection* messageSenderConnection() const override;
@@ -97,8 +105,6 @@
void platformCancelNetworkLoad();
void platformDestroyDownload();
- bool isAlwaysOnLoggingAllowed() const;
-
DownloadManager& m_downloadManager;
DownloadID m_downloadID;
Ref<DownloadManager::Client> m_client;
@@ -114,6 +120,7 @@
PAL::SessionID m_sessionID;
String m_suggestedName;
bool m_hasReceivedData { false };
+ DownloadMonitor m_monitor { *this };
};
} // namespace WebKit
Modified: trunk/Source/WebKit/NetworkProcess/Downloads/DownloadManager.cpp (243109 => 243110)
--- trunk/Source/WebKit/NetworkProcess/Downloads/DownloadManager.cpp 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/NetworkProcess/Downloads/DownloadManager.cpp 2019-03-18 22:38:55 UTC (rev 243110)
@@ -169,11 +169,10 @@
}
#endif // PLATFORM(COCOA)
-void DownloadManager::downloadFinished(Download* download)
+void DownloadManager::downloadFinished(Download& download)
{
- ASSERT(m_downloads.contains(download->downloadID()));
- m_downloads.remove(download->downloadID());
-
+ ASSERT(m_downloads.contains(download.downloadID()));
+ m_downloads.remove(download.downloadID());
}
void DownloadManager::didCreateDownload()
@@ -196,4 +195,16 @@
return m_client.downloadsAuthenticationManager();
}
+void DownloadManager::applicationDidEnterBackground()
+{
+ for (auto& download : m_downloads.values())
+ download->applicationDidEnterBackground();
+}
+
+void DownloadManager::applicationWillEnterForeground()
+{
+ for (auto& download : m_downloads.values())
+ download->applicationWillEnterForeground();
+}
+
} // namespace WebKit
Modified: trunk/Source/WebKit/NetworkProcess/Downloads/DownloadManager.h (243109 => 243110)
--- trunk/Source/WebKit/NetworkProcess/Downloads/DownloadManager.h 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/NetworkProcess/Downloads/DownloadManager.h 2019-03-18 22:38:55 UTC (rev 243110)
@@ -78,6 +78,7 @@
virtual NetworkBlobRegistry& networkBlobRegistry() = 0;
virtual void ref() const = 0;
virtual void deref() const = 0;
+ virtual uint32_t downloadMonitorSpeedMultiplier() const = 0;
};
explicit DownloadManager(Client&);
@@ -98,10 +99,13 @@
Download* download(DownloadID downloadID) { return m_downloads.get(downloadID); }
- void downloadFinished(Download*);
+ void downloadFinished(Download&);
bool isDownloading() const { return !m_downloads.isEmpty(); }
uint64_t activeDownloadCount() const { return m_downloads.size(); }
+ void applicationDidEnterBackground();
+ void applicationWillEnterForeground();
+
void didCreateDownload();
void didDestroyDownload();
Modified: trunk/Source/WebKit/NetworkProcess/Downloads/DownloadMap.cpp (243109 => 243110)
--- trunk/Source/WebKit/NetworkProcess/Downloads/DownloadMap.cpp 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/NetworkProcess/Downloads/DownloadMap.cpp 2019-03-18 22:38:55 UTC (rev 243110)
@@ -75,6 +75,11 @@
return result;
}
+auto DownloadMap::values() -> DownloadMapType::ValuesIteratorRange
+{
+ return m_downloads.values();
+}
+
} // namespace WebKit
#endif // ENABLE(TAKE_UNBOUNDED_NETWORKING_ASSERTION)
Modified: trunk/Source/WebKit/NetworkProcess/Downloads/DownloadMap.h (243109 => 243110)
--- trunk/Source/WebKit/NetworkProcess/Downloads/DownloadMap.h 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/NetworkProcess/Downloads/DownloadMap.h 2019-03-18 22:38:55 UTC (rev 243110)
@@ -49,6 +49,8 @@
DownloadMapType::AddResult add(DownloadID, std::unique_ptr<Download>&&);
bool remove(DownloadID);
+ DownloadMapType::ValuesIteratorRange values();
+
private:
DownloadMapType m_downloads;
std::unique_ptr<ProcessAssertion> m_downloadAssertion;
Added: trunk/Source/WebKit/NetworkProcess/Downloads/DownloadMonitor.cpp (0 => 243110)
--- trunk/Source/WebKit/NetworkProcess/Downloads/DownloadMonitor.cpp (rev 0)
+++ trunk/Source/WebKit/NetworkProcess/Downloads/DownloadMonitor.cpp 2019-03-18 22:38:55 UTC (rev 243110)
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 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
+ * 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#include "config.h"
+#include "DownloadMonitor.h"
+
+#include "Download.h"
+#include "Logging.h"
+
+#undef RELEASE_LOG_IF_ALLOWED
+#define RELEASE_LOG_IF_ALLOWED(fmt, ...) RELEASE_LOG_IF(m_download.isAlwaysOnLoggingAllowed(), Network, "%p - DownloadMonitor::" fmt, this, ##__VA_ARGS__)
+
+namespace WebKit {
+
+constexpr uint64_t operator"" _kbps(unsigned long long kilobytesPerSecond)
+{
+ return kilobytesPerSecond * 1024;
+}
+
+struct ThroughputInterval {
+ Seconds time;
+ uint64_t bytesPerSecond;
+};
+
+static const ThroughputInterval throughputIntervals[] = {
+ { 1_min, 1_kbps },
+ { 5_min, 2_kbps },
+ { 10_min, 4_kbps },
+ { 15_min, 8_kbps },
+ { 20_min, 16_kbps },
+ { 25_min, 32_kbps },
+ { 30_min, 64_kbps },
+ { 45_min, 96_kbps },
+ { 60_min, 128_kbps }
+};
+
+static Seconds timeUntilNextInterval(size_t currentInterval)
+{
+ RELEASE_ASSERT(currentInterval + 1 < WTF_ARRAY_LENGTH(throughputIntervals));
+ return throughputIntervals[currentInterval + 1].time - throughputIntervals[currentInterval].time;
+}
+
+DownloadMonitor::DownloadMonitor(Download& download)
+ : m_download(download)
+{
+}
+
+double DownloadMonitor::measuredThroughputRate() const
+{
+ uint64_t bytes { 0 };
+ for (const auto& timestamp : m_timestamps)
+ bytes += timestamp.bytesReceived;
+ if (!bytes)
+ return 0;
+ ASSERT(!m_timestamps.isEmpty());
+ Seconds timeDifference = m_timestamps.last().time.secondsSinceEpoch() - m_timestamps.first().time.secondsSinceEpoch();
+ double seconds = timeDifference.seconds();
+ if (!seconds)
+ return std::numeric_limits<double>::max();
+ return bytes / seconds;
+}
+
+void DownloadMonitor::downloadReceivedBytes(uint64_t bytesReceived)
+{
+ if (m_timestamps.size() > timestampCapacity - 1) {
+ ASSERT(m_timestamps.size() == timestampCapacity);
+ m_timestamps.removeFirst();
+ }
+ m_timestamps.append({ MonotonicTime::now(), bytesReceived });
+}
+
+void DownloadMonitor::applicationWillEnterForeground()
+{
+ RELEASE_LOG_IF_ALLOWED("applicationWillEnterForeground (id = %" PRIu64 ")", m_download.downloadID().downloadID());
+ m_timer.stop();
+ m_interval = 0;
+}
+
+void DownloadMonitor::applicationDidEnterBackground()
+{
+ RELEASE_LOG_IF_ALLOWED("applicationDidEnterBackground (id = %" PRIu64 ")", m_download.downloadID().downloadID());
+ ASSERT(!m_timer.isActive());
+ ASSERT(!m_interval);
+ m_timer.startOneShot(throughputIntervals[0].time / speedMultiplier());
+}
+
+uint32_t DownloadMonitor::speedMultiplier() const
+{
+ return m_download.manager().client().downloadMonitorSpeedMultiplier();
+}
+
+void DownloadMonitor::timerFired()
+{
+ RELEASE_ASSERT(m_interval < WTF_ARRAY_LENGTH(throughputIntervals));
+ if (measuredThroughputRate() < throughputIntervals[m_interval].bytesPerSecond) {
+ RELEASE_LOG_IF_ALLOWED("timerFired: cancelling download (id = %" PRIu64 ")", m_download.downloadID().downloadID());
+ m_download.cancel();
+ } else if (m_interval + 1 < WTF_ARRAY_LENGTH(throughputIntervals)) {
+ RELEASE_LOG_IF_ALLOWED("timerFired: sufficient throughput rate (id = %" PRIu64 ")", m_download.downloadID().downloadID());
+ m_timer.startOneShot(timeUntilNextInterval(m_interval++) / speedMultiplier());
+ } else
+ RELEASE_LOG_IF_ALLOWED("timerFired: Download reached threshold to not be terminated (id = %" PRIu64 ")", m_download.downloadID().downloadID());
+}
+
+} // namespace WebKit
Copied: trunk/Source/WebKit/NetworkProcess/Downloads/DownloadMonitor.h (from rev 243109, trunk/Source/WebKit/NetworkProcess/Downloads/DownloadMap.h) (0 => 243110)
--- trunk/Source/WebKit/NetworkProcess/Downloads/DownloadMonitor.h (rev 0)
+++ trunk/Source/WebKit/NetworkProcess/Downloads/DownloadMonitor.h 2019-03-18 22:38:55 UTC (rev 243110)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 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
+ * 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#pragma once
+
+#include <WebCore/Timer.h>
+#include <wtf/Deque.h>
+
+namespace WebKit {
+
+class Download;
+
+class DownloadMonitor {
+ WTF_MAKE_NONCOPYABLE(DownloadMonitor); WTF_MAKE_FAST_ALLOCATED;
+public:
+ DownloadMonitor(Download&);
+
+ void applicationDidEnterBackground();
+ void applicationWillEnterForeground();
+ void downloadReceivedBytes(uint64_t);
+ void timerFired();
+
+private:
+ Download& m_download;
+
+ double measuredThroughputRate() const;
+ uint32_t speedMultiplier() const;
+
+ struct Timestamp {
+ MonotonicTime time;
+ uint64_t bytesReceived;
+ };
+ static constexpr size_t timestampCapacity = 10;
+ Deque<Timestamp, timestampCapacity> m_timestamps;
+ WebCore::Timer m_timer { *this, &DownloadMonitor::timerFired };
+ size_t m_interval { 0 };
+};
+
+} // namespace WebKit
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp (243109 => 243110)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp 2019-03-18 22:38:55 UTC (rev 243110)
@@ -361,6 +361,8 @@
for (auto& scheme : parameters.urlSchemesRegisteredAsCanDisplayOnlyIfCanRequest)
registerURLSchemeAsCanDisplayOnlyIfCanRequest(scheme);
+
+ m_downloadMonitorSpeedMultiplier = parameters.downloadMonitorSpeedMultiplier;
RELEASE_LOG(Process, "%p - NetworkProcess::initializeNetworkProcess: Presenting process = %d", this, WebCore::presentingApplicationPID());
}
@@ -1955,6 +1957,16 @@
connection->endSuspension();
}
+void NetworkProcess::applicationDidEnterBackground()
+{
+ m_downloadManager.applicationDidEnterBackground();
+}
+
+void NetworkProcess::applicationWillEnterForeground()
+{
+ m_downloadManager.applicationWillEnterForeground();
+}
+
void NetworkProcess::processDidResume()
{
RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::processDidResume()", this);
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.h (243109 => 243110)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.h 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.h 2019-03-18 22:38:55 UTC (rev 243110)
@@ -366,6 +366,7 @@
IPC::Connection* parentProcessConnectionForDownloads() override { return parentProcessConnection(); }
AuthenticationManager& downloadsAuthenticationManager() override;
void pendingDownloadCanceled(DownloadID) override;
+ uint32_t downloadMonitorSpeedMultiplier() const override { return m_downloadMonitorSpeedMultiplier; }
// Message Handlers
void didReceiveSyncNetworkProcessMessage(IPC::Connection&, IPC::Decoder&, std::unique_ptr<IPC::Encoder>&);
@@ -391,6 +392,8 @@
#endif
void continueWillSendRequest(DownloadID, WebCore::ResourceRequest&&);
void continueDecidePendingDownloadDestination(DownloadID, String destination, SandboxExtension::Handle&&, bool allowOverwrite);
+ void applicationDidEnterBackground();
+ void applicationWillEnterForeground();
void setCacheModel(CacheModel);
void allowSpecificHTTPSCertificateForHost(const WebCore::CertificateInfo&, const String& host);
@@ -532,6 +535,7 @@
HashMap<WebCore::ClientOrigin, std::unique_ptr<WebCore::StorageQuotaManager>> managersPerOrigin;
};
HashMap<PAL::SessionID, StorageQuotaManagers> m_storageQuotaManagers;
+ uint32_t m_downloadMonitorSpeedMultiplier { 1 };
};
} // namespace WebKit
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in (243109 => 243110)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in 2019-03-18 22:38:55 UTC (rev 243110)
@@ -52,6 +52,8 @@
#if PLATFORM(COCOA)
PublishDownloadProgress(WebKit::DownloadID downloadID, URL url, WebKit::SandboxExtension::Handle sandboxExtensionHandle)
#endif
+ ApplicationDidEnterBackground()
+ ApplicationWillEnterForeground()
ContinueWillSendRequest(WebKit::DownloadID downloadID, WebCore::ResourceRequest request)
ContinueDecidePendingDownloadDestination(WebKit::DownloadID downloadID, String destination, WebKit::SandboxExtension::Handle sandboxExtensionHandle, bool allowOverwrite)
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.cpp (243109 => 243110)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.cpp 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.cpp 2019-03-18 22:38:55 UTC (rev 243110)
@@ -94,6 +94,7 @@
encoder << serviceWorkerRegistrationDirectory << serviceWorkerRegistrationDirectoryExtensionHandle << urlSchemesServiceWorkersCanHandle << shouldDisableServiceWorkerProcessTerminationDelay;
#endif
encoder << shouldEnableITPDatabase;
+ encoder << downloadMonitorSpeedMultiplier;
}
bool NetworkProcessCreationParameters::decode(IPC::Decoder& decoder, NetworkProcessCreationParameters& result)
@@ -221,6 +222,12 @@
if (!decoder.decode(result.shouldEnableITPDatabase))
return false;
+ Optional<uint32_t> downloadMonitorSpeedMultiplier;
+ decoder >> downloadMonitorSpeedMultiplier;
+ if (!downloadMonitorSpeedMultiplier)
+ return false;
+ result.downloadMonitorSpeedMultiplier = *downloadMonitorSpeedMultiplier;
+
return true;
}
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h (243109 => 243110)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h 2019-03-18 22:38:55 UTC (rev 243110)
@@ -112,6 +112,7 @@
bool shouldDisableServiceWorkerProcessTerminationDelay { false };
#endif
bool shouldEnableITPDatabase { false };
+ uint32_t downloadMonitorSpeedMultiplier { 1 };
};
} // namespace WebKit
Modified: trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.cpp (243109 => 243110)
--- trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.cpp 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.cpp 2019-03-18 22:38:55 UTC (rev 243110)
@@ -51,7 +51,7 @@
return FileSystem::pathByAppendingComponent(cachesRootPath, "origin"_s);
}
-Caches::Caches(Engine& engine, WebCore::ClientOrigin&& origin, String&& rootPath, StorageQuotaManager& quotaManager)
+Caches::Caches(Engine& engine, WebCore::ClientOrigin&& origin, String&& rootPath, WebCore::StorageQuotaManager& quotaManager)
: m_engine(&engine)
, m_origin(WTFMove(origin))
, m_rootPath(WTFMove(rootPath))
@@ -500,10 +500,10 @@
m_quotaManager->requestSpace(spaceRequired, [callback = WTFMove(callback)](auto decision) {
switch (decision) {
- case StorageQuotaManager::Decision::Deny:
+ case WebCore::StorageQuotaManager::Decision::Deny:
callback(Error::QuotaExceeded);
return;
- case StorageQuotaManager::Decision::Grant:
+ case WebCore::StorageQuotaManager::Decision::Grant:
callback({ });
};
});
Modified: trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineConnection.cpp (243109 => 243110)
--- trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineConnection.cpp 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineConnection.cpp 2019-03-18 22:38:55 UTC (rev 243110)
@@ -37,6 +37,7 @@
using namespace WebCore::DOMCacheEngine;
using namespace CacheStorage;
+#undef RELEASE_LOG_IF_ALLOWED
#define RELEASE_LOG_IF_ALLOWED(fmt, ...) RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), CacheStorage, "%p - CacheStorageEngineConnection::" fmt, &m_connection.connection(), ##__VA_ARGS__)
#define RELEASE_LOG_FUNCTION_IF_ALLOWED_IN_CALLBACK(functionName, fmt, resultGetter) \
if (!result.has_value())\
Modified: trunk/Source/WebKit/Sources.txt (243109 => 243110)
--- trunk/Source/WebKit/Sources.txt 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/Sources.txt 2019-03-18 22:38:55 UTC (rev 243110)
@@ -53,6 +53,7 @@
NetworkProcess/Downloads/Download.cpp
NetworkProcess/Downloads/DownloadManager.cpp
NetworkProcess/Downloads/DownloadMap.cpp
+NetworkProcess/Downloads/DownloadMonitor.cpp
NetworkProcess/Downloads/PendingDownload.cpp
NetworkProcess/FileAPI/NetworkBlobRegistry.cpp
Modified: trunk/Source/WebKit/SourcesCocoa.txt (243109 => 243110)
--- trunk/Source/WebKit/SourcesCocoa.txt 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/SourcesCocoa.txt 2019-03-18 22:38:55 UTC (rev 243110)
@@ -325,6 +325,7 @@
UIProcess/Cocoa/AutomationSessionClient.mm
UIProcess/Cocoa/DiagnosticLoggingClient.mm
UIProcess/Cocoa/DownloadClient.mm
+UIProcess/Cocoa/DownloadProxyMapCocoa.mm
UIProcess/Cocoa/FindClient.mm
UIProcess/Cocoa/FullscreenClient.mm
UIProcess/Cocoa/GlobalFindInPageState.mm
Modified: trunk/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp 2019-03-18 22:38:55 UTC (rev 243110)
@@ -115,6 +115,7 @@
copy->m_shouldCaptureAudioInUIProcess = this->m_shouldCaptureAudioInUIProcess;
copy->m_shouldCaptureDisplayInUIProcess = this->m_shouldCaptureDisplayInUIProcess;
copy->m_isJITEnabled = this->m_isJITEnabled;
+ copy->m_downloadMonitorSpeedMultiplier = this->m_downloadMonitorSpeedMultiplier;
#if PLATFORM(IOS_FAMILY)
copy->m_ctDataConnectionServiceType = this->m_ctDataConnectionServiceType;
#endif
Modified: trunk/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h 2019-03-18 22:38:55 UTC (rev 243110)
@@ -59,6 +59,9 @@
bool usesSingleWebProcess() const { return m_usesSingleWebProcess; }
void setUsesSingleWebProcess(bool enabled) { m_usesSingleWebProcess = enabled; }
+ uint32_t downloadMonitorSpeedMultiplier() const { return m_downloadMonitorSpeedMultiplier; }
+ void setDownloadMonitorSpeedMultiplier(uint32_t multiplier) { m_downloadMonitorSpeedMultiplier = multiplier; }
+
bool isAutomaticProcessWarmingEnabled() const
{
return m_isAutomaticProcessWarmingEnabledByClient.valueOr(m_clientWouldBenefitFromAutomaticProcessPrewarming);
@@ -228,6 +231,7 @@
WTF::String m_customWebContentServiceBundleIdentifier;
bool m_isJITEnabled { true };
bool m_usesSingleWebProcess { false };
+ uint32_t m_downloadMonitorSpeedMultiplier { 1 };
#if PLATFORM(IOS_FAMILY)
WTF::String m_ctDataConnectionServiceType;
Modified: trunk/Source/WebKit/UIProcess/API/C/WKContext.cpp (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/API/C/WKContext.cpp 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/API/C/WKContext.cpp 2019-03-18 22:38:55 UTC (rev 243110)
@@ -275,12 +275,12 @@
WKDownloadRef WKContextDownloadURLRequest(WKContextRef contextRef, WKURLRequestRef requestRef)
{
- return WebKit::toAPI(WebKit::toImpl(contextRef)->download(0, WebKit::toImpl(requestRef)->resourceRequest()));
+ return WebKit::toAPI(&WebKit::toImpl(contextRef)->download(0, WebKit::toImpl(requestRef)->resourceRequest()));
}
WKDownloadRef WKContextResumeDownload(WKContextRef contextRef, WKDataRef resumeData, WKStringRef path)
{
- return WebKit::toAPI(WebKit::toImpl(contextRef)->resumeDownload(nullptr, WebKit::toImpl(resumeData), WebKit::toWTFString(path)));
+ return WebKit::toAPI(&WebKit::toImpl(contextRef)->resumeDownload(nullptr, WebKit::toImpl(resumeData), WebKit::toWTFString(path)));
}
void WKContextSetInitializationUserDataForInjectedBundle(WKContextRef contextRef, WKTypeRef userDataRef)
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKProcessPool.mm (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKProcessPool.mm 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKProcessPool.mm 2019-03-18 22:38:55 UTC (rev 243110)
@@ -563,6 +563,11 @@
_processPool->setStorageAccessAPIEnabled(enabled);
}
+- (void)_synthesizeAppIsBackground:(BOOL)background
+{
+ _processPool->synthesizeAppIsBackground(background);
+}
+
- (void)_setAllowsAnySSLCertificateForServiceWorker:(BOOL) allows
{
#if ENABLE(SERVICE_WORKER)
@@ -587,7 +592,7 @@
- (_WKDownload *)_downloadURLRequest:(NSURLRequest *)request originatingWebView:(WKWebView *)webView
{
- return (_WKDownload *)_processPool->download([webView _page], request)->wrapper();
+ return (_WKDownload *)_processPool->download([webView _page], request).wrapper();
}
- (_WKDownload *)_resumeDownloadFromData:(NSData *)resumeData path:(NSString *)path originatingWebView:(WKWebView *)webView
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKProcessPoolPrivate.h (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKProcessPoolPrivate.h 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKProcessPoolPrivate.h 2019-03-18 22:38:55 UTC (rev 243110)
@@ -120,5 +120,6 @@
@property (nonatomic, getter=_isCookieStoragePartitioningEnabled, setter=_setCookieStoragePartitioningEnabled:) BOOL _cookieStoragePartitioningEnabled WK_API_DEPRECATED("Partitioned cookies are no longer supported", macosx(10.12.3, WK_MAC_TBA), ios(10.3, WK_IOS_TBA));
@property (nonatomic, getter=_isStorageAccessAPIEnabled, setter=_setStorageAccessAPIEnabled:) BOOL _storageAccessAPIEnabled WK_API_AVAILABLE(macosx(10.13.4), ios(11.3));
+- (void)_synthesizeAppIsBackground:(BOOL)background WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
@end
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h 2019-03-18 22:38:55 UTC (rev 243110)
@@ -69,6 +69,7 @@
@property (nonatomic) BOOL pageCacheEnabled WK_API_AVAILABLE(macosx(10.14), ios(12.0));
@property (nonatomic) BOOL suppressesConnectionTerminationOnSystemChange WK_API_AVAILABLE(macosx(10.14), ios(12.0));
@property (nonatomic, getter=isJITEnabled) BOOL JITEnabled WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+@property (nonatomic) NSUInteger downloadMonitorSpeedMultiplierForTesting WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
@end
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm 2019-03-18 22:38:55 UTC (rev 243110)
@@ -324,6 +324,16 @@
_processPoolConfiguration->setJITEnabled(enabled);
}
+- (NSUInteger)downloadMonitorSpeedMultiplierForTesting
+{
+ return _processPoolConfiguration->downloadMonitorSpeedMultiplier();
+}
+
+- (void)setDownloadMonitorSpeedMultiplierForTesting:(NSUInteger)multiplier
+{
+ _processPoolConfiguration->setDownloadMonitorSpeedMultiplier(multiplier);
+}
+
- (void)setSuppressesConnectionTerminationOnSystemChange:(BOOL)suppressesConnectionTerminationOnSystemChange
{
_processPoolConfiguration->setSuppressesConnectionTerminationOnSystemChange(suppressesConnectionTerminationOnSystemChange);
Modified: trunk/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp 2019-03-18 22:38:55 UTC (rev 243110)
@@ -1639,7 +1639,7 @@
WebKitDownload* webkitWebContextStartDownload(WebKitWebContext* context, const char* uri, WebPageProxy* initiatingPage)
{
WebCore::ResourceRequest request(String::fromUTF8(uri));
- return webkitWebContextGetOrCreateDownload(context->priv->processPool->download(initiatingPage, request));
+ return webkitWebContextGetOrCreateDownload(&context->priv->processPool->download(initiatingPage, request));
}
void webkitWebContextRemoveDownload(DownloadProxy* downloadProxy)
Modified: trunk/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp 2019-03-18 22:38:55 UTC (rev 243110)
@@ -299,10 +299,10 @@
}
#endif
-void PageClientImpl::handleDownloadRequest(DownloadProxy* download)
+void PageClientImpl::handleDownloadRequest(DownloadProxy& download)
{
if (WEBKIT_IS_WEB_VIEW(m_viewWidget))
- webkitWebViewHandleDownloadRequest(WEBKIT_WEB_VIEW(m_viewWidget), download);
+ webkitWebViewHandleDownloadRequest(WEBKIT_WEB_VIEW(m_viewWidget), &download);
}
void PageClientImpl::didCommitLoadForMainFrame(const String& /* mimeType */, bool /* useCustomContentProvider */ )
Modified: trunk/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h 2019-03-18 22:38:55 UTC (rev 243110)
@@ -103,7 +103,7 @@
void exitAcceleratedCompositingMode() override;
void updateAcceleratedCompositingMode(const LayerTreeContext&) override;
- void handleDownloadRequest(DownloadProxy*) override;
+ void handleDownloadRequest(DownloadProxy&) override;
void didChangeContentSize(const WebCore::IntSize&) override;
void didCommitLoadForMainFrame(const String& mimeType, bool useCustomContentProvider) override;
void didFailLoadForMainFrame() override;
Modified: trunk/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp 2019-03-18 22:38:55 UTC (rev 243110)
@@ -124,10 +124,9 @@
{
}
-void PageClientImpl::handleDownloadRequest(DownloadProxy* download)
+void PageClientImpl::handleDownloadRequest(DownloadProxy& download)
{
- ASSERT(download);
- m_view.handleDownloadRequest(*download);
+ m_view.handleDownloadRequest(download);
}
void PageClientImpl::didChangeContentSize(const WebCore::IntSize&)
Modified: trunk/Source/WebKit/UIProcess/API/wpe/PageClientImpl.h (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/API/wpe/PageClientImpl.h 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/API/wpe/PageClientImpl.h 2019-03-18 22:38:55 UTC (rev 243110)
@@ -74,7 +74,7 @@
void toolTipChanged(const String&, const String&) override;
void didCommitLoadForMainFrame(const String&, bool) override;
- void handleDownloadRequest(DownloadProxy*) override;
+ void handleDownloadRequest(DownloadProxy&) override;
void didChangeContentSize(const WebCore::IntSize&) override;
Copied: trunk/Source/WebKit/UIProcess/Cocoa/DownloadProxyMapCocoa.mm (from rev 243109, trunk/Source/WebKit/NetworkProcess/Downloads/DownloadMap.h) (0 => 243110)
--- trunk/Source/WebKit/UIProcess/Cocoa/DownloadProxyMapCocoa.mm (rev 0)
+++ trunk/Source/WebKit/UIProcess/Cocoa/DownloadProxyMapCocoa.mm 2019-03-18 22:38:55 UTC (rev 243110)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 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
+ * 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. AND ITS CONTRIBUTORS ``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 ITS 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 "DownloadProxyMap.h"
+
+#if PLATFORM(IOS_FAMILY)
+#import <UIKit/UIKit.h>
+#endif
+
+namespace WebKit {
+
+void DownloadProxyMap::platformCreate()
+{
+#if PLATFORM(IOS_FAMILY)
+ m_backgroundObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidEnterBackgroundNotification object:[UIApplication sharedApplication] queue:nil usingBlock:makeBlockPtr([weakThis = makeWeakPtr(*this)](NSNotification *) {
+ if (!weakThis)
+ return;
+ weakThis->applicationDidEnterBackground();
+ }).get()];
+ m_foregroundObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillEnterForegroundNotification object:[UIApplication sharedApplication] queue:nil usingBlock:makeBlockPtr([weakThis = makeWeakPtr(*this)](NSNotification *) {
+ if (!weakThis)
+ return;
+ weakThis->applicationWillEnterForeground();
+ }).get()];
+#endif
+}
+
+void DownloadProxyMap::platformDestroy()
+{
+#if PLATFORM(IOS_FAMILY)
+ [[NSNotificationCenter defaultCenter] removeObserver:m_backgroundObserver.get()];
+ [[NSNotificationCenter defaultCenter] removeObserver:m_foregroundObserver.get()];
+#endif
+}
+
+} // namespace WebKit
Modified: trunk/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm 2019-03-18 22:38:55 UTC (rev 243110)
@@ -54,11 +54,14 @@
#import <sys/param.h>
#import <wtf/FileSystem.h>
#import <wtf/ProcessPrivilege.h>
+#import <wtf/SoftLinking.h>
#import <wtf/cocoa/Entitlements.h>
#import <wtf/spi/darwin/dyldSPI.h>
#if PLATFORM(MAC)
#import <QuartzCore/CARemoteLayerServer.h>
+#else
+#import "UIKitSPI.h"
#endif
#if PLATFORM(IOS)
@@ -309,6 +312,7 @@
#endif
parameters.shouldEnableITPDatabase = [defaults boolForKey:[NSString stringWithFormat:@"InternalDebug%@", WebPreferencesKey::isITPDatabaseEnabledKey().createCFString().get()]];
+ parameters.downloadMonitorSpeedMultiplier = m_configuration->downloadMonitorSpeedMultiplier();
}
void WebProcessPool::platformInvalidateContext()
Modified: trunk/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp 2019-03-18 22:38:55 UTC (rev 243110)
@@ -209,7 +209,7 @@
m_processPool->downloadClient().didFinish(*m_processPool, *this);
// This can cause the DownloadProxy object to be deleted.
- m_downloadProxyMap.downloadFinished(this);
+ m_downloadProxyMap.downloadFinished(*this);
}
static RefPtr<API::Data> createData(const IPC::DataReference& data)
@@ -230,7 +230,7 @@
m_processPool->downloadClient().didFail(*m_processPool, *this, error);
// This can cause the DownloadProxy object to be deleted.
- m_downloadProxyMap.downloadFinished(this);
+ m_downloadProxyMap.downloadFinished(*this);
}
void DownloadProxy::didCancel(const IPC::DataReference& resumeData)
@@ -240,7 +240,7 @@
m_processPool->downloadClient().didCancel(*m_processPool, *this);
// This can cause the DownloadProxy object to be deleted.
- m_downloadProxyMap.downloadFinished(this);
+ m_downloadProxyMap.downloadFinished(*this);
}
} // namespace WebKit
Modified: trunk/Source/WebKit/UIProcess/Downloads/DownloadProxyMap.cpp (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/Downloads/DownloadProxyMap.cpp 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/Downloads/DownloadProxyMap.cpp 2019-03-18 22:38:55 UTC (rev 243110)
@@ -40,20 +40,44 @@
namespace WebKit {
DownloadProxyMap::DownloadProxyMap(NetworkProcessProxy& process)
- : m_process(&process)
+ : m_process(makeWeakPtr(process))
#if PLATFORM(COCOA)
, m_shouldTakeAssertion(WTF::processHasEntitlement("com.apple.multitasking.systemappassertions"))
#endif
{
+ platformCreate();
}
DownloadProxyMap::~DownloadProxyMap()
{
ASSERT(m_downloads.isEmpty());
+ platformDestroy();
}
-DownloadProxy* DownloadProxyMap::createDownloadProxy(WebProcessPool& processPool, const WebCore::ResourceRequest& resourceRequest)
+#if !PLATFORM(COCOA)
+void DownloadProxyMap::platformCreate()
{
+}
+
+void DownloadProxyMap::platformDestroy()
+{
+}
+#endif
+
+void DownloadProxyMap::applicationDidEnterBackground()
+{
+ if (m_process)
+ m_process->send(Messages::NetworkProcess::ApplicationDidEnterBackground(), 0);
+}
+
+void DownloadProxyMap::applicationWillEnterForeground()
+{
+ if (m_process)
+ m_process->send(Messages::NetworkProcess::ApplicationWillEnterForeground(), 0);
+}
+
+DownloadProxy& DownloadProxyMap::createDownloadProxy(WebProcessPool& processPool, const WebCore::ResourceRequest& resourceRequest)
+{
auto downloadProxy = DownloadProxy::create(*this, processPool, resourceRequest);
m_downloads.set(downloadProxy->downloadID(), downloadProxy.copyRef());
@@ -64,12 +88,12 @@
m_process->addMessageReceiver(Messages::DownloadProxy::messageReceiverName(), downloadProxy->downloadID().downloadID(), downloadProxy.get());
- return downloadProxy.ptr();
+ return downloadProxy;
}
-void DownloadProxyMap::downloadFinished(DownloadProxy* downloadProxy)
+void DownloadProxyMap::downloadFinished(DownloadProxy& downloadProxy)
{
- auto downloadID = downloadProxy->downloadID();
+ auto downloadID = downloadProxy.downloadID();
// The DownloadProxy may be holding the last reference to the process pool.
auto protectedProcessPool = makeRefPtr(m_process->processPool());
@@ -77,7 +101,7 @@
ASSERT(m_downloads.contains(downloadID));
m_process->removeMessageReceiver(Messages::DownloadProxy::messageReceiverName(), downloadID.downloadID());
- downloadProxy->invalidate();
+ downloadProxy.invalidate();
m_downloads.remove(downloadID);
if (m_downloads.isEmpty() && m_shouldTakeAssertion) {
Modified: trunk/Source/WebKit/UIProcess/Downloads/DownloadProxyMap.h (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/Downloads/DownloadProxyMap.h 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/Downloads/DownloadProxyMap.h 2019-03-18 22:38:55 UTC (rev 243110)
@@ -28,7 +28,13 @@
#include "DownloadID.h"
#include <wtf/HashMap.h>
#include <wtf/Noncopyable.h>
+#include <wtf/RetainPtr.h>
+#include <wtf/WeakPtr.h>
+#if PLATFORM(IOS_FAMILY)
+#include <objc/objc.h>
+#endif
+
namespace WebCore {
class ResourceRequest;
}
@@ -40,7 +46,7 @@
class ProcessAssertion;
class WebProcessPool;
-class DownloadProxyMap {
+class DownloadProxyMap : public CanMakeWeakPtr<DownloadProxyMap> {
WTF_MAKE_FAST_ALLOCATED;
WTF_MAKE_NONCOPYABLE(DownloadProxyMap);
@@ -48,19 +54,29 @@
explicit DownloadProxyMap(NetworkProcessProxy&);
~DownloadProxyMap();
- DownloadProxy* createDownloadProxy(WebProcessPool&, const WebCore::ResourceRequest&);
- void downloadFinished(DownloadProxy*);
+ DownloadProxy& createDownloadProxy(WebProcessPool&, const WebCore::ResourceRequest&);
+ void downloadFinished(DownloadProxy&);
bool isEmpty() const { return m_downloads.isEmpty(); }
void processDidClose();
+ void applicationDidEnterBackground();
+ void applicationWillEnterForeground();
+
private:
- NetworkProcessProxy* m_process;
+ void platformCreate();
+ void platformDestroy();
+
+ WeakPtr<NetworkProcessProxy> m_process;
HashMap<DownloadID, RefPtr<DownloadProxy>> m_downloads;
bool m_shouldTakeAssertion { false };
std::unique_ptr<ProcessAssertion> m_downloadAssertion;
+#if PLATFORM(IOS_FAMILY)
+ RetainPtr<id> m_backgroundObserver;
+ RetainPtr<id> m_foregroundObserver;
+#endif
};
} // namespace WebKit
Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp 2019-03-18 22:38:55 UTC (rev 243110)
@@ -147,8 +147,18 @@
connection()->send(Messages::NetworkProcess::CreateNetworkConnectionToWebProcess(isServiceWorkerProcess, registrableDomain), 0, IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply);
}
-DownloadProxy* NetworkProcessProxy::createDownloadProxy(const ResourceRequest& resourceRequest)
+void NetworkProcessProxy::synthesizeAppIsBackground(bool background)
{
+ if (m_downloadProxyMap) {
+ if (background)
+ m_downloadProxyMap->applicationDidEnterBackground();
+ else
+ m_downloadProxyMap->applicationWillEnterForeground();
+ }
+}
+
+DownloadProxy& NetworkProcessProxy::createDownloadProxy(const ResourceRequest& resourceRequest)
+{
if (!m_downloadProxyMap)
m_downloadProxyMap = std::make_unique<DownloadProxyMap>(*this);
Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h 2019-03-18 22:38:55 UTC (rev 243110)
@@ -66,7 +66,7 @@
class WebUserContentControllerProxy;
struct WebsiteData;
-class NetworkProcessProxy final : public AuxiliaryProcessProxy, private ProcessThrottlerClient {
+class NetworkProcessProxy final : public AuxiliaryProcessProxy, private ProcessThrottlerClient, public CanMakeWeakPtr<NetworkProcessProxy> {
public:
using RegistrableDomain = WebCore::RegistrableDomain;
using TopFrameDomain = WebCore::RegistrableDomain;
@@ -88,7 +88,7 @@
void getNetworkProcessConnection(WebProcessProxy&, Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply&&);
- DownloadProxy* createDownloadProxy(const WebCore::ResourceRequest&);
+ DownloadProxy& createDownloadProxy(const WebCore::ResourceRequest&);
void fetchWebsiteData(PAL::SessionID, OptionSet<WebsiteDataType>, OptionSet<WebsiteDataFetchOption>, CompletionHandler<void(WebsiteData)>&&);
void deleteWebsiteData(PAL::SessionID, OptionSet<WebsiteDataType>, WallTime modifiedSince, CompletionHandler<void()>&& completionHandler);
@@ -154,6 +154,7 @@
void sendProcessDidTransitionToForeground();
void sendProcessDidTransitionToBackground();
+ void synthesizeAppIsBackground(bool background);
void setIsHoldingLockedFiles(bool);
void setIsIDBDatabaseHoldingLockedFiles(bool);
Modified: trunk/Source/WebKit/UIProcess/PageClient.h (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/PageClient.h 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/PageClient.h 2019-03-18 22:38:55 UTC (rev 243110)
@@ -215,7 +215,7 @@
virtual void didFailProvisionalLoadForMainFrame() { };
virtual void didCommitLoadForMainFrame(const String& mimeType, bool useCustomContentProvider) = 0;
- virtual void handleDownloadRequest(DownloadProxy*) = 0;
+ virtual void handleDownloadRequest(DownloadProxy&) = 0;
virtual bool handleRunOpenPanel(WebPageProxy*, WebFrameProxy*, API::OpenPanelParameters*, WebOpenPanelResultListenerProxy*) { return false; }
virtual bool showShareSheet(const WebCore::ShareDataWithParsedURL&, WTF::CompletionHandler<void (bool)>&&) { return false; }
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2019-03-18 22:38:55 UTC (rev 243110)
@@ -2835,13 +2835,13 @@
DownloadID downloadID = { };
if (action == PolicyAction::Download) {
// Create a download proxy.
- auto* download = m_process->processPool().createDownloadProxy(m_decidePolicyForResponseRequest, this);
+ auto& download = m_process->processPool().createDownloadProxy(m_decidePolicyForResponseRequest, this);
if (navigation) {
- download->setWasUserInitiated(navigation->wasUserInitiated());
- download->setRedirectChain(navigation->takeRedirectChain());
+ download.setWasUserInitiated(navigation->wasUserInitiated());
+ download.setRedirectChain(navigation->takeRedirectChain());
}
- downloadID = download->downloadID();
+ downloadID = download.downloadID();
handleDownloadRequest(download);
m_decidePolicyForResponseRequest = { };
}
@@ -5452,7 +5452,7 @@
process().send(Messages::WebPage::SetMayStartMediaWhenInWindow(mayStartMedia), m_pageID);
}
-void WebPageProxy::handleDownloadRequest(DownloadProxy* download)
+void WebPageProxy::handleDownloadRequest(DownloadProxy& download)
{
pageClient().handleDownloadRequest(download);
}
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.h 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h 2019-03-18 22:38:55 UTC (rev 243110)
@@ -1102,7 +1102,7 @@
WebPageCreationParameters creationParameters(WebProcessProxy&, DrawingAreaProxy&);
- void handleDownloadRequest(DownloadProxy*);
+ void handleDownloadRequest(DownloadProxy&);
void advanceToNextMisspelling(bool startBeforeSelection);
void changeSpellingToWord(const String& word);
Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.cpp (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/WebProcessPool.cpp 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.cpp 2019-03-18 22:38:55 UTC (rev 243110)
@@ -1332,9 +1332,9 @@
return m_sessionToPageIDsMap.contains(dataStore.sessionID());
}
-DownloadProxy* WebProcessPool::download(WebPageProxy* initiatingPage, const ResourceRequest& request, const String& suggestedFilename)
+DownloadProxy& WebProcessPool::download(WebPageProxy* initiatingPage, const ResourceRequest& request, const String& suggestedFilename)
{
- auto* downloadProxy = createDownloadProxy(request, initiatingPage);
+ auto& downloadProxy = createDownloadProxy(request, initiatingPage);
PAL::SessionID sessionID = initiatingPage ? initiatingPage->sessionID() : PAL::SessionID::defaultSessionID();
if (initiatingPage)
@@ -1357,7 +1357,7 @@
updatedRequest.setHTTPUserAgent(WebPageProxy::standardUserAgent());
}
updatedRequest.setIsTopSite(false);
- networkProcess()->send(Messages::NetworkProcess::DownloadRequest(sessionID, downloadProxy->downloadID(), updatedRequest, suggestedFilename), 0);
+ networkProcess()->send(Messages::NetworkProcess::DownloadRequest(sessionID, downloadProxy.downloadID(), updatedRequest, suggestedFilename), 0);
return downloadProxy;
}
@@ -1364,9 +1364,9 @@
return downloadProxy;
}
-DownloadProxy* WebProcessPool::resumeDownload(WebPageProxy* initiatingPage, const API::Data* resumeData, const String& path)
+DownloadProxy& WebProcessPool::resumeDownload(WebPageProxy* initiatingPage, const API::Data* resumeData, const String& path)
{
- auto* downloadProxy = createDownloadProxy(ResourceRequest(), initiatingPage);
+ auto& downloadProxy = createDownloadProxy(ResourceRequest(), initiatingPage);
PAL::SessionID sessionID = initiatingPage ? initiatingPage->sessionID() : PAL::SessionID::defaultSessionID();
SandboxExtension::Handle sandboxExtensionHandle;
@@ -1374,7 +1374,7 @@
SandboxExtension::createHandle(path, SandboxExtension::Type::ReadWrite, sandboxExtensionHandle);
if (networkProcess()) {
- networkProcess()->send(Messages::NetworkProcess::ResumeDownload(sessionID, downloadProxy->downloadID(), resumeData->dataReference(), path, sandboxExtensionHandle), 0);
+ networkProcess()->send(Messages::NetworkProcess::ResumeDownload(sessionID, downloadProxy.downloadID(), resumeData->dataReference(), path, sandboxExtensionHandle), 0);
return downloadProxy;
}
@@ -1625,13 +1625,18 @@
sendToAllProcesses(Messages::WebProcess::SetDefaultRequestTimeoutInterval(timeoutInterval));
}
-DownloadProxy* WebProcessPool::createDownloadProxy(const ResourceRequest& request, WebPageProxy* originatingPage)
+DownloadProxy& WebProcessPool::createDownloadProxy(const ResourceRequest& request, WebPageProxy* originatingPage)
{
- auto downloadProxy = ensureNetworkProcess().createDownloadProxy(request);
- downloadProxy->setOriginatingPage(originatingPage);
+ auto& downloadProxy = ensureNetworkProcess().createDownloadProxy(request);
+ downloadProxy.setOriginatingPage(originatingPage);
return downloadProxy;
}
+void WebProcessPool::synthesizeAppIsBackground(bool background)
+{
+ ensureNetworkProcess().synthesizeAppIsBackground(background);
+}
+
void WebProcessPool::addMessageReceiver(IPC::StringReference messageReceiverName, IPC::MessageReceiver& messageReceiver)
{
m_messageReceiverMap.addMessageReceiver(messageReceiverName, messageReceiver);
Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.h (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/WebProcessPool.h 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.h 2019-03-18 22:38:55 UTC (rev 243110)
@@ -198,8 +198,8 @@
const String& injectedBundlePath() const { return m_configuration->injectedBundlePath(); }
- DownloadProxy* download(WebPageProxy* initiatingPage, const WebCore::ResourceRequest&, const String& suggestedFilename = { });
- DownloadProxy* resumeDownload(WebPageProxy* initiatingPage, const API::Data* resumeData, const String& path);
+ DownloadProxy& download(WebPageProxy* initiatingPage, const WebCore::ResourceRequest&, const String& suggestedFilename = { });
+ DownloadProxy& resumeDownload(WebPageProxy* initiatingPage, const API::Data* resumeData, const String& path);
void setInjectedBundleInitializationUserData(RefPtr<API::Object>&& userData) { m_injectedBundleInitializationUserData = WTFMove(userData); }
@@ -271,7 +271,7 @@
void setEnhancedAccessibility(bool);
// Downloads.
- DownloadProxy* createDownloadProxy(const WebCore::ResourceRequest&, WebPageProxy* originatingPage);
+ DownloadProxy& createDownloadProxy(const WebCore::ResourceRequest&, WebPageProxy* originatingPage);
API::DownloadClient& downloadClient() { return *m_downloadClient; }
API::LegacyContextHistoryClient& historyClient() { return *m_historyClient; }
@@ -434,6 +434,8 @@
bool alwaysRunsAtBackgroundPriority() const { return m_alwaysRunsAtBackgroundPriority; }
bool shouldTakeUIBackgroundAssertion() const { return m_shouldTakeUIBackgroundAssertion; }
+ void synthesizeAppIsBackground(bool background);
+
#if ENABLE(GAMEPAD)
void gamepadConnected(const UIGamepad&);
void gamepadDisconnected(const UIGamepad&);
Modified: trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h 2019-03-18 22:38:55 UTC (rev 243110)
@@ -75,7 +75,7 @@
void didStartProvisionalLoadForMainFrame() override;
void didFailProvisionalLoadForMainFrame() override;
void didCommitLoadForMainFrame(const String& mimeType, bool useCustomContentProvider) override;
- void handleDownloadRequest(DownloadProxy*) override;
+ void handleDownloadRequest(DownloadProxy&) override;
void didChangeContentSize(const WebCore::IntSize&) override;
void setCursor(const WebCore::Cursor&) override;
void setCursorHiddenUntilMouseMoves(bool) override;
Modified: trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm 2019-03-18 22:38:55 UTC (rev 243110)
@@ -224,7 +224,7 @@
[m_contentView _didCommitLoadForMainFrame];
}
-void PageClientImpl::handleDownloadRequest(DownloadProxy*)
+void PageClientImpl::handleDownloadRequest(DownloadProxy&)
{
}
Modified: trunk/Source/WebKit/UIProcess/mac/PageClientImplMac.h (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/mac/PageClientImplMac.h 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/mac/PageClientImplMac.h 2019-03-18 22:38:55 UTC (rev 243110)
@@ -88,7 +88,7 @@
void toolTipChanged(const String& oldToolTip, const String& newToolTip) override;
void didCommitLoadForMainFrame(const String& mimeType, bool useCustomContentProvider) override;
void didFinishLoadingDataForCustomContentProvider(const String& suggestedFilename, const IPC::DataReference&) override;
- void handleDownloadRequest(DownloadProxy*) override;
+ void handleDownloadRequest(DownloadProxy&) override;
void didChangeContentSize(const WebCore::IntSize&) override;
void setCursor(const WebCore::Cursor&) override;
void setCursorHiddenUntilMouseMoves(bool) override;
Modified: trunk/Source/WebKit/UIProcess/mac/PageClientImplMac.mm (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/mac/PageClientImplMac.mm 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/mac/PageClientImplMac.mm 2019-03-18 22:38:55 UTC (rev 243110)
@@ -295,7 +295,7 @@
{
}
-void PageClientImpl::handleDownloadRequest(DownloadProxy*)
+void PageClientImpl::handleDownloadRequest(DownloadProxy&)
{
}
Modified: trunk/Source/WebKit/UIProcess/win/PageClientImpl.cpp (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/win/PageClientImpl.cpp 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/win/PageClientImpl.cpp 2019-03-18 22:38:55 UTC (rev 243110)
@@ -229,7 +229,7 @@
notImplemented();
}
-void PageClientImpl::handleDownloadRequest(DownloadProxy* download)
+void PageClientImpl::handleDownloadRequest(DownloadProxy& download)
{
notImplemented();
}
Modified: trunk/Source/WebKit/UIProcess/win/PageClientImpl.h (243109 => 243110)
--- trunk/Source/WebKit/UIProcess/win/PageClientImpl.h 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/UIProcess/win/PageClientImpl.h 2019-03-18 22:38:55 UTC (rev 243110)
@@ -96,7 +96,7 @@
void exitAcceleratedCompositingMode() override;
void updateAcceleratedCompositingMode(const LayerTreeContext&) override;
- void handleDownloadRequest(DownloadProxy*) override;
+ void handleDownloadRequest(DownloadProxy&) override;
void didChangeContentSize(const WebCore::IntSize&) override;
void didCommitLoadForMainFrame(const String& mimeType, bool useCustomContentProvider) override;
void didFailLoadForMainFrame() override { }
Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (243109 => 243110)
--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj 2019-03-18 22:38:55 UTC (rev 243110)
@@ -3461,6 +3461,9 @@
5C20CB9E1BB0DD1800895BB1 /* NetworkSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkSession.h; sourceTree = "<group>"; };
5C26958420042F12005C439B /* WKOpenPanelParametersPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKOpenPanelParametersPrivate.h; sourceTree = "<group>"; };
5C298D9E1C3DEF2900470AFE /* PendingDownload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PendingDownload.h; sourceTree = "<group>"; };
+ 5C2B1AF3223AB72800B91CF7 /* DownloadMonitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DownloadMonitor.cpp; sourceTree = "<group>"; };
+ 5C2B1AF4223AB72800B91CF7 /* DownloadMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DownloadMonitor.h; sourceTree = "<group>"; };
+ 5C2B1AF5223C1FD200B91CF7 /* DownloadProxyMapCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DownloadProxyMapCocoa.mm; sourceTree = "<group>"; };
5C359C0C21547321009E7948 /* WKDeprecated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKDeprecated.h; sourceTree = "<group>"; };
5C3AEA8E1FE1F1DF002318D3 /* WebsitePoliciesData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebsitePoliciesData.cpp; sourceTree = "<group>"; };
5C46C0AC21B7198B00BC5991 /* WebsiteDataStoreConfiguration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebsiteDataStoreConfiguration.cpp; sourceTree = "<group>"; };
@@ -5342,6 +5345,7 @@
83891B6B1A68C30B0030F386 /* DiagnosticLoggingClient.mm */,
A1DF631118E0B7C8003A3E2A /* DownloadClient.h */,
A1DF631018E0B7C8003A3E2A /* DownloadClient.mm */,
+ 5C2B1AF5223C1FD200B91CF7 /* DownloadProxyMapCocoa.mm */,
00B9661818E25AE100CE1F88 /* FindClient.h */,
00B9661718E25AE100CE1F88 /* FindClient.mm */,
CD78E1131DB7D7ED0014A2DE /* FullscreenClient.h */,
@@ -6867,6 +6871,8 @@
5C1426F91C23F84300D41183 /* DownloadManager.h */,
51240EB9220A08CA005CFC63 /* DownloadMap.cpp */,
51240EB8220A08CA005CFC63 /* DownloadMap.h */,
+ 5C2B1AF3223AB72800B91CF7 /* DownloadMonitor.cpp */,
+ 5C2B1AF4223AB72800B91CF7 /* DownloadMonitor.h */,
5C85C7861C3F23C50061A4FA /* PendingDownload.cpp */,
5C298D9E1C3DEF2900470AFE /* PendingDownload.h */,
);
@@ -10241,9 +10247,6 @@
CreatedOnToolsVersion = 10.1;
ProvisioningStyle = Automatic;
};
- A1798B59223464C4000764BD = {
- CreatedOnToolsVersion = 10.2;
- };
E1AC2E2720F7B94C00B0897D = {
CreatedOnToolsVersion = 9.3;
ProvisioningStyle = Automatic;
Modified: trunk/Tools/ChangeLog (243109 => 243110)
--- trunk/Tools/ChangeLog 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Tools/ChangeLog 2019-03-18 22:38:55 UTC (rev 243110)
@@ -1,3 +1,28 @@
+2019-03-18 Alex Christensen <[email protected]>
+
+ Implement DownloadMonitor to prevent long-running slow downloads from background apps
+ https://bugs.webkit.org/show_bug.cgi?id=195785
+
+ Reviewed by Geoffrey Garen.
+
+ * TestWebKitAPI/TCPServer.cpp: Added.
+ (TestWebKitAPI::TCPServer::TCPServer):
+ (TestWebKitAPI::TCPServer::~TCPServer):
+ (TestWebKitAPI::TCPServer::socketBindListen):
+ (TestWebKitAPI::TCPServer::waitForAndReplyToRequests):
+ * TestWebKitAPI/TCPServer.h: Added.
+ (TestWebKitAPI::TCPServer::port const):
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/WebKitCocoa/Download.mm:
+ (-[DownloadMonitorTestDelegate _downloadDidStart:]):
+ (-[DownloadMonitorTestDelegate _downloadDidCancel:]):
+ (-[DownloadMonitorTestDelegate _download:decideDestinationWithSuggestedFilename:completionHandler:]):
+ (-[DownloadMonitorTestDelegate _download:didReceiveData:]):
+ (TestWebKitAPI::respondSlowly):
+ (TestWebKitAPI::webViewWithDownloadMonitorSpeedMultiplier):
+ (TestWebKitAPI::downloadAtRate):
+ (TestWebKitAPI::TEST):
+
2019-03-18 Saam Barati <[email protected]>
Add a plan file for JetStream 2
Added: trunk/Tools/TestWebKitAPI/TCPServer.cpp (0 => 243110)
--- trunk/Tools/TestWebKitAPI/TCPServer.cpp (rev 0)
+++ trunk/Tools/TestWebKitAPI/TCPServer.cpp 2019-03-18 22:38:55 UTC (rev 243110)
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 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
+ * 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#include "config.h"
+#include "TCPServer.h"
+
+#include <netinet/in.h>
+#include <thread>
+#include <unistd.h>
+#include <vector>
+
+namespace TestWebKitAPI {
+
+TCPServer::TCPServer(Function<void(Socket)>&& socketHandler)
+ : m_socketHandler(WTFMove(socketHandler))
+{
+ socketBindListen();
+ m_thread = std::thread(&TCPServer::waitForAndReplyToRequests, this);
+}
+
+TCPServer::~TCPServer()
+{
+ m_thread.join();
+ if (m_listeningSocket != InvalidSocket) {
+ close(m_listeningSocket);
+ m_listeningSocket = InvalidSocket;
+ }
+ if (m_connectionSocket != InvalidSocket) {
+ close(m_connectionSocket);
+ m_connectionSocket = InvalidSocket;
+ }
+}
+
+void TCPServer::socketBindListen()
+{
+ m_listeningSocket = socket(PF_INET, SOCK_STREAM, 0);
+ if (m_listeningSocket == InvalidSocket)
+ return;
+
+ // Ports 49152-65535 are unallocated ports. Try until we find one that's free.
+ for (Port port = 49152; port; port++) {
+ struct sockaddr_in name;
+ memset(&name, 0, sizeof(name));
+ name.sin_family = AF_INET;
+ name.sin_port = htons(port);
+ name.sin_addr.s_addr = htonl(INADDR_ANY);
+ if (bind(m_listeningSocket, reinterpret_cast<sockaddr*>(&name), sizeof(name)) < 0) {
+ // This port is busy. Try the next port.
+ continue;
+ }
+ const unsigned maxConnections = 1;
+ if (listen(m_listeningSocket, maxConnections) == -1) {
+ // Listening failed.
+ close(m_listeningSocket);
+ m_listeningSocket = InvalidSocket;
+ return;
+ }
+ m_port = port;
+ return; // Successfully set up listening port.
+ }
+
+ // Couldn't find an available port.
+ close(m_listeningSocket);
+ m_listeningSocket = InvalidSocket;
+}
+
+void TCPServer::waitForAndReplyToRequests()
+{
+ if (m_listeningSocket == InvalidSocket)
+ return;
+
+ m_connectionSocket = accept(m_listeningSocket, nullptr, nullptr);
+ m_socketHandler(m_connectionSocket);
+ shutdown(m_connectionSocket, SHUT_RDWR);
+}
+
+} // namespace TestWebKitAPI
Copied: trunk/Tools/TestWebKitAPI/TCPServer.h (from rev 243109, trunk/Source/WebKit/NetworkProcess/Downloads/DownloadMap.h) (0 => 243110)
--- trunk/Tools/TestWebKitAPI/TCPServer.h (rev 0)
+++ trunk/Tools/TestWebKitAPI/TCPServer.h 2019-03-18 22:38:55 UTC (rev 243110)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 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
+ * 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#pragma once
+
+#include <thread>
+#include <wtf/Function.h>
+
+namespace TestWebKitAPI {
+
+class TCPServer {
+public:
+ using Socket = int;
+ static constexpr Socket InvalidSocket = -1;
+ using Port = uint16_t;
+ static constexpr Port InvalidPort = 0;
+
+ TCPServer(Function<void(Socket)>&&);
+ ~TCPServer();
+
+ Port port() const { return m_port; }
+
+private:
+ void socketBindListen();
+ void waitForAndReplyToRequests();
+
+ Port m_port { InvalidPort };
+ Socket m_listeningSocket { InvalidSocket };
+ Socket m_connectionSocket { InvalidSocket };
+ std::thread m_thread;
+ Function<void(Socket)> m_socketHandler;
+};
+
+} // namespace TestWebKitAPI
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (243109 => 243110)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2019-03-18 22:38:55 UTC (rev 243110)
@@ -321,6 +321,7 @@
5C838F7F1DB04F900082858F /* LoadInvalidURLRequest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57901FAE1CAF137100ED64F9 /* LoadInvalidURLRequest.mm */; };
5C8BC799218CF44700813886 /* NetworkProcess.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C8BC798218CF3E900813886 /* NetworkProcess.mm */; };
5C973F5C1F58EF8B00359C27 /* WebGLPolicy.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C973F5B1F58EF0A00359C27 /* WebGLPolicy.mm */; };
+ 5C9B548E223C4CBE00B150C4 /* TCPServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C9B548C223C4BF500B150C4 /* TCPServer.cpp */; };
5C9E56851DF9145400C9EE33 /* WebsitePolicies.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C9E56841DF9143D00C9EE33 /* WebsitePolicies.mm */; };
5C9E56871DF914AE00C9EE33 /* contentBlockerCheck.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5C9E56861DF9148E00C9EE33 /* contentBlockerCheck.html */; };
5C9E59411D3EB5AC00E3C62E /* ApplicationCache.db in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5C9E593E1D3EB1DE00E3C62E /* ApplicationCache.db */; };
@@ -1719,6 +1720,8 @@
5C7C74CA1FB528D4002F9ABE /* WebViewScheduleInRunLoop.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebViewScheduleInRunLoop.mm; sourceTree = "<group>"; };
5C8BC798218CF3E900813886 /* NetworkProcess.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NetworkProcess.mm; sourceTree = "<group>"; };
5C973F5B1F58EF0A00359C27 /* WebGLPolicy.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebGLPolicy.mm; sourceTree = "<group>"; };
+ 5C9B548C223C4BF500B150C4 /* TCPServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TCPServer.cpp; sourceTree = "<group>"; };
+ 5C9B548D223C4BF500B150C4 /* TCPServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TCPServer.h; sourceTree = "<group>"; };
5C9E56841DF9143D00C9EE33 /* WebsitePolicies.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebsitePolicies.mm; sourceTree = "<group>"; };
5C9E56861DF9148E00C9EE33 /* contentBlockerCheck.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = contentBlockerCheck.html; sourceTree = "<group>"; };
5C9E593E1D3EB1DE00E3C62E /* ApplicationCache.db */ = {isa = PBXFileReference; lastKnownFileType = file; path = ApplicationCache.db; sourceTree = "<group>"; };
@@ -2400,6 +2403,8 @@
BC575BBF126F5752006F0F12 /* PlatformUtilities.cpp */,
BC131883117114A800B69727 /* PlatformUtilities.h */,
BC90951B125533D700083756 /* PlatformWebView.h */,
+ 5C9B548C223C4BF500B150C4 /* TCPServer.cpp */,
+ 5C9B548D223C4BF500B150C4 /* TCPServer.h */,
BCB9E7FA112359A300A137E0 /* Test.h */,
BC131AA8117131FC00B69727 /* TestsController.cpp */,
BCB9E7C711234E3A00A137E0 /* TestsController.h */,
@@ -4296,6 +4301,7 @@
7CCE7EA81A411A1900447C4C /* SyntheticBackingScaleFactorWindow.m in Sources */,
1C734B5320788C4800F430EA /* SystemColors.mm in Sources */,
2D70059621EDA0C6003463CB /* TabOutOfWebView.mm in Sources */,
+ 5C9B548E223C4CBE00B150C4 /* TCPServer.cpp in Sources */,
7CCE7F161A411AE600447C4C /* TerminateTwice.cpp in Sources */,
7CCE7EA91A411A1D00447C4C /* TestBrowsingContextLoadDelegate.mm in Sources */,
F46128CB211D475100D9FADB /* TestDraggingInfo.mm in Sources */,
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/Download.mm (243109 => 243110)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/Download.mm 2019-03-18 22:29:55 UTC (rev 243109)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/Download.mm 2019-03-18 22:38:55 UTC (rev 243110)
@@ -29,18 +29,21 @@
#if PLATFORM(MAC) || PLATFORM(IOS)
#import "PlatformUtilities.h"
+#import "TCPServer.h"
#import "Test.h"
#import "TestProtocol.h"
#import "TestWKWebView.h"
-#import <WebKit/_WKDownload.h>
-#import <WebKit/_WKDownloadDelegate.h>
#import <WebKit/WKNavigationDelegatePrivate.h>
#import <WebKit/WKProcessPoolPrivate.h>
#import <WebKit/WKUIDelegatePrivate.h>
#import <WebKit/WKWebView.h>
#import <WebKit/WKWebViewConfiguration.h>
+#import <WebKit/_WKDownload.h>
+#import <WebKit/_WKDownloadDelegate.h>
+#import <WebKit/_WKProcessPoolConfiguration.h>
#import <wtf/FileSystem.h>
#import <wtf/MainThread.h>
+#import <wtf/MonotonicTime.h>
#import <wtf/RetainPtr.h>
#import <wtf/WeakObjCPtr.h>
#import <wtf/text/WTFString.h>
@@ -776,4 +779,139 @@
EXPECT_NULL(processPool.get());
}
-#endif
+static bool receivedData;
+static bool didCancel;
+static RetainPtr<NSString> destination;
+
+@interface DownloadMonitorTestDelegate : NSObject <_WKDownloadDelegate>
+@end
+
+@implementation DownloadMonitorTestDelegate
+
+- (void)_downloadDidStart:(_WKDownload *)download
+{
+ didDownloadStart = true;
+}
+
+- (void)_downloadDidCancel:(_WKDownload *)download
+{
+ didCancel = true;
+}
+
+- (void)_download:(_WKDownload *)download decideDestinationWithSuggestedFilename:(NSString *)filename completionHandler:(void (^)(BOOL allowOverwrite, NSString *destination))completionHandler
+{
+ EXPECT_TRUE([filename isEqualToString:@"filename.dat"]);
+ destination = [NSTemporaryDirectory() stringByAppendingPathComponent:filename];
+ completionHandler(YES, destination.get());
+}
+
+- (void)_download:(_WKDownload *)download didReceiveData:(uint64_t)length
+{
+ receivedData = true;
+}
+
+@end
+
+namespace TestWebKitAPI {
+
+void respondSlowly(int socket, double kbps, bool& terminateServer)
+{
+ EXPECT_FALSE(isMainThread());
+ char readBuffer[1000];
+ auto bytesRead = ::read(socket, readBuffer, sizeof(readBuffer));
+ EXPECT_GT(bytesRead, 0);
+ EXPECT_TRUE(static_cast<size_t>(bytesRead) < sizeof(readBuffer));
+
+ const char* responseHeader =
+ "HTTP/1.1 200 OK\r\n"
+ "Content-Disposition: attachment; filename=\"filename.dat\"\r\n"
+ "Content-Length: 100000000\r\n\r\n";
+ auto bytesWritten = ::write(socket, responseHeader, strlen(responseHeader));
+ EXPECT_EQ(static_cast<size_t>(bytesWritten), strlen(responseHeader));
+
+ const double writesPerSecond = 100;
+ Vector<char> writeBuffer(static_cast<size_t>(1024 * kbps / writesPerSecond));
+ while (!terminateServer) {
+ auto before = MonotonicTime::now();
+ ::write(socket, writeBuffer.data(), writeBuffer.size());
+ double writeDuration = (MonotonicTime::now() - before).seconds();
+ double desiredSleep = 1.0 / writesPerSecond;
+ if (writeDuration < desiredSleep)
+ usleep(USEC_PER_SEC * (desiredSleep - writeDuration));
+ }
+}
+
+RetainPtr<WKWebView> webViewWithDownloadMonitorSpeedMultiplier(size_t multiplier)
+{
+ static auto navigationDelegate = adoptNS([DownloadNavigationDelegate new]);
+ static auto downloadDelegate = adoptNS([DownloadMonitorTestDelegate new]);
+ auto processPoolConfiguration = adoptNS([_WKProcessPoolConfiguration new]);
+ [processPoolConfiguration setDownloadMonitorSpeedMultiplierForTesting:multiplier];
+ auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
+ auto webViewConfiguration = adoptNS([WKWebViewConfiguration new]);
+ [webViewConfiguration setProcessPool:processPool.get()];
+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
+ [webView setNavigationDelegate:navigationDelegate.get()];
+ [webView configuration].processPool._downloadDelegate = downloadDelegate.get();
+ return webView;
+}
+
+enum class AppReturnsToForeground { No, Yes };
+
+void downloadAtRate(double desiredKbps, unsigned speedMultiplier, AppReturnsToForeground returnToForeground = AppReturnsToForeground::No)
+{
+ bool terminateServer = false;
+ TCPServer server([&](auto socket) {
+ respondSlowly(socket, desiredKbps, terminateServer);
+ });
+
+ auto webView = webViewWithDownloadMonitorSpeedMultiplier(speedMultiplier);
+ [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://127.0.0.1:%d/", server.port()]]]];
+ receivedData = false;
+ Util::run(&receivedData);
+ // Start the DownloadMonitor's timer.
+ [[webView configuration].processPool _synthesizeAppIsBackground:YES];
+ if (returnToForeground == AppReturnsToForeground::Yes)
+ [[webView configuration].processPool _synthesizeAppIsBackground:NO];
+ didCancel = false;
+ Util::run(&didCancel);
+ terminateServer = true;
+ [[NSFileManager defaultManager] removeItemAtURL:[NSURL fileURLWithPath:destination.get() isDirectory:NO] error:nil];
+}
+
+TEST(_WKDownload, DownloadMonitorCancel)
+{
+ downloadAtRate(0.5, 120); // Should cancel in ~0.5 seconds
+ downloadAtRate(1.5, 120); // Should cancel in ~2.5 seconds
+}
+
+TEST(_WKDownload, DownloadMonitorSurvive)
+{
+ __block BOOL timeoutReached = NO;
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2.5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
+ EXPECT_FALSE(didCancel);
+ didCancel = true;
+ timeoutReached = YES;
+ });
+
+ // Simulates an hour of downloading 150kb/s in 1 second.
+ // Timeout should be reached before this is cancelled because the download rate is high enough.
+ downloadAtRate(150.0, 3600);
+ EXPECT_TRUE(timeoutReached);
+}
+
+TEST(_WKDownload, DownloadMonitorReturnToForeground)
+{
+ __block BOOL timeoutReached = NO;
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2.5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
+ EXPECT_FALSE(didCancel);
+ didCancel = true;
+ timeoutReached = YES;
+ });
+ downloadAtRate(0.5, 120, AppReturnsToForeground::Yes);
+ EXPECT_TRUE(timeoutReached);
+}
+
+} // namespace TestWebKitAPI
+
+#endif // PLATFORM(MAC) || PLATFORM(IOS)