Diff
Modified: trunk/Source/WebCore/ChangeLog (226225 => 226226)
--- trunk/Source/WebCore/ChangeLog 2017-12-21 17:50:30 UTC (rev 226225)
+++ trunk/Source/WebCore/ChangeLog 2017-12-21 17:53:49 UTC (rev 226226)
@@ -1,3 +1,36 @@
+2017-12-21 Keith Rollin <krol...@apple.com>
+
+ Add optional logging of per-resource cookie information
+ https://bugs.webkit.org/show_bug.cgi?id=180883
+ <rdar://problem/35802295>
+
+ Reviewed by Brent Fulgham.
+
+ In order to support the tracking of the efficacy of Intelligent
+ Tracking Protection, add some logging of the cookie information
+ associated with each loaded resource. This logging is off by default
+ and is enabled with `defaults write -g WebKitLogCookieInformation
+ -bool true`.
+
+ No new tests -- no new user functionality added. Only new logging has
+ been added.
+
+ * platform/Cookie.h:
+ (WebCore::Cookie::Cookie):
+ (WebCore::Cookie::isNull const):
+ (WebCore::Cookie::encode const):
+ (WebCore::Cookie::decode):
+ * platform/network/cf/CookieJarCFNet.cpp:
+ (WebCore::canonicalCookieTime):
+ (WebCore::cookieCreatedTime):
+ (WebCore::cookieExpirationTime):
+ (WebCore::getRawCookies):
+ * platform/network/cocoa/CookieCocoa.mm:
+ (WebCore::cookieCreated):
+ (WebCore::Cookie::Cookie):
+ * platform/network/soup/CookieJarSoup.cpp:
+ (WebCore::getRawCookies):
+
2017-12-21 Brent Fulgham <bfulg...@apple.com>
Adopt new secure coding APIs in WebCore
Modified: trunk/Source/WebCore/platform/Cookie.h (226225 => 226226)
--- trunk/Source/WebCore/platform/Cookie.h 2017-12-21 17:50:30 UTC (rev 226225)
+++ trunk/Source/WebCore/platform/Cookie.h 2017-12-21 17:53:49 UTC (rev 226226)
@@ -43,11 +43,12 @@
: name(WTF::HashTableDeletedValue)
{ }
- Cookie(const String& name, const String& value, const String& domain, const String& path, double expires, bool httpOnly, bool secure, bool session, const String& comment, const URL& commentURL, const Vector<uint16_t> ports)
+ Cookie(const String& name, const String& value, const String& domain, const String& path, double created, double expires, bool httpOnly, bool secure, bool session, const String& comment, const URL& commentURL, const Vector<uint16_t> ports)
: name(name)
, value(value)
, domain(domain)
, path(path)
+ , created(created)
, expires(expires)
, httpOnly(httpOnly)
, secure(secure)
@@ -78,6 +79,7 @@
&& value.isNull()
&& domain.isNull()
&& path.isNull()
+ && created == 0
&& expires == 0
&& !httpOnly
&& !secure
@@ -90,7 +92,8 @@
String value;
String domain;
String path;
- // Expiration date, expressed as milliseconds since the UNIX epoch.
+ // Creation and expiration dates are expressed as milliseconds since the UNIX epoch.
+ double created { 0 };
double expires { 0 };
bool httpOnly { false };
bool secure { false };
@@ -116,7 +119,7 @@
template<class Encoder>
void Cookie::encode(Encoder& encoder) const
{
- encoder << name << value << domain << path << expires << httpOnly << secure << session << comment << commentURL << ports;
+ encoder << name << value << domain << path << created << expires << httpOnly << secure << session << comment << commentURL << ports;
}
template<class Decoder>
@@ -142,6 +145,11 @@
if (!path)
return std::nullopt;
+ std::optional<double> created;
+ decoder >> created;
+ if (!created)
+ return std::nullopt;
+
std::optional<double> expires;
decoder >> expires;
if (!expires)
@@ -176,7 +184,7 @@
if (!ports)
return std::nullopt;
- return {{ WTFMove(*name), WTFMove(*value), WTFMove(*domain), WTFMove(*path), WTFMove(*expires), WTFMove(*httpOnly), WTFMove(*secure), WTFMove(*session), WTFMove(*comment), WTFMove(commentURL), WTFMove(*ports) }};
+ return {{ WTFMove(*name), WTFMove(*value), WTFMove(*domain), WTFMove(*path), WTFMove(*created), WTFMove(*expires), WTFMove(*httpOnly), WTFMove(*secure), WTFMove(*session), WTFMove(*comment), WTFMove(commentURL), WTFMove(*ports) }};
}
}
Modified: trunk/Source/WebCore/platform/network/cf/CookieJarCFNet.cpp (226225 => 226226)
--- trunk/Source/WebCore/platform/network/cf/CookieJarCFNet.cpp 2017-12-21 17:50:30 UTC (rev 226225)
+++ trunk/Source/WebCore/platform/network/cf/CookieJarCFNet.cpp 2017-12-21 17:53:49 UTC (rev 226226)
@@ -70,6 +70,7 @@
static const CFStringRef s_setCookieKeyCF = CFSTR("Set-Cookie");
static const CFStringRef s_cookieCF = CFSTR("Cookie");
+static const CFStringRef s_createdCF = CFSTR("Created");
static inline RetainPtr<CFStringRef> cookieDomain(CFHTTPCookieRef cookie)
{
@@ -76,9 +77,37 @@
return adoptCF(CFHTTPCookieCopyDomain(cookie));
}
+static double canonicalCookieTime(double time)
+{
+ if (!time)
+ return time;
+
+ return (time + kCFAbsoluteTimeIntervalSince1970) * 1000;
+}
+
+static double cookieCreatedTime(CFHTTPCookieRef cookie)
+{
+ RetainPtr<CFDictionaryRef> props = adoptCF(CFHTTPCookieCopyProperties(cookie));
+ auto value = CFDictionaryGetValue(props.get(), s_createdCF);
+
+ auto asNumber = dynamic_cf_cast<CFNumberRef>(value);
+ if (asNumber) {
+ double asDouble;
+ if (CFNumberGetValue(asNumber, kCFNumberFloat64Type, &asDouble))
+ return canonicalCookieTime(asDouble);
+ return 0.0;
+ }
+
+ auto asString = dynamic_cf_cast<CFStringRef>(value);
+ if (asString)
+ return canonicalCookieTime(CFStringGetDoubleValue(asString));
+
+ return 0.0;
+}
+
static inline CFAbsoluteTime cookieExpirationTime(CFHTTPCookieRef cookie)
{
- return CFHTTPCookieGetExpirationTime(cookie);
+ return canonicalCookieTime(CFHTTPCookieGetExpirationTime(cookie));
}
static inline RetainPtr<CFStringRef> cookieName(CFHTTPCookieRef cookie)
@@ -228,7 +257,8 @@
String domain = cookieDomain(cookie).get();
String path = cookiePath(cookie).get();
- double expires = (cookieExpirationTime(cookie) + kCFAbsoluteTimeIntervalSince1970) * 1000;
+ double created = cookieCreatedTime(cookie);
+ double expires = cookieExpirationTime(cookie);
bool httpOnly = CFHTTPCookieIsHTTPOnly(cookie);
bool secure = CFHTTPCookieIsSecure(cookie);
@@ -238,7 +268,7 @@
URL commentURL;
Vector<uint16_t> ports;
- rawCookies.uncheckedAppend(Cookie(name, value, domain, path, expires, httpOnly, secure, session, comment, commentURL, ports));
+ rawCookies.uncheckedAppend(Cookie(name, value, domain, path, created, expires, httpOnly, secure, session, comment, commentURL, ports));
}
return true;
Modified: trunk/Source/WebCore/platform/network/cocoa/CookieCocoa.mm (226225 => 226226)
--- trunk/Source/WebCore/platform/network/cocoa/CookieCocoa.mm 2017-12-21 17:50:30 UTC (rev 226225)
+++ trunk/Source/WebCore/platform/network/cocoa/CookieCocoa.mm 2017-12-21 17:53:49 UTC (rev 226226)
@@ -54,8 +54,25 @@
return string;
}
+static double cookieCreated(NSHTTPCookie *cookie)
+{
+ id value = cookie.properties[@"Created"];
+
+ auto toCanonicalFormat = [](double referenceFormat) {
+ return 1000.0 * (referenceFormat + NSTimeIntervalSince1970);
+ };
+
+ if ([value isKindOfClass:[NSNumber class]])
+ return toCanonicalFormat(((NSNumber *)value).doubleValue);
+
+ if ([value isKindOfClass:[NSString class]])
+ return toCanonicalFormat(((NSString *)value).doubleValue);
+
+ return 0.0;
+}
+
Cookie::Cookie(NSHTTPCookie *cookie)
- : Cookie(cookie.name, cookie.value, cookie.domain, cookie.path, [cookie.expiresDate timeIntervalSince1970] * 1000.0,
+ : Cookie(cookie.name, cookie.value, cookie.domain, cookie.path, cookieCreated(cookie), [cookie.expiresDate timeIntervalSince1970] * 1000.0,
cookie.HTTPOnly, cookie.secure, cookie.sessionOnly, cookie.comment, cookie.commentURL, portVectorFromList(cookie.portList))
{
}
Modified: trunk/Source/WebCore/platform/network/soup/CookieJarSoup.cpp (226225 => 226226)
--- trunk/Source/WebCore/platform/network/soup/CookieJarSoup.cpp 2017-12-21 17:50:30 UTC (rev 226225)
+++ trunk/Source/WebCore/platform/network/soup/CookieJarSoup.cpp 2017-12-21 17:53:49 UTC (rev 226226)
@@ -152,7 +152,7 @@
for (GSList* iter = cookies.get(); iter; iter = g_slist_next(iter)) {
SoupCookie* cookie = static_cast<SoupCookie*>(iter->data);
rawCookies.append(Cookie(String::fromUTF8(cookie->name), String::fromUTF8(cookie->value), String::fromUTF8(cookie->domain),
- String::fromUTF8(cookie->path), cookie->expires ? static_cast<double>(soup_date_to_time_t(cookie->expires)) * 1000 : 0,
+ String::fromUTF8(cookie->path), 0, cookie->expires ? static_cast<double>(soup_date_to_time_t(cookie->expires)) * 1000 : 0,
cookie->http_only, cookie->secure, !cookie->expires, String(), URL(), Vector<uint16_t>{ }));
soup_cookie_free(cookie);
}
Modified: trunk/Source/WebKit/ChangeLog (226225 => 226226)
--- trunk/Source/WebKit/ChangeLog 2017-12-21 17:50:30 UTC (rev 226225)
+++ trunk/Source/WebKit/ChangeLog 2017-12-21 17:53:49 UTC (rev 226226)
@@ -1,3 +1,34 @@
+2017-12-21 Keith Rollin <krol...@apple.com>
+
+ Add optional logging of per-resource cookie information
+ https://bugs.webkit.org/show_bug.cgi?id=180883
+ <rdar://problem/35802295>
+
+ Reviewed by Brent Fulgham.
+
+ In order to support the tracking of the efficacy of Intelligent
+ Tracking Protection, add some logging of the cookie information
+ associated with each loaded resource. This logging is off by default
+ and is enabled with `defaults write -g WebKitLogCookieInformation
+ -bool true`.
+
+ * NetworkProcess/NetworkProcess.cpp:
+ (WebKit::NetworkProcess::initializeNetworkProcess):
+ * NetworkProcess/NetworkProcess.h:
+ (WebKit::NetworkProcess::shouldLogCookieInformation const):
+ * NetworkProcess/NetworkProcessCreationParameters.cpp:
+ (WebKit::NetworkProcessCreationParameters::encode const):
+ (WebKit::NetworkProcessCreationParameters::decode):
+ * NetworkProcess/NetworkProcessCreationParameters.h:
+ * NetworkProcess/NetworkResourceLoader.cpp:
+ (WebKit::NetworkResourceLoader::didFinishLoading):
+ (WebKit::NetworkResourceLoader::sendResultForCacheEntry):
+ (WebKit::NetworkResourceLoader::shouldLogCookieInformation const):
+ (WebKit::NetworkResourceLoader::logCookieInformation const):
+ * NetworkProcess/NetworkResourceLoader.h:
+ * UIProcess/Cocoa/WebProcessPoolCocoa.mm:
+ (WebKit::WebProcessPool::platformInitializeNetworkProcess):
+
2017-12-21 Brent Fulgham <bfulg...@apple.com>
Unreviewed Debug build fix after r226217
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp (226225 => 226226)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp 2017-12-21 17:50:30 UTC (rev 226225)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp 2017-12-21 17:53:49 UTC (rev 226226)
@@ -247,6 +247,10 @@
if (parameters.shouldUseTestingNetworkSession)
NetworkStorageSession::switchToNewTestingSession();
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING) && !RELEASE_LOG_DISABLED
+ m_logCookieInformation = parameters.logCookieInformation;
+#endif
+
#if USE(NETWORK_SESSION)
#if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
parameters.defaultSessionParameters.legacyCustomProtocolManager = supplement<LegacyCustomProtocolManager>();
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.h (226225 => 226226)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.h 2017-12-21 17:50:30 UTC (rev 226225)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.h 2017-12-21 17:53:49 UTC (rev 226226)
@@ -149,6 +149,10 @@
void preconnectTo(const WebCore::URL&, WebCore::StoredCredentialsPolicy);
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING) && !RELEASE_LOG_DISABLED
+ bool shouldLogCookieInformation() const { return m_logCookieInformation; }
+#endif
+
private:
NetworkProcess();
~NetworkProcess();
@@ -243,6 +247,9 @@
bool m_diskCacheIsDisabledForTesting;
bool m_canHandleHTTPSServerTrustEvaluation;
Seconds m_loadThrottleLatency;
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING) && !RELEASE_LOG_DISABLED
+ bool m_logCookieInformation { false };
+#endif
RefPtr<NetworkCache::Cache> m_cache;
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.cpp (226225 => 226226)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.cpp 2017-12-21 17:50:30 UTC (rev 226225)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.cpp 2017-12-21 17:53:49 UTC (rev 226226)
@@ -95,6 +95,9 @@
encoder << languages;
encoder << proxySettings;
#endif
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING) && !RELEASE_LOG_DISABLED
+ encoder << logCookieInformation;
+#endif
#if OS(LINUX)
encoder << memoryPressureMonitorHandle;
#endif
@@ -227,6 +230,11 @@
return false;
#endif
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING) && !RELEASE_LOG_DISABLED
+ if (!decoder.decode(result.logCookieInformation))
+ return false;
+#endif
+
#if OS(LINUX)
if (!decoder.decode(result.memoryPressureMonitorHandle))
return false;
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h (226225 => 226226)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h 2017-12-21 17:50:30 UTC (rev 226225)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h 2017-12-21 17:53:49 UTC (rev 226226)
@@ -110,6 +110,10 @@
WebCore::SoupNetworkProxySettings proxySettings;
#endif
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING) && !RELEASE_LOG_DISABLED
+ bool logCookieInformation { false };
+#endif
+
#if OS(LINUX)
IPC::Attachment memoryPressureMonitorHandle;
#endif
Modified: trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp (226225 => 226226)
--- trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp 2017-12-21 17:50:30 UTC (rev 226225)
+++ trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp 2017-12-21 17:53:49 UTC (rev 226226)
@@ -49,6 +49,11 @@
#include <wtf/CurrentTime.h>
#include <wtf/RunLoop.h>
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING) && !RELEASE_LOG_DISABLED
+#include <WebCore/NetworkStorageSession.h>
+#include <WebCore/PlatformCookieJar.h>
+#endif
+
using namespace WebCore;
#define RELEASE_LOG_IF_ALLOWED(fmt, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), Network, "%p - NetworkResourceLoader::" fmt, this, ##__VA_ARGS__)
@@ -395,6 +400,11 @@
return;
}
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING) && !RELEASE_LOG_DISABLED
+ if (shouldLogCookieInformation())
+ logCookieInformation();
+#endif
+
if (isSynchronous())
sendReplyToSynchronousRequest(*m_synchronousLoadData, m_bufferedData.get());
else {
@@ -596,6 +606,11 @@
}
#endif
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING) && !RELEASE_LOG_DISABLED
+ if (shouldLogCookieInformation())
+ logCookieInformation();
+#endif
+
WebCore::NetworkLoadMetrics networkLoadMetrics;
networkLoadMetrics.markComplete();
networkLoadMetrics.requestHeaderBytesSent = 0;
@@ -701,4 +716,56 @@
return m_connection->captureExtraNetworkLoadMetricsEnabled();
}
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING) && !RELEASE_LOG_DISABLED
+bool NetworkResourceLoader::shouldLogCookieInformation() const
+{
+ return NetworkProcess::singleton().shouldLogCookieInformation();
+}
+
+void NetworkResourceLoader::logCookieInformation() const
+{
+ auto networkStorageSession = WebCore::NetworkStorageSession::storageSession(sessionID());
+ ASSERT(networkStorageSession);
+
+ auto url = ""
+ auto partition = WebCore::URL(ParsedURLString, networkStorageSession->cookieStoragePartition(originalRequest(), frameID(), pageID()));
+
+ Vector<WebCore::Cookie> cookies;
+ bool result = WebCore::getRawCookies(*networkStorageSession, partition, url, frameID(), pageID(), cookies);
+
+ if (result) {
+#define LOCAL_LOG(str, ...) \
+ RELEASE_LOG_IF_ALLOWED("logCookieInformation: pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ": " str, pageID(), frameID(), identifier(), ##__VA_ARGS__)
+
+ LOCAL_LOG(R"({ "url": "%{public}s",)", url.string().utf8().data());
+ LOCAL_LOG(R"( "partition": "%{public}s",)", partition.string().utf8().data());
+ LOCAL_LOG(R"( "referer": "%{public}s",)", originalRequest().httpReferrer().utf8().data());
+ LOCAL_LOG(R"( "cookies": [)");
+
+ auto size = cookies.size();
+ decltype(size) count = 0;
+ for (const auto& cookie : cookies) {
+ const char* trailingComma = ",";
+ if (++count == size)
+ trailingComma = "";
+
+ LOCAL_LOG(R"( { "name": "%{public}s")", cookie.name.utf8().data());
+ LOCAL_LOG(R"( "value": "%{public}s")", cookie.value.utf8().data());
+ LOCAL_LOG(R"( "domain": "%{public}s")", cookie.domain.utf8().data());
+ LOCAL_LOG(R"( "path": "%{public}s")", cookie.path.utf8().data());
+ LOCAL_LOG(R"( "created": %f)", cookie.created);
+ LOCAL_LOG(R"( "expires": %f)", cookie.expires);
+ LOCAL_LOG(R"( "httpOnly": %{public}s)", cookie.httpOnly ? "true" : "false");
+ LOCAL_LOG(R"( "secure": %{public}s)", cookie.secure ? "true" : "false");
+ LOCAL_LOG(R"( "session": %{public}s)", cookie.session ? "true" : "false");
+ LOCAL_LOG(R"( "comment": "%{public}s")", cookie.comment.utf8().data());
+ LOCAL_LOG(R"( "commentURL": "%{public}s")", cookie.commentURL.string().utf8().data());
+ LOCAL_LOG(R"( }%{public}s)", trailingComma);
+ }
+ LOCAL_LOG(R"(]})");
+#undef LOCAL_LOG
+ }
+}
+#endif
+
} // namespace WebKit
Modified: trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.h (226225 => 226226)
--- trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.h 2017-12-21 17:50:30 UTC (rev 226225)
+++ trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.h 2017-12-21 17:53:49 UTC (rev 226226)
@@ -134,6 +134,11 @@
void consumeSandboxExtensions();
void invalidateSandboxExtensions();
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING) && !RELEASE_LOG_DISABLED
+ bool shouldLogCookieInformation() const;
+ void logCookieInformation() const;
+#endif
+
const NetworkResourceLoadParameters m_parameters;
Ref<NetworkConnectionToWebProcess> m_connection;
Modified: trunk/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm (226225 => 226226)
--- trunk/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm 2017-12-21 17:50:30 UTC (rev 226225)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm 2017-12-21 17:53:49 UTC (rev 226226)
@@ -86,6 +86,10 @@
static NSString * const WebKitSuppressMemoryPressureHandlerDefaultsKey = @"WebKitSuppressMemoryPressureHandler";
static NSString * const WebKitNetworkLoadThrottleLatencyMillisecondsDefaultsKey = @"WebKitNetworkLoadThrottleLatencyMilliseconds";
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING) && !RELEASE_LOG_DISABLED
+static NSString * const WebKitLogCookieInformationDefaultsKey = @"WebKitLogCookieInformation";
+#endif
+
#if ENABLE(NETWORK_CAPTURE)
static NSString * const WebKitRecordReplayModeDefaultsKey = @"WebKitRecordReplayMode";
static NSString * const WebKitRecordReplayCacheLocationDefaultsKey = @"WebKitRecordReplayCacheLocation";
@@ -308,6 +312,10 @@
parameters.cookieStoragePartitioningEnabled = cookieStoragePartitioningEnabled();
parameters.storageAccessAPIEnabled = storageAccessAPIEnabled();
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING) && !RELEASE_LOG_DISABLED
+ parameters.logCookieInformation = [defaults boolForKey:WebKitLogCookieInformationDefaultsKey];
+#endif
+
#if ENABLE(NETWORK_CAPTURE)
parameters.recordReplayMode = [defaults stringForKey:WebKitRecordReplayModeDefaultsKey];
parameters.recordReplayCacheLocation = [defaults stringForKey:WebKitRecordReplayCacheLocationDefaultsKey];