[GTK][WPE] Implement a basic DNS cache
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 21 Jun 2019 05:37:04 +0000 (05:37 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 21 Jun 2019 05:37:04 +0000 (05:37 +0000)
https://bugs.webkit.org/show_bug.cgi?id=196094

Patch by Patrick Griffis  <pgriffis@igalia.com> and Carlos Garcia Campos <cgarcia@igalia.com> on 2019-06-20
Reviewed by Michael Catanzaro.

This adds a simple cache to all DNS operations in the network process.

* NetworkProcess/glib/DNSCache.cpp: Added.
(WebKit::DNSCache::DNSCache):
(WebKit::DNSCache::mapForType):
(WebKit::DNSCache::lookup):
(WebKit::DNSCache::update):
(WebKit::DNSCache::removeExpiredResponsesInMap):
(WebKit::DNSCache::pruneResponsesInMap):
(WebKit::DNSCache::removeExpiredResponsesFired):
(WebKit::DNSCache::clear):
* NetworkProcess/glib/DNSCache.h: Added.
* NetworkProcess/glib/WebKitCachedResolver.cpp: Added.
(addressListVectorToGList):
(addressListGListToVector):
(webkitCachedResolverLookupByName):
(webkitCachedResolverLookupByNameAsync):
(webkitCachedResolverLookupByNameFinish):
(dnsCacheType):
(webkitCachedResolverLookupByNameWithFlags):
(webkitCachedResolverLookupByNameWithFlagsAsync):
(webkitCachedResolverLookupByNameWithFlagsFinish):
(webkitCachedResolverLookupByAddress):
(webkitCachedResolverLookupByAddressAsync):
(webkitCachedResolverLookupByAddressFinish):
(webkitCachedResolverLookupRecords):
(webkitCachedResolverLookupRecordsAsync):
(webkitCachedResolverLookupRecordsFinish):
(webkitCachedResolverReload):
(webkit_cached_resolver_class_init):
(webkitCachedResolverNew):
* NetworkProcess/glib/WebKitCachedResolver.h: Added.
* NetworkProcess/soup/NetworkProcessSoup.cpp:
(WebKit::NetworkProcess::platformInitializeNetworkProcess):
* PlatformGTK.cmake:
* PlatformWPE.cmake:
* SourcesGTK.txt:
* SourcesWPE.txt:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@246671 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit/ChangeLog
Source/WebKit/NetworkProcess/glib/DNSCache.cpp [new file with mode: 0644]
Source/WebKit/NetworkProcess/glib/DNSCache.h [new file with mode: 0644]
Source/WebKit/NetworkProcess/glib/WebKitCachedResolver.cpp [new file with mode: 0644]
Source/WebKit/NetworkProcess/glib/WebKitCachedResolver.h [new file with mode: 0644]
Source/WebKit/NetworkProcess/soup/NetworkProcessSoup.cpp
Source/WebKit/PlatformGTK.cmake
Source/WebKit/PlatformWPE.cmake
Source/WebKit/SourcesGTK.txt
Source/WebKit/SourcesWPE.txt

index 7e14851..8077ccd 100644 (file)
@@ -1,3 +1,49 @@
+2019-06-20  Patrick Griffis  <pgriffis@igalia.com> and Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        [GTK][WPE] Implement a basic DNS cache
+        https://bugs.webkit.org/show_bug.cgi?id=196094
+
+        Reviewed by Michael Catanzaro.
+
+        This adds a simple cache to all DNS operations in the network process.
+
+        * NetworkProcess/glib/DNSCache.cpp: Added.
+        (WebKit::DNSCache::DNSCache):
+        (WebKit::DNSCache::mapForType):
+        (WebKit::DNSCache::lookup):
+        (WebKit::DNSCache::update):
+        (WebKit::DNSCache::removeExpiredResponsesInMap):
+        (WebKit::DNSCache::pruneResponsesInMap):
+        (WebKit::DNSCache::removeExpiredResponsesFired):
+        (WebKit::DNSCache::clear):
+        * NetworkProcess/glib/DNSCache.h: Added.
+        * NetworkProcess/glib/WebKitCachedResolver.cpp: Added.
+        (addressListVectorToGList):
+        (addressListGListToVector):
+        (webkitCachedResolverLookupByName):
+        (webkitCachedResolverLookupByNameAsync):
+        (webkitCachedResolverLookupByNameFinish):
+        (dnsCacheType):
+        (webkitCachedResolverLookupByNameWithFlags):
+        (webkitCachedResolverLookupByNameWithFlagsAsync):
+        (webkitCachedResolverLookupByNameWithFlagsFinish):
+        (webkitCachedResolverLookupByAddress):
+        (webkitCachedResolverLookupByAddressAsync):
+        (webkitCachedResolverLookupByAddressFinish):
+        (webkitCachedResolverLookupRecords):
+        (webkitCachedResolverLookupRecordsAsync):
+        (webkitCachedResolverLookupRecordsFinish):
+        (webkitCachedResolverReload):
+        (webkit_cached_resolver_class_init):
+        (webkitCachedResolverNew):
+        * NetworkProcess/glib/WebKitCachedResolver.h: Added.
+        * NetworkProcess/soup/NetworkProcessSoup.cpp:
+        (WebKit::NetworkProcess::platformInitializeNetworkProcess):
+        * PlatformGTK.cmake:
+        * PlatformWPE.cmake:
+        * SourcesGTK.txt:
+        * SourcesWPE.txt:
+
 2019-06-20  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         [GTK] Stop pretending WebCore::Widget can have a platform widget
diff --git a/Source/WebKit/NetworkProcess/glib/DNSCache.cpp b/Source/WebKit/NetworkProcess/glib/DNSCache.cpp
new file mode 100644 (file)
index 0000000..12b9a95
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2019 Igalia S.L.
+ *
+ * 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 "DNSCache.h"
+
+namespace WebKit {
+
+static const Seconds expireInterval = 60_s;
+static const unsigned maxCacheSize = 400;
+
+DNSCache::DNSCache()
+    : m_expiredTimer(RunLoop::main(), this, &DNSCache::removeExpiredResponsesFired)
+{
+    m_expiredTimer.setPriority(RunLoopSourcePriority::ReleaseUnusedResourcesTimer);
+}
+
+DNSCache::DNSCacheMap& DNSCache::mapForType(Type type)
+{
+    switch (type) {
+    case Type::Default:
+        return m_dnsMap;
+    case Type::IPv4Only:
+#if GLIB_CHECK_VERSION(2, 59, 0)
+        return m_ipv4Map;
+#else
+        return m_dnsMap;
+#endif
+    case Type::IPv6Only:
+#if GLIB_CHECK_VERSION(2, 59, 0)
+        return m_ipv6Map;
+#else
+        return m_dnsMap;
+#endif
+    }
+
+    RELEASE_ASSERT_NOT_REACHED();
+    return m_dnsMap;
+}
+
+Optional<Vector<GRefPtr<GInetAddress>>> DNSCache::lookup(const CString& host, Type type)
+{
+    LockHolder locker(m_lock);
+    auto& map = mapForType(type);
+    auto it = map.find(host);
+    if (it == map.end())
+        return WTF::nullopt;
+
+    auto& response = it->value;
+    if (response.expirationTime <= MonotonicTime::now()) {
+        map.remove(it);
+        return WTF::nullopt;
+    }
+
+    return response.addressList;
+}
+
+void DNSCache::update(const CString& host, Vector<GRefPtr<GInetAddress>>&& addressList, Type type)
+{
+    LockHolder locker(m_lock);
+    auto& map = mapForType(type);
+    CachedResponse response = { WTFMove(addressList), MonotonicTime::now() + expireInterval };
+    auto addResult = map.set(host, WTFMove(response));
+    if (addResult.isNewEntry)
+        pruneResponsesInMap(map);
+    m_expiredTimer.startOneShot(expireInterval);
+}
+
+void DNSCache::removeExpiredResponsesInMap(DNSCacheMap& map)
+{
+    map.removeIf([now = MonotonicTime::now()](auto& entry) {
+        return entry.value.expirationTime <= now;
+    });
+}
+
+void DNSCache::pruneResponsesInMap(DNSCacheMap& map)
+{
+    if (map.size() <= maxCacheSize)
+        return;
+
+    // First try to remove expired responses.
+    removeExpiredResponsesInMap(map);
+    if (map.size() <= maxCacheSize)
+        return;
+
+    Vector<CString> keys = copyToVector(map.keys());
+    std::sort(keys.begin(), keys.end(), [&map](const CString& a, const CString& b) {
+        return map.get(a).expirationTime < map.get(b).expirationTime;
+    });
+
+    unsigned responsesToRemoveCount = keys.size() - maxCacheSize;
+    for (unsigned i = 0; i < responsesToRemoveCount; ++i)
+        map.remove(keys[i]);
+}
+
+void DNSCache::removeExpiredResponsesFired()
+{
+    LockHolder locker(m_lock);
+    removeExpiredResponsesInMap(m_dnsMap);
+#if GLIB_CHECK_VERSION(2, 59, 0)
+    removeExpiredResponsesInMap(m_ipv4Map);
+    removeExpiredResponsesInMap(m_ipv6Map);
+#endif
+}
+
+void DNSCache::clear()
+{
+    LockHolder locker(m_lock);
+    m_dnsMap.clear();
+#if GLIB_CHECK_VERSION(2, 59, 0)
+    m_ipv4Map.clear();
+    m_ipv6Map.clear();
+#endif
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/NetworkProcess/glib/DNSCache.h b/Source/WebKit/NetworkProcess/glib/DNSCache.h
new file mode 100644 (file)
index 0000000..d420edd
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2019 Igalia S.L.
+ *
+ * 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 <wtf/HashMap.h>
+#include <wtf/Lock.h>
+#include <wtf/MonotonicTime.h>
+#include <wtf/Optional.h>
+#include <wtf/RunLoop.h>
+#include <wtf/Vector.h>
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/text/CString.h>
+
+namespace WebKit {
+
+class DNSCache {
+public:
+    DNSCache();
+    ~DNSCache() = default;
+
+    enum class Type { Default, IPv4Only, IPv6Only };
+    Optional<Vector<GRefPtr<GInetAddress>>> lookup(const CString& host, Type = Type::Default);
+    void update(const CString& host, Vector<GRefPtr<GInetAddress>>&&, Type = Type::Default);
+    void clear();
+
+private:
+    struct CachedResponse {
+        Vector<GRefPtr<GInetAddress>> addressList;
+        MonotonicTime expirationTime;
+    };
+
+    using DNSCacheMap = HashMap<CString, CachedResponse>;
+
+    DNSCacheMap& mapForType(Type);
+    void removeExpiredResponsesFired();
+    void removeExpiredResponsesInMap(DNSCacheMap&);
+    void pruneResponsesInMap(DNSCacheMap&);
+
+    Lock m_lock;
+    DNSCacheMap m_dnsMap;
+#if GLIB_CHECK_VERSION(2, 59, 0)
+    DNSCacheMap m_ipv4Map;
+    DNSCacheMap m_ipv6Map;
+#endif
+    RunLoop::Timer<DNSCache> m_expiredTimer;
+};
+
+} // namespace WebKit
diff --git a/Source/WebKit/NetworkProcess/glib/WebKitCachedResolver.cpp b/Source/WebKit/NetworkProcess/glib/WebKitCachedResolver.cpp
new file mode 100644 (file)
index 0000000..c544b65
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2019 Igalia S.L.
+ *
+ * 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 "WebKitCachedResolver.h"
+
+#include "DNSCache.h"
+#include <wtf/glib/GUniquePtr.h>
+#include <wtf/glib/WTFGType.h>
+
+using namespace WebKit;
+
+typedef struct {
+    GRefPtr<GResolver> wrappedResolver;
+    DNSCache cache;
+} WebKitCachedResolverPrivate;
+
+struct _WebKitCachedResolver {
+    GResolver parentInstance;
+
+    WebKitCachedResolverPrivate* priv;
+};
+
+struct _WebKitCachedResolverClass {
+    GResolverClass parentClass;
+};
+
+WEBKIT_DEFINE_TYPE(WebKitCachedResolver, webkit_cached_resolver, G_TYPE_RESOLVER)
+
+static GList* addressListVectorToGList(const Vector<GRefPtr<GInetAddress>>& addressList)
+{
+    GList* returnValue = nullptr;
+    for (const auto& address : addressList)
+        returnValue = g_list_prepend(returnValue, g_object_ref(address.get()));
+    return g_list_reverse(returnValue);
+}
+
+static Vector<GRefPtr<GInetAddress>> addressListGListToVector(GList* addressList)
+{
+    Vector<GRefPtr<GInetAddress>> returnValue;
+    for (GList* it = addressList; it && it->data; it = g_list_next(it))
+        returnValue.append(G_INET_ADDRESS(it->data));
+    return returnValue;
+}
+
+struct LookupAsyncData {
+    CString hostname;
+#if GLIB_CHECK_VERSION(2, 59, 0)
+    DNSCache::Type dnsCacheType { DNSCache::Type::Default };
+#endif
+};
+WEBKIT_DEFINE_ASYNC_DATA_STRUCT(LookupAsyncData)
+
+static GList* webkitCachedResolverLookupByName(GResolver* resolver, const char* hostname, GCancellable* cancellable, GError** error)
+{
+    auto* priv = WEBKIT_CACHED_RESOLVER(resolver)->priv;
+    auto addressList = priv->cache.lookup(hostname);
+    if (addressList)
+        return addressListVectorToGList(addressList.value());
+
+    auto* returnValue = g_resolver_lookup_by_name(priv->wrappedResolver.get(), hostname, cancellable, error);
+    if (returnValue)
+        priv->cache.update(hostname, addressListGListToVector(returnValue));
+    return returnValue;
+}
+
+static void webkitCachedResolverLookupByNameAsync(GResolver* resolver, const char* hostname, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
+{
+    GRefPtr<GTask> task = adoptGRef(g_task_new(resolver, cancellable, callback, userData));
+    auto* priv = WEBKIT_CACHED_RESOLVER(resolver)->priv;
+    auto addressList = priv->cache.lookup(hostname);
+    if (addressList) {
+        g_task_return_pointer(task.get(), addressListVectorToGList(addressList.value()), reinterpret_cast<GDestroyNotify>(g_resolver_free_addresses));
+        return;
+    }
+
+    auto* asyncData = createLookupAsyncData();
+    asyncData->hostname = hostname;
+    g_task_set_task_data(task.get(), asyncData, reinterpret_cast<GDestroyNotify>(destroyLookupAsyncData));
+    g_resolver_lookup_by_name_async(priv->wrappedResolver.get(), hostname, cancellable, [](GObject* resolver, GAsyncResult* result, gpointer userData) {
+        GRefPtr<GTask> task = adoptGRef(G_TASK(userData));
+        GUniqueOutPtr<GError> error;
+        if (auto* addressList = g_resolver_lookup_by_name_finish(G_RESOLVER(resolver), result, &error.outPtr())) {
+            auto* priv = WEBKIT_CACHED_RESOLVER(g_task_get_source_object(task.get()))->priv;
+            auto* asyncData = static_cast<LookupAsyncData*>(g_task_get_task_data(task.get()));
+            priv->cache.update(asyncData->hostname, addressListGListToVector(addressList));
+            g_task_return_pointer(task.get(), addressList, reinterpret_cast<GDestroyNotify>(g_resolver_free_addresses));
+        } else
+            g_task_return_error(task.get(), error.get());
+    }, task.leakRef());
+}
+
+static GList* webkitCachedResolverLookupByNameFinish(GResolver* resolver, GAsyncResult* result, GError** error)
+{
+    g_return_val_if_fail(g_task_is_valid(result, resolver), nullptr);
+
+    return static_cast<GList*>(g_task_propagate_pointer(G_TASK(result), error));
+}
+
+#if GLIB_CHECK_VERSION(2, 59, 0)
+static inline DNSCache::Type dnsCacheType(GResolverNameLookupFlags flags)
+{
+    // A cache is kept for each type of response to avoid the overcomplication of combining or filtering results.
+    if (flags & G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY)
+        return DNSCache::Type::IPv4Only;
+
+    if (flags & G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY)
+        return DNSCache::Type::IPv6Only;
+
+    return DNSCache::Type::Default;
+}
+
+static GList* webkitCachedResolverLookupByNameWithFlags(GResolver* resolver, const char* hostname, GResolverNameLookupFlags flags, GCancellable* cancellable, GError** error)
+{
+    auto* priv = WEBKIT_CACHED_RESOLVER(resolver)->priv;
+    auto cacheType = dnsCacheType(flags);
+    auto addressList = priv->cache.lookup(hostname, cacheType);
+    if (addressList)
+        return addressListVectorToGList(addressList.value());
+
+    auto* returnValue = g_resolver_lookup_by_name_with_flags(priv->wrappedResolver.get(), hostname, flags, cancellable, error);
+    if (returnValue)
+        priv->cache.update(hostname, addressListGListToVector(returnValue), cacheType);
+    return returnValue;
+}
+
+static void webkitCachedResolverLookupByNameWithFlagsAsync(GResolver* resolver, const gchar* hostname, GResolverNameLookupFlags flags, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
+{
+    GRefPtr<GTask> task = adoptGRef(g_task_new(resolver, cancellable, callback, userData));
+    auto* priv = WEBKIT_CACHED_RESOLVER(resolver)->priv;
+    auto cacheType = dnsCacheType(flags);
+    auto addressList = priv->cache.lookup(hostname, cacheType);
+    if (addressList) {
+        g_task_return_pointer(task.get(), addressListVectorToGList(addressList.value()), reinterpret_cast<GDestroyNotify>(g_resolver_free_addresses));
+        return;
+    }
+
+    auto* asyncData = createLookupAsyncData();
+    asyncData->hostname = hostname;
+    asyncData->dnsCacheType = cacheType;
+    g_task_set_task_data(task.get(), asyncData, reinterpret_cast<GDestroyNotify>(destroyLookupAsyncData));
+    g_resolver_lookup_by_name_with_flags_async(priv->wrappedResolver.get(), hostname, flags, cancellable, [](GObject* resolver, GAsyncResult* result, gpointer userData) {
+        GRefPtr<GTask> task = adoptGRef(G_TASK(userData));
+        GUniqueOutPtr<GError> error;
+        if (auto* addressList = g_resolver_lookup_by_name_with_flags_finish(G_RESOLVER(resolver), result, &error.outPtr())) {
+            auto* priv = WEBKIT_CACHED_RESOLVER(g_task_get_source_object(task.get()))->priv;
+            auto* asyncData = static_cast<LookupAsyncData*>(g_task_get_task_data(task.get()));
+            priv->cache.update(asyncData->hostname, addressListGListToVector(addressList), asyncData->dnsCacheType);
+            g_task_return_pointer(task.get(), addressList, reinterpret_cast<GDestroyNotify>(g_resolver_free_addresses));
+        } else
+            g_task_return_error(task.get(), error.get());
+    }, task.leakRef());
+}
+
+static GList* webkitCachedResolverLookupByNameWithFlagsFinish(GResolver* resolver, GAsyncResult* result, GError** error)
+{
+    g_return_val_if_fail(g_task_is_valid(result, resolver), nullptr);
+
+    return static_cast<GList*>(g_task_propagate_pointer(G_TASK(result), error));
+}
+#endif // GLIB_CHECK_VERSION(2, 59, 0)
+
+static char* webkitCachedResolverLookupByAddress(GResolver* resolver, GInetAddress* address, GCancellable* cancellable, GError** error)
+{
+    return g_resolver_lookup_by_address(WEBKIT_CACHED_RESOLVER(resolver)->priv->wrappedResolver.get(), address, cancellable, error);
+}
+
+static void webkitCachedResolverLookupByAddressAsync(GResolver* resolver, GInetAddress* address, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
+{
+    g_resolver_lookup_by_address_async(WEBKIT_CACHED_RESOLVER(resolver)->priv->wrappedResolver.get(), address, cancellable, callback, userData);
+}
+
+static char* webkitCachedResolverLookupByAddressFinish(GResolver* resolver, GAsyncResult* result, GError** error)
+{
+    return g_resolver_lookup_by_address_finish(WEBKIT_CACHED_RESOLVER(resolver)->priv->wrappedResolver.get(), result, error);
+}
+
+static GList* webkitCachedResolverLookupRecords(GResolver* resolver, const char* rrname, GResolverRecordType recordType, GCancellable* cancellable, GError** error)
+{
+    return g_resolver_lookup_records(WEBKIT_CACHED_RESOLVER(resolver)->priv->wrappedResolver.get(), rrname, recordType, cancellable, error);
+}
+
+static void webkitCachedResolverLookupRecordsAsync(GResolver* resolver, const char* rrname, GResolverRecordType recordType, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
+{
+    g_resolver_lookup_records_async(WEBKIT_CACHED_RESOLVER(resolver)->priv->wrappedResolver.get(), rrname, recordType, cancellable, callback, userData);
+}
+
+static GList* webkitCachedResolverLookupRecordsFinish(GResolver* resolver, GAsyncResult* result, GError** error)
+{
+    return g_resolver_lookup_records_finish(WEBKIT_CACHED_RESOLVER(resolver)->priv->wrappedResolver.get(), result, error);
+}
+
+static void webkitCachedResolverReload(GResolver* resolver)
+{
+    WEBKIT_CACHED_RESOLVER(resolver)->priv->cache.clear();
+}
+
+static void webkit_cached_resolver_class_init(WebKitCachedResolverClass* klass)
+{
+    GResolverClass* resolverClass = G_RESOLVER_CLASS(klass);
+    resolverClass->lookup_by_name = webkitCachedResolverLookupByName;
+    resolverClass->lookup_by_name_async = webkitCachedResolverLookupByNameAsync;
+    resolverClass->lookup_by_name_finish = webkitCachedResolverLookupByNameFinish;
+#if GLIB_CHECK_VERSION(2, 59, 0)
+    resolverClass->lookup_by_name_with_flags = webkitCachedResolverLookupByNameWithFlags;
+    resolverClass->lookup_by_name_with_flags_async = webkitCachedResolverLookupByNameWithFlagsAsync;
+    resolverClass->lookup_by_name_with_flags_finish = webkitCachedResolverLookupByNameWithFlagsFinish;
+#endif
+    resolverClass->lookup_by_address = webkitCachedResolverLookupByAddress;
+    resolverClass->lookup_by_address_async = webkitCachedResolverLookupByAddressAsync;
+    resolverClass->lookup_by_address_finish = webkitCachedResolverLookupByAddressFinish;
+    resolverClass->lookup_records = webkitCachedResolverLookupRecords;
+    resolverClass->lookup_records_async = webkitCachedResolverLookupRecordsAsync;
+    resolverClass->lookup_records_finish = webkitCachedResolverLookupRecordsFinish;
+    resolverClass->reload = webkitCachedResolverReload;
+}
+
+GResolver* webkitCachedResolverNew(GRefPtr<GResolver>&& wrappedResolver)
+{
+    g_return_val_if_fail(wrappedResolver, nullptr);
+
+    auto* resolver = WEBKIT_CACHED_RESOLVER(g_object_new(WEBKIT_TYPE_CACHED_RESOLVER, nullptr));
+    resolver->priv->wrappedResolver = WTFMove(wrappedResolver);
+    return G_RESOLVER(resolver);
+}
diff --git a/Source/WebKit/NetworkProcess/glib/WebKitCachedResolver.h b/Source/WebKit/NetworkProcess/glib/WebKitCachedResolver.h
new file mode 100644 (file)
index 0000000..b0b37d1
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 Igalia S.L.
+ *
+ * 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 <gio/gio.h>
+#include <wtf/glib/GRefPtr.h>
+
+G_BEGIN_DECLS
+
+#define WEBKIT_TYPE_CACHED_RESOLVER            (webkit_cached_resolver_get_type())
+#define WEBKIT_CACHED_RESOLVER(object)         (G_TYPE_CHECK_INSTANCE_CAST((object), WEBKIT_TYPE_CACHED_RESOLVER, WebKitCachedResolver))
+#define WEBKIT_IS_CACHED_RESOLVER(object)      (G_TYPE_CHECK_INSTANCE_TYPE((object), WEBKIT_TYPE_CACHED_RESOLVER))
+#define WEBKIT_CACHED_RESOLVER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_CACHED_RESOLVER, WebKitCachedResolverClass))
+#define WEBKIT_IS_CACHED_RESOLVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_CACHED_RESOLVER))
+#define WEBKIT_CACHED_RESOLVER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_CACHED_RESOLVER, WebKitCachedResolverClass))
+
+typedef struct _WebKitCachedResolver WebKitCachedResolver;
+typedef struct _WebKitCachedResolverClass WebKitCachedResolverClass;
+
+GType webkit_cached_resolver_get_type(void);
+
+GResolver* webkitCachedResolverNew(GRefPtr<GResolver>&&);
+
+G_END_DECLS
index 3cab506..dca7c41 100644 (file)
@@ -31,6 +31,7 @@
 #include "NetworkProcessCreationParameters.h"
 #include "ResourceCachesToClear.h"
 #include "WebCookieManager.h"
+#include "WebKitCachedResolver.h"
 #include <WebCore/CertificateInfo.h>
 #include <WebCore/NetworkStorageSession.h>
 #include <WebCore/NotImplemented.h>
@@ -109,6 +110,9 @@ void NetworkProcess::platformInitializeNetworkProcess(const NetworkProcessCreati
     ASSERT(!parameters.diskCacheDirectory.isEmpty());
     m_diskCacheDirectory = parameters.diskCacheDirectory;
 
+    GRefPtr<GResolver> cachedResolver = adoptGRef(webkitCachedResolverNew(adoptGRef(g_resolver_get_default())));
+    g_resolver_set_default(cachedResolver.get());
+
     SoupNetworkSession::clearOldSoupCache(FileSystem::directoryName(m_diskCacheDirectory));
 
     OptionSet<NetworkCache::Cache::Option> cacheOptions { NetworkCache::Cache::Option::RegisterNotify };
index 633d905..0c7f77b 100644 (file)
@@ -374,6 +374,7 @@ list(APPEND WebKit_INCLUDE_DIRECTORIES
     "${FORWARDING_HEADERS_DIR}/JavaScriptCore/glib"
     "${WEBKIT_DIR}/PluginProcess/unix"
     "${WEBKIT_DIR}/NetworkProcess/CustomProtocols/soup"
+    "${WEBKIT_DIR}/NetworkProcess/glib"
     "${WEBKIT_DIR}/NetworkProcess/gtk"
     "${WEBKIT_DIR}/NetworkProcess/soup"
     "${WEBKIT_DIR}/NetworkProcess/unix"
index 4322ab2..1a635fb 100644 (file)
@@ -233,6 +233,7 @@ list(APPEND WebKit_INCLUDE_DIRECTORIES
     "${DERIVED_SOURCES_DIR}"
     "${DERIVED_SOURCES_WPE_API_DIR}"
     "${WEBKIT_DIR}/NetworkProcess/CustomProtocols/soup"
+    "${WEBKIT_DIR}/NetworkProcess/glib"
     "${WEBKIT_DIR}/NetworkProcess/soup"
     "${WEBKIT_DIR}/NetworkProcess/unix"
     "${WEBKIT_DIR}/Platform/IPC/glib"
index 17b9003..d3fea01 100644 (file)
@@ -33,6 +33,9 @@ NetworkProcess/CustomProtocols/soup/LegacyCustomProtocolManagerSoup.cpp
 NetworkProcess/cache/NetworkCacheDataSoup.cpp
 NetworkProcess/cache/NetworkCacheIOChannelSoup.cpp
 
+NetworkProcess/glib/DNSCache.cpp
+NetworkProcess/glib/WebKitCachedResolver.cpp
+
 NetworkProcess/soup/NetworkDataTaskSoup.cpp
 NetworkProcess/soup/NetworkProcessMainSoup.cpp
 NetworkProcess/soup/NetworkProcessSoup.cpp
index edf5c3a..0f3e634 100644 (file)
@@ -33,6 +33,9 @@ NetworkProcess/CustomProtocols/soup/LegacyCustomProtocolManagerSoup.cpp
 NetworkProcess/cache/NetworkCacheDataSoup.cpp
 NetworkProcess/cache/NetworkCacheIOChannelSoup.cpp
 
+NetworkProcess/glib/DNSCache.cpp
+NetworkProcess/glib/WebKitCachedResolver.cpp
+
 NetworkProcess/soup/NetworkDataTaskSoup.cpp
 NetworkProcess/soup/NetworkProcessMainSoup.cpp
 NetworkProcess/soup/NetworkProcessSoup.cpp