<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[196622] trunk</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/196622">196622</a></dd>
<dt>Author</dt> <dd>bfulgham@apple.com</dd>
<dt>Date</dt> <dd>2016-02-15 21:36:38 -0800 (Mon, 15 Feb 2016)</dd>
</dl>
<h3>Log Message</h3>
<pre>[Mac] Gather some rudimentary statistics during resource load
https://bugs.webkit.org/show_bug.cgi?id=153575
<rdar://problem/24075254>
Reviewed by Brady Eidson.
Source/WebCore:
Tested by: http/tests/navigation/statistics.html
* CMakeLists.txt:
* PlatformWin.cmake:
* WebCore.xcodeproj/project.pbxproj:
* dom/Document.cpp:
(WebCore::Document::updateLastHandledUserGestureTimestamp): Log user interaction
with the ResourceLoadObserver.
* loader/DocumentLoader.cpp:
(WebCore::DocumentLoader::willSendRequest): Track load statistics if the
user interacted with the document.
* loader/ResourceLoadObserver.cpp: Added.
* loader/ResourceLoadObserver.h: Added.
* loader/ResourceLoadStatistics.cpp: Added.
* loader/ResourceLoadStatistics.h: Added.
* loader/SubresourceLoader.cpp:
(WebCore::SubresourceLoader::willSendRequestInternal): Track load statistics.
* page/Settings.cpp:
(WebCore::Settings::setResourceLoadStatisticsEnabled): Added.
* page/Settings.h:
(WebCore::Settings::resourceLoadStatisticsEnabled): Added.
* platform/Logging.h:
* testing/Internals.cpp:
(WebCore::Internals::resourceLoadStatisticsForOrigin):
(WebCore::Internals::setResourceLoadStatisticsEnabled):
* testing/Internals.h:
* testing/Internals.idl:
Source/WebKit/mac:
* Misc/WebKitNSStringExtras.h:
* Misc/WebKitNSStringExtras.mm:
(+[NSString _webkit_localStorageDirectoryWithBundleIdentifier:]): Added.
* WebView/WebPreferenceKeysPrivate.h:
* WebView/WebPreferences.mm:
(+[WebPreferences initialize]):
(-[WebPreferences resourceLoadStatisticsEnabled]): Added.
(-[WebPreferences setResourceLoadStatisticsEnabled:]): Added.
* WebView/WebPreferencesPrivate.h:
* WebView/WebView.mm:
(WebKitInitializeApplicationCachePathIfNecessary):
(WebKitInitializeApplicationStatisticsStoragePathIfNecessary): Added.
(-[WebView _commonInitializationWithFrameName:groupName:]): Add call to new
initialization method.
(-[WebView _preferencesChanged:]): Track changes in the user's desire to
monitor resource load statistics.
(+[WebView _applicationWillTerminate]): Write statistics to disk (if preferences
say to do so.)
Tools:
* MiniBrowser/mac/SettingsController.h:
* MiniBrowser/mac/SettingsController.m:
(-[SettingsController _populateMenu]): Add menu item for new debug flag.
(-[SettingsController toggleResourceLoadStatisticsEnabled:]): Added.
(-[SettingsController resourceLoadStatisticsEnabled]): Added.
* MiniBrowser/mac/WK1BrowserWindowController.m:
(-[WK1BrowserWindowController didChangeSettings]): React to changes in
users's desire to track resource load statistics.
LayoutTests:
* http/tests/navigation/resources/redirect-on-reload-updates-history-item-statistics.php: Added.
* http/tests/navigation/resources/redirect-updates-history-item-done-statistics.html: Added.
* http/tests/navigation/statistics-expected.txt: Added.
* http/tests/navigation/statistics.html: Added.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreCMakeListstxt">trunk/Source/WebCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorePlatformWincmake">trunk/Source/WebCore/PlatformWin.cmake</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCoredomDocumentcpp">trunk/Source/WebCore/dom/Document.cpp</a></li>
<li><a href="#trunkSourceWebCoreloaderDocumentLoadercpp">trunk/Source/WebCore/loader/DocumentLoader.cpp</a></li>
<li><a href="#trunkSourceWebCoreloaderSubresourceLoadercpp">trunk/Source/WebCore/loader/SubresourceLoader.cpp</a></li>
<li><a href="#trunkSourceWebCorepageSettingscpp">trunk/Source/WebCore/page/Settings.cpp</a></li>
<li><a href="#trunkSourceWebCorepageSettingsh">trunk/Source/WebCore/page/Settings.h</a></li>
<li><a href="#trunkSourceWebCoreplatformLoggingh">trunk/Source/WebCore/platform/Logging.h</a></li>
<li><a href="#trunkSourceWebCoretestingInternalscpp">trunk/Source/WebCore/testing/Internals.cpp</a></li>
<li><a href="#trunkSourceWebCoretestingInternalsh">trunk/Source/WebCore/testing/Internals.h</a></li>
<li><a href="#trunkSourceWebCoretestingInternalsidl">trunk/Source/WebCore/testing/Internals.idl</a></li>
<li><a href="#trunkSourceWebKitmacChangeLog">trunk/Source/WebKit/mac/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitmacMiscWebKitNSStringExtrash">trunk/Source/WebKit/mac/Misc/WebKitNSStringExtras.h</a></li>
<li><a href="#trunkSourceWebKitmacMiscWebKitNSStringExtrasmm">trunk/Source/WebKit/mac/Misc/WebKitNSStringExtras.mm</a></li>
<li><a href="#trunkSourceWebKitmacWebKitexp">trunk/Source/WebKit/mac/WebKit.exp</a></li>
<li><a href="#trunkSourceWebKitmacWebViewWebPreferenceKeysPrivateh">trunk/Source/WebKit/mac/WebView/WebPreferenceKeysPrivate.h</a></li>
<li><a href="#trunkSourceWebKitmacWebViewWebPreferencesmm">trunk/Source/WebKit/mac/WebView/WebPreferences.mm</a></li>
<li><a href="#trunkSourceWebKitmacWebViewWebPreferencesPrivateh">trunk/Source/WebKit/mac/WebView/WebPreferencesPrivate.h</a></li>
<li><a href="#trunkSourceWebKitmacWebViewWebViewmm">trunk/Source/WebKit/mac/WebView/WebView.mm</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsDumpRenderTreemacDumpRenderTreemm">trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm</a></li>
<li><a href="#trunkToolsMiniBrowsermacSettingsControllerh">trunk/Tools/MiniBrowser/mac/SettingsController.h</a></li>
<li><a href="#trunkToolsMiniBrowsermacSettingsControllerm">trunk/Tools/MiniBrowser/mac/SettingsController.m</a></li>
<li><a href="#trunkToolsMiniBrowsermacWK1BrowserWindowControllerm">trunk/Tools/MiniBrowser/mac/WK1BrowserWindowController.m</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestshttptestsnavigationresourcesredirectonreloadupdateshistoryitemstatisticsphp">trunk/LayoutTests/http/tests/navigation/resources/redirect-on-reload-updates-history-item-statistics.php</a></li>
<li><a href="#trunkLayoutTestshttptestsnavigationresourcesredirectupdateshistoryitemdonestatisticshtml">trunk/LayoutTests/http/tests/navigation/resources/redirect-updates-history-item-done-statistics.html</a></li>
<li><a href="#trunkLayoutTestshttptestsnavigationstatisticsexpectedtxt">trunk/LayoutTests/http/tests/navigation/statistics-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttptestsnavigationstatisticshtml">trunk/LayoutTests/http/tests/navigation/statistics.html</a></li>
<li><a href="#trunkSourceWebCoreloaderResourceLoadObservercpp">trunk/Source/WebCore/loader/ResourceLoadObserver.cpp</a></li>
<li><a href="#trunkSourceWebCoreloaderResourceLoadObserverh">trunk/Source/WebCore/loader/ResourceLoadObserver.h</a></li>
<li><a href="#trunkSourceWebCoreloaderResourceLoadStatisticscpp">trunk/Source/WebCore/loader/ResourceLoadStatistics.cpp</a></li>
<li><a href="#trunkSourceWebCoreloaderResourceLoadStatisticsh">trunk/Source/WebCore/loader/ResourceLoadStatistics.h</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/LayoutTests/ChangeLog        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2016-02-15 Brent Fulgham <bfulgham@apple.com>
+
+ [Mac] Gather some rudimentary statistics during resource load
+ https://bugs.webkit.org/show_bug.cgi?id=153575
+ <rdar://problem/24075254>
+
+ Reviewed by Brady Eidson.
+
+ * http/tests/navigation/resources/redirect-on-reload-updates-history-item-statistics.php: Added.
+ * http/tests/navigation/resources/redirect-updates-history-item-done-statistics.html: Added.
+ * http/tests/navigation/statistics-expected.txt: Added.
+ * http/tests/navigation/statistics.html: Added.
+
</ins><span class="cx"> 2016-02-15 Chris Dumez <cdumez@apple.com>
</span><span class="cx">
</span><span class="cx"> The following properties should exist on the global object: AudioTrackList, AudioTrack, VideoTrackList, VideoTrack
</span></span></pre></div>
<a id="trunkLayoutTestshttptestsnavigationresourcesredirectonreloadupdateshistoryitemstatisticsphp"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/navigation/resources/redirect-on-reload-updates-history-item-statistics.php (0 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/navigation/resources/redirect-on-reload-updates-history-item-statistics.php         (rev 0)
+++ trunk/LayoutTests/http/tests/navigation/resources/redirect-on-reload-updates-history-item-statistics.php        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -0,0 +1,44 @@
</span><ins>+<?php
+header('cache-control: no-store');
+
+$location=$_COOKIE['location'];
+if ($location!="") {
+ header('Status: 303 See Other');
+ header('Location: '.$location);
+ exit;
+}
+?>
+
+<script src='redirect-updates-history-item.js'></script>
+<script>
+onunload = function() {
+ // no page cache
+}
+
+onload = function() {
+ setTimeout(function() {
+ // The first time through here (sessionStorage.done is false), this
+ // code inserts a new history item using pushState, and then it
+ // triggers a reload of the history item. However, we set the
+ // "location" cookie so that when we reload this page, we actually
+ // redirect to the value of the "location" cookie.
+ //
+ // This loads the "goback" page, which bounces us back here after
+ // setting sessionStorage.done to true. The point of this test is to
+ // ensure that going back actually performs a real navigation as
+ // opposed to performing a "same document navigation" as would normally
+ // be done when navigating back after a pushState.
+
+ if (sessionStorage.done) {
+ location.replace("redirect-updates-history-item-done-statistics.html");
+ } else {
+ history.pushState(null, null, "");
+
+ setLocationCookie("redirect-on-reload-updates-history-item-goback.html");
+ location.reload();
+ }
+ }, 0);
+}
+</script>
+
+<p>redirect-on-reload-updates-history-item.php: You should not see this text!</p>
</ins></span></pre></div>
<a id="trunkLayoutTestshttptestsnavigationresourcesredirectupdateshistoryitemdonestatisticshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/navigation/resources/redirect-updates-history-item-done-statistics.html (0 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/navigation/resources/redirect-updates-history-item-done-statistics.html         (rev 0)
+++ trunk/LayoutTests/http/tests/navigation/resources/redirect-updates-history-item-done-statistics.html        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -0,0 +1,13 @@
</span><ins>+<script src="redirect-updates-history-item.js"></script>
+<script>
+clearLocationCookie();
+
+onload = function() {
+ if (window.testRunner) {
+ testRunner.notifyDone();
+ log("Dumping Resource Load Statistics:");
+ log(window.internals.resourceLoadStatisticsForOrigin("127.0.0.1"));
+ }
+}
+</script>
+<body>PASS</body>
</ins></span></pre></div>
<a id="trunkLayoutTestshttptestsnavigationstatisticsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/navigation/statistics-expected.txt (0 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/navigation/statistics-expected.txt         (rev 0)
+++ trunk/LayoutTests/http/tests/navigation/statistics-expected.txt        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+main frame - has 1 onunload handler(s)
+main frame - has 1 onunload handler(s)
+PASS
+Dumping Resource Load Statistics:
+
+
+
+============== Back Forward List ==============
+ http://127.0.0.1:8000/navigation/statistics.html **nav target**
+curr-> http://127.0.0.1:8000/navigation/resources/redirect-updates-history-item-done-statistics.html **nav target**
+ http://127.0.0.1:8000/navigation/resources/redirect-on-reload-updates-history-item-goback.html **nav target**
+===============================================
</ins></span></pre></div>
<a id="trunkLayoutTestshttptestsnavigationstatisticshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/navigation/statistics.html (0 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/navigation/statistics.html         (rev 0)
+++ trunk/LayoutTests/http/tests/navigation/statistics.html        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -0,0 +1,25 @@
</span><ins>+<script src="resources/redirect-updates-history-item.js"></script>
+<script>
+
+// Test that we properly update a history item when reloading the history item
+// results in a redirect to a different document. We verify that the resulting
+// document is not treated as the same document as the original document in
+// history. See redirect-on-reload-updates-history-item.php for more details.
+
+if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.dumpBackForwardList();
+ window.internals.setResourceLoadStatisticsEnabled(true);
+ testRunner.waitUntilDone();
+}
+onload = function() {
+ setTimeout(function() {
+ // These fields are used by subsequent pages in this test. Clear them
+ // to avoid confusing the test with old state.
+ clearLocationCookie();
+ delete sessionStorage.done;
+
+ location = 'resources/redirect-on-reload-updates-history-item-statistics.php';
+ }, 0);
+}
+</script>
</ins></span></pre></div>
<a id="trunkSourceWebCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/CMakeLists.txt (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/CMakeLists.txt        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Source/WebCore/CMakeLists.txt        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -1936,6 +1936,8 @@
</span><span class="cx"> loader/PolicyChecker.cpp
</span><span class="cx"> loader/ProgressTracker.cpp
</span><span class="cx"> loader/ResourceLoadNotifier.cpp
</span><ins>+ loader/ResourceLoadObserver.cpp
+ loader/ResourceLoadStatistics.cpp
</ins><span class="cx"> loader/ResourceLoader.cpp
</span><span class="cx"> loader/SinkDocument.cpp
</span><span class="cx"> loader/SubframeLoader.cpp
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Source/WebCore/ChangeLog        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -1,3 +1,39 @@
</span><ins>+2016-02-15 Brent Fulgham <bfulgham@apple.com>
+
+ [Mac] Gather some rudimentary statistics during resource load
+ https://bugs.webkit.org/show_bug.cgi?id=153575
+ <rdar://problem/24075254>
+
+ Reviewed by Brady Eidson.
+
+ Tested by: http/tests/navigation/statistics.html
+
+ * CMakeLists.txt:
+ * PlatformWin.cmake:
+ * WebCore.xcodeproj/project.pbxproj:
+ * dom/Document.cpp:
+ (WebCore::Document::updateLastHandledUserGestureTimestamp): Log user interaction
+ with the ResourceLoadObserver.
+ * loader/DocumentLoader.cpp:
+ (WebCore::DocumentLoader::willSendRequest): Track load statistics if the
+ user interacted with the document.
+ * loader/ResourceLoadObserver.cpp: Added.
+ * loader/ResourceLoadObserver.h: Added.
+ * loader/ResourceLoadStatistics.cpp: Added.
+ * loader/ResourceLoadStatistics.h: Added.
+ * loader/SubresourceLoader.cpp:
+ (WebCore::SubresourceLoader::willSendRequestInternal): Track load statistics.
+ * page/Settings.cpp:
+ (WebCore::Settings::setResourceLoadStatisticsEnabled): Added.
+ * page/Settings.h:
+ (WebCore::Settings::resourceLoadStatisticsEnabled): Added.
+ * platform/Logging.h:
+ * testing/Internals.cpp:
+ (WebCore::Internals::resourceLoadStatisticsForOrigin):
+ (WebCore::Internals::setResourceLoadStatisticsEnabled):
+ * testing/Internals.h:
+ * testing/Internals.idl:
+
</ins><span class="cx"> 2016-02-15 Chris Dumez <cdumez@apple.com>
</span><span class="cx">
</span><span class="cx"> The following properties should exist on the global object: AudioTrackList, AudioTrack, VideoTrackList, VideoTrack
</span></span></pre></div>
<a id="trunkSourceWebCorePlatformWincmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/PlatformWin.cmake (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/PlatformWin.cmake        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Source/WebCore/PlatformWin.cmake        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -64,6 +64,8 @@
</span><span class="cx"> platform/audio/PlatformMediaSessionManager.cpp
</span><span class="cx">
</span><span class="cx"> platform/cf/FileSystemCF.cpp
</span><ins>+ platform/cf/KeyedDecoderCF.cpp
+ platform/cf/KeyedEncoderCF.cpp
</ins><span class="cx"> platform/cf/SharedBufferCF.cpp
</span><span class="cx">
</span><span class="cx"> platform/cf/win/CertificateCFWin.cpp
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -2517,6 +2517,8 @@
</span><span class="cx">                 65E0E9441133C89F00B4CB10 /* JSDOMWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 65E0E9431133C89F00B4CB10 /* JSDOMWrapper.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 65FEA86909833ADE00BED4AB /* Page.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65FEA86809833ADE00BED4AB /* Page.cpp */; };
</span><span class="cx">                 6B3480940EEF50D400AC1B41 /* NativeImagePtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 6B3480920EEF50D400AC1B41 /* NativeImagePtr.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                6B693A2E1C51A82E00B03BEF /* ResourceLoadObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 6B693A2D1C51A82E00B03BEF /* ResourceLoadObserver.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                6B693A341C51A95D00B03BEF /* ResourceLoadObserver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6B693A331C51A95D00B03BEF /* ResourceLoadObserver.cpp */; };
</ins><span class="cx">                 6C4C96DE1AD4483500365A50 /* JSReadableStreamController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6C4C96DA1AD4483500365A50 /* JSReadableStreamController.cpp */; };
</span><span class="cx">                 6C4C96DF1AD4483500365A50 /* JSReadableStreamController.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C4C96DB1AD4483500365A50 /* JSReadableStreamController.h */; };
</span><span class="cx">                 6C638895A96CCEE50C8C946C /* CachedResourceRequestInitiators.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C638893A96CCEE50C8C946C /* CachedResourceRequestInitiators.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -2691,6 +2693,8 @@
</span><span class="cx">                 7A74ECBA101839A600BF939E /* InspectorDOMStorageAgent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A74ECB8101839A500BF939E /* InspectorDOMStorageAgent.cpp */; };
</span><span class="cx">                 7A74ECBB101839A600BF939E /* InspectorDOMStorageAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A74ECB9101839A600BF939E /* InspectorDOMStorageAgent.h */; };
</span><span class="cx">                 7A74ECBD101839DA00BF939E /* JSInspectorFrontendHostCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A74ECBC101839DA00BF939E /* JSInspectorFrontendHostCustom.cpp */; };
</span><ins>+                7A929CA61C598A9E004DF226 /* ResourceLoadStatistics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A929CA11C598378004DF226 /* ResourceLoadStatistics.cpp */; };
+                7A929CA71C598AA9004DF226 /* ResourceLoadStatistics.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A929CA21C598378004DF226 /* ResourceLoadStatistics.h */; };
</ins><span class="cx">                 7A93868518DCC14500B8263D /* VTTScanner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A93868218DCC14500B8263D /* VTTScanner.cpp */; };
</span><span class="cx">                 7A93868618DCC14500B8263D /* VTTScanner.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A93868318DCC14500B8263D /* VTTScanner.h */; };
</span><span class="cx">                 7AA3A699194A64E7001CBD24 /* TileController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7AA3A695194A64E7001CBD24 /* TileController.cpp */; };
</span><span class="lines">@@ -10088,6 +10092,8 @@
</span><span class="cx">                 65F80697054D9F86008BF776 /* BlockExceptions.mm */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = BlockExceptions.mm; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
</span><span class="cx">                 65FEA86809833ADE00BED4AB /* Page.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Page.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 6B3480920EEF50D400AC1B41 /* NativeImagePtr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = NativeImagePtr.h; sourceTree = "<group>"; };
</span><ins>+                6B693A2D1C51A82E00B03BEF /* ResourceLoadObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResourceLoadObserver.h; sourceTree = "<group>"; };
+                6B693A331C51A95D00B03BEF /* ResourceLoadObserver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ResourceLoadObserver.cpp; sourceTree = "<group>"; };
</ins><span class="cx">                 6C4C96DA1AD4483500365A50 /* JSReadableStreamController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSReadableStreamController.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 6C4C96DB1AD4483500365A50 /* JSReadableStreamController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSReadableStreamController.h; sourceTree = "<group>"; };
</span><span class="cx">                 6C638893A96CCEE50C8C946C /* CachedResourceRequestInitiators.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CachedResourceRequestInitiators.h; sourceTree = "<group>"; };
</span><span class="lines">@@ -10292,6 +10298,8 @@
</span><span class="cx">                 7A74ECB8101839A500BF939E /* InspectorDOMStorageAgent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorDOMStorageAgent.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 7A74ECB9101839A600BF939E /* InspectorDOMStorageAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorDOMStorageAgent.h; sourceTree = "<group>"; };
</span><span class="cx">                 7A74ECBC101839DA00BF939E /* JSInspectorFrontendHostCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSInspectorFrontendHostCustom.cpp; sourceTree = "<group>"; };
</span><ins>+                7A929CA11C598378004DF226 /* ResourceLoadStatistics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ResourceLoadStatistics.cpp; sourceTree = "<group>"; };
+                7A929CA21C598378004DF226 /* ResourceLoadStatistics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResourceLoadStatistics.h; sourceTree = "<group>"; };
</ins><span class="cx">                 7A93868218DCC14500B8263D /* VTTScanner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VTTScanner.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 7A93868318DCC14500B8263D /* VTTScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VTTScanner.h; sourceTree = "<group>"; };
</span><span class="cx">                 7AA3A695194A64E7001CBD24 /* TileController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TileController.cpp; sourceTree = "<group>"; };
</span><span class="lines">@@ -22689,6 +22697,10 @@
</span><span class="cx">                                 51EE7B371AA50B0500F92B21 /* ResourceLoadInfo.h */,
</span><span class="cx">                                 973E325410883B7C005BC493 /* ResourceLoadNotifier.cpp */,
</span><span class="cx">                                 973E325510883B7C005BC493 /* ResourceLoadNotifier.h */,
</span><ins>+                                6B693A331C51A95D00B03BEF /* ResourceLoadObserver.cpp */,
+                                6B693A2D1C51A82E00B03BEF /* ResourceLoadObserver.h */,
+                                7A929CA11C598378004DF226 /* ResourceLoadStatistics.cpp */,
+                                7A929CA21C598378004DF226 /* ResourceLoadStatistics.h */,
</ins><span class="cx">                                 51327D5F11A33A2B004F9D65 /* SinkDocument.cpp */,
</span><span class="cx">                                 51327D5E11A33A2B004F9D65 /* SinkDocument.h */,
</span><span class="cx">                                 D000ED2511C1B9CD00C47726 /* SubframeLoader.cpp */,
</span><span class="lines">@@ -24855,6 +24867,7 @@
</span><span class="cx">                         isa = PBXHeadersBuildPhase;
</span><span class="cx">                         buildActionMask = 2147483647;
</span><span class="cx">                         files = (
</span><ins>+                                6B693A2E1C51A82E00B03BEF /* ResourceLoadObserver.h in Headers */,
</ins><span class="cx">                                 FE115FAB167988CD00249134 /* AbstractDatabaseServer.h in Headers */,
</span><span class="cx">                                 41E1B1D10FF5986900576B3B /* AbstractWorker.h in Headers */,
</span><span class="cx">                                 29A8122E0FBB9C1D00510293 /* AccessibilityARIAGridCell.h in Headers */,
</span><span class="lines">@@ -25084,6 +25097,7 @@
</span><span class="cx">                                 99CC0B4F18BE9849006CEBCC /* CapturingInputCursor.h in Headers */,
</span><span class="cx">                                 CDC734151977896D0046BFC5 /* CARingBuffer.h in Headers */,
</span><span class="cx">                                 6550B69E099DF0270090D781 /* CDATASection.h in Headers */,
</span><ins>+                                7A929CA71C598AA9004DF226 /* ResourceLoadStatistics.h in Headers */,
</ins><span class="cx">                                 CDE8B5ED1A69777300B4B66A /* CDMPrivateClearKey.h in Headers */,
</span><span class="cx">                                 CD318623199F1E2A0030A0F7 /* CDMPrivateMediaSourceAVFObjC.h in Headers */,
</span><span class="cx">                                 CDDD571518B57A8200A94FCB /* CDMSession.h in Headers */,
</span><span class="lines">@@ -29148,6 +29162,7 @@
</span><span class="cx">                                 E164FAA518315E1A00DB4E61 /* CryptoKeyRSAMac.cpp in Sources */,
</span><span class="cx">                                 E125F859182C1AA600D84CD9 /* CryptoKeySerializationRaw.cpp in Sources */,
</span><span class="cx">                                 31BC742D1AAFF45C006B4340 /* CSSAnimationTriggerScrollValue.cpp in Sources */,
</span><ins>+                                7A929CA61C598A9E004DF226 /* ResourceLoadStatistics.cpp in Sources */,
</ins><span class="cx">                                 CAE9F90F146441F000C245B0 /* CSSAspectRatioValue.cpp in Sources */,
</span><span class="cx">                                 FBD6AF8B15EF25E5008B7110 /* CSSBasicShapes.cpp in Sources */,
</span><span class="cx">                                 E16A84F914C85CCC002977DF /* CSSBorderImage.cpp in Sources */,
</span><span class="lines">@@ -30120,6 +30135,7 @@
</span><span class="cx">                                 BCBFB53C0DCD29CF0019B3E5 /* JSDOMWindowShell.cpp in Sources */,
</span><span class="cx">                                 FD7868B9136B999200D403DF /* JSDynamicsCompressorNode.cpp in Sources */,
</span><span class="cx">                                 65DF31F909D1CC60000BE325 /* JSElement.cpp in Sources */,
</span><ins>+                                6B693A341C51A95D00B03BEF /* ResourceLoadObserver.cpp in Sources */,
</ins><span class="cx">                                 BC2ED5550C6B9BD300920BFF /* JSElementCustom.cpp in Sources */,
</span><span class="cx">                                 2ECF7ADC10162B3800427DE7 /* JSErrorEvent.cpp in Sources */,
</span><span class="cx">                                 F3D461481161D53200CA0D09 /* JSErrorHandler.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Document.cpp (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Document.cpp        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Source/WebCore/dom/Document.cpp        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -134,6 +134,7 @@
</span><span class="cx"> #include "RenderLayerCompositor.h"
</span><span class="cx"> #include "RenderView.h"
</span><span class="cx"> #include "RenderWidget.h"
</span><ins>+#include "ResourceLoadObserver.h"
</ins><span class="cx"> #include "RuntimeEnabledFeatures.h"
</span><span class="cx"> #include "SVGDocumentExtensions.h"
</span><span class="cx"> #include "SVGElement.h"
</span><span class="lines">@@ -6396,6 +6397,9 @@
</span><span class="cx">
</span><span class="cx"> void Document::updateLastHandledUserGestureTimestamp()
</span><span class="cx"> {
</span><ins>+ if (!m_lastHandledUserGestureTimestamp)
+ ResourceLoadObserver::sharedObserver().logUserInteraction(*this);
+
</ins><span class="cx"> m_lastHandledUserGestureTimestamp = monotonicallyIncreasingTime();
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreloaderDocumentLoadercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/DocumentLoader.cpp (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/DocumentLoader.cpp        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Source/WebCore/loader/DocumentLoader.cpp        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -59,6 +59,7 @@
</span><span class="cx"> #include "PolicyChecker.h"
</span><span class="cx"> #include "ProgressTracker.h"
</span><span class="cx"> #include "ResourceHandle.h"
</span><ins>+#include "ResourceLoadObserver.h"
</ins><span class="cx"> #include "SchemeRegistry.h"
</span><span class="cx"> #include "ScriptController.h"
</span><span class="cx"> #include "SecurityPolicy.h"
</span><span class="lines">@@ -524,9 +525,19 @@
</span><span class="cx"> timing().addRedirect(redirectResponse.url(), newRequest.url());
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ ASSERT(m_frame);
+
+ Frame& topFrame = m_frame->tree().top();
+
+ ASSERT(m_frame->document());
+ ASSERT(topFrame.document());
+
+ if (Settings::resourceLoadStatisticsEnabled())
+ ResourceLoadObserver::sharedObserver().logFrameNavigation(!redirectResponse.isNull(), m_frame->document()->url(), newRequest.url(), m_frame->isMainFrame(), topFrame.document()->url());
+
</ins><span class="cx"> // Update cookie policy base URL as URL changes, except for subframes, which use the
</span><span class="cx"> // URL of the main frame which doesn't change when we redirect.
</span><del>- if (frameLoader()->frame().isMainFrame())
</del><ins>+ if (m_frame->isMainFrame())
</ins><span class="cx"> newRequest.setFirstPartyForCookies(newRequest.url());
</span><span class="cx">
</span><span class="cx"> // If we're fielding a redirect in response to a POST, force a load from origin, since
</span><span class="lines">@@ -536,7 +547,6 @@
</span><span class="cx"> if (newRequest.cachePolicy() == UseProtocolCachePolicy && isPostOrRedirectAfterPost(newRequest, redirectResponse))
</span><span class="cx"> newRequest.setCachePolicy(ReloadIgnoringCacheData);
</span><span class="cx">
</span><del>- Frame& topFrame = m_frame->tree().top();
</del><span class="cx"> if (&topFrame != m_frame) {
</span><span class="cx"> if (!frameLoader()->mixedContentChecker().canDisplayInsecureContent(topFrame.document()->securityOrigin(), MixedContentChecker::ContentType::Active, newRequest.url())) {
</span><span class="cx"> cancelMainResourceLoad(frameLoader()->cancelledError(newRequest));
</span></span></pre></div>
<a id="trunkSourceWebCoreloaderResourceLoadObservercpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/loader/ResourceLoadObserver.cpp (0 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/ResourceLoadObserver.cpp         (rev 0)
+++ trunk/Source/WebCore/loader/ResourceLoadObserver.cpp        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -0,0 +1,373 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * 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 "ResourceLoadObserver.h"
+
+#include "Document.h"
+#include "KeyedCoding.h"
+#include "Logging.h"
+#include "NetworkStorageSession.h"
+#include "PlatformStrategies.h"
+#include "ResourceLoadStatistics.h"
+#include "SecurityOrigin.h"
+#include "Settings.h"
+#include "SharedBuffer.h"
+#include "URL.h"
+#include <wtf/NeverDestroyed.h>
+#include <wtf/text/StringBuilder.h>
+
+#define LOG_STATISTICS_TO_FILE 0
+
+namespace WebCore {
+
+ResourceLoadObserver& ResourceLoadObserver::sharedObserver()
+{
+ static NeverDestroyed<ResourceLoadObserver> resourceLoadObserver;
+ return resourceLoadObserver;
+}
+
+void ResourceLoadObserver::logFrameNavigation(bool isRedirect, const URL& sourceURL, const URL& targetURL, bool isMainFrame, const URL& mainFrameURL)
+{
+ if (!Settings::resourceLoadStatisticsEnabled())
+ return;
+
+ if (!targetURL.isValid() || !mainFrameURL.isValid())
+ return;
+
+ auto targetHost = targetURL.host();
+ auto mainFrameHost = mainFrameURL.host();
+
+ if (targetHost.isEmpty() || mainFrameHost.isEmpty() || targetHost == mainFrameHost || targetHost == sourceURL.host())
+ return;
+
+ auto targetPrimaryDomain = primaryDomain(targetURL);
+ auto mainFramePrimaryDomain = primaryDomain(mainFrameURL);
+ auto sourcePrimaryDomain = primaryDomain(sourceURL);
+
+ if (targetPrimaryDomain == mainFramePrimaryDomain || targetPrimaryDomain == sourcePrimaryDomain)
+ return;
+
+ auto targetOrigin = SecurityOrigin::create(targetURL);
+ auto& targetStatistics = resourceStatisticsForPrimaryDomain(targetPrimaryDomain);
+
+ if (isMainFrame)
+ targetStatistics.topFrameHasBeenNavigatedToBefore = true;
+ else {
+ targetStatistics.subframeHasBeenLoadedBefore = true;
+
+ auto mainFrameOrigin = SecurityOrigin::create(mainFrameURL);
+ targetStatistics.subframeUnderTopFrameOrigins.add(mainFramePrimaryDomain);
+ }
+
+ if (isRedirect) {
+ auto& redirectingOriginResourceStatistics = resourceStatisticsForPrimaryDomain(sourcePrimaryDomain);
+
+ if (isPrevalentResource(targetPrimaryDomain))
+ redirectingOriginResourceStatistics.redirectedToOtherPrevalentResourceOrigins.add(targetPrimaryDomain);
+
+ if (isMainFrame) {
+ ++targetStatistics.topFrameHasBeenRedirectedTo;
+ ++redirectingOriginResourceStatistics.topFrameHasBeenRedirectedFrom;
+ } else {
+ ++targetStatistics.subframeHasBeenRedirectedTo;
+ ++redirectingOriginResourceStatistics.subframeHasBeenRedirectedFrom;
+ redirectingOriginResourceStatistics.subframeUniqueRedirectsTo.add(targetPrimaryDomain);
+
+ ++targetStatistics.subframeSubResourceCount;
+ }
+ } else {
+ if (sourcePrimaryDomain.isNull() || sourcePrimaryDomain.isEmpty() || sourcePrimaryDomain == "nullOrigin") {
+ if (isMainFrame)
+ ++targetStatistics.topFrameInitialLoadCount;
+ else
+ ++targetStatistics.subframeSubResourceCount;
+ } else {
+ auto& sourceOriginResourceStatistics = resourceStatisticsForPrimaryDomain(sourcePrimaryDomain);
+
+ if (isMainFrame) {
+ ++sourceOriginResourceStatistics.topFrameHasBeenNavigatedFrom;
+ ++targetStatistics.topFrameHasBeenNavigatedTo;
+ } else {
+ ++sourceOriginResourceStatistics.subframeHasBeenNavigatedFrom;
+ ++targetStatistics.subframeHasBeenNavigatedTo;
+ }
+ }
+ }
+
+ targetStatistics.checkAndSetAsPrevalentResourceIfNecessary(m_resourceStatisticsMap.size());
+}
+
+void ResourceLoadObserver::logSubresourceLoading(bool isRedirect, const URL& sourceURL, const URL& targetURL, const URL& mainFrameURL)
+{
+ if (!Settings::resourceLoadStatisticsEnabled())
+ return;
+
+ auto targetHost = targetURL.host();
+ auto mainFrameHost = mainFrameURL.host();
+
+ if (targetHost.isEmpty() || mainFrameHost.isEmpty() || targetHost == mainFrameHost || targetHost == sourceURL.host())
+ return;
+
+ auto targetPrimaryDomain = primaryDomain(targetURL);
+ auto mainFramePrimaryDomain = primaryDomain(mainFrameURL);
+ auto sourcePrimaryDomain = primaryDomain(sourceURL);
+
+ if (targetPrimaryDomain == mainFramePrimaryDomain || targetPrimaryDomain == sourcePrimaryDomain)
+ return;
+
+ auto& targetStatistics = resourceStatisticsForPrimaryDomain(targetPrimaryDomain);
+
+ auto mainFrameOrigin = SecurityOrigin::create(mainFrameURL);
+ targetStatistics.subresourceUnderTopFrameOrigins.add(mainFramePrimaryDomain);
+
+ if (isRedirect) {
+ auto& redirectingOriginStatistics = resourceStatisticsForPrimaryDomain(sourcePrimaryDomain);
+
+ if (isPrevalentResource(targetPrimaryDomain))
+ redirectingOriginStatistics.redirectedToOtherPrevalentResourceOrigins.add(targetPrimaryDomain);
+
+ ++redirectingOriginStatistics.subresourceHasBeenRedirectedFrom;
+ ++targetStatistics.subresourceHasBeenRedirectedTo;
+
+ redirectingOriginStatistics.subresourceUniqueRedirectsTo.add(targetPrimaryDomain);
+
+ ++targetStatistics.subresourceHasBeenSubresourceCount;
+
+ auto totalVisited = std::max(m_originsVisitedMap.size(), 1U);
+
+ targetStatistics.subresourceHasBeenSubresourceCountDividedByTotalNumberOfOriginsVisited = static_cast<double>(targetStatistics.subresourceHasBeenSubresourceCount) / totalVisited;
+ } else {
+ ++targetStatistics.subresourceHasBeenSubresourceCount;
+
+ auto totalVisited = std::max(m_originsVisitedMap.size(), 1U);
+
+ targetStatistics.subresourceHasBeenSubresourceCountDividedByTotalNumberOfOriginsVisited = static_cast<double>(targetStatistics.subresourceHasBeenSubresourceCount) / totalVisited;
+ }
+
+ targetStatistics.checkAndSetAsPrevalentResourceIfNecessary(m_resourceStatisticsMap.size());
+}
+
+void ResourceLoadObserver::logUserInteraction(const Document& document)
+{
+ if (!Settings::resourceLoadStatisticsEnabled())
+ return;
+
+ auto& statistics = resourceStatisticsForPrimaryDomain(primaryDomain(document.url()));
+ statistics.hadUserInteraction = true;
+}
+
+bool ResourceLoadObserver::isPrevalentResource(const String& primaryDomain) const
+{
+ auto mapEntry = m_resourceStatisticsMap.find(primaryDomain);
+ if (mapEntry == m_resourceStatisticsMap.end())
+ return false;
+
+ return mapEntry->value.isPrevalentResource;
+}
+
+ResourceLoadStatistics& ResourceLoadObserver::resourceStatisticsForPrimaryDomain(const String& primaryDomain)
+{
+ if (!m_resourceStatisticsMap.contains(primaryDomain))
+ m_resourceStatisticsMap.set(primaryDomain, ResourceLoadStatistics());
+
+ return m_resourceStatisticsMap.find(primaryDomain)->value;
+}
+
+String ResourceLoadObserver::primaryDomain(const URL& url)
+{
+ String host = url.host();
+ Vector<String> hostSplitOnDot;
+
+ host.split('.', false, hostSplitOnDot);
+
+ String primaryDomain;
+ if (host.isNull())
+ primaryDomain = "nullOrigin";
+ else if (hostSplitOnDot.size() < 3)
+ primaryDomain = host;
+ else {
+ // Skip TLD and then up to two domains smaller than 4 characters
+ int primaryDomainCutOffIndex = hostSplitOnDot.size() - 2;
+
+ // Start with TLD as a given part
+ size_t numberOfParts = 1;
+ for (; primaryDomainCutOffIndex >= 0; --primaryDomainCutOffIndex) {
+ ++numberOfParts;
+
+ // We have either a domain part that's 4 chars or longer, or 3 domain parts including TLD
+ if (hostSplitOnDot.at(primaryDomainCutOffIndex).length() >= 4 || numberOfParts >= 3)
+ break;
+ }
+
+ if (primaryDomainCutOffIndex < 0)
+ primaryDomain = host;
+ else {
+ StringBuilder builder;
+ builder.append(hostSplitOnDot.at(primaryDomainCutOffIndex));
+ for (size_t j = primaryDomainCutOffIndex + 1; j < hostSplitOnDot.size(); ++j) {
+ builder.append('.');
+ builder.append(hostSplitOnDot[j]);
+ }
+ primaryDomain = builder.toString();
+ }
+ }
+
+ return primaryDomain;
+}
+
+typedef HashMap<String, ResourceLoadStatistics>::KeyValuePairType StatisticsValue;
+
+void ResourceLoadObserver::writeDataToDisk()
+{
+ if (!Settings::resourceLoadStatisticsEnabled())
+ return;
+
+ auto encoder = KeyedEncoder::encoder();
+ encoder->encodeUInt32("originsVisited", m_resourceStatisticsMap.size());
+
+ encoder->encodeObjects("browsingStatistics", m_resourceStatisticsMap.begin(), m_resourceStatisticsMap.end(), [this](KeyedEncoder& encoderInner, const StatisticsValue& origin) {
+ origin.value.encode(encoderInner, origin.key);
+ });
+
+ writeEncoderToDisk(*encoder.get(), "full_browsing_session");
+}
+
+void ResourceLoadObserver::writeDataToDisk(const String& origin, const ResourceLoadStatistics& resourceStatistics) const
+{
+ if (!Settings::resourceLoadStatisticsEnabled())
+ return;
+
+ auto encoder = KeyedEncoder::encoder();
+ encoder->encodeUInt32("originsVisited", 1);
+
+ encoder->encodeObject(origin, resourceStatistics, [this, &origin](KeyedEncoder& encoder, const ResourceLoadStatistics& resourceStatistics) {
+ resourceStatistics.encode(encoder, origin);
+ });
+
+ String label = origin;
+ label.replace('/', '_');
+ label.replace(':', '+');
+ writeEncoderToDisk(*encoder.get(), label);
+}
+
+void ResourceLoadObserver::setStatisticsStorageDirectory(const String& path)
+{
+ m_storagePath = path;
+}
+
+String ResourceLoadObserver::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");
+}
+
+void ResourceLoadObserver::readDataFromDiskIfNeeded()
+{
+ if (!Settings::resourceLoadStatisticsEnabled())
+ return;
+
+ if (m_resourceStatisticsMap.size())
+ return;
+
+ auto decoder = createDecoderFromDisk("full_browsing_session");
+ if (!decoder)
+ return;
+
+ unsigned visitedOrigins = 0;
+ decoder->decodeUInt32("originsVisited", visitedOrigins);
+
+ Vector<String> loadedOrigins;
+ decoder->decodeObjects("browsingStatistics", loadedOrigins, [this](KeyedDecoder& decoderInner, String& origin) {
+ if (!decoderInner.decodeString("PrevalentResourceOrigin", origin))
+ return false;
+
+ ResourceLoadStatistics statistics;
+ if (!statistics.decode(decoderInner, origin))
+ return false;
+
+ m_resourceStatisticsMap.set(origin, statistics);
+
+ return true;
+ });
+
+ ASSERT(visitedOrigins == static_cast<size_t>(loadedOrigins.size()));
+}
+
+std::unique_ptr<KeyedDecoder> ResourceLoadObserver::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 ResourceLoadObserver::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 ResourceLoadObserver::statisticsForOrigin(const String& origin)
+{
+ if (!m_resourceStatisticsMap.contains(origin))
+ return emptyString();
+
+ auto& statistics = m_resourceStatisticsMap.find(origin)->value;
+ return "Statistics for " + origin + ":\n" + statistics.toString();
+}
+
+}
</ins></span></pre></div>
<a id="trunkSourceWebCoreloaderResourceLoadObserverh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/loader/ResourceLoadObserver.h (0 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/ResourceLoadObserver.h         (rev 0)
+++ trunk/Source/WebCore/loader/ResourceLoadObserver.h        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -0,0 +1,77 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * 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. ``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
+ * 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.
+ */
+
+#ifndef ResourceLoadObserver_h
+#define ResourceLoadObserver_h
+
+#include <wtf/HashMap.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class Document;
+class KeyedDecoder;
+class KeyedEncoder;
+class URL;
+
+struct ResourceLoadStatistics;
+
+class ResourceLoadObserver {
+ friend class NeverDestroyed<ResourceLoadObserver>;
+public:
+ WEBCORE_EXPORT static ResourceLoadObserver& sharedObserver();
+
+ void logFrameNavigation(bool isRedirect, const URL& sourceURL, const URL& targetURL, bool isMainFrame, const URL& mainFrameURL);
+ void logSubresourceLoading(bool isRedirect, const URL& sourceURL, const URL& targetURL, const URL& mainFrameURL);
+ void logUserInteraction(const Document&);
+
+ WEBCORE_EXPORT void writeDataToDisk();
+ WEBCORE_EXPORT void readDataFromDiskIfNeeded();
+ WEBCORE_EXPORT void setStatisticsStorageDirectory(const String&);
+
+ WEBCORE_EXPORT String statisticsForOrigin(const String&);
+
+private:
+ ResourceLoadStatistics& resourceStatisticsForPrimaryDomain(const String&);
+
+ static String primaryDomain(const URL&);
+
+ bool isPrevalentResource(const String&) const;
+
+ String persistentStoragePath(const String& label) const;
+
+ void writeDataToDisk(const String& origin, const ResourceLoadStatistics&) const;
+
+ std::unique_ptr<KeyedDecoder> createDecoderFromDisk(const String& label) const;
+ void writeEncoderToDisk(KeyedEncoder&, const String& label) const;
+
+ HashMap<String, size_t> m_originsVisitedMap;
+ HashMap<String, ResourceLoadStatistics> m_resourceStatisticsMap;
+ String m_storagePath;
+};
+
+} // namespace WebCore
+
+#endif /* ResourceLoadObserver_h */
</ins></span></pre></div>
<a id="trunkSourceWebCoreloaderResourceLoadStatisticscpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/loader/ResourceLoadStatistics.cpp (0 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/ResourceLoadStatistics.cpp         (rev 0)
+++ trunk/Source/WebCore/loader/ResourceLoadStatistics.cpp        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -0,0 +1,312 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * 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. ``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
+ * 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 "ResourceLoadStatistics.h"
+
+#include "KeyedCoding.h"
+#include <wtf/text/StringBuilder.h>
+#include <wtf/text/StringHash.h>
+
+namespace WebCore {
+
+static const unsigned minimumOriginsVisitedForPrevalenceClassification = 100;
+
+// Sub frame thresholds
+static const unsigned subframeUnderTopFrameOriginsThresholdAbsolute = 3;
+
+// Subresource thresholds
+static const unsigned subresourceUnderTopFrameOriginsThresholdAbsolute = 5;
+static const unsigned subresourceHasBeenRedirectedFromToUniqueDomainsThresholdAbsolute = 3;
+static const unsigned redirectedToOtherPrevalentResourceOriginsThresholdAbsolute = 2;
+
+bool ResourceLoadStatistics::checkAndSetAsPrevalentResourceIfNecessary(unsigned originsVisitedSoFar)
+{
+ if (originsVisitedSoFar < minimumOriginsVisitedForPrevalenceClassification || isPrevalentResource)
+ return false;
+
+ if (hasPrevalentResourceCharacteristics()) {
+ isPrevalentResource = true;
+ return true;
+ }
+
+ return false;
+}
+
+bool ResourceLoadStatistics::hasPrevalentResourceCharacteristics() const
+{
+ return subframeUnderTopFrameOrigins.size() > subframeUnderTopFrameOriginsThresholdAbsolute
+ || subresourceUnderTopFrameOrigins.size() > subresourceUnderTopFrameOriginsThresholdAbsolute
+ || subresourceUniqueRedirectsTo.size() > subresourceHasBeenRedirectedFromToUniqueDomainsThresholdAbsolute
+ || redirectedToOtherPrevalentResourceOrigins.size() > redirectedToOtherPrevalentResourceOriginsThresholdAbsolute;
+}
+
+typedef WTF::HashMap<String, unsigned, StringHash, HashTraits<String>, HashTraits<unsigned>>::KeyValuePairType ResourceLoadStatisticsValue;
+
+static void encodeHashCountedSet(KeyedEncoder& encoder, const String& label, const HashCountedSet<String>& hashCountedSet)
+{
+ if (hashCountedSet.isEmpty())
+ return;
+
+ encoder.encodeObjects(label, hashCountedSet.begin(), hashCountedSet.end(), [](KeyedEncoder& encoderInner, const ResourceLoadStatisticsValue& origin) {
+ encoderInner.encodeString("origin", origin.key);
+ encoderInner.encodeUInt32("count", origin.value);
+ });
+}
+
+void ResourceLoadStatistics::encode(KeyedEncoder& encoder, const String& origin) const
+{
+ encoder.encodeString("PrevalentResourceOrigin", origin);
+
+ // User interaction
+ encoder.encodeBool("hadUserInteraction", hadUserInteraction);
+
+ // Top frame stats
+ encoder.encodeBool("topFrameHasBeenNavigatedToBefore", topFrameHasBeenNavigatedToBefore);
+ encoder.encodeUInt32("topFrameHasBeenRedirectedTo", topFrameHasBeenRedirectedTo);
+ encoder.encodeUInt32("topFrameHasBeenRedirectedFrom", topFrameHasBeenRedirectedFrom);
+ encoder.encodeUInt32("topFrameInitialLoadCount", topFrameInitialLoadCount);
+ encoder.encodeUInt32("topFrameHasBeenNavigatedTo", topFrameHasBeenNavigatedTo);
+ encoder.encodeUInt32("topFrameHasBeenNavigatedFrom", topFrameHasBeenNavigatedFrom);
+
+ // Subframe stats
+ encoder.encodeBool("subframeHasBeenLoadedBefore", subframeHasBeenLoadedBefore);
+ encoder.encodeUInt32("subframeHasBeenRedirectedTo", subframeHasBeenRedirectedTo);
+ encoder.encodeUInt32("subframeHasBeenRedirectedFrom", subframeHasBeenRedirectedFrom);
+ encoder.encodeUInt32("subframeSubResourceCount", subframeSubResourceCount);
+ encodeHashCountedSet(encoder, "subframeUnderTopFrameOrigins", subframeUnderTopFrameOrigins);
+ encodeHashCountedSet(encoder, "subframeUniqueRedirectsTo", subframeUniqueRedirectsTo);
+ encoder.encodeUInt32("subframeHasBeenNavigatedTo", subframeHasBeenNavigatedTo);
+ encoder.encodeUInt32("subframeHasBeenNavigatedFrom", subframeHasBeenNavigatedFrom);
+
+ // Subresource stats
+ encoder.encodeUInt32("subresourceHasBeenRedirectedFrom", subresourceHasBeenRedirectedFrom);
+ encoder.encodeUInt32("subresourceHasBeenRedirectedTo", subresourceHasBeenRedirectedTo);
+ encoder.encodeUInt32("subresourceHasBeenSubresourceCount", subresourceHasBeenSubresourceCount);
+ encoder.encodeDouble("subresourceHasBeenSubresourceCountDividedByTotalNumberOfOriginsVisited", subresourceHasBeenSubresourceCountDividedByTotalNumberOfOriginsVisited);
+ encodeHashCountedSet(encoder, "subresourceUnderTopFrameOrigins", subresourceUnderTopFrameOrigins);
+ encodeHashCountedSet(encoder, "subresourceUniqueRedirectsTo", subresourceUniqueRedirectsTo);
+
+ // Prevalent Resource
+ encodeHashCountedSet(encoder, "redirectedToOtherPrevalentResourceOrigins", redirectedToOtherPrevalentResourceOrigins);
+ encoder.encodeBool("isPrevalentResource", isPrevalentResource);
+}
+
+static void decodeHashCountedSet(KeyedDecoder& decoder, const String& label, HashCountedSet<String>& hashCountedSet)
+{
+ Vector<String> ignore;
+ decoder.decodeObjects(label, ignore, [&hashCountedSet](KeyedDecoder& decoderInner, String& origin) {
+ if (!decoderInner.decodeString("origin", origin))
+ return false;
+
+ unsigned count;
+ if (!decoderInner.decodeUInt32("count", count))
+ return false;
+
+ // FIXME: Create a HashCountedSet method to do this efficiently
+ for (unsigned i = 0; i < count; ++i)
+ hashCountedSet.add(origin);
+ return true;
+ });
+}
+
+bool ResourceLoadStatistics::decode(KeyedDecoder& decoder, const String& origin)
+{
+ String storedOrigin;
+ if (!decoder.decodeString("PrevalentResourceOrigin", storedOrigin))
+ return false;
+
+ ASSERT_UNUSED(origin, storedOrigin == origin);
+
+ // User interaction
+ if (!decoder.decodeBool("hadUserInteraction", hadUserInteraction))
+ return false;
+
+ // Top frame stats
+ if (!decoder.decodeBool("topFrameHasBeenNavigatedToBefore", topFrameHasBeenNavigatedToBefore))
+ return false;
+
+ if (!decoder.decodeUInt32("topFrameHasBeenRedirectedTo", topFrameHasBeenRedirectedTo))
+ return false;
+
+ if (!decoder.decodeUInt32("topFrameHasBeenRedirectedFrom", topFrameHasBeenRedirectedFrom))
+ return false;
+
+ if (!decoder.decodeUInt32("topFrameInitialLoadCount", topFrameInitialLoadCount))
+ return false;
+
+ if (!decoder.decodeUInt32("topFrameHasBeenNavigatedTo", topFrameHasBeenNavigatedTo))
+ return false;
+
+ if (!decoder.decodeUInt32("topFrameHasBeenNavigatedFrom", topFrameHasBeenNavigatedFrom))
+ return false;
+
+ // Subframe stats
+ if (!decoder.decodeBool("subframeHasBeenLoadedBefore", subframeHasBeenLoadedBefore))
+ return false;
+
+ if (!decoder.decodeUInt32("subframeHasBeenRedirectedTo", subframeHasBeenRedirectedTo))
+ return false;
+
+ if (!decoder.decodeUInt32("subframeHasBeenRedirectedFrom", subframeHasBeenRedirectedFrom))
+ return false;
+
+ if (!decoder.decodeUInt32("subframeSubResourceCount", subframeSubResourceCount))
+ return false;
+
+ decodeHashCountedSet(decoder, "subframeUnderTopFrameOrigins", subframeUnderTopFrameOrigins);
+ decodeHashCountedSet(decoder, "subframeUniqueRedirectsTo", subframeUniqueRedirectsTo);
+
+ if (!decoder.decodeUInt32("subframeHasBeenNavigatedTo", subframeHasBeenNavigatedTo))
+ return false;
+
+ if (!decoder.decodeUInt32("subframeHasBeenNavigatedFrom", subframeHasBeenNavigatedFrom))
+ return false;
+
+ // Subresource stats
+ if (!decoder.decodeUInt32("subresourceHasBeenRedirectedFrom", subresourceHasBeenRedirectedFrom))
+ return false;
+
+ if (!decoder.decodeUInt32("subresourceHasBeenRedirectedTo", subresourceHasBeenRedirectedTo))
+ return false;
+
+ if (!decoder.decodeUInt32("subresourceHasBeenSubresourceCount", subresourceHasBeenSubresourceCount))
+ return false;
+
+ if (!decoder.decodeDouble("subresourceHasBeenSubresourceCountDividedByTotalNumberOfOriginsVisited", subresourceHasBeenSubresourceCountDividedByTotalNumberOfOriginsVisited))
+ return false;
+
+ decodeHashCountedSet(decoder, "subresourceUnderTopFrameOrigins", subresourceUnderTopFrameOrigins);
+ decodeHashCountedSet(decoder, "subresourceUniqueRedirectsTo", subresourceUniqueRedirectsTo);
+
+ // Prevalent Resource
+ decodeHashCountedSet(decoder, "redirectedToOtherPrevalentResourceOrigins", redirectedToOtherPrevalentResourceOrigins);
+
+ if (!decoder.decodeBool("isPrevalentResource", isPrevalentResource))
+ return false;
+
+ return true;
+}
+
+static void appendBoolean(StringBuilder& builder, const String& label, bool flag)
+{
+ builder.append(" ");
+ builder.append(label);
+ builder.append(": ");
+ builder.append(flag ? "Yes" : "No");
+}
+
+static void appendHashCountedSet(StringBuilder& builder, const String& label, const HashCountedSet<String>& hashCountedSet)
+{
+ if (hashCountedSet.isEmpty())
+ return;
+
+ builder.append(" ");
+ builder.append(label);
+ builder.append(":\n");
+
+ for (auto& entry : hashCountedSet) {
+ builder.append(" ");
+ builder.append(entry.key);
+ builder.append(": ");
+ builder.appendNumber(entry.value);
+ builder.append('\n');
+ }
+
+}
+
+String ResourceLoadStatistics::toString() const
+{
+ StringBuilder builder;
+
+ // User interaction
+ appendBoolean(builder, "hadUserInteraction", hadUserInteraction);
+ builder.append('\n');
+
+ // Top frame stats
+ appendBoolean(builder, "topFrameHasBeenNavigatedToBefore", topFrameHasBeenNavigatedToBefore);
+ builder.append('\n');
+ builder.append(" topFrameHasBeenRedirectedTo: ");
+ builder.appendNumber(topFrameHasBeenRedirectedTo);
+ builder.append('\n');
+ builder.append(" topFrameHasBeenRedirectedFrom: ");
+ builder.appendNumber(topFrameHasBeenRedirectedFrom);
+ builder.append('\n');
+ builder.append(" topFrameInitialLoadCount: ");
+ builder.appendNumber(topFrameInitialLoadCount);
+ builder.append('\n');
+ builder.append(" topFrameHasBeenNavigatedTo: ");
+ builder.appendNumber(topFrameHasBeenNavigatedTo);
+ builder.append('\n');
+ builder.append(" topFrameHasBeenNavigatedFrom: ");
+ builder.appendNumber(topFrameHasBeenNavigatedFrom);
+ builder.append('\n');
+
+ // Subframe stats
+ appendBoolean(builder, "subframeHasBeenLoadedBefore", subframeHasBeenLoadedBefore);
+ builder.append('\n');
+ builder.append(" subframeHasBeenRedirectedTo: ");
+ builder.appendNumber(subframeHasBeenRedirectedTo);
+ builder.append('\n');
+ builder.append(" subframeHasBeenRedirectedFrom: ");
+ builder.appendNumber(subframeHasBeenRedirectedFrom);
+ builder.append('\n');
+ builder.append(" subframeSubResourceCount: ");
+ builder.appendNumber(subframeSubResourceCount);
+ builder.append('\n');
+ appendHashCountedSet(builder, "subframeUnderTopFrameOrigins", subframeUnderTopFrameOrigins);
+ appendHashCountedSet(builder, "subframeUniqueRedirectsTo", subframeUniqueRedirectsTo);
+ builder.append(" subframeHasBeenNavigatedTo: ");
+ builder.appendNumber(subframeHasBeenNavigatedTo);
+ builder.append('\n');
+ builder.append(" subframeHasBeenNavigatedFrom: ");
+ builder.appendNumber(subframeHasBeenNavigatedFrom);
+ builder.append('\n');
+
+ // Subresource stats
+ builder.append(" subresourceHasBeenRedirectedFrom: ");
+ builder.appendNumber(subresourceHasBeenRedirectedFrom);
+ builder.append('\n');
+ builder.append(" subresourceHasBeenRedirectedTo: ");
+ builder.appendNumber(subresourceHasBeenRedirectedTo);
+ builder.append('\n');
+ builder.append(" subresourceHasBeenSubresourceCount: ");
+ builder.appendNumber(subresourceHasBeenSubresourceCount);
+ builder.append('\n');
+ builder.append(" subresourceHasBeenSubresourceCountDividedByTotalNumberOfOriginsVisited: ");
+ builder.appendNumber(subresourceHasBeenSubresourceCountDividedByTotalNumberOfOriginsVisited);
+ builder.append('\n');
+ appendHashCountedSet(builder, "subresourceUnderTopFrameOrigins", subresourceUnderTopFrameOrigins);
+ appendHashCountedSet(builder, "subresourceUniqueRedirectsTo", subresourceUniqueRedirectsTo);
+
+ // Prevalent Resource
+ appendHashCountedSet(builder, "redirectedToOtherPrevalentResourceOrigins", redirectedToOtherPrevalentResourceOrigins);
+ appendBoolean(builder, "isPrevalentResource", isPrevalentResource);
+ builder.append('\n');
+
+ return builder.toString();
+}
+
+}
</ins></span></pre></div>
<a id="trunkSourceWebCoreloaderResourceLoadStatisticsh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/loader/ResourceLoadStatistics.h (0 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/ResourceLoadStatistics.h         (rev 0)
+++ trunk/Source/WebCore/loader/ResourceLoadStatistics.h        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -0,0 +1,84 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * 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. ``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
+ * 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.
+ */
+
+#ifndef ResourceLoadStatistics_h
+#define ResourceLoadStatistics_h
+
+#include <wtf/HashCountedSet.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class KeyedDecoder;
+class KeyedEncoder;
+
+struct ResourceLoadStatistics {
+ bool checkAndSetAsPrevalentResourceIfNecessary(unsigned originsVisitedSoFar);
+
+ bool hasPrevalentRedirection() const;
+ bool hasPrevalentResourceCharacteristics() const;
+
+ void encode(KeyedEncoder&, const String& origin) const;
+ bool decode(KeyedDecoder&, const String& origin);
+
+ String toString() const;
+
+ // User interaction
+ bool hadUserInteraction { false };
+
+ // Top frame stats
+ unsigned topFrameHasBeenRedirectedTo { 0 };
+ unsigned topFrameHasBeenRedirectedFrom { 0 };
+ unsigned topFrameInitialLoadCount { 0 };
+ unsigned topFrameHasBeenNavigatedTo { 0 };
+ unsigned topFrameHasBeenNavigatedFrom { 0 };
+ bool topFrameHasBeenNavigatedToBefore { false };
+
+ // Subframe stats
+ HashCountedSet<String> subframeUnderTopFrameOrigins;
+ unsigned subframeHasBeenRedirectedTo { 0 };
+ unsigned subframeHasBeenRedirectedFrom { 0 };
+ HashCountedSet<String> subframeUniqueRedirectsTo;
+ unsigned subframeSubResourceCount { 0 };
+ unsigned subframeHasBeenNavigatedTo { 0 };
+ unsigned subframeHasBeenNavigatedFrom { 0 };
+ bool subframeHasBeenLoadedBefore { false };
+
+ // Subresource stats
+ HashCountedSet<String> subresourceUnderTopFrameOrigins;
+ unsigned subresourceHasBeenSubresourceCount { 0 };
+ double subresourceHasBeenSubresourceCountDividedByTotalNumberOfOriginsVisited { 0.0 };
+ unsigned subresourceHasBeenRedirectedFrom { 0 };
+ unsigned subresourceHasBeenRedirectedTo { 0 };
+ HashCountedSet<String> subresourceUniqueRedirectsTo;
+
+ // Prevalent resource stats
+ HashCountedSet<String> redirectedToOtherPrevalentResourceOrigins;
+ bool isPrevalentResource { false };
+};
+
+} // namespace WebCore
+
+#endif // ResourceLoadStatistics_h
</ins></span></pre></div>
<a id="trunkSourceWebCoreloaderSubresourceLoadercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/SubresourceLoader.cpp (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/SubresourceLoader.cpp        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Source/WebCore/loader/SubresourceLoader.cpp        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -40,6 +40,7 @@
</span><span class="cx"> #include "MainFrame.h"
</span><span class="cx"> #include "MemoryCache.h"
</span><span class="cx"> #include "Page.h"
</span><ins>+#include "ResourceLoadObserver.h"
</ins><span class="cx"> #include "Settings.h"
</span><span class="cx"> #include <wtf/Ref.h>
</span><span class="cx"> #include <wtf/RefCountedLeakCounter.h>
</span><span class="lines">@@ -189,6 +190,9 @@
</span><span class="cx"> ResourceLoader::willSendRequestInternal(newRequest, redirectResponse);
</span><span class="cx"> if (newRequest.isNull())
</span><span class="cx"> cancel();
</span><ins>+
+ if (Settings::resourceLoadStatisticsEnabled())
+ ResourceLoadObserver::sharedObserver().logSubresourceLoading(!redirectResponse.isNull(), redirectResponse.url(), newRequest.url(), m_frame ? m_frame->mainFrame().document()->url() : URL());
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void SubresourceLoader::didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
</span></span></pre></div>
<a id="trunkSourceWebCorepageSettingscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/Settings.cpp (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/Settings.cpp        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Source/WebCore/page/Settings.cpp        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -96,6 +96,7 @@
</span><span class="cx"> bool Settings::gShouldRewriteConstAsVar = false;
</span><span class="cx"> bool Settings::gShouldRespectPriorityInCSSAttributeSetters = false;
</span><span class="cx"> bool Settings::gLowPowerVideoAudioBufferSizeEnabled = false;
</span><ins>+bool Settings::gResourceLoadStatisticsEnabledEnabled = false;
</ins><span class="cx">
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx"> bool Settings::gNetworkDataUsageTrackingEnabled = false;
</span><span class="lines">@@ -699,6 +700,11 @@
</span><span class="cx"> gLowPowerVideoAudioBufferSizeEnabled = flag;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void Settings::setResourceLoadStatisticsEnabled(bool flag)
+{
+ gResourceLoadStatisticsEnabledEnabled = flag;
+}
+
</ins><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx"> void Settings::setAudioSessionCategoryOverride(unsigned sessionCategory)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebCorepageSettingsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/Settings.h (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/Settings.h        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Source/WebCore/page/Settings.h        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -242,6 +242,9 @@
</span><span class="cx"> static bool lowPowerVideoAudioBufferSizeEnabled() { return gLowPowerVideoAudioBufferSizeEnabled; }
</span><span class="cx"> WEBCORE_EXPORT static void setLowPowerVideoAudioBufferSizeEnabled(bool);
</span><span class="cx">
</span><ins>+ static bool resourceLoadStatisticsEnabled() { return gResourceLoadStatisticsEnabledEnabled; }
+ WEBCORE_EXPORT static void setResourceLoadStatisticsEnabled(bool);
+
</ins><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx"> WEBCORE_EXPORT static void setAudioSessionCategoryOverride(unsigned);
</span><span class="cx"> static unsigned audioSessionCategoryOverride();
</span><span class="lines">@@ -377,6 +380,7 @@
</span><span class="cx"> #endif
</span><span class="cx">
</span><span class="cx"> static bool gLowPowerVideoAudioBufferSizeEnabled;
</span><ins>+ static bool gResourceLoadStatisticsEnabledEnabled;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformLoggingh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/Logging.h (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/Logging.h        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Source/WebCore/platform/Logging.h        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -86,6 +86,7 @@
</span><span class="cx"> M(WebGL) \
</span><span class="cx"> M(WebReplay) \
</span><span class="cx"> M(WheelEventTestTriggers) \
</span><ins>+ M(ResourceLoadObserver) \
</ins><span class="cx">
</span><span class="cx"> #define DECLARE_LOG_CHANNEL(name) \
</span><span class="cx"> WEBCORE_EXPORT extern WTFLogChannel JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, name);
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.cpp (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.cpp        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Source/WebCore/testing/Internals.cpp        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -102,6 +102,7 @@
</span><span class="cx"> #include "RenderTreeAsText.h"
</span><span class="cx"> #include "RenderView.h"
</span><span class="cx"> #include "RenderedDocumentMarker.h"
</span><ins>+#include "ResourceLoadObserver.h"
</ins><span class="cx"> #include "RuntimeEnabledFeatures.h"
</span><span class="cx"> #include "SchemeRegistry.h"
</span><span class="cx"> #include "ScriptedAnimationController.h"
</span><span class="lines">@@ -3460,4 +3461,14 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx">
</span><ins>+String Internals::resourceLoadStatisticsForOrigin(String origin)
+{
+ return ResourceLoadObserver::sharedObserver().statisticsForOrigin(origin);
</ins><span class="cx"> }
</span><ins>+
+void Internals::setResourceLoadStatisticsEnabled(bool enable)
+{
+ Settings::setResourceLoadStatisticsEnabled(enable);
+}
+
+}
</ins></span></pre></div>
<a id="trunkSourceWebCoretestingInternalsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.h (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.h        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Source/WebCore/testing/Internals.h        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -462,6 +462,9 @@
</span><span class="cx"> String userVisibleString(const DOMURL*);
</span><span class="cx"> void setShowAllPlugins(bool);
</span><span class="cx">
</span><ins>+ String resourceLoadStatisticsForOrigin(String origin);
+ void setResourceLoadStatisticsEnabled(bool);
+
</ins><span class="cx"> #if ENABLE(STREAMS_API)
</span><span class="cx"> bool isReadableStreamDisturbed(ScriptState&, JSC::JSValue);
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalsidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.idl (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.idl        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Source/WebCore/testing/Internals.idl        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -433,4 +433,7 @@
</span><span class="cx"> void setShowAllPlugins(boolean showAll);
</span><span class="cx">
</span><span class="cx"> [Conditional=STREAMS_API, CallWith=ScriptState] boolean isReadableStreamDisturbed(any stream);
</span><ins>+
+ DOMString resourceLoadStatisticsForOrigin(DOMString domain);
+ void setResourceLoadStatisticsEnabled(boolean enable);
</ins><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebKitmacChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/ChangeLog (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/ChangeLog        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Source/WebKit/mac/ChangeLog        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -1,3 +1,30 @@
</span><ins>+2016-02-15 Brent Fulgham <bfulgham@apple.com>
+
+ [Mac] Gather some rudimentary statistics during resource load
+ https://bugs.webkit.org/show_bug.cgi?id=153575
+ <rdar://problem/24075254>
+
+ Reviewed by Brady Eidson.
+
+ * Misc/WebKitNSStringExtras.h:
+ * Misc/WebKitNSStringExtras.mm:
+ (+[NSString _webkit_localStorageDirectoryWithBundleIdentifier:]): Added.
+ * WebView/WebPreferenceKeysPrivate.h:
+ * WebView/WebPreferences.mm:
+ (+[WebPreferences initialize]):
+ (-[WebPreferences resourceLoadStatisticsEnabled]): Added.
+ (-[WebPreferences setResourceLoadStatisticsEnabled:]): Added.
+ * WebView/WebPreferencesPrivate.h:
+ * WebView/WebView.mm:
+ (WebKitInitializeApplicationCachePathIfNecessary):
+ (WebKitInitializeApplicationStatisticsStoragePathIfNecessary): Added.
+ (-[WebView _commonInitializationWithFrameName:groupName:]): Add call to new
+ initialization method.
+ (-[WebView _preferencesChanged:]): Track changes in the user's desire to
+ monitor resource load statistics.
+ (+[WebView _applicationWillTerminate]): Write statistics to disk (if preferences
+ say to do so.)
+
</ins><span class="cx"> 2016-02-13 Mark Lam <mark.lam@apple.com>
</span><span class="cx">
</span><span class="cx"> Add thread violation checks to WebView public APIs.
</span></span></pre></div>
<a id="trunkSourceWebKitmacMiscWebKitNSStringExtrash"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/Misc/WebKitNSStringExtras.h (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/Misc/WebKitNSStringExtras.h        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Source/WebKit/mac/Misc/WebKitNSStringExtras.h        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> #endif
</span><span class="cx">
</span><span class="cx"> extern NSString *WebKitLocalCacheDefaultsKey;
</span><ins>+extern NSString *WebKitResourceLoadStatisticsDirectoryDefaultsKey;
</ins><span class="cx">
</span><span class="cx"> @interface NSString (WebKitExtras)
</span><span class="cx">
</span><span class="lines">@@ -65,5 +66,6 @@
</span><span class="cx"> #endif
</span><span class="cx">
</span><span class="cx"> + (NSString *)_webkit_localCacheDirectoryWithBundleIdentifier:(NSString*)bundleIdentifier;
</span><ins>++ (NSString *)_webkit_localStorageDirectoryWithBundleIdentifier:(NSString*)bundleIdentifier;
</ins><span class="cx">
</span><span class="cx"> @end
</span></span></pre></div>
<a id="trunkSourceWebKitmacMiscWebKitNSStringExtrasmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/Misc/WebKitNSStringExtras.mm (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/Misc/WebKitNSStringExtras.mm        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Source/WebKit/mac/Misc/WebKitNSStringExtras.mm        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -46,6 +46,7 @@
</span><span class="cx"> #endif
</span><span class="cx">
</span><span class="cx"> NSString *WebKitLocalCacheDefaultsKey = @"WebKitLocalCache";
</span><ins>+NSString *WebKitResourceLoadStatisticsDirectoryDefaultsKey = @"WebKitResourceLoadStatisticsDirectory";
</ins><span class="cx">
</span><span class="cx"> using namespace WebCore;
</span><span class="cx">
</span><span class="lines">@@ -311,4 +312,20 @@
</span><span class="cx"> return [cacheDir stringByAppendingPathComponent:bundleIdentifier];
</span><span class="cx"> }
</span><span class="cx">
</span><ins>++ (NSString *)_webkit_localStorageDirectoryWithBundleIdentifier:(NSString*)bundleIdentifier
+{
+ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+ NSString *storageDirectory = [defaults objectForKey:WebKitResourceLoadStatisticsDirectoryDefaultsKey];
+
+ if (!storageDirectory || ![storageDirectory isKindOfClass:[NSString class]]) {
+ NSError *error;
+ NSString *storageDirectory = [[[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:&error] path];
+
+ if (!storageDirectory || ![storageDirectory isKindOfClass:[NSString class]])
+ storageDirectory = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support"];
+ }
+
+ return [storageDirectory stringByAppendingPathComponent:bundleIdentifier];
+}
+
</ins><span class="cx"> @end
</span></span></pre></div>
<a id="trunkSourceWebKitmacWebKitexp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/WebKit.exp (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/WebKit.exp        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Source/WebKit/mac/WebKit.exp        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -80,6 +80,7 @@
</span><span class="cx"> _WebKitErrorPlugInNameKey
</span><span class="cx"> _WebKitErrorPlugInPageURLStringKey
</span><span class="cx"> _WebKitLocalCacheDefaultsKey
</span><ins>+_WebKitResourceLoadStatisticsDirectoryDefaultsKey
</ins><span class="cx"> _WebLocalizedString
</span><span class="cx"> _WebPlugInAttributesKey
</span><span class="cx"> _WebPlugInBaseURLKey
</span></span></pre></div>
<a id="trunkSourceWebKitmacWebViewWebPreferenceKeysPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/WebView/WebPreferenceKeysPrivate.h (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/WebView/WebPreferenceKeysPrivate.h        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Source/WebKit/mac/WebView/WebPreferenceKeysPrivate.h        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -136,6 +136,7 @@
</span><span class="cx"> #define WebKitNotificationsEnabledKey @"WebKitNotificationsEnabled"
</span><span class="cx"> #define WebKitSuppressesIncrementalRenderingKey @"WebKitSuppressesIncrementalRendering"
</span><span class="cx"> #define WebKitSubpixelCSSOMElementMetricsEnabledPreferenceKey @"WebKitSubpixelCSSOMElementMetricsEnabled"
</span><ins>+#define WebKitResourceLoadStatisticsEnabledPreferenceKey @"WebKitResourceLoadStatisticsEnabled"
</ins><span class="cx"> #if TARGET_OS_IPHONE
</span><span class="cx"> #define WebKitAudioSessionCategoryOverride @"WebKitAudioSessionCategoryOverride"
</span><span class="cx"> #define WebKitAVKitEnabled @"WebKitAVKitEnabled"
</span></span></pre></div>
<a id="trunkSourceWebKitmacWebViewWebPreferencesmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/WebView/WebPreferences.mm (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/WebView/WebPreferences.mm        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Source/WebKit/mac/WebView/WebPreferences.mm        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -505,6 +505,7 @@
</span><span class="cx"> [NSNumber numberWithBool:NO], WebKitForceSoftwareWebGLRenderingPreferenceKey,
</span><span class="cx"> [NSNumber numberWithBool:NO], WebKitAccelerated2dCanvasEnabledPreferenceKey,
</span><span class="cx"> [NSNumber numberWithBool:NO], WebKitSubpixelCSSOMElementMetricsEnabledPreferenceKey,
</span><ins>+ [NSNumber numberWithBool:NO], WebKitResourceLoadStatisticsEnabledPreferenceKey,
</ins><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx"> [NSNumber numberWithBool:YES], WebKitFrameFlatteningEnabledPreferenceKey,
</span><span class="cx"> #else
</span><span class="lines">@@ -1829,6 +1830,16 @@
</span><span class="cx"> [self _setBoolValue:enabled forKey:WebKitDisplayListDrawingEnabledPreferenceKey];
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+- (BOOL)resourceLoadStatisticsEnabled
+{
+ return [self _boolValueForKey:WebKitResourceLoadStatisticsEnabledPreferenceKey];
+}
+
+- (void)setResourceLoadStatisticsEnabled:(BOOL)enabled
+{
+ [self _setBoolValue:enabled forKey:WebKitResourceLoadStatisticsEnabledPreferenceKey];
+}
+
</ins><span class="cx"> - (BOOL)canvasUsesAcceleratedDrawing
</span><span class="cx"> {
</span><span class="cx"> return [self _boolValueForKey:WebKitCanvasUsesAcceleratedDrawingPreferenceKey];
</span></span></pre></div>
<a id="trunkSourceWebKitmacWebViewWebPreferencesPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/WebView/WebPreferencesPrivate.h (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/WebView/WebPreferencesPrivate.h        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Source/WebKit/mac/WebView/WebPreferencesPrivate.h        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -203,6 +203,9 @@
</span><span class="cx"> - (BOOL)displayListDrawingEnabled;
</span><span class="cx"> - (void)setDisplayListDrawingEnabled:(BOOL)enabled;
</span><span class="cx">
</span><ins>+- (BOOL)resourceLoadStatisticsEnabled;
+- (void)setResourceLoadStatisticsEnabled:(BOOL)enabled;
+
</ins><span class="cx"> - (BOOL)canvasUsesAcceleratedDrawing;
</span><span class="cx"> - (void)setCanvasUsesAcceleratedDrawing:(BOOL)enabled;
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebKitmacWebViewWebViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/WebView/WebView.mm (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/WebView/WebView.mm        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Source/WebKit/mac/WebView/WebView.mm        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -168,6 +168,7 @@
</span><span class="cx"> #import <WebCore/RenderView.h>
</span><span class="cx"> #import <WebCore/RenderWidget.h>
</span><span class="cx"> #import <WebCore/ResourceHandle.h>
</span><ins>+#import <WebCore/ResourceLoadObserver.h>
</ins><span class="cx"> #import <WebCore/ResourceRequest.h>
</span><span class="cx"> #import <WebCore/RuntimeApplicationChecks.h>
</span><span class="cx"> #import <WebCore/RuntimeEnabledFeatures.h>
</span><span class="lines">@@ -746,9 +747,28 @@
</span><span class="cx"> NSString* cacheDir = [NSString _webkit_localCacheDirectoryWithBundleIdentifier:appName];
</span><span class="cx">
</span><span class="cx"> webApplicationCacheStorage().setCacheDirectory(cacheDir);
</span><ins>+
</ins><span class="cx"> initialized = YES;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+static void WebKitInitializeApplicationStatisticsStoragePathIfNecessary()
+{
+ static BOOL initialized = NO;
+ if (initialized)
+ return;
+
+ NSString *appName = [[NSBundle mainBundle] bundleIdentifier];
+ if (!appName)
+ appName = [[NSProcessInfo processInfo] processName];
+
+ ASSERT(appName);
+
+ NSString *supportDirectory = [NSString _webkit_localStorageDirectoryWithBundleIdentifier:appName];
+ ResourceLoadObserver::sharedObserver().setStatisticsStorageDirectory(supportDirectory);
+
+ initialized = YES;
+}
+
</ins><span class="cx"> static bool shouldEnableLoadDeferring()
</span><span class="cx"> {
</span><span class="cx"> return !applicationIsAdobeInstaller();
</span><span class="lines">@@ -943,6 +963,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> WebKitInitializeStorageIfNecessary();
</span><span class="cx"> WebKitInitializeApplicationCachePathIfNecessary();
</span><ins>+ WebKitInitializeApplicationStatisticsStoragePathIfNecessary();
</ins><span class="cx"> #if ENABLE(GAMEPAD)
</span><span class="cx"> WebKitInitializeGamepadProviderIfNecessary();
</span><span class="cx"> #endif
</span><span class="lines">@@ -2452,6 +2473,9 @@
</span><span class="cx">
</span><span class="cx"> settings.setHiddenPageCSSAnimationSuspensionEnabled([preferences hiddenPageCSSAnimationSuspensionEnabled]);
</span><span class="cx">
</span><ins>+ settings.setResourceLoadStatisticsEnabled([preferences resourceLoadStatisticsEnabled]);
+ ResourceLoadObserver::sharedObserver().readDataFromDiskIfNeeded();
+
</ins><span class="cx"> #if ENABLE(GAMEPAD)
</span><span class="cx"> RuntimeEnabledFeatures::sharedFeatures().setGamepadsEnabled([preferences gamepadsEnabled]);
</span><span class="cx"> #endif
</span><span class="lines">@@ -4820,6 +4844,8 @@
</span><span class="cx"> {
</span><span class="cx"> applicationIsTerminating = YES;
</span><span class="cx">
</span><ins>+ ResourceLoadObserver::sharedObserver().writeDataToDisk();
+
</ins><span class="cx"> if (fastDocumentTeardownEnabled())
</span><span class="cx"> [self closeAllWebViews];
</span><span class="cx">
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Tools/ChangeLog        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -1,3 +1,20 @@
</span><ins>+2016-02-15 Brent Fulgham <bfulgham@apple.com>
+
+ [Mac] Gather some rudimentary statistics during resource load
+ https://bugs.webkit.org/show_bug.cgi?id=153575
+ <rdar://problem/24075254>
+
+ Reviewed by Brady Eidson.
+
+ * MiniBrowser/mac/SettingsController.h:
+ * MiniBrowser/mac/SettingsController.m:
+ (-[SettingsController _populateMenu]): Add menu item for new debug flag.
+ (-[SettingsController toggleResourceLoadStatisticsEnabled:]): Added.
+ (-[SettingsController resourceLoadStatisticsEnabled]): Added.
+ * MiniBrowser/mac/WK1BrowserWindowController.m:
+ (-[WK1BrowserWindowController didChangeSettings]): React to changes in
+ users's desire to track resource load statistics.
+
</ins><span class="cx"> 2016-02-15 Csaba Osztrogonác <ossy@webkit.org>
</span><span class="cx">
</span><span class="cx"> [EFL] Update Tools/efl/install-dependencies
</span></span></pre></div>
<a id="trunkToolsDumpRenderTreemacDumpRenderTreemm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -1053,6 +1053,7 @@
</span><span class="cx"> WebDatabaseDirectoryDefaultsKey: [libraryPath stringByAppendingPathComponent:@"Databases"],
</span><span class="cx"> WebStorageDirectoryDefaultsKey: [libraryPath stringByAppendingPathComponent:@"LocalStorage"],
</span><span class="cx"> WebKitLocalCacheDefaultsKey: [libraryPath stringByAppendingPathComponent:@"LocalCache"],
</span><ins>+ WebKitResourceLoadStatisticsDirectoryDefaultsKey: [libraryPath stringByAppendingPathComponent:@"LocalStorage"],
</ins><span class="cx"> #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED > 101000
</span><span class="cx"> // This needs to also be added to argument domain because of <rdar://problem/20210002>.
</span><span class="cx"> @"AppleSystemFontOSSubversion": @(10),
</span></span></pre></div>
<a id="trunkToolsMiniBrowsermacSettingsControllerh"></a>
<div class="modfile"><h4>Modified: trunk/Tools/MiniBrowser/mac/SettingsController.h (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/MiniBrowser/mac/SettingsController.h        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Tools/MiniBrowser/mac/SettingsController.h        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2014-2016 Apple Inc. All rights reserved.
</ins><span class="cx"> *
</span><span class="cx"> * Redistribution and use in source and binary forms, with or without
</span><span class="cx"> * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -48,6 +48,7 @@
</span><span class="cx"> @property (nonatomic, readonly) BOOL subPixelCSSOMMetricsEnabled;
</span><span class="cx"> @property (nonatomic, readonly) BOOL acceleratedDrawingEnabled;
</span><span class="cx"> @property (nonatomic, readonly) BOOL displayListDrawingEnabled;
</span><ins>+@property (nonatomic, readonly) BOOL resourceLoadStatisticsEnabled;
</ins><span class="cx"> @property (nonatomic, readonly) NSString *defaultURL;
</span><span class="cx">
</span><span class="cx"> @end
</span></span></pre></div>
<a id="trunkToolsMiniBrowsermacSettingsControllerm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/MiniBrowser/mac/SettingsController.m (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/MiniBrowser/mac/SettingsController.m        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Tools/MiniBrowser/mac/SettingsController.m        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2014-2016 Apple Inc. All rights reserved.
</ins><span class="cx"> *
</span><span class="cx"> * Redistribution and use in source and binary forms, with or without
</span><span class="cx"> * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -39,6 +39,7 @@
</span><span class="cx"> static NSString * const IncrementalRenderingSuppressedPreferenceKey = @"IncrementalRenderingSuppressed";
</span><span class="cx"> static NSString * const AcceleratedDrawingEnabledPreferenceKey = @"AcceleratedDrawingEnabled";
</span><span class="cx"> static NSString * const DisplayListDrawingEnabledPreferenceKey = @"DisplayListDrawingEnabled";
</span><ins>+static NSString * const ResourceLoadStatisticsEnabledPreferenceKey = @"ResourceLoadStatisticsEnabled";
</ins><span class="cx">
</span><span class="cx"> static NSString * const NonFastScrollableRegionOverlayVisiblePreferenceKey = @"NonFastScrollableRegionOverlayVisible";
</span><span class="cx"> static NSString * const WheelEventHandlerRegionOverlayVisiblePreferenceKey = @"WheelEventHandlerRegionOverlayVisible";
</span><span class="lines">@@ -140,6 +141,7 @@
</span><span class="cx">
</span><span class="cx"> [self _addHeaderWithTitle:@"WebKit1-only Settings"];
</span><span class="cx"> [self _addItemWithTitle:@"Enable Subpixel CSSOM Metrics" action:@selector(toggleEnableSubPixelCSSOMMetrics:) indented:YES];
</span><ins>+ [self _addItemWithTitle:@"Enable Resource Load Statistics" action:@selector(toggleResourceLoadStatisticsEnabled:) indented:NO];
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> - (BOOL)validateMenuItem:(NSMenuItem *)menuItem
</span><span class="lines">@@ -162,6 +164,8 @@
</span><span class="cx"> [menuItem setState:[self acceleratedDrawingEnabled] ? NSOnState : NSOffState];
</span><span class="cx"> else if (action == @selector(toggleDisplayListDrawingEnabled:))
</span><span class="cx"> [menuItem setState:[self displayListDrawingEnabled] ? NSOnState : NSOffState];
</span><ins>+ else if (action == @selector(toggleResourceLoadStatisticsEnabled:))
+ [menuItem setState:[self resourceLoadStatisticsEnabled] ? NSOnState : NSOffState];
</ins><span class="cx"> else if (action == @selector(toggleShowTiledScrollingIndicator:))
</span><span class="cx"> [menuItem setState:[self tiledScrollingIndicatorVisible] ? NSOnState : NSOffState];
</span><span class="cx"> else if (action == @selector(toggleShowResourceUsageOverlay:))
</span><span class="lines">@@ -316,6 +320,16 @@
</span><span class="cx"> return [[NSUserDefaults standardUserDefaults] boolForKey:ResourceUsageOverlayVisiblePreferenceKey];
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+- (void)toggleResourceLoadStatisticsEnabled:(id)sender
+{
+ [self _toggleBooleanDefault:ResourceLoadStatisticsEnabledPreferenceKey];
+}
+
+- (BOOL)resourceLoadStatisticsEnabled
+{
+ return [[NSUserDefaults standardUserDefaults] boolForKey:ResourceLoadStatisticsEnabledPreferenceKey];
+}
+
</ins><span class="cx"> - (void)toggleEnableSubPixelCSSOMMetrics:(id)sender
</span><span class="cx"> {
</span><span class="cx"> [self _toggleBooleanDefault:EnableSubPixelCSSOMMetricsPreferenceKey];
</span></span></pre></div>
<a id="trunkToolsMiniBrowsermacWK1BrowserWindowControllerm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/MiniBrowser/mac/WK1BrowserWindowController.m (196621 => 196622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/MiniBrowser/mac/WK1BrowserWindowController.m        2016-02-16 05:32:56 UTC (rev 196621)
+++ trunk/Tools/MiniBrowser/mac/WK1BrowserWindowController.m        2016-02-16 05:36:38 UTC (rev 196622)
</span><span class="lines">@@ -260,6 +260,7 @@
</span><span class="cx"> [[WebPreferences standardPreferences] setShowRepaintCounter:settings.layerBordersVisible];
</span><span class="cx"> [[WebPreferences standardPreferences] setSuppressesIncrementalRendering:settings.incrementalRenderingSuppressed];
</span><span class="cx"> [[WebPreferences standardPreferences] setAcceleratedDrawingEnabled:settings.acceleratedDrawingEnabled];
</span><ins>+ [[WebPreferences standardPreferences] setResourceLoadStatisticsEnabled:settings.resourceLoadStatisticsEnabled];
</ins><span class="cx">
</span><span class="cx"> BOOL useTransparentWindows = settings.useTransparentWindows;
</span><span class="cx"> if (useTransparentWindows != !self.window.isOpaque) {
</span></span></pre>
</div>
</div>
</body>
</html>