WebKit Bugzilla
Attachment 348871 Details for
Bug 189213
: Add infrastructure to dump resource load statistics
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-189213-20180904163321.patch (text/plain), 18.83 KB, created by
Woodrow Wang
on 2018-09-04 16:33:21 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Woodrow Wang
Created:
2018-09-04 16:33:21 PDT
Size:
18.83 KB
patch
obsolete
>Subversion Revision: 235612 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 6d91c21c52bc86aad149d3dcb985d4e37ce0f075..d1dd886f6b2df60facaa6ba3c07c1fa6320bf447 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,15 @@ >+2018-08-31 Woodrow Wang <woodrow_wang@apple.com> >+ >+ Add infrastructure to dump resource load statistics >+ https://bugs.webkit.org/show_bug.cgi?id=189213 >+ >+ Reviewed by Daniel Bates. >+ >+ The dumping functionality is not currently used, but will be included in tests for >+ <https://bugs.webkit.org/show_bug.cgi?id=187773>. >+ >+ * loader/ResourceLoadStatistics.h: >+ > 2018-09-04 Woodrow Wang <woodrow_wang@apple.com> > > Added runtime feature flag for web API statistics >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index 6d14330c2bbc2cdb6c250f682ab3a6db8567e66f..6dd3c6a696d0e64c934d144e0a3874551d24dd1f 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,23 @@ >+2018-08-31 Woodrow Wang <woodrow_wang@apple.com> >+ >+ Add infrastructure to dump resource load statistics >+ https://bugs.webkit.org/show_bug.cgi?id=189213 >+ >+ Reviewed by Daniel Bates. >+ >+ The dumping functionality is not currently used, but will be included in tests for >+ <https://bugs.webkit.org/show_bug.cgi?id=187773>. >+ >+ * UIProcess/API/C/WKWebsiteDataStoreRef.cpp: >+ (WKWebsiteDataStoreDumpResourceLoadStatistics): >+ * UIProcess/API/C/WKWebsiteDataStoreRef.h: >+ * UIProcess/ResourceLoadStatisticsMemoryStore.cpp: >+ (WebKit::ResourceLoadStatisticsMemoryStore::dumpResourceLoadStatistics const): >+ * UIProcess/ResourceLoadStatisticsMemoryStore.h: >+ * UIProcess/WebResourceLoadStatisticsStore.cpp: >+ (WebKit::WebResourceLoadStatisticsStore::dumpResourceLoadStatistics): >+ * UIProcess/WebResourceLoadStatisticsStore.h: >+ > 2018-09-04 Woodrow Wang <woodrow_wang@apple.com> > > Added runtime feature flag for web API statistics >diff --git a/Source/WebCore/loader/ResourceLoadStatistics.h b/Source/WebCore/loader/ResourceLoadStatistics.h >index 8c9ed4c2ba1fb34a59b6322d9beebaff83b62d40..27a17ff93551619013ebb8ec05ac25d3d561b668 100644 >--- a/Source/WebCore/loader/ResourceLoadStatistics.h >+++ b/Source/WebCore/loader/ResourceLoadStatistics.h >@@ -58,7 +58,7 @@ struct ResourceLoadStatistics { > WEBCORE_EXPORT void encode(KeyedEncoder&) const; > WEBCORE_EXPORT bool decode(KeyedDecoder&, unsigned modelVersion); > >- String toString() const; >+ WEBCORE_EXPORT String toString() const; > > WEBCORE_EXPORT void merge(const ResourceLoadStatistics&); > >diff --git a/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp b/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp >index 802d1cd938d83022e061cdacfa4e3371f9c68966..68a1658126d1ad24f045792055a54119f5bf1edd 100644 >--- a/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp >+++ b/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp >@@ -30,6 +30,7 @@ > #include "APIWebsiteDataStore.h" > #include "WKAPICast.h" > #include "WKSecurityOriginRef.h" >+#include "WKString.h" > #include "WebResourceLoadStatisticsStore.h" > #include "WebResourceLoadStatisticsTelemetry.h" > #include "WebsiteData.h" >@@ -143,6 +144,19 @@ void WKWebsiteDataStoreSetStatisticsVeryPrevalentResource(WKWebsiteDataStoreRef > }); > } > >+void WKWebsiteDataStoreDumpResourceLoadStatistics(WKWebsiteDataStoreRef dataStoreRef, void* context, WKWebsiteDataStoreDumpResourceLoadStatisticsFunction callback) >+{ >+ auto* store = WebKit::toImpl(dataStoreRef)->websiteDataStore().resourceLoadStatistics(); >+ if (!store) { >+ callback(WebKit::toAPI(emptyString().impl()), context); >+ return; >+ } >+ >+ store->dumpResourceLoadStatistics([context, callback] (const String& resourceLoadStatistics) { >+ callback(WebKit::toAPI(resourceLoadStatistics.impl()), context); >+ }); >+} >+ > void WKWebsiteDataStoreIsStatisticsPrevalentResource(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, void* context, WKWebsiteDataStoreIsStatisticsPrevalentResourceFunction callback) > { > auto* store = WebKit::toImpl(dataStoreRef)->websiteDataStore().resourceLoadStatistics(); >diff --git a/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h b/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h >index 0662dcf2807783c01912e8cdd77087fee1f9354f..02e7bce612ed153744daf96981f9835ed892d3c0 100644 >--- a/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h >+++ b/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h >@@ -49,6 +49,8 @@ typedef void (*WKWebsiteDataStoreStatisticsPrevalentResourceFunction)(void* func > WK_EXPORT void WKWebsiteDataStoreSetStatisticsPrevalentResource(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, bool value, void* context, WKWebsiteDataStoreStatisticsPrevalentResourceFunction completionHandler); > typedef void (*WKWebsiteDataStoreStatisticsVeryPrevalentResourceFunction)(void* functionContext); > WK_EXPORT void WKWebsiteDataStoreSetStatisticsVeryPrevalentResource(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, bool value, void* context, WKWebsiteDataStoreStatisticsVeryPrevalentResourceFunction completionHandler); >+typedef void (*WKWebsiteDataStoreDumpResourceLoadStatisticsFunction)(WKStringRef resourceLoadStatisticsRepresentation, void* functionContext); >+WK_EXPORT void WKWebsiteDataStoreDumpResourceLoadStatistics(WKWebsiteDataStoreRef dataStoreRef, void* context, WKWebsiteDataStoreDumpResourceLoadStatisticsFunction callback); > typedef void (*WKWebsiteDataStoreIsStatisticsPrevalentResourceFunction)(bool isPrevalentResource, void* functionContext); > WK_EXPORT void WKWebsiteDataStoreIsStatisticsPrevalentResource(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, void* context, WKWebsiteDataStoreIsStatisticsPrevalentResourceFunction callback); > WK_EXPORT void WKWebsiteDataStoreIsStatisticsVeryPrevalentResource(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, void* context, WKWebsiteDataStoreIsStatisticsPrevalentResourceFunction callback); >diff --git a/Source/WebKit/UIProcess/ResourceLoadStatisticsMemoryStore.cpp b/Source/WebKit/UIProcess/ResourceLoadStatisticsMemoryStore.cpp >index 17ce7bd05c9453985930ce4e362e3a542f539b2b..b545adf5d10bf44c87988578d44e72b1d5ad40c7 100644 >--- a/Source/WebKit/UIProcess/ResourceLoadStatisticsMemoryStore.cpp >+++ b/Source/WebKit/UIProcess/ResourceLoadStatisticsMemoryStore.cpp >@@ -671,6 +671,17 @@ void ResourceLoadStatisticsMemoryStore::setPrevalentResource(WebCore::ResourceLo > mapEntry->value.isPrevalentResource = true; > } > } >+ >+String ResourceLoadStatisticsMemoryStore::dumpResourceLoadStatistics() const >+{ >+ ASSERT(!RunLoop::isMain()); >+ >+ StringBuilder result; >+ result.appendLiteral("Resource load statistics:\n\n"); >+ for (auto& mapEntry : m_resourceStatisticsMap.values()) >+ result.append(mapEntry.toString()); >+ return result.toString(); >+} > > bool ResourceLoadStatisticsMemoryStore::isPrevalentResource(const String& primaryDomain) const > { >diff --git a/Source/WebKit/UIProcess/ResourceLoadStatisticsMemoryStore.h b/Source/WebKit/UIProcess/ResourceLoadStatisticsMemoryStore.h >index b79f0fe504f79283e3d6706092fa8e4a07ddc45b..634b82d1fe848e4175b4011d96c0531383dda5a4 100644 >--- a/Source/WebKit/UIProcess/ResourceLoadStatisticsMemoryStore.h >+++ b/Source/WebKit/UIProcess/ResourceLoadStatisticsMemoryStore.h >@@ -83,6 +83,7 @@ public: > bool isRegisteredAsRedirectingTo(const String& hostRedirectedFromPrimaryDomain, const String& hostRedirectedToPrimaryDomain) const; > > void clearPrevalentResource(const String& primaryDomain); >+ String dumpResourceLoadStatistics() const; > bool isPrevalentResource(const String& primaryDomain) const; > bool isVeryPrevalentResource(const String& primaryDomain) const; > void setPrevalentResource(const String& primaryDomain); >diff --git a/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.cpp b/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.cpp >index 6cd9dc4b7d74e0087901b05903b3bd2336a7a40d..6c5089afeb5de3f4859ce14d0631ebca07240a4d 100644 >--- a/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.cpp >+++ b/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.cpp >@@ -493,6 +493,18 @@ void WebResourceLoadStatisticsStore::setVeryPrevalentResource(const URL& url, Co > postTaskReply(WTFMove(completionHandler)); > }); > } >+ >+void WebResourceLoadStatisticsStore::dumpResourceLoadStatistics(CompletionHandler<void(const String&)>&& completionHandler) >+{ >+ ASSERT(RunLoop::isMain()); >+ >+ postTask([this, completionHandler = WTFMove(completionHandler)] () mutable { >+ String result = m_memoryStore ? m_memoryStore->dumpResourceLoadStatistics() : emptyString(); >+ postTaskReply([result = result.isolatedCopy(), completionHandler = WTFMove(completionHandler)] () mutable { >+ completionHandler(result); >+ }); >+ }); >+} > > void WebResourceLoadStatisticsStore::isPrevalentResource(const URL& url, CompletionHandler<void (bool)>&& completionHandler) > { >diff --git a/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.h b/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.h >index fb2440887d6a28e626169197b69c916e286ea423..f0f50a8cb5bcb1b87b512b24b29d9c17a19e4467 100644 >--- a/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.h >+++ b/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.h >@@ -91,6 +91,7 @@ public: > void setLastSeen(const WebCore::URL&, Seconds, CompletionHandler<void()>&&); > void setPrevalentResource(const WebCore::URL&, CompletionHandler<void()>&&); > void setVeryPrevalentResource(const WebCore::URL&, CompletionHandler<void()>&&); >+ void dumpResourceLoadStatistics(CompletionHandler<void(const String&)>&&); > void isPrevalentResource(const WebCore::URL&, CompletionHandler<void(bool)>&&); > void isVeryPrevalentResource(const WebCore::URL&, CompletionHandler<void(bool)>&&); > void isRegisteredAsSubresourceUnder(const WebCore::URL& subresource, const WebCore::URL& topFrame, CompletionHandler<void(bool)>&&); >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index 14c204b4abc7fa2bffe4ee11dabfefa6188837db..7faf0c890b631c50160845800a3a85340f706906 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,27 @@ >+2018-08-31 Woodrow Wang <woodrow_wang@apple.com> >+ >+ Add infrastructure to dump resource load statistics >+ https://bugs.webkit.org/show_bug.cgi?id=189213 >+ >+ Reviewed by Daniel Bates. >+ >+ The dumping functionality is not currently used, but will be included in tests for >+ <https://bugs.webkit.org/show_bug.cgi?id=187773>. >+ >+ * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl: >+ * WebKitTestRunner/InjectedBundle/TestRunner.cpp: >+ (WTR::TestRunner::setDumpResourceLoadStatistics): >+ * WebKitTestRunner/InjectedBundle/TestRunner.h: >+ * WebKitTestRunner/TestController.cpp: >+ (WTR::resourceStatisticsStringResultCallback): >+ (WTR::TestController::dumpResourceLoadStatistics): >+ * WebKitTestRunner/TestController.h: >+ * WebKitTestRunner/TestInvocation.cpp: >+ (WTR::TestInvocation::dumpResults): >+ (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle): >+ (WTR::TestInvocation::setDumpResourceLoadStatistics): >+ * WebKitTestRunner/TestInvocation.h: >+ > 2018-09-04 Woodrow Wang <woodrow_wang@apple.com> > > Added runtime feature flag for web API statistics >diff --git a/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl b/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl >index 2981aba723168e35e2ff4ab6436b96d7dbb96a79..227bf1092dccc5bf890e5fcf1e4684b84b59cd8b 100644 >--- a/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl >+++ b/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl >@@ -56,6 +56,7 @@ interface TestRunner { > void dumpDatabaseCallbacks(); > void dumpDOMAsWebArchive(); > void dumpPolicyDelegateCallbacks(); >+ void dumpResourceLoadStatistics(); > > void clearDOMCaches(); > void clearDOMCache(DOMString origin); >diff --git a/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp b/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp >index 344d5af1c57c6877fddf2ec47c92dde353b1ebcd..a3ed22b869444214f98435027db8526fb0fc5f04 100644 >--- a/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp >+++ b/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp >@@ -1462,6 +1462,12 @@ void TestRunner::statisticsCallDidSetVeryPrevalentResourceCallback() > { > callTestRunnerCallback(SetStatisticsVeryPrevalentResourceCallbackID); > } >+ >+void TestRunner::dumpResourceLoadStatistics() >+{ >+ WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("dumpResourceLoadStatistics")); >+ WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), nullptr, nullptr); >+} > > bool TestRunner::isStatisticsPrevalentResource(JSStringRef hostName) > { >diff --git a/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h b/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h >index bfd928ef07c5582f7fd9e395b26a444c9c32e343..95d596aa8e821283e60ed0cfd6e1796049eeb358 100644 >--- a/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h >+++ b/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h >@@ -91,6 +91,7 @@ public: > void dumpDatabaseCallbacks() { m_dumpDatabaseCallbacks = true; } > void dumpDOMAsWebArchive() { setWhatToDump(WhatToDump::DOMAsWebArchive); } > void dumpPolicyDelegateCallbacks() { m_dumpPolicyCallbacks = true; } >+ void dumpResourceLoadStatistics(); > > void setShouldDumpFrameLoadCallbacks(bool value); > void setShouldDumpProgressFinishedCallback(bool value) { m_dumpProgressFinishedCallback = value; } >diff --git a/Tools/WebKitTestRunner/TestController.cpp b/Tools/WebKitTestRunner/TestController.cpp >index 7cdaaf0a869abac2ba66d57fbfeea2d732791a4f..d5a93b2aa48d497e54a6914d4605a573a7f4cb57 100644 >--- a/Tools/WebKitTestRunner/TestController.cpp >+++ b/Tools/WebKitTestRunner/TestController.cpp >@@ -2805,7 +2805,16 @@ struct ResourceStatisticsCallbackContext { > TestController& testController; > bool done { false }; > bool result { false }; >+ WKStringRef resourceLoadStatisticsRepresentation; > }; >+ >+static void resourceStatisticsStringResultCallback(WKStringRef resourceLoadStatisticsRepresentation, void* userData) >+{ >+ auto* context = static_cast<ResourceStatisticsCallbackContext*>(userData); >+ context->resourceLoadStatisticsRepresentation = resourceLoadStatisticsRepresentation; >+ context->done = true; >+ context->testController.notifyDone(); >+} > > static void resourceStatisticsVoidResultCallback(void* userData) > { >@@ -2866,6 +2875,15 @@ void TestController::setStatisticsVeryPrevalentResource(WKStringRef host, bool v > runUntil(context.done, noTimeout); > m_currentInvocation->didSetVeryPrevalentResource(); > } >+ >+WKStringRef TestController::dumpResourceLoadStatistics() >+{ >+ auto* dataStore = WKContextGetWebsiteDataStore(platformContext()); >+ ResourceStatisticsCallbackContext context(*this); >+ WKWebsiteDataStoreDumpResourceLoadStatistics(dataStore, &context, resourceStatisticsStringResultCallback); >+ runUntil(context.done, noTimeout); >+ return context.resourceLoadStatisticsRepresentation; >+} > > bool TestController::isStatisticsPrevalentResource(WKStringRef host) > { >diff --git a/Tools/WebKitTestRunner/TestController.h b/Tools/WebKitTestRunner/TestController.h >index cf75d6676bfb46135c640618306419de17c895ca..aa4e3fe907119e44a6857c243fcb837362416fad 100644 >--- a/Tools/WebKitTestRunner/TestController.h >+++ b/Tools/WebKitTestRunner/TestController.h >@@ -191,6 +191,7 @@ public: > void setStatisticsLastSeen(WKStringRef hostName, double seconds); > void setStatisticsPrevalentResource(WKStringRef hostName, bool value); > void setStatisticsVeryPrevalentResource(WKStringRef hostName, bool value); >+ WKStringRef dumpResourceLoadStatistics(); > bool isStatisticsPrevalentResource(WKStringRef hostName); > bool isStatisticsVeryPrevalentResource(WKStringRef hostName); > bool isStatisticsRegisteredAsSubresourceUnder(WKStringRef subresourceHost, WKStringRef topFrameHost); >diff --git a/Tools/WebKitTestRunner/TestInvocation.cpp b/Tools/WebKitTestRunner/TestInvocation.cpp >index 13b21bedd5174071bda7b61b390efd788533c409..36f4cac84ec1ba0791633db2e3522eb154cff759 100644 >--- a/Tools/WebKitTestRunner/TestInvocation.cpp >+++ b/Tools/WebKitTestRunner/TestInvocation.cpp >@@ -250,6 +250,9 @@ void TestInvocation::forceRepaintDoneCallback(WKErrorRef error, void* context) > > void TestInvocation::dumpResults() > { >+ if (m_shouldDumpResourceLoadStatistics) >+ m_textOutput.append(m_savedResourceLoadStatistics.isEmpty() ? toWTFString(TestController::singleton().dumpResourceLoadStatistics()) : m_savedResourceLoadStatistics); >+ > if (m_textOutput.length() || !m_audioResult) > dump(m_textOutput.toString().utf8().data()); > else >@@ -1069,6 +1072,11 @@ WKRetainPtr<WKTypeRef> TestInvocation::didReceiveSynchronousMessageFromInjectedB > return nullptr; > } > >+ if (WKStringIsEqualToUTF8CString(messageName, "dumpResourceLoadStatistics")) { >+ dumpResourceLoadStatistics(); >+ return nullptr; >+ } >+ > if (WKStringIsEqualToUTF8CString(messageName, "IsStatisticsPrevalentResource")) { > ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID()); > >@@ -1351,6 +1359,8 @@ WKRetainPtr<WKTypeRef> TestInvocation::didReceiveSynchronousMessageFromInjectedB > } > > if (WKStringIsEqualToUTF8CString(messageName, "StatisticsResetToConsistentState")) { >+ if (m_shouldDumpResourceLoadStatistics) >+ m_savedResourceLoadStatistics = toWTFString(TestController::singleton().dumpResourceLoadStatistics()); > TestController::singleton().statisticsResetToConsistentState(); > return nullptr; > } >@@ -1580,4 +1590,9 @@ void TestInvocation::didRemoveAllSessionCredentials() > WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0); > } > >+void TestInvocation::dumpResourceLoadStatistics() >+{ >+ m_shouldDumpResourceLoadStatistics = true; >+} >+ > } // namespace WTR >diff --git a/Tools/WebKitTestRunner/TestInvocation.h b/Tools/WebKitTestRunner/TestInvocation.h >index 3c050edadb1cefda962a5c47319b8f11bcd26af3..3fb4bb78aa4d82dbf95e77642a39ac41cef31c81 100644 >--- a/Tools/WebKitTestRunner/TestInvocation.h >+++ b/Tools/WebKitTestRunner/TestInvocation.h >@@ -83,6 +83,8 @@ public: > > void didRemoveAllSessionCredentials(); > >+ void dumpResourceLoadStatistics(); >+ > private: > WKRetainPtr<WKMutableDictionaryRef> createTestSettingsDictionary(); > >@@ -129,9 +131,11 @@ private: > bool m_dumpFrameLoadCallbacks { false }; > bool m_dumpPixels { false }; > bool m_pixelResultIsPending { false }; >+ bool m_shouldDumpResourceLoadStatistics { false }; > WhatToDump m_whatToDump { WhatToDump::RenderTree }; > > StringBuilder m_textOutput; >+ String m_savedResourceLoadStatistics; > WKRetainPtr<WKDataRef> m_audioResult; > WKRetainPtr<WKImageRef> m_pixelResult; > WKRetainPtr<WKArrayRef> m_repaintRects;
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 189213
:
348679
|
348683
|
348690
|
348859
|
348864
|
348871
|
348877
|
348895
|
348930
|
348942
|
348949