Don't use invalidated ResourceLoadStatistics iterators
[WebKit-https.git] / Source / WebCore / loader / ResourceLoadStatisticsStore.cpp
index 08dda42..24f63ae 100644 (file)
 
 namespace WebCore {
 
-Ref<ResourceLoadStatisticsStore> ResourceLoadStatisticsStore::create(const String& resourceLoadStatisticsDirectory)
-{
-    return adoptRef(*new ResourceLoadStatisticsStore(resourceLoadStatisticsDirectory));
-}
+static const unsigned minimumOriginsLoadedForProcessing = 100;
 
 Ref<ResourceLoadStatisticsStore> ResourceLoadStatisticsStore::create()
 {
     return adoptRef(*new ResourceLoadStatisticsStore());
 }
     
-ResourceLoadStatisticsStore::ResourceLoadStatisticsStore(const String& resourceLoadStatisticsDirectory)
-    : m_storagePath(resourceLoadStatisticsDirectory)
-{
-}
-    
 bool ResourceLoadStatisticsStore::isPrevalentResource(const String& primaryDomain) const
 {
     auto mapEntry = m_resourceStatisticsMap.find(primaryDomain);
@@ -65,7 +57,7 @@ bool ResourceLoadStatisticsStore::isPrevalentResource(const String& primaryDomai
     return mapEntry->value.isPrevalentResource;
 }
     
-ResourceLoadStatistics& ResourceLoadStatisticsStore::resourceStatisticsForPrimaryDomain(const String& primaryDomain)
+ResourceLoadStatistics& ResourceLoadStatisticsStore::ensureResourceStatisticsForPrimaryDomain(const String& primaryDomain)
 {
     auto addResult = m_resourceStatisticsMap.ensure(primaryDomain, [&primaryDomain] {
         return ResourceLoadStatistics(primaryDomain);
@@ -74,45 +66,31 @@ ResourceLoadStatistics& ResourceLoadStatisticsStore::resourceStatisticsForPrimar
     return addResult.iterator->value;
 }
 
+void ResourceLoadStatisticsStore::setResourceStatisticsForPrimaryDomain(const String& primaryDomain, ResourceLoadStatistics&& statistics)
+{
+    m_resourceStatisticsMap.set(primaryDomain, WTFMove(statistics));
+}
+
 typedef HashMap<String, ResourceLoadStatistics>::KeyValuePairType StatisticsValue;
 
-void ResourceLoadStatisticsStore::writeDataToDisk()
+std::unique_ptr<KeyedEncoder> ResourceLoadStatisticsStore::createEncoderFromData()
 {
     auto encoder = KeyedEncoder::encoder();
     
     encoder->encodeObjects("browsingStatistics", m_resourceStatisticsMap.begin(), m_resourceStatisticsMap.end(), [this](KeyedEncoder& encoderInner, const StatisticsValue& origin) {
         origin.value.encode(encoderInner);
     });
-    
-    writeEncoderToDisk(*encoder.get(), "full_browsing_session");
-}
 
-void ResourceLoadStatisticsStore::setStatisticsStorageDirectory(const String& path)
-{
-    m_storagePath = path;
-    readDataFromDiskIfNeeded();
-}
-
-String ResourceLoadStatisticsStore::persistentStoragePath(const String& label) const
-{
-    if (m_storagePath.isEmpty())
-        return emptyString();
-
-    // TODO Decide what to call this file
-    return pathByAppendingComponent(m_storagePath, label + "_resourceLog.plist");
+    return encoder;
 }
 
-void ResourceLoadStatisticsStore::readDataFromDiskIfNeeded()
+void ResourceLoadStatisticsStore::readDataFromDecoder(KeyedDecoder& decoder)
 {
     if (m_resourceStatisticsMap.size())
         return;
 
-    auto decoder = createDecoderFromDisk("full_browsing_session");
-    if (!decoder)
-        return;
-
     Vector<ResourceLoadStatistics> loadedStatistics;
-    bool succeeded = decoder->decodeObjects("browsingStatistics", loadedStatistics, [this](KeyedDecoder& decoderInner, ResourceLoadStatistics& statistics) {
+    bool succeeded = decoder.decodeObjects("browsingStatistics", loadedStatistics, [this](KeyedDecoder& decoderInner, ResourceLoadStatistics& statistics) {
         return statistics.decode(decoderInner);
     });
 
@@ -123,48 +101,6 @@ void ResourceLoadStatisticsStore::readDataFromDiskIfNeeded()
         m_resourceStatisticsMap.set(statistics.highLevelDomain, statistics);
 }
 
-std::unique_ptr<KeyedDecoder> ResourceLoadStatisticsStore::createDecoderFromDisk(const String& label) const
-{
-    String resourceLog = persistentStoragePath(label);
-    if (resourceLog.isEmpty())
-        return nullptr;
-    
-    RefPtr<SharedBuffer> rawData = SharedBuffer::createWithContentsOfFile(resourceLog);
-    if (!rawData)
-        return nullptr;
-    
-    return KeyedDecoder::decoder(reinterpret_cast<const uint8_t*>(rawData->data()), rawData->size());
-}
-    
-void ResourceLoadStatisticsStore::writeEncoderToDisk(KeyedEncoder& encoder, const String& label) const
-{
-#if LOG_STATISTICS_TO_FILE
-    RefPtr<SharedBuffer> rawData = encoder.finishEncoding();
-    if (!rawData)
-        return;
-    
-    String resourceLog = persistentStoragePath(label);
-    if (resourceLog.isEmpty())
-        return;
-
-    if (!m_storagePath.isEmpty())
-        makeAllDirectories(m_storagePath);
-
-    auto handle = openFile(resourceLog, OpenForWrite);
-    if (!handle)
-        return;
-    
-    int64_t writtenBytes = writeToFile(handle, rawData->data(), rawData->size());
-    closeFile(handle);
-    
-    if (writtenBytes != static_cast<int64_t>(rawData->size()))
-        WTFLogAlways("ResourceLoadStatistics: We only wrote %lld out of %d bytes to disk", writtenBytes, rawData->size());
-#else
-    UNUSED_PARAM(encoder);
-    UNUSED_PARAM(label);
-#endif
-}
-
 String ResourceLoadStatisticsStore::statisticsForOrigin(const String& origin)
 {
     auto iter = m_resourceStatisticsMap.find(origin);
@@ -204,7 +140,19 @@ void ResourceLoadStatisticsStore::setNotificationCallback(std::function<void()>
 
 void ResourceLoadStatisticsStore::fireDataModificationHandler()
 {
-    m_dataAddedHandler();
+    if (m_dataAddedHandler)
+        m_dataAddedHandler();
 }
 
+bool ResourceLoadStatisticsStore::hasEnoughDataForStatisticsProcessing()
+{
+    return m_resourceStatisticsMap.size() >= minimumOriginsLoadedForProcessing;
+}
+
+void ResourceLoadStatisticsStore::processStatistics(std::function<void(ResourceLoadStatistics&)>&& processFunction)
+{
+    ASSERT(hasEnoughDataForStatisticsProcessing());
+    for (auto& resourceStatistic : m_resourceStatisticsMap.values())
+        processFunction(resourceStatistic);
+}
 }