<!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
&lt;rdar://problem/24075254&gt;

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  &lt;bfulgham@apple.com&gt;
+
+        [Mac] Gather some rudimentary statistics during resource load 
+        https://bugs.webkit.org/show_bug.cgi?id=153575
+        &lt;rdar://problem/24075254&gt;
+
+        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  &lt;cdumez@apple.com&gt;
</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>+&lt;?php
+header('cache-control: no-store');
+
+$location=$_COOKIE['location'];
+if ($location!=&quot;&quot;) {
+    header('Status: 303 See Other');
+    header('Location: '.$location);
+    exit;
+}
+?&gt;
+
+&lt;script src='redirect-updates-history-item.js'&gt;&lt;/script&gt;
+&lt;script&gt;
+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
+        // &quot;location&quot; cookie so that when we reload this page, we actually
+        // redirect to the value of the &quot;location&quot; cookie.
+        //
+        // This loads the &quot;goback&quot; 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 &quot;same document navigation&quot; as would normally
+        // be done when navigating back after a pushState.
+
+        if (sessionStorage.done) {
+            location.replace(&quot;redirect-updates-history-item-done-statistics.html&quot;); 
+        } else {
+            history.pushState(null, null, &quot;&quot;);
+
+            setLocationCookie(&quot;redirect-on-reload-updates-history-item-goback.html&quot;);
+            location.reload();
+        }
+    }, 0);
+}
+&lt;/script&gt;
+
+&lt;p&gt;redirect-on-reload-updates-history-item.php: You should not see this text!&lt;/p&gt;
</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>+&lt;script src=&quot;redirect-updates-history-item.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+clearLocationCookie();
+
+onload = function() {
+    if (window.testRunner) {
+        testRunner.notifyDone();
+        log(&quot;Dumping Resource Load Statistics:&quot;);
+        log(window.internals.resourceLoadStatisticsForOrigin(&quot;127.0.0.1&quot;));
+    }
+}
+&lt;/script&gt;
+&lt;body&gt;PASS&lt;/body&gt;
</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-&gt;  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>+&lt;script src=&quot;resources/redirect-updates-history-item.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+
+// 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);
+}
+&lt;/script&gt;
</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  &lt;bfulgham@apple.com&gt;
+
+        [Mac] Gather some rudimentary statistics during resource load 
+        https://bugs.webkit.org/show_bug.cgi?id=153575
+        &lt;rdar://problem/24075254&gt;
+
+        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  &lt;cdumez@apple.com&gt;
</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 = &quot;&lt;group&gt;&quot;; tabWidth = 8; usesTabs = 0; };
</span><span class="cx">                 65FEA86809833ADE00BED4AB /* Page.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Page.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 6B3480920EEF50D400AC1B41 /* NativeImagePtr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = NativeImagePtr.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                6B693A2D1C51A82E00B03BEF /* ResourceLoadObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResourceLoadObserver.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                6B693A331C51A95D00B03BEF /* ResourceLoadObserver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ResourceLoadObserver.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 6C4C96DA1AD4483500365A50 /* JSReadableStreamController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSReadableStreamController.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 6C4C96DB1AD4483500365A50 /* JSReadableStreamController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSReadableStreamController.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 6C638893A96CCEE50C8C946C /* CachedResourceRequestInitiators.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CachedResourceRequestInitiators.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</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 = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 7A74ECB9101839A600BF939E /* InspectorDOMStorageAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorDOMStorageAgent.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 7A74ECBC101839DA00BF939E /* JSInspectorFrontendHostCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSInspectorFrontendHostCustom.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                7A929CA11C598378004DF226 /* ResourceLoadStatistics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ResourceLoadStatistics.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                7A929CA21C598378004DF226 /* ResourceLoadStatistics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResourceLoadStatistics.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 7A93868218DCC14500B8263D /* VTTScanner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VTTScanner.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 7A93868318DCC14500B8263D /* VTTScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VTTScanner.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 7AA3A695194A64E7001CBD24 /* TileController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TileController.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</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 &quot;RenderLayerCompositor.h&quot;
</span><span class="cx"> #include &quot;RenderView.h&quot;
</span><span class="cx"> #include &quot;RenderWidget.h&quot;
</span><ins>+#include &quot;ResourceLoadObserver.h&quot;
</ins><span class="cx"> #include &quot;RuntimeEnabledFeatures.h&quot;
</span><span class="cx"> #include &quot;SVGDocumentExtensions.h&quot;
</span><span class="cx"> #include &quot;SVGElement.h&quot;
</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 &quot;PolicyChecker.h&quot;
</span><span class="cx"> #include &quot;ProgressTracker.h&quot;
</span><span class="cx"> #include &quot;ResourceHandle.h&quot;
</span><ins>+#include &quot;ResourceLoadObserver.h&quot;
</ins><span class="cx"> #include &quot;SchemeRegistry.h&quot;
</span><span class="cx"> #include &quot;ScriptController.h&quot;
</span><span class="cx"> #include &quot;SecurityPolicy.h&quot;
</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&amp; topFrame = m_frame-&gt;tree().top();
+
+    ASSERT(m_frame-&gt;document());
+    ASSERT(topFrame.document());
+
+    if (Settings::resourceLoadStatisticsEnabled())
+        ResourceLoadObserver::sharedObserver().logFrameNavigation(!redirectResponse.isNull(), m_frame-&gt;document()-&gt;url(), newRequest.url(), m_frame-&gt;isMainFrame(), topFrame.document()-&gt;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()-&gt;frame().isMainFrame())
</del><ins>+    if (m_frame-&gt;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 &amp;&amp; isPostOrRedirectAfterPost(newRequest, redirectResponse))
</span><span class="cx">         newRequest.setCachePolicy(ReloadIgnoringCacheData);
</span><span class="cx"> 
</span><del>-    Frame&amp; topFrame = m_frame-&gt;tree().top();
</del><span class="cx">     if (&amp;topFrame != m_frame) {
</span><span class="cx">         if (!frameLoader()-&gt;mixedContentChecker().canDisplayInsecureContent(topFrame.document()-&gt;securityOrigin(), MixedContentChecker::ContentType::Active, newRequest.url())) {
</span><span class="cx">             cancelMainResourceLoad(frameLoader()-&gt;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 &quot;config.h&quot;
+#include &quot;ResourceLoadObserver.h&quot;
+
+#include &quot;Document.h&quot;
+#include &quot;KeyedCoding.h&quot;
+#include &quot;Logging.h&quot;
+#include &quot;NetworkStorageSession.h&quot;
+#include &quot;PlatformStrategies.h&quot;
+#include &quot;ResourceLoadStatistics.h&quot;
+#include &quot;SecurityOrigin.h&quot;
+#include &quot;Settings.h&quot;
+#include &quot;SharedBuffer.h&quot;
+#include &quot;URL.h&quot;
+#include &lt;wtf/NeverDestroyed.h&gt;
+#include &lt;wtf/text/StringBuilder.h&gt;
+
+#define LOG_STATISTICS_TO_FILE 0
+
+namespace WebCore {
+
+ResourceLoadObserver&amp; ResourceLoadObserver::sharedObserver()
+{
+    static NeverDestroyed&lt;ResourceLoadObserver&gt; resourceLoadObserver;
+    return resourceLoadObserver;
+}
+    
+void ResourceLoadObserver::logFrameNavigation(bool isRedirect, const URL&amp; sourceURL, const URL&amp; targetURL, bool isMainFrame, const URL&amp; 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&amp; targetStatistics = resourceStatisticsForPrimaryDomain(targetPrimaryDomain);
+    
+    if (isMainFrame)
+        targetStatistics.topFrameHasBeenNavigatedToBefore = true;
+    else {
+        targetStatistics.subframeHasBeenLoadedBefore = true;
+
+        auto mainFrameOrigin = SecurityOrigin::create(mainFrameURL);
+        targetStatistics.subframeUnderTopFrameOrigins.add(mainFramePrimaryDomain);
+    }
+    
+    if (isRedirect) {
+        auto&amp; 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 == &quot;nullOrigin&quot;) {
+            if (isMainFrame)
+                ++targetStatistics.topFrameInitialLoadCount;
+            else
+                ++targetStatistics.subframeSubResourceCount;
+        } else {
+            auto&amp; 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&amp; sourceURL, const URL&amp; targetURL, const URL&amp; 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&amp; targetStatistics = resourceStatisticsForPrimaryDomain(targetPrimaryDomain);
+
+    auto mainFrameOrigin = SecurityOrigin::create(mainFrameURL);
+    targetStatistics.subresourceUnderTopFrameOrigins.add(mainFramePrimaryDomain);
+
+    if (isRedirect) {
+        auto&amp; 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&lt;double&gt;(targetStatistics.subresourceHasBeenSubresourceCount) / totalVisited;
+    } else {
+        ++targetStatistics.subresourceHasBeenSubresourceCount;
+
+        auto totalVisited = std::max(m_originsVisitedMap.size(), 1U);
+        
+        targetStatistics.subresourceHasBeenSubresourceCountDividedByTotalNumberOfOriginsVisited = static_cast&lt;double&gt;(targetStatistics.subresourceHasBeenSubresourceCount) / totalVisited;
+    }
+    
+    targetStatistics.checkAndSetAsPrevalentResourceIfNecessary(m_resourceStatisticsMap.size());
+}
+    
+void ResourceLoadObserver::logUserInteraction(const Document&amp; document)
+{
+    if (!Settings::resourceLoadStatisticsEnabled())
+        return;
+
+    auto&amp; statistics = resourceStatisticsForPrimaryDomain(primaryDomain(document.url()));
+    statistics.hadUserInteraction = true;
+}
+    
+bool ResourceLoadObserver::isPrevalentResource(const String&amp; primaryDomain) const
+{
+    auto mapEntry = m_resourceStatisticsMap.find(primaryDomain);
+    if (mapEntry == m_resourceStatisticsMap.end())
+        return false;
+
+    return mapEntry-&gt;value.isPrevalentResource;
+}
+    
+ResourceLoadStatistics&amp; ResourceLoadObserver::resourceStatisticsForPrimaryDomain(const String&amp; primaryDomain)
+{
+    if (!m_resourceStatisticsMap.contains(primaryDomain))
+        m_resourceStatisticsMap.set(primaryDomain, ResourceLoadStatistics());
+    
+    return m_resourceStatisticsMap.find(primaryDomain)-&gt;value;
+}
+
+String ResourceLoadObserver::primaryDomain(const URL&amp; url)
+{
+    String host = url.host();
+    Vector&lt;String&gt; hostSplitOnDot;
+    
+    host.split('.', false, hostSplitOnDot);
+
+    String primaryDomain;
+    if (host.isNull())
+        primaryDomain = &quot;nullOrigin&quot;;
+    else if (hostSplitOnDot.size() &lt; 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 &gt;= 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() &gt;= 4 || numberOfParts &gt;= 3)
+                break;
+        }
+
+        if (primaryDomainCutOffIndex &lt; 0)
+            primaryDomain = host;
+        else {
+            StringBuilder builder;
+            builder.append(hostSplitOnDot.at(primaryDomainCutOffIndex));
+            for (size_t j = primaryDomainCutOffIndex + 1; j &lt; hostSplitOnDot.size(); ++j) {
+                builder.append('.');
+                builder.append(hostSplitOnDot[j]);
+            }
+            primaryDomain = builder.toString();
+        }
+    }
+
+    return primaryDomain;
+}
+
+typedef HashMap&lt;String, ResourceLoadStatistics&gt;::KeyValuePairType StatisticsValue;
+
+void ResourceLoadObserver::writeDataToDisk()
+{
+    if (!Settings::resourceLoadStatisticsEnabled())
+        return;
+    
+    auto encoder = KeyedEncoder::encoder();
+    encoder-&gt;encodeUInt32(&quot;originsVisited&quot;, m_resourceStatisticsMap.size());
+    
+    encoder-&gt;encodeObjects(&quot;browsingStatistics&quot;, m_resourceStatisticsMap.begin(), m_resourceStatisticsMap.end(), [this](KeyedEncoder&amp; encoderInner, const StatisticsValue&amp; origin) {
+        origin.value.encode(encoderInner, origin.key);
+    });
+    
+    writeEncoderToDisk(*encoder.get(), &quot;full_browsing_session&quot;);
+}
+
+void ResourceLoadObserver::writeDataToDisk(const String&amp; origin, const ResourceLoadStatistics&amp; resourceStatistics) const
+{
+    if (!Settings::resourceLoadStatisticsEnabled())
+        return;
+
+    auto encoder = KeyedEncoder::encoder();
+    encoder-&gt;encodeUInt32(&quot;originsVisited&quot;, 1);
+    
+    encoder-&gt;encodeObject(origin, resourceStatistics, [this, &amp;origin](KeyedEncoder&amp; encoder, const ResourceLoadStatistics&amp; resourceStatistics) {
+        resourceStatistics.encode(encoder, origin);
+    });
+    
+    String label = origin;
+    label.replace('/', '_');
+    label.replace(':', '+');
+    writeEncoderToDisk(*encoder.get(), label);
+}
+
+void ResourceLoadObserver::setStatisticsStorageDirectory(const String&amp; path)
+{
+    m_storagePath = path;
+}
+
+String ResourceLoadObserver::persistentStoragePath(const String&amp; label) const
+{
+    if (m_storagePath.isEmpty())
+        return emptyString();
+
+    // TODO Decide what to call this file
+    return pathByAppendingComponent(m_storagePath, label + &quot;_resourceLog.plist&quot;);
+}
+
+void ResourceLoadObserver::readDataFromDiskIfNeeded()
+{
+    if (!Settings::resourceLoadStatisticsEnabled())
+        return;
+
+    if (m_resourceStatisticsMap.size())
+        return;
+
+    auto decoder = createDecoderFromDisk(&quot;full_browsing_session&quot;);
+    if (!decoder)
+        return;
+
+    unsigned visitedOrigins = 0;
+    decoder-&gt;decodeUInt32(&quot;originsVisited&quot;, visitedOrigins);
+        
+    Vector&lt;String&gt; loadedOrigins;
+    decoder-&gt;decodeObjects(&quot;browsingStatistics&quot;, loadedOrigins, [this](KeyedDecoder&amp; decoderInner, String&amp; origin) {
+        if (!decoderInner.decodeString(&quot;PrevalentResourceOrigin&quot;, origin))
+            return false;
+
+        ResourceLoadStatistics statistics;
+        if (!statistics.decode(decoderInner, origin))
+            return false;
+
+        m_resourceStatisticsMap.set(origin, statistics);
+            
+        return true;
+    });
+        
+    ASSERT(visitedOrigins == static_cast&lt;size_t&gt;(loadedOrigins.size()));
+}
+
+std::unique_ptr&lt;KeyedDecoder&gt; ResourceLoadObserver::createDecoderFromDisk(const String&amp; label) const
+{
+    String resourceLog = persistentStoragePath(label);
+    if (resourceLog.isEmpty())
+        return nullptr;
+    
+    RefPtr&lt;SharedBuffer&gt; rawData = SharedBuffer::createWithContentsOfFile(resourceLog);
+    if (!rawData)
+        return nullptr;
+    
+    return KeyedDecoder::decoder(reinterpret_cast&lt;const uint8_t*&gt;(rawData-&gt;data()), rawData-&gt;size());
+}
+    
+void ResourceLoadObserver::writeEncoderToDisk(KeyedEncoder&amp; encoder, const String&amp; label) const
+{
+#if LOG_STATISTICS_TO_FILE
+    RefPtr&lt;SharedBuffer&gt; 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-&gt;data(), rawData-&gt;size());
+    closeFile(handle);
+    
+    if (writtenBytes != static_cast&lt;int64_t&gt;(rawData-&gt;size()))
+        WTFLogAlways(&quot;ResourceLoadStatistics: We only wrote %lld out of %d bytes to disk&quot;, writtenBytes, rawData-&gt;size());
+#else
+    UNUSED_PARAM(encoder);
+    UNUSED_PARAM(label);
+#endif
+}
+
+String ResourceLoadObserver::statisticsForOrigin(const String&amp; origin)
+{
+    if (!m_resourceStatisticsMap.contains(origin))
+        return emptyString();
+    
+    auto&amp; statistics = m_resourceStatisticsMap.find(origin)-&gt;value;
+    return &quot;Statistics for &quot; + origin + &quot;:\n&quot; + 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 &lt;wtf/HashMap.h&gt;
+#include &lt;wtf/text/WTFString.h&gt;
+
+namespace WebCore {
+
+class Document;
+class KeyedDecoder;
+class KeyedEncoder;
+class URL;
+
+struct ResourceLoadStatistics;
+
+class ResourceLoadObserver {
+    friend class NeverDestroyed&lt;ResourceLoadObserver&gt;;
+public:
+    WEBCORE_EXPORT static ResourceLoadObserver&amp; sharedObserver();
+    
+    void logFrameNavigation(bool isRedirect, const URL&amp; sourceURL, const URL&amp; targetURL, bool isMainFrame, const URL&amp; mainFrameURL);
+    void logSubresourceLoading(bool isRedirect, const URL&amp; sourceURL, const URL&amp; targetURL, const URL&amp; mainFrameURL);
+    void logUserInteraction(const Document&amp;);
+
+    WEBCORE_EXPORT void writeDataToDisk();
+    WEBCORE_EXPORT void readDataFromDiskIfNeeded();
+    WEBCORE_EXPORT void setStatisticsStorageDirectory(const String&amp;);
+
+    WEBCORE_EXPORT String statisticsForOrigin(const String&amp;);
+
+private:
+    ResourceLoadStatistics&amp; resourceStatisticsForPrimaryDomain(const String&amp;);
+    
+    static String primaryDomain(const URL&amp;);
+
+    bool isPrevalentResource(const String&amp;) const;
+
+    String persistentStoragePath(const String&amp; label) const;
+
+    void writeDataToDisk(const String&amp; origin, const ResourceLoadStatistics&amp;) const;
+
+    std::unique_ptr&lt;KeyedDecoder&gt; createDecoderFromDisk(const String&amp; label) const;
+    void writeEncoderToDisk(KeyedEncoder&amp;, const String&amp; label) const;
+
+    HashMap&lt;String, size_t&gt; m_originsVisitedMap;
+    HashMap&lt;String, ResourceLoadStatistics&gt; 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 &quot;config.h&quot;
+#include &quot;ResourceLoadStatistics.h&quot;
+
+#include &quot;KeyedCoding.h&quot;
+#include &lt;wtf/text/StringBuilder.h&gt;
+#include &lt;wtf/text/StringHash.h&gt;
+
+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 &lt; minimumOriginsVisitedForPrevalenceClassification || isPrevalentResource)
+        return false;
+
+    if (hasPrevalentResourceCharacteristics()) {
+        isPrevalentResource = true;
+        return true;
+    }
+
+    return false;
+}
+
+bool ResourceLoadStatistics::hasPrevalentResourceCharacteristics() const
+{
+    return subframeUnderTopFrameOrigins.size() &gt; subframeUnderTopFrameOriginsThresholdAbsolute
+        || subresourceUnderTopFrameOrigins.size() &gt; subresourceUnderTopFrameOriginsThresholdAbsolute
+        || subresourceUniqueRedirectsTo.size() &gt; subresourceHasBeenRedirectedFromToUniqueDomainsThresholdAbsolute
+        || redirectedToOtherPrevalentResourceOrigins.size() &gt; redirectedToOtherPrevalentResourceOriginsThresholdAbsolute;
+}
+
+typedef WTF::HashMap&lt;String, unsigned, StringHash, HashTraits&lt;String&gt;, HashTraits&lt;unsigned&gt;&gt;::KeyValuePairType ResourceLoadStatisticsValue;
+
+static void encodeHashCountedSet(KeyedEncoder&amp; encoder, const String&amp; label, const HashCountedSet&lt;String&gt;&amp; hashCountedSet)
+{
+    if (hashCountedSet.isEmpty())
+        return;
+
+    encoder.encodeObjects(label, hashCountedSet.begin(), hashCountedSet.end(), [](KeyedEncoder&amp; encoderInner, const ResourceLoadStatisticsValue&amp; origin) {
+        encoderInner.encodeString(&quot;origin&quot;, origin.key);
+        encoderInner.encodeUInt32(&quot;count&quot;, origin.value);
+    });
+}
+
+void ResourceLoadStatistics::encode(KeyedEncoder&amp; encoder, const String&amp; origin) const
+{
+    encoder.encodeString(&quot;PrevalentResourceOrigin&quot;, origin);
+    
+    // User interaction
+    encoder.encodeBool(&quot;hadUserInteraction&quot;, hadUserInteraction);
+    
+    // Top frame stats
+    encoder.encodeBool(&quot;topFrameHasBeenNavigatedToBefore&quot;, topFrameHasBeenNavigatedToBefore);
+    encoder.encodeUInt32(&quot;topFrameHasBeenRedirectedTo&quot;, topFrameHasBeenRedirectedTo);
+    encoder.encodeUInt32(&quot;topFrameHasBeenRedirectedFrom&quot;, topFrameHasBeenRedirectedFrom);
+    encoder.encodeUInt32(&quot;topFrameInitialLoadCount&quot;, topFrameInitialLoadCount);
+    encoder.encodeUInt32(&quot;topFrameHasBeenNavigatedTo&quot;, topFrameHasBeenNavigatedTo);
+    encoder.encodeUInt32(&quot;topFrameHasBeenNavigatedFrom&quot;, topFrameHasBeenNavigatedFrom);
+    
+    // Subframe stats
+    encoder.encodeBool(&quot;subframeHasBeenLoadedBefore&quot;, subframeHasBeenLoadedBefore);
+    encoder.encodeUInt32(&quot;subframeHasBeenRedirectedTo&quot;, subframeHasBeenRedirectedTo);
+    encoder.encodeUInt32(&quot;subframeHasBeenRedirectedFrom&quot;, subframeHasBeenRedirectedFrom);
+    encoder.encodeUInt32(&quot;subframeSubResourceCount&quot;, subframeSubResourceCount);
+    encodeHashCountedSet(encoder, &quot;subframeUnderTopFrameOrigins&quot;, subframeUnderTopFrameOrigins);
+    encodeHashCountedSet(encoder, &quot;subframeUniqueRedirectsTo&quot;, subframeUniqueRedirectsTo);
+    encoder.encodeUInt32(&quot;subframeHasBeenNavigatedTo&quot;, subframeHasBeenNavigatedTo);
+    encoder.encodeUInt32(&quot;subframeHasBeenNavigatedFrom&quot;, subframeHasBeenNavigatedFrom);
+    
+    // Subresource stats
+    encoder.encodeUInt32(&quot;subresourceHasBeenRedirectedFrom&quot;, subresourceHasBeenRedirectedFrom);
+    encoder.encodeUInt32(&quot;subresourceHasBeenRedirectedTo&quot;, subresourceHasBeenRedirectedTo);
+    encoder.encodeUInt32(&quot;subresourceHasBeenSubresourceCount&quot;, subresourceHasBeenSubresourceCount);
+    encoder.encodeDouble(&quot;subresourceHasBeenSubresourceCountDividedByTotalNumberOfOriginsVisited&quot;, subresourceHasBeenSubresourceCountDividedByTotalNumberOfOriginsVisited);
+    encodeHashCountedSet(encoder, &quot;subresourceUnderTopFrameOrigins&quot;, subresourceUnderTopFrameOrigins);
+    encodeHashCountedSet(encoder, &quot;subresourceUniqueRedirectsTo&quot;, subresourceUniqueRedirectsTo);
+    
+    // Prevalent Resource
+    encodeHashCountedSet(encoder, &quot;redirectedToOtherPrevalentResourceOrigins&quot;, redirectedToOtherPrevalentResourceOrigins);
+    encoder.encodeBool(&quot;isPrevalentResource&quot;, isPrevalentResource);
+}
+
+static void decodeHashCountedSet(KeyedDecoder&amp; decoder, const String&amp; label, HashCountedSet&lt;String&gt;&amp; hashCountedSet)
+{
+    Vector&lt;String&gt; ignore;
+    decoder.decodeObjects(label, ignore, [&amp;hashCountedSet](KeyedDecoder&amp; decoderInner, String&amp; origin) {
+        if (!decoderInner.decodeString(&quot;origin&quot;, origin))
+            return false;
+        
+        unsigned count;
+        if (!decoderInner.decodeUInt32(&quot;count&quot;, count))
+            return false;
+        
+        // FIXME: Create a HashCountedSet method to do this efficiently
+        for (unsigned i = 0; i &lt; count; ++i)
+            hashCountedSet.add(origin);
+        return true;
+    });
+}
+
+bool ResourceLoadStatistics::decode(KeyedDecoder&amp; decoder, const String&amp; origin)
+{
+    String storedOrigin;
+    if (!decoder.decodeString(&quot;PrevalentResourceOrigin&quot;, storedOrigin))
+        return false;
+    
+    ASSERT_UNUSED(origin, storedOrigin == origin);
+    
+    // User interaction
+    if (!decoder.decodeBool(&quot;hadUserInteraction&quot;, hadUserInteraction))
+        return false;
+    
+    // Top frame stats
+    if (!decoder.decodeBool(&quot;topFrameHasBeenNavigatedToBefore&quot;, topFrameHasBeenNavigatedToBefore))
+        return false;
+    
+    if (!decoder.decodeUInt32(&quot;topFrameHasBeenRedirectedTo&quot;, topFrameHasBeenRedirectedTo))
+        return false;
+    
+    if (!decoder.decodeUInt32(&quot;topFrameHasBeenRedirectedFrom&quot;, topFrameHasBeenRedirectedFrom))
+        return false;
+    
+    if (!decoder.decodeUInt32(&quot;topFrameInitialLoadCount&quot;, topFrameInitialLoadCount))
+        return false;
+    
+    if (!decoder.decodeUInt32(&quot;topFrameHasBeenNavigatedTo&quot;, topFrameHasBeenNavigatedTo))
+        return false;
+    
+    if (!decoder.decodeUInt32(&quot;topFrameHasBeenNavigatedFrom&quot;, topFrameHasBeenNavigatedFrom))
+        return false;
+    
+    // Subframe stats
+    if (!decoder.decodeBool(&quot;subframeHasBeenLoadedBefore&quot;, subframeHasBeenLoadedBefore))
+        return false;
+    
+    if (!decoder.decodeUInt32(&quot;subframeHasBeenRedirectedTo&quot;, subframeHasBeenRedirectedTo))
+        return false;
+    
+    if (!decoder.decodeUInt32(&quot;subframeHasBeenRedirectedFrom&quot;, subframeHasBeenRedirectedFrom))
+        return false;
+    
+    if (!decoder.decodeUInt32(&quot;subframeSubResourceCount&quot;, subframeSubResourceCount))
+        return false;
+
+    decodeHashCountedSet(decoder, &quot;subframeUnderTopFrameOrigins&quot;, subframeUnderTopFrameOrigins);
+    decodeHashCountedSet(decoder, &quot;subframeUniqueRedirectsTo&quot;, subframeUniqueRedirectsTo);
+    
+    if (!decoder.decodeUInt32(&quot;subframeHasBeenNavigatedTo&quot;, subframeHasBeenNavigatedTo))
+        return false;
+    
+    if (!decoder.decodeUInt32(&quot;subframeHasBeenNavigatedFrom&quot;, subframeHasBeenNavigatedFrom))
+        return false;
+    
+    // Subresource stats
+    if (!decoder.decodeUInt32(&quot;subresourceHasBeenRedirectedFrom&quot;, subresourceHasBeenRedirectedFrom))
+        return false;
+    
+    if (!decoder.decodeUInt32(&quot;subresourceHasBeenRedirectedTo&quot;, subresourceHasBeenRedirectedTo))
+        return false;
+    
+    if (!decoder.decodeUInt32(&quot;subresourceHasBeenSubresourceCount&quot;, subresourceHasBeenSubresourceCount))
+        return false;
+    
+    if (!decoder.decodeDouble(&quot;subresourceHasBeenSubresourceCountDividedByTotalNumberOfOriginsVisited&quot;, subresourceHasBeenSubresourceCountDividedByTotalNumberOfOriginsVisited))
+        return false;
+
+    decodeHashCountedSet(decoder, &quot;subresourceUnderTopFrameOrigins&quot;, subresourceUnderTopFrameOrigins);
+    decodeHashCountedSet(decoder, &quot;subresourceUniqueRedirectsTo&quot;, subresourceUniqueRedirectsTo);
+    
+    // Prevalent Resource
+    decodeHashCountedSet(decoder, &quot;redirectedToOtherPrevalentResourceOrigins&quot;, redirectedToOtherPrevalentResourceOrigins);
+    
+    if (!decoder.decodeBool(&quot;isPrevalentResource&quot;, isPrevalentResource))
+        return false;
+    
+    return true;
+}
+
+static void appendBoolean(StringBuilder&amp; builder, const String&amp; label, bool flag)
+{
+    builder.append(&quot;    &quot;);
+    builder.append(label);
+    builder.append(&quot;: &quot;);
+    builder.append(flag ? &quot;Yes&quot; : &quot;No&quot;);
+}
+
+static void appendHashCountedSet(StringBuilder&amp; builder, const String&amp; label, const HashCountedSet&lt;String&gt;&amp; hashCountedSet)
+{
+    if (hashCountedSet.isEmpty())
+        return;
+
+    builder.append(&quot;    &quot;);
+    builder.append(label);
+    builder.append(&quot;:\n&quot;);
+
+    for (auto&amp; entry : hashCountedSet) {
+        builder.append(&quot;        &quot;);
+        builder.append(entry.key);
+        builder.append(&quot;: &quot;);
+        builder.appendNumber(entry.value);
+        builder.append('\n');
+    }
+    
+}
+
+String ResourceLoadStatistics::toString() const
+{
+    StringBuilder builder;
+    
+    // User interaction
+    appendBoolean(builder, &quot;hadUserInteraction&quot;, hadUserInteraction);
+    builder.append('\n');
+    
+    // Top frame stats
+    appendBoolean(builder, &quot;topFrameHasBeenNavigatedToBefore&quot;, topFrameHasBeenNavigatedToBefore);
+    builder.append('\n');
+    builder.append(&quot;    topFrameHasBeenRedirectedTo: &quot;);
+    builder.appendNumber(topFrameHasBeenRedirectedTo);
+    builder.append('\n');
+    builder.append(&quot;    topFrameHasBeenRedirectedFrom: &quot;);
+    builder.appendNumber(topFrameHasBeenRedirectedFrom);
+    builder.append('\n');
+    builder.append(&quot;    topFrameInitialLoadCount: &quot;);
+    builder.appendNumber(topFrameInitialLoadCount);
+    builder.append('\n');
+    builder.append(&quot;    topFrameHasBeenNavigatedTo: &quot;);
+    builder.appendNumber(topFrameHasBeenNavigatedTo);
+    builder.append('\n');
+    builder.append(&quot;    topFrameHasBeenNavigatedFrom: &quot;);
+    builder.appendNumber(topFrameHasBeenNavigatedFrom);
+    builder.append('\n');
+    
+    // Subframe stats
+    appendBoolean(builder, &quot;subframeHasBeenLoadedBefore&quot;, subframeHasBeenLoadedBefore);
+    builder.append('\n');
+    builder.append(&quot;    subframeHasBeenRedirectedTo: &quot;);
+    builder.appendNumber(subframeHasBeenRedirectedTo);
+    builder.append('\n');
+    builder.append(&quot;    subframeHasBeenRedirectedFrom: &quot;);
+    builder.appendNumber(subframeHasBeenRedirectedFrom);
+    builder.append('\n');
+    builder.append(&quot;    subframeSubResourceCount: &quot;);
+    builder.appendNumber(subframeSubResourceCount);
+    builder.append('\n');
+    appendHashCountedSet(builder, &quot;subframeUnderTopFrameOrigins&quot;, subframeUnderTopFrameOrigins);
+    appendHashCountedSet(builder, &quot;subframeUniqueRedirectsTo&quot;, subframeUniqueRedirectsTo);
+    builder.append(&quot;    subframeHasBeenNavigatedTo: &quot;);
+    builder.appendNumber(subframeHasBeenNavigatedTo);
+    builder.append('\n');
+    builder.append(&quot;    subframeHasBeenNavigatedFrom: &quot;);
+    builder.appendNumber(subframeHasBeenNavigatedFrom);
+    builder.append('\n');
+    
+    // Subresource stats
+    builder.append(&quot;    subresourceHasBeenRedirectedFrom: &quot;);
+    builder.appendNumber(subresourceHasBeenRedirectedFrom);
+    builder.append('\n');
+    builder.append(&quot;    subresourceHasBeenRedirectedTo: &quot;);
+    builder.appendNumber(subresourceHasBeenRedirectedTo);
+    builder.append('\n');
+    builder.append(&quot;    subresourceHasBeenSubresourceCount: &quot;);
+    builder.appendNumber(subresourceHasBeenSubresourceCount);
+    builder.append('\n');
+    builder.append(&quot;    subresourceHasBeenSubresourceCountDividedByTotalNumberOfOriginsVisited: &quot;);
+    builder.appendNumber(subresourceHasBeenSubresourceCountDividedByTotalNumberOfOriginsVisited);
+    builder.append('\n');
+    appendHashCountedSet(builder, &quot;subresourceUnderTopFrameOrigins&quot;, subresourceUnderTopFrameOrigins);
+    appendHashCountedSet(builder, &quot;subresourceUniqueRedirectsTo&quot;, subresourceUniqueRedirectsTo);
+    
+    // Prevalent Resource
+    appendHashCountedSet(builder, &quot;redirectedToOtherPrevalentResourceOrigins&quot;, redirectedToOtherPrevalentResourceOrigins);
+    appendBoolean(builder, &quot;isPrevalentResource&quot;, 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 &lt;wtf/HashCountedSet.h&gt;
+#include &lt;wtf/text/WTFString.h&gt;
+
+namespace WebCore {
+
+class KeyedDecoder;
+class KeyedEncoder;
+
+struct ResourceLoadStatistics {
+    bool checkAndSetAsPrevalentResourceIfNecessary(unsigned originsVisitedSoFar);
+
+    bool hasPrevalentRedirection() const;
+    bool hasPrevalentResourceCharacteristics() const;
+
+    void encode(KeyedEncoder&amp;, const String&amp; origin) const;
+    bool decode(KeyedDecoder&amp;, const String&amp; 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&lt;String&gt; subframeUnderTopFrameOrigins;
+    unsigned subframeHasBeenRedirectedTo { 0 };
+    unsigned subframeHasBeenRedirectedFrom { 0 };
+    HashCountedSet&lt;String&gt; subframeUniqueRedirectsTo;
+    unsigned subframeSubResourceCount { 0 };
+    unsigned subframeHasBeenNavigatedTo { 0 };
+    unsigned subframeHasBeenNavigatedFrom { 0 };
+    bool subframeHasBeenLoadedBefore { false };
+    
+    // Subresource stats
+    HashCountedSet&lt;String&gt; subresourceUnderTopFrameOrigins;
+    unsigned subresourceHasBeenSubresourceCount { 0 };
+    double subresourceHasBeenSubresourceCountDividedByTotalNumberOfOriginsVisited { 0.0 };
+    unsigned subresourceHasBeenRedirectedFrom { 0 };
+    unsigned subresourceHasBeenRedirectedTo { 0 };
+    HashCountedSet&lt;String&gt; subresourceUniqueRedirectsTo;
+    
+    // Prevalent resource stats
+    HashCountedSet&lt;String&gt; 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 &quot;MainFrame.h&quot;
</span><span class="cx"> #include &quot;MemoryCache.h&quot;
</span><span class="cx"> #include &quot;Page.h&quot;
</span><ins>+#include &quot;ResourceLoadObserver.h&quot;
</ins><span class="cx"> #include &quot;Settings.h&quot;
</span><span class="cx"> #include &lt;wtf/Ref.h&gt;
</span><span class="cx"> #include &lt;wtf/RefCountedLeakCounter.h&gt;
</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-&gt;mainFrame().document()-&gt;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 &quot;RenderTreeAsText.h&quot;
</span><span class="cx"> #include &quot;RenderView.h&quot;
</span><span class="cx"> #include &quot;RenderedDocumentMarker.h&quot;
</span><ins>+#include &quot;ResourceLoadObserver.h&quot;
</ins><span class="cx"> #include &quot;RuntimeEnabledFeatures.h&quot;
</span><span class="cx"> #include &quot;SchemeRegistry.h&quot;
</span><span class="cx"> #include &quot;ScriptedAnimationController.h&quot;
</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&amp;, 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  &lt;bfulgham@apple.com&gt;
+
+        [Mac] Gather some rudimentary statistics during resource load 
+        https://bugs.webkit.org/show_bug.cgi?id=153575
+        &lt;rdar://problem/24075254&gt;
+
+        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  &lt;mark.lam@apple.com&gt;
</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 = @&quot;WebKitLocalCache&quot;;
</span><ins>+NSString *WebKitResourceLoadStatisticsDirectoryDefaultsKey = @&quot;WebKitResourceLoadStatisticsDirectory&quot;;
</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:&amp;error] path];
+        
+        if (!storageDirectory || ![storageDirectory isKindOfClass:[NSString class]])
+            storageDirectory = [NSHomeDirectory() stringByAppendingPathComponent:@&quot;Library/Application Support&quot;];
+    }
+
+    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 @&quot;WebKitNotificationsEnabled&quot;
</span><span class="cx"> #define WebKitSuppressesIncrementalRenderingKey @&quot;WebKitSuppressesIncrementalRendering&quot;
</span><span class="cx"> #define WebKitSubpixelCSSOMElementMetricsEnabledPreferenceKey @&quot;WebKitSubpixelCSSOMElementMetricsEnabled&quot;
</span><ins>+#define WebKitResourceLoadStatisticsEnabledPreferenceKey @&quot;WebKitResourceLoadStatisticsEnabled&quot;
</ins><span class="cx"> #if TARGET_OS_IPHONE
</span><span class="cx"> #define WebKitAudioSessionCategoryOverride @&quot;WebKitAudioSessionCategoryOverride&quot;
</span><span class="cx"> #define WebKitAVKitEnabled @&quot;WebKitAVKitEnabled&quot;
</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 &lt;WebCore/RenderView.h&gt;
</span><span class="cx"> #import &lt;WebCore/RenderWidget.h&gt;
</span><span class="cx"> #import &lt;WebCore/ResourceHandle.h&gt;
</span><ins>+#import &lt;WebCore/ResourceLoadObserver.h&gt;
</ins><span class="cx"> #import &lt;WebCore/ResourceRequest.h&gt;
</span><span class="cx"> #import &lt;WebCore/RuntimeApplicationChecks.h&gt;
</span><span class="cx"> #import &lt;WebCore/RuntimeEnabledFeatures.h&gt;
</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  &lt;bfulgham@apple.com&gt;
+
+        [Mac] Gather some rudimentary statistics during resource load 
+        https://bugs.webkit.org/show_bug.cgi?id=153575
+        &lt;rdar://problem/24075254&gt;
+
+        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  &lt;ossy@webkit.org&gt;
</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:@&quot;Databases&quot;],
</span><span class="cx">         WebStorageDirectoryDefaultsKey: [libraryPath stringByAppendingPathComponent:@&quot;LocalStorage&quot;],
</span><span class="cx">         WebKitLocalCacheDefaultsKey: [libraryPath stringByAppendingPathComponent:@&quot;LocalCache&quot;],
</span><ins>+        WebKitResourceLoadStatisticsDirectoryDefaultsKey: [libraryPath stringByAppendingPathComponent:@&quot;LocalStorage&quot;],
</ins><span class="cx"> #if PLATFORM(MAC) &amp;&amp; __MAC_OS_X_VERSION_MIN_REQUIRED &gt; 101000
</span><span class="cx">         // This needs to also be added to argument domain because of &lt;rdar://problem/20210002&gt;.
</span><span class="cx">         @&quot;AppleSystemFontOSSubversion&quot;: @(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 = @&quot;IncrementalRenderingSuppressed&quot;;
</span><span class="cx"> static NSString * const AcceleratedDrawingEnabledPreferenceKey = @&quot;AcceleratedDrawingEnabled&quot;;
</span><span class="cx"> static NSString * const DisplayListDrawingEnabledPreferenceKey = @&quot;DisplayListDrawingEnabled&quot;;
</span><ins>+static NSString * const ResourceLoadStatisticsEnabledPreferenceKey = @&quot;ResourceLoadStatisticsEnabled&quot;;
</ins><span class="cx"> 
</span><span class="cx"> static NSString * const NonFastScrollableRegionOverlayVisiblePreferenceKey = @&quot;NonFastScrollableRegionOverlayVisible&quot;;
</span><span class="cx"> static NSString * const WheelEventHandlerRegionOverlayVisiblePreferenceKey = @&quot;WheelEventHandlerRegionOverlayVisible&quot;;
</span><span class="lines">@@ -140,6 +141,7 @@
</span><span class="cx"> 
</span><span class="cx">     [self _addHeaderWithTitle:@&quot;WebKit1-only Settings&quot;];
</span><span class="cx">     [self _addItemWithTitle:@&quot;Enable Subpixel CSSOM Metrics&quot; action:@selector(toggleEnableSubPixelCSSOMMetrics:) indented:YES];
</span><ins>+    [self _addItemWithTitle:@&quot;Enable Resource Load Statistics&quot; 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>