Source/WebKit/ChangeLog

 12021-09-24 Ben Nham <nham@apple.com>
 2
 3 Pending preconnect key should include User-Agent
 4 https://bugs.webkit.org/show_bug.cgi?id=230565
 5
 6 Reviewed by Chris Dumez.
 7
 8 When using an HTTPS proxy, the HTTP connection cache key used for connection coalescing in
 9 CFNetwork includes the User-Agent (<rdar://problem/59434166>). This means we should also
 10 include it in the preconnect cache key. Otherwise, we might delay the main resource load on
 11 preconnect unnecessarily in cases where the User-Agent mismatches and the preconnect gets
 12 thrown away. This can happen if (for instance) a page is force-loaded into desktop or mobile
 13 mode on iOS, which causes a UA change after the call to decidePolicyForNavigationAction.
 14
 15 * NetworkProcess/NetworkLoadScheduler.cpp:
 16 (WebKit::mainResourceLoadKey):
 17 (WebKit::NetworkLoadScheduler::scheduleMainResourceLoad):
 18 (WebKit::NetworkLoadScheduler::unscheduleMainResourceLoad):
 19 (WebKit::NetworkLoadScheduler::startedPreconnectForMainResource):
 20 (WebKit::NetworkLoadScheduler::finishedPreconnectForMainResource):
 21 * NetworkProcess/NetworkLoadScheduler.h:
 22 * NetworkProcess/NetworkProcess.cpp:
 23 (WebKit::NetworkProcess::preconnectTo):
 24
1252021-09-24 Devin Rousso <drousso@apple.com>
226
327 Add typechecking `is` overloads for `std::unique_ptr`, `WTF::UniqueRef`, and `WTF::WeakPtr`

Source/WebKit/NetworkProcess/NetworkLoadScheduler.cpp

@@void NetworkLoadScheduler::unscheduleLoad(NetworkLoad& load)
153153 context->unschedule(load);
154154}
155155
 156// We add User-Agent to the preconnect key since it part of the HTTP connection cache key used for
 157// coalescing sockets in CFNetwork when using an HTTPS proxy (<rdar://problem/59434166>).
 158static std::tuple<String, String> mainResourceLoadKey(const String& protocolHostAndPort, const String& userAgent)
 159{
 160 return std::make_tuple(protocolHostAndPort.isNull() ? emptyString() : protocolHostAndPort, userAgent.isNull() ? emptyString() : userAgent);
 161}
 162
156163void NetworkLoadScheduler::scheduleMainResourceLoad(NetworkLoad& load)
157164{
158165 String protocolHostAndPort = load.url().protocolHostAndPort();

@@void NetworkLoadScheduler::scheduleMainResourceLoad(NetworkLoad& load)
161168 return;
162169 }
163170
164  auto iter = m_pendingMainResourcePreconnects.find(protocolHostAndPort);
 171 auto iter = m_pendingMainResourcePreconnects.find(mainResourceLoadKey(protocolHostAndPort, load.parameters().request.httpUserAgent()));
165172 if (iter == m_pendingMainResourcePreconnects.end()) {
166173 load.start();
167174 return;

@@void NetworkLoadScheduler::unscheduleMainResourceLoad(NetworkLoad& load, const W
185192 if (metrics)
186193 updateOriginProtocolInfo(protocolHostAndPort, metrics->protocol);
187194
188  auto iter = m_pendingMainResourcePreconnects.find(protocolHostAndPort);
 195 auto iter = m_pendingMainResourcePreconnects.find(mainResourceLoadKey(protocolHostAndPort, load.parameters().request.httpUserAgent()));
189196 if (iter == m_pendingMainResourcePreconnects.end())
190197 return;
191198

@@void NetworkLoadScheduler::unscheduleMainResourceLoad(NetworkLoad& load, const W
194201 maybePrunePreconnectInfo(iter);
195202}
196203
197 void NetworkLoadScheduler::startedPreconnectForMainResource(const URL& url)
 204void NetworkLoadScheduler::startedPreconnectForMainResource(const URL& url, const String& userAgent)
198205{
199  auto iter = m_pendingMainResourcePreconnects.find(url.protocolHostAndPort());
 206 auto key = mainResourceLoadKey(url.protocolHostAndPort(), userAgent);
 207 auto iter = m_pendingMainResourcePreconnects.find(key);
200208 if (iter != m_pendingMainResourcePreconnects.end()) {
201209 PendingMainResourcePreconnectInfo& info = iter->value;
202210 info.pendingPreconnects++;

@@void NetworkLoadScheduler::startedPreconnectForMainResource(const URL& url)
204212 }
205213
206214 PendingMainResourcePreconnectInfo info;
207  m_pendingMainResourcePreconnects.add(url.protocolHostAndPort(), WTFMove(info));
 215 m_pendingMainResourcePreconnects.add(key, WTFMove(info));
208216}
209217
210 void NetworkLoadScheduler::finishedPreconnectForMainResource(const URL& url, const WebCore::ResourceError& error)
 218void NetworkLoadScheduler::finishedPreconnectForMainResource(const URL& url, const String& userAgent, const WebCore::ResourceError& error)
211219{
212  auto iter = m_pendingMainResourcePreconnects.find(url.protocolHostAndPort());
 220 auto iter = m_pendingMainResourcePreconnects.find(mainResourceLoadKey(url.protocolHostAndPort(), userAgent));
213221 if (iter == m_pendingMainResourcePreconnects.end())
214222 return;
215223

Source/WebKit/NetworkProcess/NetworkLoadScheduler.h

2828#include <WebCore/LoadSchedulingMode.h>
2929#include <WebCore/NetworkLoadMetrics.h>
3030#include <WebCore/PageIdentifier.h>
 31#include <tuple>
3132#include <wtf/HashMap.h>
3233#include <wtf/HashSet.h>
3334#include <wtf/ListHashSet.h>

@@public:
5051 void schedule(NetworkLoad&);
5152 void unschedule(NetworkLoad&, const WebCore::NetworkLoadMetrics* = nullptr);
5253
53  void startedPreconnectForMainResource(const URL&);
54  void finishedPreconnectForMainResource(const URL&, const WebCore::ResourceError&);
 54 void startedPreconnectForMainResource(const URL&, const String& userAgent);
 55 void finishedPreconnectForMainResource(const URL&, const String& userAgent, const WebCore::ResourceError&);
5556
5657 void setResourceLoadSchedulingMode(WebCore::PageIdentifier, WebCore::LoadSchedulingMode);
5758 void prioritizeLoads(const Vector<NetworkLoad*>&);

@@private:
7778 unsigned pendingPreconnects {1};
7879 ListHashSet<NetworkLoad *> pendingLoads;
7980 };
80  using PendingPreconnectMap = HashMap<String, PendingMainResourcePreconnectInfo>;
 81 // Maps (protocolHostAndPort, userAgent) => PendingMainResourcePreconnectInfo.
 82 using PendingPreconnectMap = HashMap<std::tuple<String, String>, PendingMainResourcePreconnectInfo>;
8183 PendingPreconnectMap m_pendingMainResourcePreconnects;
8284
8385 void maybePrunePreconnectInfo(PendingPreconnectMap::iterator&);

Source/WebKit/NetworkProcess/NetworkProcess.cpp

@@void NetworkProcess::preconnectTo(PAL::SessionID sessionID, WebPageProxyIdentifi
14011401 parameters.storedCredentialsPolicy = storedCredentialsPolicy;
14021402 parameters.shouldPreconnectOnly = PreconnectOnly::Yes;
14031403
1404  networkSession->networkLoadScheduler().startedPreconnectForMainResource(url);
1405  auto task = new PreconnectTask(*networkSession, WTFMove(parameters), [networkSession, url](const WebCore::ResourceError& error) {
1406  networkSession->networkLoadScheduler().finishedPreconnectForMainResource(url, error);
 1404 networkSession->networkLoadScheduler().startedPreconnectForMainResource(url, userAgent);
 1405 auto task = new PreconnectTask(*networkSession, WTFMove(parameters), [networkSession, url, userAgent](const WebCore::ResourceError& error) {
 1406 networkSession->networkLoadScheduler().finishedPreconnectForMainResource(url, userAgent, error);
14071407 });
14081408 task->setTimeout(10_s);
14091409 task->start();