<!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>[162710] trunk/Source/WebKit2</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/162710">162710</a></dd>
<dt>Author</dt> <dd>timothy_horton@apple.com</dd>
<dt>Date</dt> <dd>2014-01-24 10:56:23 -0800 (Fri, 24 Jan 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>WebKit2 View Gestures (Swipe): Add a simple cache of view snapshots
https://bugs.webkit.org/show_bug.cgi?id=127438

Reviewed by Sam Weinig.

Add a cache of bitmap snapshots of the WKView, taken via OS X's window server
snapshotting mechanism. For now, we store all snapshots; refinements to the
caching strategy (or really having one at all) will come in future patches.

Snapshots are stored in a side map, with a UUID that allows references
to be stored inside WebBackForwardListItem (and serialized along with
the back-forward list when it is copied).

* Shared/WebBackForwardListItem.h:
(WebKit::WebBackForwardListItem::setSnapshotUUID):
(WebKit::WebBackForwardListItem::snapshotUUID):
* UIProcess/cf/WebBackForwardListCF.cpp:
(WebKit::WebBackForwardList::createCFDictionaryRepresentation):
(WebKit::extractBackForwardListEntriesFromArray):
Store and serialize a UUID along with each back-forward list item which
identifies that item's view snapshot in the ViewSnapshotStore.

* UIProcess/cf/WebPageProxyCF.cpp:
Bump the session state data version, as we changed the WebBackForwardList format.

* UIProcess/API/Cocoa/WKViewPrivate.h:
* UIProcess/API/mac/PageClientImpl.h:
* UIProcess/API/mac/PageClientImpl.mm:
(WebKit::PageClientImpl::takeViewSnapshot):

* UIProcess/API/mac/WKView.mm:
(-[WKView _takeViewSnapshot]):
Add _takeViewSnapshot IPI, which is used by ViewSnapshotStore via the PageClient
to take a snapshot of the view.

(-[WKView saveBackForwardSnapshotForCurrentItem]):
Add saveBackForwardSnapshotForCurrentItem SPI, which clients could potentially
use when they know they're about to manipulate the view hierarchy in such a way
that they want the current back-forward item's snapshot to be up to date.

* UIProcess/API/mac/WKViewInternal.h:
* UIProcess/PageClient.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::WebPageProxy):
(WebKit::WebPageProxy::recordNavigationSnapshot):
(WebKit::WebPageProxy::goForward):
(WebKit::WebPageProxy::goBack):
(WebKit::WebPageProxy::goToBackForwardItem):
(WebKit::WebPageProxy::didStartProvisionalLoadForFrame):
Update the current back-forward item's snapshot immediately before navigating.

* UIProcess/WebPageProxy.h:
(WebKit::WebPageProxy::shouldRecordNavigationSnapshots):
(WebKit::WebPageProxy::setShouldRecordNavigationSnapshots):
Expose the ability to enable taking view snapshots on every navigation.
This is off by default, so we won't be taking any snapshots yet.

* UIProcess/mac/ViewSnapshotStore.h: Added.
(WebKit::ViewSnapshotStore::disableSnapshotting):
(WebKit::ViewSnapshotStore::enableSnapshotting):
* UIProcess/mac/ViewSnapshotStore.mm: Added.
(WebKit::ViewSnapshotStore::ViewSnapshotStore):
(WebKit::ViewSnapshotStore::~ViewSnapshotStore):
(WebKit::ViewSnapshotStore::shared):
(WebKit::ViewSnapshotStore::recordSnapshot):
(WebKit::ViewSnapshotStore::snapshotAndRenderTreeSize):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::takeViewSnapshot):
* WebKit2.xcodeproj/project.pbxproj:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2SharedWebBackForwardListItemh">trunk/Source/WebKit2/Shared/WebBackForwardListItem.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoaWKViewPrivateh">trunk/Source/WebKit2/UIProcess/API/Cocoa/WKViewPrivate.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPImacPageClientImplh">trunk/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPImacPageClientImplmm">trunk/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPImacWKViewmm">trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPImacWKViewInternalh">trunk/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessPageClienth">trunk/Source/WebKit2/UIProcess/PageClient.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebPageProxycpp">trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebPageProxyh">trunk/Source/WebKit2/UIProcess/WebPageProxy.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcesscfWebBackForwardListCFcpp">trunk/Source/WebKit2/UIProcess/cf/WebBackForwardListCF.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcesscfWebPageProxyCFcpp">trunk/Source/WebKit2/UIProcess/cf/WebPageProxyCF.cpp</a></li>
<li><a href="#trunkSourceWebKit2WebKit2xcodeprojprojectpbxproj">trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2UIProcessmacViewSnapshotStoreh">trunk/Source/WebKit2/UIProcess/mac/ViewSnapshotStore.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessmacViewSnapshotStoremm">trunk/Source/WebKit2/UIProcess/mac/ViewSnapshotStore.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (162709 => 162710)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-01-24 18:46:39 UTC (rev 162709)
+++ trunk/Source/WebKit2/ChangeLog        2014-01-24 18:56:23 UTC (rev 162710)
</span><span class="lines">@@ -1,3 +1,75 @@
</span><ins>+2014-01-24  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        WebKit2 View Gestures (Swipe): Add a simple cache of view snapshots
+        https://bugs.webkit.org/show_bug.cgi?id=127438
+
+        Reviewed by Sam Weinig.
+
+        Add a cache of bitmap snapshots of the WKView, taken via OS X's window server
+        snapshotting mechanism. For now, we store all snapshots; refinements to the
+        caching strategy (or really having one at all) will come in future patches.
+
+        Snapshots are stored in a side map, with a UUID that allows references
+        to be stored inside WebBackForwardListItem (and serialized along with
+        the back-forward list when it is copied).
+
+        * Shared/WebBackForwardListItem.h:
+        (WebKit::WebBackForwardListItem::setSnapshotUUID):
+        (WebKit::WebBackForwardListItem::snapshotUUID):
+        * UIProcess/cf/WebBackForwardListCF.cpp:
+        (WebKit::WebBackForwardList::createCFDictionaryRepresentation):
+        (WebKit::extractBackForwardListEntriesFromArray):
+        Store and serialize a UUID along with each back-forward list item which
+        identifies that item's view snapshot in the ViewSnapshotStore.
+
+        * UIProcess/cf/WebPageProxyCF.cpp:
+        Bump the session state data version, as we changed the WebBackForwardList format.
+
+        * UIProcess/API/Cocoa/WKViewPrivate.h:
+        * UIProcess/API/mac/PageClientImpl.h:
+        * UIProcess/API/mac/PageClientImpl.mm:
+        (WebKit::PageClientImpl::takeViewSnapshot):
+
+        * UIProcess/API/mac/WKView.mm:
+        (-[WKView _takeViewSnapshot]):
+        Add _takeViewSnapshot IPI, which is used by ViewSnapshotStore via the PageClient
+        to take a snapshot of the view.
+
+        (-[WKView saveBackForwardSnapshotForCurrentItem]):
+        Add saveBackForwardSnapshotForCurrentItem SPI, which clients could potentially
+        use when they know they're about to manipulate the view hierarchy in such a way
+        that they want the current back-forward item's snapshot to be up to date.
+
+        * UIProcess/API/mac/WKViewInternal.h:
+        * UIProcess/PageClient.h:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::WebPageProxy):
+        (WebKit::WebPageProxy::recordNavigationSnapshot):
+        (WebKit::WebPageProxy::goForward):
+        (WebKit::WebPageProxy::goBack):
+        (WebKit::WebPageProxy::goToBackForwardItem):
+        (WebKit::WebPageProxy::didStartProvisionalLoadForFrame):
+        Update the current back-forward item's snapshot immediately before navigating.
+
+        * UIProcess/WebPageProxy.h:
+        (WebKit::WebPageProxy::shouldRecordNavigationSnapshots):
+        (WebKit::WebPageProxy::setShouldRecordNavigationSnapshots):
+        Expose the ability to enable taking view snapshots on every navigation.
+        This is off by default, so we won't be taking any snapshots yet.
+
+        * UIProcess/mac/ViewSnapshotStore.h: Added.
+        (WebKit::ViewSnapshotStore::disableSnapshotting):
+        (WebKit::ViewSnapshotStore::enableSnapshotting):
+        * UIProcess/mac/ViewSnapshotStore.mm: Added.
+        (WebKit::ViewSnapshotStore::ViewSnapshotStore):
+        (WebKit::ViewSnapshotStore::~ViewSnapshotStore):
+        (WebKit::ViewSnapshotStore::shared):
+        (WebKit::ViewSnapshotStore::recordSnapshot):
+        (WebKit::ViewSnapshotStore::snapshotAndRenderTreeSize):
+        * UIProcess/mac/WebPageProxyMac.mm:
+        (WebKit::WebPageProxy::takeViewSnapshot):
+        * WebKit2.xcodeproj/project.pbxproj:
+
</ins><span class="cx"> 2014-01-24  Brady Eidson  &lt;beidson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         IDB: support createIndex/deleteIndex messaging
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedWebBackForwardListItemh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/WebBackForwardListItem.h (162709 => 162710)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/WebBackForwardListItem.h        2014-01-24 18:46:39 UTC (rev 162709)
+++ trunk/Source/WebKit2/Shared/WebBackForwardListItem.h        2014-01-24 18:56:23 UTC (rev 162710)
</span><span class="lines">@@ -60,6 +60,9 @@
</span><span class="cx">     void setBackForwardData(const uint8_t* buffer, size_t size);
</span><span class="cx">     const Vector&lt;uint8_t&gt;&amp; backForwardData() const { return m_backForwardData; }
</span><span class="cx"> 
</span><ins>+    void setSnapshotUUID(const String&amp; uuid) { m_snapshotUUID = uuid; }
+    const String&amp; snapshotUUID() const { return m_snapshotUUID; }
+
</ins><span class="cx">     void encode(IPC::ArgumentEncoder&amp;) const;
</span><span class="cx">     static PassRefPtr&lt;WebBackForwardListItem&gt; decode(IPC::ArgumentDecoder&amp;);
</span><span class="cx"> 
</span><span class="lines">@@ -73,6 +76,7 @@
</span><span class="cx">     String m_title;
</span><span class="cx">     uint64_t m_itemID;
</span><span class="cx">     Vector&lt;uint8_t&gt; m_backForwardData;
</span><ins>+    String m_snapshotUUID;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> typedef Vector&lt;RefPtr&lt;WebBackForwardListItem&gt;&gt; BackForwardListItemVector;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoaWKViewPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKViewPrivate.h (162709 => 162710)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKViewPrivate.h        2014-01-24 18:46:39 UTC (rev 162709)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKViewPrivate.h        2014-01-24 18:56:23 UTC (rev 162710)
</span><span class="lines">@@ -89,6 +89,8 @@
</span><span class="cx"> 
</span><span class="cx"> - (void)setMagnification:(double)magnification centeredAtPoint:(NSPoint)point;
</span><span class="cx"> 
</span><ins>+- (void)saveBackForwardSnapshotForCurrentItem;
+
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> @end
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPImacPageClientImplh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h (162709 => 162710)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h        2014-01-24 18:46:39 UTC (rev 162709)
+++ trunk/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h        2014-01-24 18:56:23 UTC (rev 162710)
</span><span class="lines">@@ -113,6 +113,8 @@
</span><span class="cx">     virtual void exitAcceleratedCompositingMode();
</span><span class="cx">     virtual void updateAcceleratedCompositingMode(const LayerTreeContext&amp;);
</span><span class="cx"> 
</span><ins>+    virtual RetainPtr&lt;CGImageRef&gt; takeViewSnapshot() override;
+
</ins><span class="cx">     virtual void accessibilityWebProcessTokenReceived(const IPC::DataReference&amp;);
</span><span class="cx"> 
</span><span class="cx">     virtual void pluginFocusOrWindowFocusChanged(uint64_t pluginComplexTextInputIdentifier, bool pluginHasFocusAndWindowHasFocus);
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPImacPageClientImplmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm (162709 => 162710)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm        2014-01-24 18:46:39 UTC (rev 162709)
+++ trunk/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm        2014-01-24 18:56:23 UTC (rev 162710)
</span><span class="lines">@@ -434,6 +434,11 @@
</span><span class="cx">     [m_wkView _setAcceleratedCompositingModeRootLayer:rootLayer];
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RetainPtr&lt;CGImageRef&gt; PageClientImpl::takeViewSnapshot()
+{
+    return [m_wkView _takeViewSnapshot];
+}
+
</ins><span class="cx"> void PageClientImpl::pluginFocusOrWindowFocusChanged(uint64_t pluginComplexTextInputIdentifier, bool pluginHasFocusAndWindowHasFocus)
</span><span class="cx"> {
</span><span class="cx">     [m_wkView _pluginFocusOrWindowFocusChanged:pluginHasFocusAndWindowHasFocus pluginComplexTextInputIdentifier:pluginComplexTextInputIdentifier];
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPImacWKViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm (162709 => 162710)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm        2014-01-24 18:46:39 UTC (rev 162709)
+++ trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm        2014-01-24 18:56:23 UTC (rev 162710)
</span><span class="lines">@@ -50,6 +50,7 @@
</span><span class="cx"> #import &quot;TextCheckerState.h&quot;
</span><span class="cx"> #import &quot;TiledCoreAnimationDrawingAreaProxy.h&quot;
</span><span class="cx"> #import &quot;ViewGestureController.h&quot;
</span><ins>+#import &quot;ViewSnapshotStore.h&quot;
</ins><span class="cx"> #import &quot;WKAPICast.h&quot;
</span><span class="cx"> #import &quot;WKFullScreenWindowController.h&quot;
</span><span class="cx"> #import &quot;WKPrintingView.h&quot;
</span><span class="lines">@@ -57,6 +58,7 @@
</span><span class="cx"> #import &quot;WKTextInputWindowController.h&quot;
</span><span class="cx"> #import &quot;WKViewInternal.h&quot;
</span><span class="cx"> #import &quot;WKViewPrivate.h&quot;
</span><ins>+#import &quot;WebBackForwardList.h&quot;
</ins><span class="cx"> #import &quot;WebContext.h&quot;
</span><span class="cx"> #import &quot;WebEventFactory.h&quot;
</span><span class="cx"> #import &quot;WebKit2Initialize.h&quot;
</span><span class="lines">@@ -113,6 +115,17 @@
</span><span class="cx"> - (void)_maskRoundedBottomCorners:(NSRect)clipRect;
</span><span class="cx"> @end
</span><span class="cx"> 
</span><ins>+#if defined(__has_include) &amp;&amp; __has_include(&lt;CoreGraphics/CoreGraphicsPrivate.h&gt;)
+#import &lt;CoreGraphics/CoreGraphicsPrivate.h&gt;
+#endif
+
+extern &quot;C&quot; {
+typedef uint32_t CGSConnectionID;
+typedef uint32_t CGSWindowID;
+CGSConnectionID CGSMainConnectionID(void);
+CGError CGSGetScreenRectForWindow(CGSConnectionID cid, CGSWindowID wid, CGRect *rect);
+};
+
</ins><span class="cx"> using namespace WebKit;
</span><span class="cx"> using namespace WebCore;
</span><span class="cx"> 
</span><span class="lines">@@ -2497,6 +2510,26 @@
</span><span class="cx">     [CATransaction commit];
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (RetainPtr&lt;CGImageRef&gt;)_takeViewSnapshot
+{
+    NSWindow *window = self.window;
+
+    if (![window windowNumber])
+        return nullptr;
+
+    RetainPtr&lt;CGImageRef&gt; windowSnapshotImage = adoptCF(CGWindowListCreateImage(CGRectNull, kCGWindowListOptionIncludingWindow, [window windowNumber], kCGWindowImageBoundsIgnoreFraming | kCGWindowImageShouldBeOpaque));
+
+    NSRect windowCaptureRect = [self convertRect:self.bounds toView:nil];
+    NSRect windowCaptureScreenRect = [window convertRectToScreen:windowCaptureRect];
+    CGRect windowScreenRect;
+    CGSGetScreenRectForWindow(CGSMainConnectionID(), (CGSWindowID)[window windowNumber], &amp;windowScreenRect);
+
+    NSRect croppedImageRect = windowCaptureRect;
+    croppedImageRect.origin.y = windowScreenRect.size.height - windowCaptureScreenRect.size.height - NSMinY(windowCaptureRect);
+
+    return adoptCF(CGImageCreateWithImageInRect(windowSnapshotImage.get(), NSRectToCGRect([window convertRectToBacking:croppedImageRect])));
+}
+
</ins><span class="cx"> - (void)_setAccessibilityWebProcessToken:(NSData *)data
</span><span class="cx"> {
</span><span class="cx">     _data-&gt;_remoteAccessibilityChild = WKAXRemoteElementForToken(data);
</span><span class="lines">@@ -2813,6 +2846,11 @@
</span><span class="cx"> 
</span><span class="cx"> @implementation WKView (Private)
</span><span class="cx"> 
</span><ins>+- (void)saveBackForwardSnapshotForCurrentItem
+{
+    _data-&gt;_page-&gt;recordNavigationSnapshot();
+}
+
</ins><span class="cx"> - (void)_registerDraggedTypes
</span><span class="cx"> {
</span><span class="cx">     NSMutableSet *types = [[NSMutableSet alloc] initWithArray:PasteboardTypes::forEditing()];
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPImacWKViewInternalh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h (162709 => 162710)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h        2014-01-24 18:46:39 UTC (rev 162709)
+++ trunk/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h        2014-01-24 18:56:23 UTC (rev 162710)
</span><span class="lines">@@ -70,6 +70,8 @@
</span><span class="cx"> 
</span><span class="cx"> - (void)_setAcceleratedCompositingModeRootLayer:(CALayer *)rootLayer;
</span><span class="cx"> 
</span><ins>+- (RetainPtr&lt;CGImageRef&gt;)_takeViewSnapshot;
+
</ins><span class="cx"> - (void)_setAccessibilityWebProcessToken:(NSData *)data;
</span><span class="cx"> 
</span><span class="cx"> - (void)_pluginFocusOrWindowFocusChanged:(BOOL)pluginHasFocusAndWindowHasFocus pluginComplexTextInputIdentifier:(uint64_t)pluginComplexTextInputIdentifier;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessPageClienth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/PageClient.h (162709 => 162710)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/PageClient.h        2014-01-24 18:46:39 UTC (rev 162709)
+++ trunk/Source/WebKit2/UIProcess/PageClient.h        2014-01-24 18:56:23 UTC (rev 162710)
</span><span class="lines">@@ -172,6 +172,7 @@
</span><span class="cx">     virtual void notifyInputContextAboutDiscardedComposition() = 0;
</span><span class="cx">     virtual void makeFirstResponder() = 0;
</span><span class="cx">     virtual void setAcceleratedCompositingRootLayer(CALayer *) = 0;
</span><ins>+    virtual RetainPtr&lt;CGImageRef&gt; takeViewSnapshot() = 0;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if USE(APPKIT)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (162709 => 162710)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2014-01-24 18:46:39 UTC (rev 162709)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2014-01-24 18:56:23 UTC (rev 162710)
</span><span class="lines">@@ -124,6 +124,10 @@
</span><span class="cx"> #include &quot;NetworkProcessMessages.h&quot;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if PLATFORM(MAC)
+#include &quot;ViewSnapshotStore.h&quot;
+#endif
+
</ins><span class="cx"> // This controls what strategy we use for mouse wheel coalescing.
</span><span class="cx"> #define MERGE_WHEEL_EVENTS 1
</span><span class="cx"> 
</span><span class="lines">@@ -309,6 +313,7 @@
</span><span class="cx">     , m_rubberBandsAtBottom(true)
</span><span class="cx">     , m_backgroundExtendsBeyondPage(false)
</span><span class="cx">     , m_mainFrameInViewSourceMode(false)
</span><ins>+    , m_shouldRecordNavigationSnapshots(false)
</ins><span class="cx">     , m_pageCount(0)
</span><span class="cx">     , m_renderTreeSize(0)
</span><span class="cx">     , m_shouldSendEventsSynchronously(false)
</span><span class="lines">@@ -750,6 +755,16 @@
</span><span class="cx">     m_process-&gt;responsivenessTimer()-&gt;start();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebPageProxy::recordNavigationSnapshot()
+{
+    if (!m_shouldRecordNavigationSnapshots)
+        return;
+
+#if PLATFORM(MAC)
+    ViewSnapshotStore::shared().recordSnapshot(*this);
+#endif
+}
+
</ins><span class="cx"> void WebPageProxy::goForward()
</span><span class="cx"> {
</span><span class="cx">     if (isValid() &amp;&amp; !canGoForward())
</span><span class="lines">@@ -759,6 +774,8 @@
</span><span class="cx">     if (!forwardItem)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    recordNavigationSnapshot();
+
</ins><span class="cx">     auto transaction = m_pageLoadState.transaction();
</span><span class="cx"> 
</span><span class="cx">     m_pageLoadState.setPendingAPIRequestURL(transaction, forwardItem-&gt;url());
</span><span class="lines">@@ -786,6 +803,8 @@
</span><span class="cx">     if (!backItem)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    recordNavigationSnapshot();
+
</ins><span class="cx">     auto transaction = m_pageLoadState.transaction();
</span><span class="cx"> 
</span><span class="cx">     m_pageLoadState.setPendingAPIRequestURL(transaction, backItem-&gt;url());
</span><span class="lines">@@ -810,6 +829,8 @@
</span><span class="cx">         reattachToWebProcessWithItem(item);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><ins>+
+    recordNavigationSnapshot();
</ins><span class="cx">     
</span><span class="cx">     auto transaction = m_pageLoadState.transaction();
</span><span class="cx"> 
</span><span class="lines">@@ -2107,8 +2128,10 @@
</span><span class="cx">     MESSAGE_CHECK(frame);
</span><span class="cx">     MESSAGE_CHECK_URL(url);
</span><span class="cx"> 
</span><del>-    if (frame-&gt;isMainFrame())
</del><ins>+    if (frame-&gt;isMainFrame()) {
+        recordNavigationSnapshot();
</ins><span class="cx">         m_pageLoadState.didStartProvisionalLoad(transaction, url, unreachableURL);
</span><ins>+    }
</ins><span class="cx"> 
</span><span class="cx">     frame-&gt;setUnreachableURL(unreachableURL);
</span><span class="cx">     frame-&gt;didStartProvisionalLoad(url);
</span><span class="lines">@@ -4359,6 +4382,11 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+RetainPtr&lt;CGImageRef&gt; WebPageProxy::takeViewSnapshot()
+{
+    return m_pageClient.takeViewSnapshot();
+}
+
</ins><span class="cx"> #endif // PLATFORM(MAC)
</span><span class="cx"> 
</span><span class="cx"> #if USE(SOUP) &amp;&amp; !ENABLE(CUSTOM_PROTOCOLS)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (162709 => 162710)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2014-01-24 18:46:39 UTC (rev 162709)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2014-01-24 18:56:23 UTC (rev 162710)
</span><span class="lines">@@ -858,7 +858,15 @@
</span><span class="cx">         
</span><span class="cx">     void setScrollPinningBehavior(WebCore::ScrollPinningBehavior);
</span><span class="cx">     WebCore::ScrollPinningBehavior scrollPinningBehavior() { return m_scrollPinningBehavior; }
</span><del>-        
</del><ins>+
+    bool shouldRecordNavigationSnapshots() const { return m_shouldRecordNavigationSnapshots; }
+    void setShouldRecordNavigationSnapshots(bool shouldRecordSnapshots) { m_shouldRecordNavigationSnapshots = shouldRecordSnapshots; }
+    void recordNavigationSnapshot();
+
+#if PLATFORM(MAC)
+    RetainPtr&lt;CGImageRef&gt; takeViewSnapshot();
+#endif
+
</ins><span class="cx"> private:
</span><span class="cx">     WebPageProxy(PageClient&amp;, WebProcessProxy&amp;, WebPageGroup&amp;, API::Session&amp;, uint64_t pageID);
</span><span class="cx">     void platformInitialize();
</span><span class="lines">@@ -1359,7 +1367,9 @@
</span><span class="cx">     bool m_backgroundExtendsBeyondPage;
</span><span class="cx"> 
</span><span class="cx">     bool m_mainFrameInViewSourceMode;
</span><del>-        
</del><ins>+
+    bool m_shouldRecordNavigationSnapshots;
+
</ins><span class="cx">     unsigned m_pageCount;
</span><span class="cx"> 
</span><span class="cx">     WebCore::IntRect m_visibleScrollerThumbRect;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcesscfWebBackForwardListCFcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/cf/WebBackForwardListCF.cpp (162709 => 162710)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/cf/WebBackForwardListCF.cpp        2014-01-24 18:46:39 UTC (rev 162709)
+++ trunk/Source/WebKit2/UIProcess/cf/WebBackForwardListCF.cpp        2014-01-24 18:56:23 UTC (rev 162710)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2010, 2011, 2012 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2010, 2011, 2012, 2014 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">@@ -58,6 +58,7 @@
</span><span class="cx"> static CFStringRef sessionHistoryEntryURLKey = CFSTR(&quot;SessionHistoryEntryURL&quot;);
</span><span class="cx"> static CFStringRef sessionHistoryEntryOriginalURLKey = CFSTR(&quot;SessionHistoryEntryOriginalURL&quot;);
</span><span class="cx"> static CFStringRef sessionHistoryEntryDataKey = CFSTR(&quot;SessionHistoryEntryData&quot;);
</span><ins>+static CFStringRef sessionHistoryEntrySnapshotUUIDKey = CFSTR(&quot;SessionHistoryEntrySnapshotUUID&quot;);
</ins><span class="cx"> 
</span><span class="cx"> static bool extractBackForwardListEntriesFromArray(CFArrayRef, BackForwardListItemVector&amp;);
</span><span class="cx"> 
</span><span class="lines">@@ -104,15 +105,16 @@
</span><span class="cx">         RetainPtr&lt;CFStringRef&gt; url = m_entries[i]-&gt;url().createCFString();
</span><span class="cx">         RetainPtr&lt;CFStringRef&gt; title = m_entries[i]-&gt;title().createCFString();
</span><span class="cx">         RetainPtr&lt;CFStringRef&gt; originalURL = m_entries[i]-&gt;originalURL().createCFString();
</span><ins>+        RetainPtr&lt;CFStringRef&gt; uuid = m_entries[i]-&gt;snapshotUUID().createCFString();
</ins><span class="cx"> 
</span><span class="cx">         // FIXME: This uses the IPC data encoding format, which means that whenever we change the IPC encoding we need to bump the CurrentSessionStateDataVersion
</span><span class="cx">         // constant in WebPageProxyCF.cpp. The IPC data format is meant to be an implementation detail, and not something that should be written to disk.
</span><span class="cx">         RetainPtr&lt;CFDataRef&gt; entryData = adoptCF(CFDataCreate(kCFAllocatorDefault, m_entries[i]-&gt;backForwardData().data(), m_entries[i]-&gt;backForwardData().size()));
</span><del>-        
-        const void* keys[4] = { sessionHistoryEntryURLKey, sessionHistoryEntryTitleKey, sessionHistoryEntryOriginalURLKey, sessionHistoryEntryDataKey };
-        const void* values[4] = { url.get(), title.get(), originalURL.get(), entryData.get() };
</del><span class="cx"> 
</span><del>-        RetainPtr&lt;CFDictionaryRef&gt; entryDictionary = adoptCF(CFDictionaryCreate(0, keys, values, 4, &amp;kCFTypeDictionaryKeyCallBacks, &amp;kCFTypeDictionaryValueCallBacks));
</del><ins>+        const void* keys[5] = { sessionHistoryEntryURLKey, sessionHistoryEntryTitleKey, sessionHistoryEntryOriginalURLKey, sessionHistoryEntryDataKey, sessionHistoryEntrySnapshotUUIDKey };
+        const void* values[5] = { url.get(), title.get(), originalURL.get(), entryData.get(), uuid.get() };
+
+        RetainPtr&lt;CFDictionaryRef&gt; entryDictionary = adoptCF(CFDictionaryCreate(0, keys, values, 5, &amp;kCFTypeDictionaryKeyCallBacks, &amp;kCFTypeDictionaryValueCallBacks));
</ins><span class="cx">         CFArrayAppendValue(entries.get(), entryDictionary.get());
</span><span class="cx">     }
</span><span class="cx">         
</span><span class="lines">@@ -309,13 +311,21 @@
</span><span class="cx">             return false;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        CFStringRef snapshotUUID = (CFStringRef)CFDictionaryGetValue(entryDictionary, sessionHistoryEntrySnapshotUUIDKey);
+        if (!snapshotUUID || CFGetTypeID(snapshotUUID) != CFStringGetTypeID()) {
+            LOG(SessionState, &quot;WebBackForwardList entry at index %i does not have a valid snapshot UUID&quot;, (int)i);
+            return false;
+        }
+
</ins><span class="cx">         CFDataRef backForwardData = (CFDataRef)CFDictionaryGetValue(entryDictionary, sessionHistoryEntryDataKey);
</span><span class="cx">         if (!backForwardData || CFGetTypeID(backForwardData) != CFDataGetTypeID()) {
</span><span class="cx">             LOG(SessionState, &quot;WebBackForwardList entry at index %i does not have back/forward data&quot;, (int)i);
</span><span class="cx">             return false;
</span><span class="cx">         }
</span><del>-        
-        entries.append(WebBackForwardListItem::create(originalURL, entryURL, entryTitle, CFDataGetBytePtr(backForwardData), CFDataGetLength(backForwardData), generateWebBackForwardItemID()));
</del><ins>+
+        auto item = WebBackForwardListItem::create(originalURL, entryURL, entryTitle, CFDataGetBytePtr(backForwardData), CFDataGetLength(backForwardData), generateWebBackForwardItemID());
+        item-&gt;setSnapshotUUID(snapshotUUID);
+        entries.append(item);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     return true;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcesscfWebPageProxyCFcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/cf/WebPageProxyCF.cpp (162709 => 162710)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/cf/WebPageProxyCF.cpp        2014-01-24 18:46:39 UTC (rev 162709)
+++ trunk/Source/WebKit2/UIProcess/cf/WebPageProxyCF.cpp        2014-01-24 18:56:23 UTC (rev 162710)
</span><span class="lines">@@ -44,7 +44,7 @@
</span><span class="cx"> static CFStringRef sessionHistoryKey = CFSTR(&quot;SessionHistory&quot;);
</span><span class="cx"> static CFStringRef provisionalURLKey = CFSTR(&quot;ProvisionalURL&quot;);
</span><span class="cx"> 
</span><del>-static const UInt32 CurrentSessionStateDataVersion = 2;
</del><ins>+static const UInt32 CurrentSessionStateDataVersion = 3;
</ins><span class="cx"> 
</span><span class="cx"> PassRefPtr&lt;API::Data&gt; WebPageProxy::sessionStateData(WebPageProxySessionStateFilterCallback filter, void* context) const
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessmacViewSnapshotStoreh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit2/UIProcess/mac/ViewSnapshotStore.h (0 => 162710)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/mac/ViewSnapshotStore.h                                (rev 0)
+++ trunk/Source/WebKit2/UIProcess/mac/ViewSnapshotStore.h        2014-01-24 18:56:23 UTC (rev 162710)
</span><span class="lines">@@ -0,0 +1,61 @@
</span><ins>+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef ViewSnapshotStore_h
+#define ViewSnapshotStore_h
+
+#include &lt;wtf/HashMap.h&gt;
+#include &lt;wtf/Noncopyable.h&gt;
+#include &lt;wtf/RetainPtr.h&gt;
+#include &lt;wtf/text/WTFString.h&gt;
+
+namespace WebKit {
+
+class WebBackForwardListItem;
+class WebPageProxy;
+
+class ViewSnapshotStore {
+    WTF_MAKE_NONCOPYABLE(ViewSnapshotStore);
+public:
+    ViewSnapshotStore();
+    ~ViewSnapshotStore();
+
+    static ViewSnapshotStore&amp; shared();
+
+    void recordSnapshot(WebPageProxy&amp;);
+    std::pair&lt;RetainPtr&lt;CGImageRef&gt;, uint64_t&gt; snapshotAndRenderTreeSize(WebBackForwardListItem*);
+
+    void disableSnapshotting() { m_enabled = false; }
+    void enableSnapshotting() { m_enabled = true; }
+
+private:
+    HashMap&lt;String, std::pair&lt;RetainPtr&lt;CGImageRef&gt;, uint64_t&gt;&gt; m_snapshotMap;
+
+    bool m_enabled;
+};
+
+} // namespace WebKit
+
+#endif // ViewSnapshotStore_h
</ins></span></pre></div>
<a id="trunkSourceWebKit2UIProcessmacViewSnapshotStoremm"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit2/UIProcess/mac/ViewSnapshotStore.mm (0 => 162710)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/mac/ViewSnapshotStore.mm                                (rev 0)
+++ trunk/Source/WebKit2/UIProcess/mac/ViewSnapshotStore.mm        2014-01-24 18:56:23 UTC (rev 162710)
</span><span class="lines">@@ -0,0 +1,83 @@
</span><ins>+/*
+ * Copyright (C) 2014 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.
+ */
+
+#import &quot;config.h&quot;
+#import &quot;ViewSnapshotStore.h&quot;
+
+#import &quot;WebBackForwardList.h&quot;
+#import &quot;WebPageProxy.h&quot;
+#import &lt;CoreGraphics/CoreGraphics.h&gt;
+#import &lt;WebCore/UUID.h&gt;
+
+using namespace WebCore;
+
+namespace WebKit {
+
+ViewSnapshotStore::ViewSnapshotStore()
+    : m_enabled(true)
+{
+}
+
+ViewSnapshotStore::~ViewSnapshotStore()
+{
+}
+
+ViewSnapshotStore&amp; ViewSnapshotStore::shared()
+{
+    static ViewSnapshotStore&amp; store = *new ViewSnapshotStore;
+    return store;
+}
+
+void ViewSnapshotStore::recordSnapshot(WebPageProxy&amp; webPageProxy)
+{
+    RefPtr&lt;WebBackForwardListItem&gt; item = webPageProxy.backForwardList().currentItem();
+
+    if (!m_enabled)
+        return;
+
+    if (!item)
+        return;
+
+    RetainPtr&lt;CGImageRef&gt; snapshot = webPageProxy.takeViewSnapshot();
+
+    String oldSnapshotUUID = item-&gt;snapshotUUID();
+    if (!oldSnapshotUUID.isEmpty())
+        m_snapshotMap.remove(oldSnapshotUUID);
+
+    item-&gt;setSnapshotUUID(createCanonicalUUIDString());
+    m_snapshotMap.add(item-&gt;snapshotUUID(), std::make_pair(snapshot, webPageProxy.renderTreeSize()));
+}
+
+std::pair&lt;RetainPtr&lt;CGImageRef&gt;, uint64_t&gt; ViewSnapshotStore::snapshotAndRenderTreeSize(WebBackForwardListItem* item)
+{
+    const auto&amp; snapshotAndRenderTreeSize = m_snapshotMap.find(item-&gt;snapshotUUID());
+
+    if (snapshotAndRenderTreeSize == m_snapshotMap.end())
+        return std::make_pair(nullptr, 0);
+
+    return std::make_pair(snapshotAndRenderTreeSize-&gt;value.first.get(), snapshotAndRenderTreeSize-&gt;value.second);
+}
+
+} // namespace WebKit
</ins></span></pre></div>
<a id="trunkSourceWebKit2WebKit2xcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj (162709 => 162710)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj        2014-01-24 18:46:39 UTC (rev 162709)
+++ trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj        2014-01-24 18:56:23 UTC (rev 162710)
</span><span class="lines">@@ -416,6 +416,8 @@
</span><span class="cx">                 2D429BFD1721E2C700EC681F /* PDFPluginPasswordField.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D429BFB1721E2BA00EC681F /* PDFPluginPasswordField.mm */; };
</span><span class="cx">                 2D47B56C1810714E003A3AEE /* RemoteLayerBackingStore.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D47B56A1810714E003A3AEE /* RemoteLayerBackingStore.mm */; };
</span><span class="cx">                 2D47B56D1810714E003A3AEE /* RemoteLayerBackingStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D47B56B1810714E003A3AEE /* RemoteLayerBackingStore.h */; };
</span><ins>+                2D6CD119189058A500E5A4A0 /* ViewSnapshotStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D6CD117189058A500E5A4A0 /* ViewSnapshotStore.h */; };
+                2D6CD11A189058A500E5A4A0 /* ViewSnapshotStore.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D6CD118189058A500E5A4A0 /* ViewSnapshotStore.mm */; };
</ins><span class="cx">                 2D819B9E18627EE9001F03D1 /* ViewGestureGeometryCollector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2D819B99186275B3001F03D1 /* ViewGestureGeometryCollector.cpp */; };
</span><span class="cx">                 2D819BA11862800E001F03D1 /* ViewGestureGeometryCollectorMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2D819B9F1862800E001F03D1 /* ViewGestureGeometryCollectorMessageReceiver.cpp */; };
</span><span class="cx">                 2D819BA21862800E001F03D1 /* ViewGestureGeometryCollectorMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D819BA01862800E001F03D1 /* ViewGestureGeometryCollectorMessages.h */; };
</span><span class="lines">@@ -2070,6 +2072,8 @@
</span><span class="cx">                 2D429BFB1721E2BA00EC681F /* PDFPluginPasswordField.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PDFPluginPasswordField.mm; path = PDF/PDFPluginPasswordField.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2D47B56A1810714E003A3AEE /* RemoteLayerBackingStore.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RemoteLayerBackingStore.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2D47B56B1810714E003A3AEE /* RemoteLayerBackingStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoteLayerBackingStore.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                2D6CD117189058A500E5A4A0 /* ViewSnapshotStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewSnapshotStore.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                2D6CD118189058A500E5A4A0 /* ViewSnapshotStore.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ViewSnapshotStore.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 2D819B99186275B3001F03D1 /* ViewGestureGeometryCollector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ViewGestureGeometryCollector.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2D819B9A186275B3001F03D1 /* ViewGestureGeometryCollector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewGestureGeometryCollector.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2D819B9B186275B3001F03D1 /* ViewGestureGeometryCollector.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ViewGestureGeometryCollector.messages.in; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -5693,6 +5697,8 @@
</span><span class="cx">                                 2D125C5C1857EA05003BA3CB /* ViewGestureController.h */,
</span><span class="cx">                                 2D125C5D1857EA05003BA3CB /* ViewGestureController.mm */,
</span><span class="cx">                                 2D1B5D5A18586599006C6596 /* ViewGestureController.messages.in */,
</span><ins>+                                2D6CD117189058A500E5A4A0 /* ViewSnapshotStore.h */,
+                                2D6CD118189058A500E5A4A0 /* ViewSnapshotStore.mm */,
</ins><span class="cx">                                 728E86EF1795188C0087879E /* WebColorPickerMac.h */,
</span><span class="cx">                                 728E86F01795188C0087879E /* WebColorPickerMac.mm */,
</span><span class="cx">                                 1A1C648611F415B700553C19 /* WebContextMac.mm */,
</span><span class="lines">@@ -6667,6 +6673,7 @@
</span><span class="cx">                                 BC857FE612B843D800EDEB2E /* WKOpenPanelParameters.h in Headers */,
</span><span class="cx">                                 BC1DFE8F12B31CA8005DF730 /* WKOpenPanelResultListener.h in Headers */,
</span><span class="cx">                                 BCD597D7112B56DC00EC8C23 /* WKPage.h in Headers */,
</span><ins>+                                2D6CD119189058A500E5A4A0 /* ViewSnapshotStore.h in Headers */,
</ins><span class="cx">                                 BC7B633712A45ABA00D174A4 /* WKPageGroup.h in Headers */,
</span><span class="cx">                                 BC2D021912AC426C00E732A3 /* WKPageLoadTypes.h in Headers */,
</span><span class="cx">                                 93BDEB01171DD7AF00BFEE1B /* WKPageLoadTypesPrivate.h in Headers */,
</span><span class="lines">@@ -7497,6 +7504,7 @@
</span><span class="cx">                                 BCE81D98131AE02100241910 /* DictionaryPopupInfo.cpp in Sources */,
</span><span class="cx">                                 5167EEA1170377BF007681CA /* DiskCacheMonitor.mm in Sources */,
</span><span class="cx">                                 2DA9448F1884E3B500ED86DB /* WKGeolocationProviderIOS.mm in Sources */,
</span><ins>+                                2D6CD11A189058A500E5A4A0 /* ViewSnapshotStore.mm in Sources */,
</ins><span class="cx">                                 518E8F0716B2093700E91429 /* Download.cpp in Sources */,
</span><span class="cx">                                 2D47B56C1810714E003A3AEE /* RemoteLayerBackingStore.mm in Sources */,
</span><span class="cx">                                 518E8F0916B2093700E91429 /* DownloadAuthenticationClient.cpp in Sources */,
</span></span></pre>
</div>
</div>

</body>
</html>