WebKit Bugzilla
Attachment 347374 Details for
Bug 188702
: NetworkLoad::willPerformHTTPRedirection should pass its completionHandler to its client
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-188702-20180817114400.patch (text/plain), 21.02 KB, created by
Alex Christensen
on 2018-08-17 11:44:00 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Alex Christensen
Created:
2018-08-17 11:44:00 PDT
Size:
21.02 KB
patch
obsolete
>Index: Source/WebKit/ChangeLog >=================================================================== >--- Source/WebKit/ChangeLog (revision 234991) >+++ Source/WebKit/ChangeLog (working copy) >@@ -1,3 +1,34 @@ >+2018-08-17 Alex Christensen <achristensen@webkit.org> >+ >+ NetworkLoad::willPerformHTTPRedirection should pass its completionHandler to its client >+ https://bugs.webkit.org/show_bug.cgi?id=188702 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * NetworkProcess/Downloads/PendingDownload.cpp: >+ (WebKit::PendingDownload::willSendRedirectedRequest): >+ (WebKit::PendingDownload::continueWillSendRequest): >+ * NetworkProcess/Downloads/PendingDownload.h: >+ * NetworkProcess/NetworkLoad.cpp: >+ (WebKit::NetworkLoad::~NetworkLoad): >+ (WebKit::NetworkLoad::willPerformHTTPRedirection): >+ (WebKit::NetworkLoad::continueWillSendRequest): Deleted. >+ * NetworkProcess/NetworkLoad.h: >+ * NetworkProcess/NetworkLoadClient.h: >+ * NetworkProcess/NetworkResourceLoader.cpp: >+ (WebKit::NetworkResourceLoader::~NetworkResourceLoader): >+ (WebKit::NetworkResourceLoader::willSendRedirectedRequest): >+ (WebKit::NetworkResourceLoader::continueWillSendRedirectedRequest): >+ (WebKit::NetworkResourceLoader::continueWillSendRequest): >+ (WebKit::NetworkResourceLoader::dispatchWillSendRequestForCacheEntry): >+ * NetworkProcess/NetworkResourceLoader.h: >+ * NetworkProcess/PreconnectTask.cpp: >+ (WebKit::PreconnectTask::willSendRedirectedRequest): >+ * NetworkProcess/PreconnectTask.h: >+ * NetworkProcess/cache/NetworkCacheSpeculativeLoad.cpp: >+ (WebKit::NetworkCache::SpeculativeLoad::willSendRedirectedRequest): >+ * NetworkProcess/cache/NetworkCacheSpeculativeLoad.h: >+ > 2018-08-17 Alex Christensen <achristensen@webkit.org> > > Pass webPageID and webFrameID to NetworkLoad for speculative loads >Index: Source/WebKit/NetworkProcess/NetworkLoad.cpp >=================================================================== >--- Source/WebKit/NetworkProcess/NetworkLoad.cpp (revision 234990) >+++ Source/WebKit/NetworkProcess/NetworkLoad.cpp (working copy) >@@ -118,8 +118,6 @@ void NetworkLoad::initialize(NetworkSess > NetworkLoad::~NetworkLoad() > { > ASSERT(RunLoop::isMain()); >- if (m_redirectCompletionHandler) >- m_redirectCompletionHandler({ }); > if (m_responseCompletionHandler) > m_responseCompletionHandler(PolicyAction::Ignore); > if (m_task) >@@ -147,34 +145,6 @@ void NetworkLoad::cancel() > m_task->cancel(); > } > >-void NetworkLoad::continueWillSendRequest(WebCore::ResourceRequest&& newRequest) >-{ >-#if PLATFORM(COCOA) >- m_currentRequest.updateFromDelegatePreservingOldProperties(newRequest.nsURLRequest(HTTPBodyUpdatePolicy::DoNotUpdateHTTPBody)); >-#elif USE(SOUP) >- // FIXME: Implement ResourceRequest::updateFromDelegatePreservingOldProperties. See https://bugs.webkit.org/show_bug.cgi?id=126127. >- m_currentRequest.updateFromDelegatePreservingOldProperties(newRequest); >-#endif >- >-#if ENABLE(NETWORK_CAPTURE) >- if (m_recorder) >- m_recorder->recordRedirectSent(newRequest); >-#endif >- >- auto redirectCompletionHandler = std::exchange(m_redirectCompletionHandler, nullptr); >- ASSERT(redirectCompletionHandler); >- if (m_currentRequest.isNull()) { >- NetworkLoadMetrics emptyMetrics; >- didCompleteWithError(cancelledError(m_currentRequest), emptyMetrics); >- if (redirectCompletionHandler) >- redirectCompletionHandler({ }); >- return; >- } >- >- if (redirectCompletionHandler) >- redirectCompletionHandler(ResourceRequest(m_currentRequest)); >-} >- > void NetworkLoad::continueDidReceiveResponse() > { > if (m_responseCompletionHandler) { >@@ -234,10 +204,8 @@ void NetworkLoad::willPerformHTTPRedirec > { > ASSERT(!redirectResponse.isNull()); > ASSERT(RunLoop::isMain()); >- ASSERT(!m_redirectCompletionHandler); > > redirectResponse.setSource(ResourceResponse::Source::Network); >- m_redirectCompletionHandler = WTFMove(completionHandler); > > #if ENABLE(NETWORK_CAPTURE) > if (m_recorder) >@@ -248,7 +216,27 @@ void NetworkLoad::willPerformHTTPRedirec > request.setRequester(oldRequest.requester()); > > m_currentRequest = request; >- m_client.get().willSendRedirectedRequest(WTFMove(oldRequest), WTFMove(request), WTFMove(redirectResponse)); >+ m_client.get().willSendRedirectedRequest(WTFMove(oldRequest), WTFMove(request), WTFMove(redirectResponse), [this, completionHandler = WTFMove(completionHandler)] (auto&& newRequest) mutable { >+ >+#if PLATFORM(COCOA) >+ m_currentRequest.updateFromDelegatePreservingOldProperties(newRequest.nsURLRequest(HTTPBodyUpdatePolicy::DoNotUpdateHTTPBody)); >+#elif USE(SOUP) >+ // FIXME: Implement ResourceRequest::updateFromDelegatePreservingOldProperties. See https://bugs.webkit.org/show_bug.cgi?id=126127. >+ m_currentRequest.updateFromDelegatePreservingOldProperties(newRequest); >+#endif >+ >+#if ENABLE(NETWORK_CAPTURE) >+ if (m_recorder) >+ m_recorder->recordRedirectSent(newRequest); >+#endif >+ >+ if (m_currentRequest.isNull()) { >+ WebCore::NetworkLoadMetrics emptyMetrics; >+ didCompleteWithError(cancelledError(m_currentRequest), emptyMetrics); >+ return completionHandler({ }); >+ } >+ completionHandler(ResourceRequest(m_currentRequest)); >+ }); > } > > void NetworkLoad::didReceiveChallenge(AuthenticationChallenge&& challenge, ChallengeCompletionHandler&& completionHandler) >Index: Source/WebKit/NetworkProcess/NetworkLoad.h >=================================================================== >--- Source/WebKit/NetworkProcess/NetworkLoad.h (revision 234941) >+++ Source/WebKit/NetworkProcess/NetworkLoad.h (working copy) >@@ -58,7 +58,6 @@ public: > > const NetworkLoadParameters& parameters() const { return m_parameters; } > >- void continueWillSendRequest(WebCore::ResourceRequest&&); > void continueDidReceiveResponse(); > > void convertTaskToDownload(PendingDownload&, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&); >@@ -93,7 +92,6 @@ private: > > std::reference_wrapper<NetworkLoadClient> m_client; > const NetworkLoadParameters m_parameters; >- CompletionHandler<void(WebCore::ResourceRequest&&)> m_redirectCompletionHandler; > RefPtr<NetworkDataTask> m_task; > ResponseCompletionHandler m_responseCompletionHandler; > >Index: Source/WebKit/NetworkProcess/NetworkLoadClient.h >=================================================================== >--- Source/WebKit/NetworkProcess/NetworkLoadClient.h (revision 234941) >+++ Source/WebKit/NetworkProcess/NetworkLoadClient.h (working copy) >@@ -33,11 +33,14 @@ > namespace WebCore { > class NetworkLoadMetrics; > class ProtectionSpace; >+class ResourceRequest; > class SharedBuffer; > } > > namespace WebKit { > >+using RedirectCompletionHandler = CompletionHandler<void(WebCore::ResourceRequest&&)>; >+ > class NetworkLoadClient { > public: > virtual ~NetworkLoadClient() { } >@@ -47,7 +50,7 @@ public: > virtual bool isAllowedToAskUserForCredentials() const = 0; > > virtual void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) = 0; >- virtual void willSendRedirectedRequest(WebCore::ResourceRequest&&, WebCore::ResourceRequest&& redirectRequest, WebCore::ResourceResponse&& redirectResponse) = 0; >+ virtual void willSendRedirectedRequest(WebCore::ResourceRequest&&, WebCore::ResourceRequest&& redirectRequest, WebCore::ResourceResponse&& redirectResponse, RedirectCompletionHandler&&) = 0; > enum class ShouldContinueDidReceiveResponse { No, Yes }; > virtual ShouldContinueDidReceiveResponse didReceiveResponse(WebCore::ResourceResponse&&) = 0; > virtual void didReceiveBuffer(Ref<WebCore::SharedBuffer>&&, int reportedEncodedDataLength) = 0; >Index: Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp >=================================================================== >--- Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp (revision 234941) >+++ Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp (working copy) >@@ -134,6 +134,8 @@ NetworkResourceLoader::~NetworkResourceL > ASSERT(RunLoop::isMain()); > ASSERT(!m_networkLoad); > ASSERT(!isSynchronous() || !m_synchronousLoadData->delayedReply); >+ if (m_redirectCompletionHandler) >+ m_redirectCompletionHandler({ }); > } > > bool NetworkResourceLoader::canUseCache(const ResourceRequest& request) const >@@ -577,7 +579,7 @@ void NetworkResourceLoader::didBlockAuth > send(Messages::WebResourceLoader::DidBlockAuthenticationChallenge()); > } > >-void NetworkResourceLoader::willSendRedirectedRequest(ResourceRequest&& request, ResourceRequest&& redirectRequest, ResourceResponse&& redirectResponse) >+void NetworkResourceLoader::willSendRedirectedRequest(ResourceRequest&& request, ResourceRequest&& redirectRequest, ResourceResponse&& redirectResponse, RedirectCompletionHandler&& completionHandler) > { > ++m_redirectCount; > >@@ -586,7 +588,7 @@ void NetworkResourceLoader::willSendRedi > > if (m_networkLoadChecker) { > m_networkLoadChecker->storeRedirectionIfNeeded(request, redirectResponse); >- m_networkLoadChecker->checkRedirection(WTFMove(request), WTFMove(redirectRequest), WTFMove(redirectResponse), this, [protectedThis = makeRef(*this), this, storedCredentialsPolicy = m_networkLoadChecker->storedCredentialsPolicy()](auto&& result) mutable { >+ m_networkLoadChecker->checkRedirection(WTFMove(request), WTFMove(redirectRequest), WTFMove(redirectResponse), this, [protectedThis = makeRef(*this), this, storedCredentialsPolicy = m_networkLoadChecker->storedCredentialsPolicy(), completionHandler = WTFMove(completionHandler)](auto&& result) mutable { > if (!result.has_value()) { > if (result.error().isCancellation()) > return; >@@ -614,17 +616,18 @@ void NetworkResourceLoader::willSendRedi > } > > m_shouldRestartLoad = storedCredentialsPolicy != m_networkLoadChecker->storedCredentialsPolicy(); >- this->continueWillSendRedirectedRequest(WTFMove(result->request), WTFMove(result->redirectRequest), WTFMove(result->redirectResponse)); >+ this->continueWillSendRedirectedRequest(WTFMove(result->request), WTFMove(result->redirectRequest), WTFMove(result->redirectResponse), WTFMove(completionHandler)); > }); > return; > } >- continueWillSendRedirectedRequest(WTFMove(request), WTFMove(redirectRequest), WTFMove(redirectResponse)); >+ continueWillSendRedirectedRequest(WTFMove(request), WTFMove(redirectRequest), WTFMove(redirectResponse), WTFMove(completionHandler)); > } > >-void NetworkResourceLoader::continueWillSendRedirectedRequest(ResourceRequest&& request, ResourceRequest&& redirectRequest, ResourceResponse&& redirectResponse) >+void NetworkResourceLoader::continueWillSendRedirectedRequest(ResourceRequest&& request, ResourceRequest&& redirectRequest, ResourceResponse&& redirectResponse, RedirectCompletionHandler&& completionHandler) > { > ASSERT(!isSynchronous()); > >+ m_redirectCompletionHandler = WTFMove(completionHandler); > send(Messages::WebResourceLoader::WillSendRequest(redirectRequest, sanitizeResponseIfPossible(WTFMove(redirectResponse), ResourceResponse::SanitizationType::Redirection))); > } > >@@ -700,8 +703,8 @@ void NetworkResourceLoader::continueWill > return; > } > >- if (m_networkLoad) >- m_networkLoad->continueWillSendRequest(WTFMove(newRequest)); >+ if (m_redirectCompletionHandler) >+ m_redirectCompletionHandler(WTFMove(newRequest)); > } > > void NetworkResourceLoader::continueDidReceiveResponse() >@@ -895,7 +898,7 @@ void NetworkResourceLoader::dispatchWill > LOG(NetworkCache, "(NetworkProcess) Executing cached redirect"); > > m_isWaitingContinueWillSendRequestForCachedRedirect = true; >- willSendRedirectedRequest(WTFMove(request), ResourceRequest { *entry->redirectRequest() }, ResourceResponse { entry->response() }); >+ willSendRedirectedRequest(WTFMove(request), ResourceRequest { *entry->redirectRequest() }, ResourceResponse { entry->response() }, [](auto) { }); > } > > IPC::Connection* NetworkResourceLoader::messageSenderConnection() >Index: Source/WebKit/NetworkProcess/NetworkResourceLoader.h >=================================================================== >--- Source/WebKit/NetworkProcess/NetworkResourceLoader.h (revision 234941) >+++ Source/WebKit/NetworkProcess/NetworkResourceLoader.h (working copy) >@@ -96,7 +96,7 @@ public: > void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) override; > bool isSynchronous() const override; > bool isAllowedToAskUserForCredentials() const override { return m_isAllowedToAskUserForCredentials; } >- void willSendRedirectedRequest(WebCore::ResourceRequest&&, WebCore::ResourceRequest&& redirectRequest, WebCore::ResourceResponse&&) override; >+ void willSendRedirectedRequest(WebCore::ResourceRequest&&, WebCore::ResourceRequest&& redirectRequest, WebCore::ResourceResponse&&, RedirectCompletionHandler&&) override; > ShouldContinueDidReceiveResponse didReceiveResponse(WebCore::ResourceResponse&&) override; > void didReceiveBuffer(Ref<WebCore::SharedBuffer>&&, int reportedEncodedDataLength) override; > void didFinishLoading(const WebCore::NetworkLoadMetrics&) override; >@@ -163,7 +163,7 @@ private: > void logCookieInformation() const; > #endif > >- void continueWillSendRedirectedRequest(WebCore::ResourceRequest&& request, WebCore::ResourceRequest&& redirectRequest, WebCore::ResourceResponse&&); >+ void continueWillSendRedirectedRequest(WebCore::ResourceRequest&&, WebCore::ResourceRequest&& redirectRequest, WebCore::ResourceResponse&&, RedirectCompletionHandler&&); > void didFinishWithRedirectResponse(WebCore::ResourceResponse&&); > WebCore::ResourceResponse sanitizeResponseIfPossible(WebCore::ResourceResponse&&, WebCore::ResourceResponse::SanitizationType); > >@@ -206,6 +206,7 @@ private: > std::unique_ptr<NetworkCache::Entry> m_cacheEntryWaitingForContinueDidReceiveResponse; > std::unique_ptr<NetworkLoadChecker> m_networkLoadChecker; > bool m_shouldRestartLoad { false }; >+ RedirectCompletionHandler m_redirectCompletionHandler; > > std::optional<NetworkActivityTracker> m_networkActivityTracker; > }; >Index: Source/WebKit/NetworkProcess/PreconnectTask.cpp >=================================================================== >--- Source/WebKit/NetworkProcess/PreconnectTask.cpp (revision 234941) >+++ Source/WebKit/NetworkProcess/PreconnectTask.cpp (working copy) >@@ -63,9 +63,10 @@ PreconnectTask::~PreconnectTask() > { > } > >-void PreconnectTask::willSendRedirectedRequest(ResourceRequest&&, ResourceRequest&& redirectRequest, ResourceResponse&& redirectResponse) >+void PreconnectTask::willSendRedirectedRequest(ResourceRequest&&, ResourceRequest&& redirectRequest, ResourceResponse&& redirectResponse, RedirectCompletionHandler&& completionHandler) > { > ASSERT_NOT_REACHED(); >+ completionHandler({ }); > } > > auto PreconnectTask::didReceiveResponse(ResourceResponse&&) -> ShouldContinueDidReceiveResponse >Index: Source/WebKit/NetworkProcess/PreconnectTask.h >=================================================================== >--- Source/WebKit/NetworkProcess/PreconnectTask.h (revision 234941) >+++ Source/WebKit/NetworkProcess/PreconnectTask.h (working copy) >@@ -50,7 +50,7 @@ private: > bool isSynchronous() const final { return false; } > bool isAllowedToAskUserForCredentials() const final { return false; } > void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) final; >- void willSendRedirectedRequest(WebCore::ResourceRequest&&, WebCore::ResourceRequest&& redirectRequest, WebCore::ResourceResponse&& redirectResponse) final; >+ void willSendRedirectedRequest(WebCore::ResourceRequest&&, WebCore::ResourceRequest&& redirectRequest, WebCore::ResourceResponse&& redirectResponse, RedirectCompletionHandler&&) final; > ShouldContinueDidReceiveResponse didReceiveResponse(WebCore::ResourceResponse&&) final; > void didReceiveBuffer(Ref<WebCore::SharedBuffer>&&, int reportedEncodedDataLength) final; > void didFinishLoading(const WebCore::NetworkLoadMetrics&) final; >Index: Source/WebKit/NetworkProcess/Downloads/PendingDownload.cpp >=================================================================== >--- Source/WebKit/NetworkProcess/Downloads/PendingDownload.cpp (revision 234941) >+++ Source/WebKit/NetworkProcess/Downloads/PendingDownload.cpp (working copy) >@@ -59,14 +59,15 @@ PendingDownload::PendingDownload(std::un > m_networkLoad->convertTaskToDownload(*this, request, response); > } > >-void PendingDownload::willSendRedirectedRequest(WebCore::ResourceRequest&&, WebCore::ResourceRequest&& redirectRequest, WebCore::ResourceResponse&& redirectResponse) >+void PendingDownload::willSendRedirectedRequest(WebCore::ResourceRequest&&, WebCore::ResourceRequest&& redirectRequest, WebCore::ResourceResponse&& redirectResponse, RedirectCompletionHandler&& completionHandler) > { >+ m_redirectCompletionHandler = WTFMove(completionHandler); > send(Messages::DownloadProxy::WillSendRequest(WTFMove(redirectRequest), WTFMove(redirectResponse))); > }; > > void PendingDownload::continueWillSendRequest(WebCore::ResourceRequest&& newRequest) > { >- m_networkLoad->continueWillSendRequest(WTFMove(newRequest)); >+ m_redirectCompletionHandler(WTFMove(newRequest)); > } > > void PendingDownload::cancel() >Index: Source/WebKit/NetworkProcess/Downloads/PendingDownload.h >=================================================================== >--- Source/WebKit/NetworkProcess/Downloads/PendingDownload.h (revision 234941) >+++ Source/WebKit/NetworkProcess/Downloads/PendingDownload.h (working copy) >@@ -53,7 +53,7 @@ private: > void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) override { } > bool isSynchronous() const override { return false; } > bool isAllowedToAskUserForCredentials() const final { return m_isAllowedToAskUserForCredentials; } >- void willSendRedirectedRequest(WebCore::ResourceRequest&&, WebCore::ResourceRequest&& redirectRequest, WebCore::ResourceResponse&& redirectResponse) override; >+ void willSendRedirectedRequest(WebCore::ResourceRequest&&, WebCore::ResourceRequest&& redirectRequest, WebCore::ResourceResponse&& redirectResponse, RedirectCompletionHandler&&) override; > ShouldContinueDidReceiveResponse didReceiveResponse(WebCore::ResourceResponse&&) override { return ShouldContinueDidReceiveResponse::No; }; > void didReceiveBuffer(Ref<WebCore::SharedBuffer>&&, int reportedEncodedDataLength) override { }; > void didFinishLoading(const WebCore::NetworkLoadMetrics&) override { }; >@@ -66,6 +66,7 @@ private: > private: > std::unique_ptr<NetworkLoad> m_networkLoad; > bool m_isAllowedToAskUserForCredentials; >+ RedirectCompletionHandler m_redirectCompletionHandler; > }; > > } >Index: Source/WebKit/NetworkProcess/cache/NetworkCacheSpeculativeLoad.cpp >=================================================================== >--- Source/WebKit/NetworkProcess/cache/NetworkCacheSpeculativeLoad.cpp (revision 234991) >+++ Source/WebKit/NetworkProcess/cache/NetworkCacheSpeculativeLoad.cpp (working copy) >@@ -67,7 +67,7 @@ SpeculativeLoad::~SpeculativeLoad() > ASSERT(!m_networkLoad); > } > >-void SpeculativeLoad::willSendRedirectedRequest(ResourceRequest&& request, ResourceRequest&& redirectRequest, ResourceResponse&& redirectResponse) >+void SpeculativeLoad::willSendRedirectedRequest(ResourceRequest&& request, ResourceRequest&& redirectRequest, ResourceResponse&& redirectResponse, RedirectCompletionHandler&& completionHandler) > { > LOG(NetworkCacheSpeculativePreloading, "Speculative redirect %s -> %s", request.url().string().utf8().data(), redirectRequest.url().string().utf8().data()); > >@@ -77,6 +77,7 @@ void SpeculativeLoad::willSendRedirected > m_cacheEntry = m_cache->makeRedirectEntry(request, redirectResponse, redirectRequest); > > // Don't follow the redirect. The redirect target will be registered for speculative load when it is loaded. >+ completionHandler({ }); > didComplete(); > } > >Index: Source/WebKit/NetworkProcess/cache/NetworkCacheSpeculativeLoad.h >=================================================================== >--- Source/WebKit/NetworkProcess/cache/NetworkCacheSpeculativeLoad.h (revision 234991) >+++ Source/WebKit/NetworkProcess/cache/NetworkCacheSpeculativeLoad.h (working copy) >@@ -55,7 +55,7 @@ private: > void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) override { } > bool isSynchronous() const override { return false; } > bool isAllowedToAskUserForCredentials() const final { return false; } >- void willSendRedirectedRequest(WebCore::ResourceRequest&&, WebCore::ResourceRequest&& redirectRequest, WebCore::ResourceResponse&& redirectResponse) override; >+ void willSendRedirectedRequest(WebCore::ResourceRequest&&, WebCore::ResourceRequest&& redirectRequest, WebCore::ResourceResponse&& redirectResponse, RedirectCompletionHandler&&) override; > ShouldContinueDidReceiveResponse didReceiveResponse(WebCore::ResourceResponse&&) override; > void didReceiveBuffer(Ref<WebCore::SharedBuffer>&&, int reportedEncodedDataLength) override; > void didFinishLoading(const WebCore::NetworkLoadMetrics&) override;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 188702
:
347373
|
347374
|
347380
|
347384
|
347386
|
347391
|
347394