<!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>[160405] 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/160405">160405</a></dd>
<dt>Author</dt> <dd>mitz@apple.com</dd>
<dt>Date</dt> <dd>2013-12-10 18:07:33 -0800 (Tue, 10 Dec 2013)</dd>
</dl>

<h3>Log Message</h3>
<pre>All observable PageLoadState properties should change in an atomic fashion, with properly nested change notifications
https://bugs.webkit.org/show_bug.cgi?id=125431

Reviewed by Anders Carlsson.

Made PageLoadState maintain two copies of its state data members, one representing the
committed state and one possibly containing uncommitted changes. When changes are committed,
change notifications are sent and the uncommitted state is copied into the committed state.
Changes can be committed explicitly at any time, but are also committed when the last
outstanding transaction ends. Transactions are RAII objects vended by the PageLoadState.
Mutating the PageLoadState requires holding a Transaction, which is enforced by making all
the mutating member functions take a Transaction::Token. Passing a Token also marks the
PageLoadState as possibly having uncommitted changes.

* UIProcess/API/Cocoa/WKBrowsingContextController.mm:
Added PageLoadStateObserver::{will,did}ChangeActiveURL overrides that call
-{will,did}ChangeValueForKey:.

* UIProcess/PageLoadState.cpp:
Moved constant from the middle of the file to the beginning and reworded comment.
(WebKit::PageLoadState::PageLoadState): Added initializers for new member variables, removed
initialization of members that are not part of Data, which initializes them in its
constructor.
(WebKit::PageLoadState::endTransaction): Added. Calles when a Transaction is destructed.
Decrements the outstanding transaction count, and if it is zero, commits changes.
(WebKit::PageLoadState::commitChanges): Added. Checks for differences in observable
properties between the committed state and the uncommitted state, then makes appropriate
willChange Observer callbacks, then copies the uncommitted state into the committed state,
then makes appropriate didChange Observer callbacks in reverse order. Also added active URL
to the set of observable properties.
(WebKit::PageLoadState::reset): Changed to take a transaction token, act on
m_uncommittedState, and not make observer callbacks.
(WebKit::PageLoadState::isLoading): Changed to access m_committedState.
(WebKit::PageLoadState::activeURL): Changed to call a static function factored out of this.
(WebKit::PageLoadState::estimatedProgress): Ditto.
(WebKit::PageLoadState::pendingAPIRequestURL): Changed to access m_committedState.
(WebKit::PageLoadState::setPendingAPIRequestURL): Changed to take a transaction token, act
on m_uncommittedState, and not make observer callbacks.
(WebKit::PageLoadState::clearPendingAPIRequestURL): Ditto.
(WebKit::PageLoadState::didStartProvisionalLoad): Ditto.
(WebKit::PageLoadState::didReceiveServerRedirectForProvisionalLoad): Ditto.
(WebKit::PageLoadState::didFailProvisionalLoad): Ditto.
(WebKit::PageLoadState::didCommitLoad): Ditto.
(WebKit::PageLoadState::didFinishLoad): Ditto.
(WebKit::PageLoadState::didFailLoad): Ditto.
(WebKit::PageLoadState::didSameDocumentNavigation): Ditto.
(WebKit::PageLoadState::setUnreachableURL): Ditto.
(WebKit::PageLoadState::title): Changed to access m_committedState.
(WebKit::PageLoadState::setTitle): Changed to take a transaction token, act on
m_uncommittedState, and not make observer callbacks.
(WebKit::PageLoadState::didStartProgress): Ditto.
(WebKit::PageLoadState::didChangeProgress): Ditto.
(WebKit::PageLoadState::didFinishProgress): Ditto.
* UIProcess/PageLoadState.h:
(WebKit::PageLoadState::Transaction::Transaction): Added. Calls
PageLoadState::beginTransaction.
(WebKit::PageLoadState::Transaction::~Transaction): Added. Calls
PageLoadState::endTransaction.
(WebKit::PageLoadState::Transaction::Token::Token): Added. Sets m_mayHaveUncommittedChanges.
(WebKit::PageLoadState::transaction): Added. Returns a Transaction for this PageLoadState.
(WebKit::PageLoadState::provisionalURL): Changed to access m_committedState.
(WebKit::PageLoadState::url): Ditto.
(WebKit::PageLoadState::unreachableURL): Ditto.
(WebKit::PageLoadState::beginTransaction): Added. Increments the outstanding transaction
count.
(WebKit::PageLoadState::Data::Data): Added. Moved internal state members into this struct
and made its constructor initialize state and estimatedProgress.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::loadURL): Changed to create a PageLoadState::Transaction and pass it
along.
(WebKit::WebPageProxy::loadURLRequest): Ditto.
(WebKit::WebPageProxy::loadAlternateHTMLString): Ditto.
(WebKit::WebPageProxy::reload): Ditto.
(WebKit::WebPageProxy::goForward): Ditto.
(WebKit::WebPageProxy::goBack): Ditto.
(WebKit::WebPageProxy::goToBackForwardItem): Ditto.
(WebKit::WebPageProxy::receivedPolicyDecision): Ditto.
(WebKit::WebPageProxy::didStartProgress): Ditto. Also added a call to
PageLoadState::commitChanges before calling the client, so that the client sees the updated
state.
(WebKit::WebPageProxy::didChangeProgress): Ditto.
(WebKit::WebPageProxy::didFinishProgress): Ditto.
(WebKit::WebPageProxy::didStartProvisionalLoadForFrame): Ditto.
(WebKit::WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame): Ditto.
(WebKit::WebPageProxy::didFailProvisionalLoadForFrame): Ditto.
(WebKit::WebPageProxy::didCommitLoadForFrame): Ditto.
(WebKit::WebPageProxy::didFinishLoadForFrame): Ditto.
(WebKit::WebPageProxy::didFailLoadForFrame): Ditto.
(WebKit::WebPageProxy::didSameDocumentNavigationForFrame): Ditto.
(WebKit::WebPageProxy::didReceiveTitleForFrame): Ditto.
(WebKit::WebPageProxy::decidePolicyForNavigationAction): Changed to create a
PageLoadState::Transaction and pass it along.
(WebKit::WebPageProxy::processDidCrash): Ditto. This addressed a FIXME about the client not
seeing the state prior to the crash, because now the changes cuased by reset() aren’t
committed until after the client callback.

* UIProcess/cf/WebPageProxyCF.cpp:
(WebKit::WebPageProxy::restoreFromSessionStateData): Changed to create a
PageLoadState::Transaction and pass it along.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoaWKBrowsingContextControllermm">trunk/Source/WebKit2/UIProcess/API/Cocoa/WKBrowsingContextController.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessPageLoadStatecpp">trunk/Source/WebKit2/UIProcess/PageLoadState.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessPageLoadStateh">trunk/Source/WebKit2/UIProcess/PageLoadState.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebPageProxycpp">trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcesscfWebPageProxyCFcpp">trunk/Source/WebKit2/UIProcess/cf/WebPageProxyCF.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (160404 => 160405)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2013-12-11 01:28:40 UTC (rev 160404)
+++ trunk/Source/WebKit2/ChangeLog        2013-12-11 02:07:33 UTC (rev 160405)
</span><span class="lines">@@ -1,3 +1,106 @@
</span><ins>+2013-12-10  Dan Bernstein  &lt;mitz@apple.com&gt;
+
+        All observable PageLoadState properties should change in an atomic fashion, with properly nested change notifications
+        https://bugs.webkit.org/show_bug.cgi?id=125431
+
+        Reviewed by Anders Carlsson.
+
+        Made PageLoadState maintain two copies of its state data members, one representing the
+        committed state and one possibly containing uncommitted changes. When changes are committed,
+        change notifications are sent and the uncommitted state is copied into the committed state.
+        Changes can be committed explicitly at any time, but are also committed when the last
+        outstanding transaction ends. Transactions are RAII objects vended by the PageLoadState.
+        Mutating the PageLoadState requires holding a Transaction, which is enforced by making all
+        the mutating member functions take a Transaction::Token. Passing a Token also marks the
+        PageLoadState as possibly having uncommitted changes.
+
+        * UIProcess/API/Cocoa/WKBrowsingContextController.mm:
+        Added PageLoadStateObserver::{will,did}ChangeActiveURL overrides that call
+        -{will,did}ChangeValueForKey:.
+
+        * UIProcess/PageLoadState.cpp:
+        Moved constant from the middle of the file to the beginning and reworded comment.
+        (WebKit::PageLoadState::PageLoadState): Added initializers for new member variables, removed
+        initialization of members that are not part of Data, which initializes them in its
+        constructor.
+        (WebKit::PageLoadState::endTransaction): Added. Calles when a Transaction is destructed.
+        Decrements the outstanding transaction count, and if it is zero, commits changes.
+        (WebKit::PageLoadState::commitChanges): Added. Checks for differences in observable
+        properties between the committed state and the uncommitted state, then makes appropriate
+        willChange Observer callbacks, then copies the uncommitted state into the committed state,
+        then makes appropriate didChange Observer callbacks in reverse order. Also added active URL
+        to the set of observable properties.
+        (WebKit::PageLoadState::reset): Changed to take a transaction token, act on
+        m_uncommittedState, and not make observer callbacks.
+        (WebKit::PageLoadState::isLoading): Changed to access m_committedState.
+        (WebKit::PageLoadState::activeURL): Changed to call a static function factored out of this.
+        (WebKit::PageLoadState::estimatedProgress): Ditto.
+        (WebKit::PageLoadState::pendingAPIRequestURL): Changed to access m_committedState.
+        (WebKit::PageLoadState::setPendingAPIRequestURL): Changed to take a transaction token, act
+        on m_uncommittedState, and not make observer callbacks.
+        (WebKit::PageLoadState::clearPendingAPIRequestURL): Ditto.
+        (WebKit::PageLoadState::didStartProvisionalLoad): Ditto.
+        (WebKit::PageLoadState::didReceiveServerRedirectForProvisionalLoad): Ditto.
+        (WebKit::PageLoadState::didFailProvisionalLoad): Ditto.
+        (WebKit::PageLoadState::didCommitLoad): Ditto.
+        (WebKit::PageLoadState::didFinishLoad): Ditto.
+        (WebKit::PageLoadState::didFailLoad): Ditto.
+        (WebKit::PageLoadState::didSameDocumentNavigation): Ditto.
+        (WebKit::PageLoadState::setUnreachableURL): Ditto.
+        (WebKit::PageLoadState::title): Changed to access m_committedState.
+        (WebKit::PageLoadState::setTitle): Changed to take a transaction token, act on
+        m_uncommittedState, and not make observer callbacks.
+        (WebKit::PageLoadState::didStartProgress): Ditto.
+        (WebKit::PageLoadState::didChangeProgress): Ditto.
+        (WebKit::PageLoadState::didFinishProgress): Ditto.
+        * UIProcess/PageLoadState.h:
+        (WebKit::PageLoadState::Transaction::Transaction): Added. Calls
+        PageLoadState::beginTransaction.
+        (WebKit::PageLoadState::Transaction::~Transaction): Added. Calls
+        PageLoadState::endTransaction.
+        (WebKit::PageLoadState::Transaction::Token::Token): Added. Sets m_mayHaveUncommittedChanges.
+        (WebKit::PageLoadState::transaction): Added. Returns a Transaction for this PageLoadState.
+        (WebKit::PageLoadState::provisionalURL): Changed to access m_committedState.
+        (WebKit::PageLoadState::url): Ditto.
+        (WebKit::PageLoadState::unreachableURL): Ditto.
+        (WebKit::PageLoadState::beginTransaction): Added. Increments the outstanding transaction
+        count.
+        (WebKit::PageLoadState::Data::Data): Added. Moved internal state members into this struct
+        and made its constructor initialize state and estimatedProgress.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::loadURL): Changed to create a PageLoadState::Transaction and pass it
+        along.
+        (WebKit::WebPageProxy::loadURLRequest): Ditto.
+        (WebKit::WebPageProxy::loadAlternateHTMLString): Ditto.
+        (WebKit::WebPageProxy::reload): Ditto.
+        (WebKit::WebPageProxy::goForward): Ditto.
+        (WebKit::WebPageProxy::goBack): Ditto.
+        (WebKit::WebPageProxy::goToBackForwardItem): Ditto.
+        (WebKit::WebPageProxy::receivedPolicyDecision): Ditto.
+        (WebKit::WebPageProxy::didStartProgress): Ditto. Also added a call to
+        PageLoadState::commitChanges before calling the client, so that the client sees the updated
+        state.
+        (WebKit::WebPageProxy::didChangeProgress): Ditto.
+        (WebKit::WebPageProxy::didFinishProgress): Ditto.
+        (WebKit::WebPageProxy::didStartProvisionalLoadForFrame): Ditto.
+        (WebKit::WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame): Ditto.
+        (WebKit::WebPageProxy::didFailProvisionalLoadForFrame): Ditto.
+        (WebKit::WebPageProxy::didCommitLoadForFrame): Ditto.
+        (WebKit::WebPageProxy::didFinishLoadForFrame): Ditto.
+        (WebKit::WebPageProxy::didFailLoadForFrame): Ditto.
+        (WebKit::WebPageProxy::didSameDocumentNavigationForFrame): Ditto.
+        (WebKit::WebPageProxy::didReceiveTitleForFrame): Ditto.
+        (WebKit::WebPageProxy::decidePolicyForNavigationAction): Changed to create a
+        PageLoadState::Transaction and pass it along.
+        (WebKit::WebPageProxy::processDidCrash): Ditto. This addressed a FIXME about the client not
+        seeing the state prior to the crash, because now the changes cuased by reset() aren’t
+        committed until after the client callback.
+
+        * UIProcess/cf/WebPageProxyCF.cpp:
+        (WebKit::WebPageProxy::restoreFromSessionStateData): Changed to create a
+        PageLoadState::Transaction and pass it along.
+
</ins><span class="cx"> 2013-12-10  Ryuan Choi  &lt;ryuan.choi@samsung.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed EFL build fix attempt
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoaWKBrowsingContextControllermm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKBrowsingContextController.mm (160404 => 160405)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKBrowsingContextController.mm        2013-12-11 01:28:40 UTC (rev 160404)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKBrowsingContextController.mm        2013-12-11 02:07:33 UTC (rev 160405)
</span><span class="lines">@@ -84,6 +84,16 @@
</span><span class="cx">         [m_controller didChangeValueForKey:@&quot;title&quot;];
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    virtual void willChangeActiveURL() OVERRIDE
+    {
+        [m_controller willChangeValueForKey:@&quot;activeURL&quot;];
+    }
+
+    virtual void didChangeActiveURL() OVERRIDE
+    {
+        [m_controller didChangeValueForKey:@&quot;activeURL&quot;];
+    }
+
</ins><span class="cx">     virtual void willChangeEstimatedProgress() OVERRIDE
</span><span class="cx">     {
</span><span class="cx">         [m_controller willChangeValueForKey:@&quot;estimatedProgress&quot;];
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessPageLoadStatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/PageLoadState.cpp (160404 => 160405)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/PageLoadState.cpp        2013-12-11 01:28:40 UTC (rev 160404)
+++ trunk/Source/WebKit2/UIProcess/PageLoadState.cpp        2013-12-11 02:07:33 UTC (rev 160405)
</span><span class="lines">@@ -28,9 +28,12 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> 
</span><ins>+// Progress always starts at this value. This helps provide feedback as soon as a load starts.
+static const double initialProgressValue = 0.1;
+
</ins><span class="cx"> PageLoadState::PageLoadState()
</span><del>-    : m_state(State::Finished)
-    , m_estimatedProgress(0)
</del><ins>+    : m_mayHaveUncommittedChanges(false)
+    , m_outstandingTransactionCount(0)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -54,185 +57,233 @@
</span><span class="cx">     m_observers.remove(index);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void PageLoadState::reset()
</del><ins>+void PageLoadState::endTransaction()
</ins><span class="cx"> {
</span><del>-    setState(State::Finished);
</del><ins>+    ASSERT(m_outstandingTransactionCount &gt; 0);
</ins><span class="cx"> 
</span><del>-    m_pendingAPIRequestURL = String();
-    m_provisionalURL = String();
-    m_url = String();
</del><ins>+    if (!--m_outstandingTransactionCount)
+        commitChanges();
+}
</ins><span class="cx"> 
</span><del>-    m_unreachableURL = String();
</del><ins>+void PageLoadState::commitChanges()
+{
+    if (!m_mayHaveUncommittedChanges)
+        return;
+
+    m_mayHaveUncommittedChanges = false;
+
+    bool titleChanged = m_committedState.title != m_uncommittedState.title;
+    bool isLoadingChanged = isLoadingState(m_committedState.state) != isLoadingState(m_uncommittedState.state);
+    bool activeURLChanged = activeURL(m_committedState) != activeURL(m_uncommittedState);
+    bool estimatedProgressChanged = estimatedProgress(m_committedState) != estimatedProgress(m_uncommittedState);
+
+    if (titleChanged)
+        callObserverCallback(&amp;Observer::willChangeTitle);
+    if (isLoadingChanged)
+        callObserverCallback(&amp;Observer::willChangeIsLoading);
+    if (activeURLChanged)
+        callObserverCallback(&amp;Observer::willChangeActiveURL);
+    if (estimatedProgressChanged)
+        callObserverCallback(&amp;Observer::willChangeEstimatedProgress);
+
+    m_committedState = m_uncommittedState;
+
+    // The &quot;did&quot; ordering is the reverse of the &quot;will&quot;. This is a requirement of Cocoa Key-Value Observing.
+    if (estimatedProgressChanged)
+        callObserverCallback(&amp;Observer::didChangeEstimatedProgress);
+    if (activeURLChanged)
+        callObserverCallback(&amp;Observer::didChangeActiveURL);
+    if (isLoadingChanged)
+        callObserverCallback(&amp;Observer::didChangeIsLoading);
+    if (titleChanged)
+        callObserverCallback(&amp;Observer::didChangeTitle);
+}
+
+void PageLoadState::reset(const Transaction::Token&amp; token)
+{
+    ASSERT_UNUSED(token, &amp;token.m_pageLoadState == this);
+
+    m_uncommittedState.state = State::Finished;
+
+    m_uncommittedState.pendingAPIRequestURL = String();
+    m_uncommittedState.provisionalURL = String();
+    m_uncommittedState.url = String();
+
+    m_uncommittedState.unreachableURL = String();
</ins><span class="cx">     m_lastUnreachableURL = String();
</span><span class="cx"> 
</span><del>-    callObserverCallback(&amp;Observer::willChangeTitle);
-    m_title = String();
-    callObserverCallback(&amp;Observer::didChangeTitle);
</del><ins>+    m_uncommittedState.title = String();
</ins><span class="cx"> 
</span><del>-    callObserverCallback(&amp;Observer::willChangeEstimatedProgress);
-    m_estimatedProgress = 0;
-    callObserverCallback(&amp;Observer::didChangeEstimatedProgress);
</del><ins>+    m_uncommittedState.estimatedProgress = 0;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool PageLoadState::isLoading() const
</span><span class="cx"> {
</span><del>-    return isLoadingState(m_state);
</del><ins>+    return isLoadingState(m_committedState.state);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-String PageLoadState::activeURL() const
</del><ins>+String PageLoadState::activeURL(const Data&amp; data)
</ins><span class="cx"> {
</span><span class="cx">     // If there is a currently pending URL, it is the active URL,
</span><span class="cx">     // even when there's no main frame yet, as it might be the
</span><span class="cx">     // first API request.
</span><del>-    if (!m_pendingAPIRequestURL.isNull())
-        return m_pendingAPIRequestURL;
</del><ins>+    if (!data.pendingAPIRequestURL.isNull())
+        return data.pendingAPIRequestURL;
</ins><span class="cx"> 
</span><del>-    if (!m_unreachableURL.isEmpty())
-        return m_unreachableURL;
</del><ins>+    if (!data.unreachableURL.isEmpty())
+        return data.unreachableURL;
</ins><span class="cx"> 
</span><del>-    switch (m_state) {
</del><ins>+    switch (data.state) {
</ins><span class="cx">     case State::Provisional:
</span><del>-        return m_provisionalURL;
</del><ins>+        return data.provisionalURL;
</ins><span class="cx">     case State::Committed:
</span><span class="cx">     case State::Finished:
</span><del>-        return m_url;
</del><ins>+        return data.url;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     ASSERT_NOT_REACHED();
</span><span class="cx">     return String();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-// Always start progress at initialProgressValue. This helps provide feedback as
-// soon as a load starts.
</del><ins>+String PageLoadState::activeURL() const
+{
+    return activeURL(m_committedState);
+}
</ins><span class="cx"> 
</span><del>-static const double initialProgressValue = 0.1;
-
-double PageLoadState::estimatedProgress() const
</del><ins>+double PageLoadState::estimatedProgress(const Data&amp; data)
</ins><span class="cx"> {
</span><del>-    if (!m_pendingAPIRequestURL.isNull())
</del><ins>+    if (!data.pendingAPIRequestURL.isNull())
</ins><span class="cx">         return initialProgressValue;
</span><span class="cx"> 
</span><del>-    return m_estimatedProgress;
</del><ins>+    return data.estimatedProgress;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+double PageLoadState::estimatedProgress() const
+{
+    return estimatedProgress(m_committedState);
+}
+
</ins><span class="cx"> const String&amp; PageLoadState::pendingAPIRequestURL() const
</span><span class="cx"> {
</span><del>-    return m_pendingAPIRequestURL;
</del><ins>+    return m_committedState.pendingAPIRequestURL;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void PageLoadState::setPendingAPIRequestURL(const String&amp; pendingAPIRequestURL)
</del><ins>+void PageLoadState::setPendingAPIRequestURL(const Transaction::Token&amp; token, const String&amp; pendingAPIRequestURL)
</ins><span class="cx"> {
</span><del>-    callObserverCallback(&amp;Observer::willChangeEstimatedProgress);
-    m_pendingAPIRequestURL = pendingAPIRequestURL;
-    callObserverCallback(&amp;Observer::didChangeEstimatedProgress);
</del><ins>+    ASSERT_UNUSED(token, &amp;token.m_pageLoadState == this);
+    m_uncommittedState.pendingAPIRequestURL = pendingAPIRequestURL;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void PageLoadState::clearPendingAPIRequestURL()
</del><ins>+void PageLoadState::clearPendingAPIRequestURL(const Transaction::Token&amp; token)
</ins><span class="cx"> {
</span><del>-    callObserverCallback(&amp;Observer::willChangeEstimatedProgress);
-    m_pendingAPIRequestURL = String();
-    callObserverCallback(&amp;Observer::didChangeEstimatedProgress);
</del><ins>+    ASSERT_UNUSED(token, &amp;token.m_pageLoadState == this);
+    m_uncommittedState.pendingAPIRequestURL = String();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void PageLoadState::didStartProvisionalLoad(const String&amp; url, const String&amp; unreachableURL)
</del><ins>+void PageLoadState::didStartProvisionalLoad(const Transaction::Token&amp; token, const String&amp; url, const String&amp; unreachableURL)
</ins><span class="cx"> {
</span><del>-    ASSERT(m_provisionalURL.isEmpty());
</del><ins>+    ASSERT_UNUSED(token, &amp;token.m_pageLoadState == this);
+    ASSERT(m_uncommittedState.provisionalURL.isEmpty());
</ins><span class="cx"> 
</span><del>-    setState(State::Provisional);
</del><ins>+    m_uncommittedState.state = State::Provisional;
</ins><span class="cx"> 
</span><del>-    m_provisionalURL = url;
</del><ins>+    m_uncommittedState.provisionalURL = url;
</ins><span class="cx"> 
</span><del>-    setUnreachableURL(unreachableURL);
</del><ins>+    setUnreachableURL(token, unreachableURL);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void PageLoadState::didReceiveServerRedirectForProvisionalLoad(const String&amp; url)
</del><ins>+void PageLoadState::didReceiveServerRedirectForProvisionalLoad(const Transaction::Token&amp; token, const String&amp; url)
</ins><span class="cx"> {
</span><del>-    ASSERT(m_state == State::Provisional);
</del><ins>+    ASSERT_UNUSED(token, &amp;token.m_pageLoadState == this);
+    ASSERT(m_uncommittedState.state == State::Provisional);
</ins><span class="cx"> 
</span><del>-    m_provisionalURL = url;
</del><ins>+    m_uncommittedState.provisionalURL = url;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void PageLoadState::didFailProvisionalLoad()
</del><ins>+void PageLoadState::didFailProvisionalLoad(const Transaction::Token&amp; token)
</ins><span class="cx"> {
</span><del>-    ASSERT(m_state == State::Provisional);
</del><ins>+    ASSERT_UNUSED(token, &amp;token.m_pageLoadState == this);
+    ASSERT(m_uncommittedState.state == State::Provisional);
</ins><span class="cx"> 
</span><del>-    setState(State::Finished);
</del><ins>+    m_uncommittedState.state = State::Finished;
</ins><span class="cx"> 
</span><del>-    m_provisionalURL = String();
-    m_unreachableURL = m_lastUnreachableURL;
</del><ins>+    m_uncommittedState.provisionalURL = String();
+    m_uncommittedState.unreachableURL = m_lastUnreachableURL;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void PageLoadState::didCommitLoad()
</del><ins>+void PageLoadState::didCommitLoad(const Transaction::Token&amp; token)
</ins><span class="cx"> {
</span><del>-    ASSERT(m_state == State::Provisional);
</del><ins>+    ASSERT_UNUSED(token, &amp;token.m_pageLoadState == this);
+    ASSERT(m_uncommittedState.state == State::Provisional);
</ins><span class="cx"> 
</span><del>-    setState(State::Committed);
</del><ins>+    m_uncommittedState.state = State::Committed;
</ins><span class="cx"> 
</span><del>-    m_url = m_provisionalURL;
-    m_provisionalURL = String();
</del><ins>+    m_uncommittedState.url = m_uncommittedState.provisionalURL;
+    m_uncommittedState.provisionalURL = String();
</ins><span class="cx"> 
</span><del>-    m_title = String();
</del><ins>+    m_uncommittedState.title = String();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void PageLoadState::didFinishLoad()
</del><ins>+void PageLoadState::didFinishLoad(const Transaction::Token&amp; token)
</ins><span class="cx"> {
</span><del>-    ASSERT(m_state == State::Committed);
-    ASSERT(m_provisionalURL.isEmpty());
</del><ins>+    ASSERT_UNUSED(token, &amp;token.m_pageLoadState == this);
+    ASSERT(m_uncommittedState.state == State::Committed);
+    ASSERT(m_uncommittedState.provisionalURL.isEmpty());
</ins><span class="cx"> 
</span><del>-    setState(State::Finished);
</del><ins>+    m_uncommittedState.state = State::Finished;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void PageLoadState::didFailLoad()
</del><ins>+void PageLoadState::didFailLoad(const Transaction::Token&amp; token)
</ins><span class="cx"> {
</span><del>-    ASSERT(m_provisionalURL.isEmpty());
</del><ins>+    ASSERT_UNUSED(token, &amp;token.m_pageLoadState == this);
+    ASSERT(m_uncommittedState.provisionalURL.isEmpty());
</ins><span class="cx"> 
</span><del>-    setState(State::Finished);
</del><ins>+    m_uncommittedState.state = State::Finished;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void PageLoadState::didSameDocumentNavigation(const String&amp; url)
</del><ins>+void PageLoadState::didSameDocumentNavigation(const Transaction::Token&amp; token, const String&amp; url)
</ins><span class="cx"> {
</span><del>-    ASSERT(!m_url.isEmpty());
</del><ins>+    ASSERT_UNUSED(token, &amp;token.m_pageLoadState == this);
+    ASSERT(!m_uncommittedState.url.isEmpty());
</ins><span class="cx"> 
</span><del>-    m_url = url;
</del><ins>+    m_uncommittedState.url = url;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void PageLoadState::setUnreachableURL(const String&amp; unreachableURL)
</del><ins>+void PageLoadState::setUnreachableURL(const Transaction::Token&amp; token, const String&amp; unreachableURL)
</ins><span class="cx"> {
</span><del>-    m_lastUnreachableURL = m_unreachableURL;
-    m_unreachableURL = unreachableURL;
</del><ins>+    ASSERT_UNUSED(token, &amp;token.m_pageLoadState == this);
+
+    m_lastUnreachableURL = m_uncommittedState.unreachableURL;
+    m_uncommittedState.unreachableURL = unreachableURL;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> const String&amp; PageLoadState::title() const
</span><span class="cx"> {
</span><del>-    return m_title;
</del><ins>+    return m_committedState.title;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void PageLoadState::setTitle(const String&amp; title)
</del><ins>+void PageLoadState::setTitle(const Transaction::Token&amp; token, const String&amp; title)
</ins><span class="cx"> {
</span><del>-    callObserverCallback(&amp;Observer::willChangeTitle);
-    m_title = title;
-    callObserverCallback(&amp;Observer::didChangeTitle);
</del><ins>+    ASSERT_UNUSED(token, &amp;token.m_pageLoadState == this);
+    m_uncommittedState.title = title;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void PageLoadState::didStartProgress()
</del><ins>+void PageLoadState::didStartProgress(const Transaction::Token&amp; token)
</ins><span class="cx"> {
</span><del>-    callObserverCallback(&amp;Observer::willChangeEstimatedProgress);
-    m_estimatedProgress = initialProgressValue;
-    callObserverCallback(&amp;Observer::didChangeEstimatedProgress);
</del><ins>+    ASSERT_UNUSED(token, &amp;token.m_pageLoadState == this);
+    m_uncommittedState.estimatedProgress = initialProgressValue;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void PageLoadState::didChangeProgress(double value)
</del><ins>+void PageLoadState::didChangeProgress(const Transaction::Token&amp; token, double value)
</ins><span class="cx"> {
</span><del>-    callObserverCallback(&amp;Observer::willChangeEstimatedProgress);
-    m_estimatedProgress = value;
-    callObserverCallback(&amp;Observer::didChangeEstimatedProgress);
</del><ins>+    ASSERT_UNUSED(token, &amp;token.m_pageLoadState == this);
+    m_uncommittedState.estimatedProgress = value;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void PageLoadState::didFinishProgress()
</del><ins>+void PageLoadState::didFinishProgress(const Transaction::Token&amp; token)
</ins><span class="cx"> {
</span><del>-    callObserverCallback(&amp;Observer::willChangeEstimatedProgress);
-    m_estimatedProgress = 1;
-    callObserverCallback(&amp;Observer::didChangeEstimatedProgress);
</del><ins>+    ASSERT_UNUSED(token, &amp;token.m_pageLoadState == this);
+    m_uncommittedState.estimatedProgress = 1;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool PageLoadState::isLoadingState(State state)
</span><span class="lines">@@ -250,25 +301,6 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void PageLoadState::setState(State state)
-{
-    if (m_state == state)
-        return;
-
-    bool isLoadingIsChanging = false;
-
-    if (isLoadingState(m_state) != isLoadingState(state))
-        isLoadingIsChanging = true;
-
-    if (isLoadingIsChanging)
-        callObserverCallback(&amp;Observer::willChangeIsLoading);
-
-    m_state = state;
-
-    if (isLoadingIsChanging)
-        callObserverCallback(&amp;Observer::didChangeIsLoading);
-}
-
</del><span class="cx"> void PageLoadState::callObserverCallback(void (Observer::*callback)())
</span><span class="cx"> {
</span><span class="cx">     for (auto* observer : m_observers)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessPageLoadStateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/PageLoadState.h (160404 => 160405)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/PageLoadState.h        2013-12-11 01:28:40 UTC (rev 160404)
+++ trunk/Source/WebKit2/UIProcess/PageLoadState.h        2013-12-11 02:07:33 UTC (rev 160405)
</span><span class="lines">@@ -51,69 +51,137 @@
</span><span class="cx">         virtual void willChangeTitle() = 0;
</span><span class="cx">         virtual void didChangeTitle() = 0;
</span><span class="cx"> 
</span><ins>+        virtual void willChangeActiveURL() = 0;
+        virtual void didChangeActiveURL() = 0;
+
</ins><span class="cx">         virtual void willChangeEstimatedProgress() = 0;
</span><span class="cx">         virtual void didChangeEstimatedProgress() = 0;
</span><span class="cx">     };
</span><span class="cx"> 
</span><ins>+    class Transaction {
+        WTF_MAKE_NONCOPYABLE(Transaction);
+    public:
+        Transaction(Transaction&amp;&amp; other)
+            : m_pageLoadState(other.m_pageLoadState)
+        {
+            other.m_pageLoadState = nullptr;
+        }
+
+        ~Transaction()
+        {
+            if (m_pageLoadState)
+                m_pageLoadState-&gt;endTransaction();
+        }
+
+    private:
+        friend class PageLoadState;
+
+        explicit Transaction(PageLoadState&amp; pageLoadState)
+            : m_pageLoadState(&amp;pageLoadState)
+        {
+            m_pageLoadState-&gt;beginTransaction();
+        }
+
+        class Token {
+        public:
+            Token(Transaction&amp; transaction)
+#if !ASSERT_DISABLED
+                : m_pageLoadState(*transaction.m_pageLoadState)
+#endif
+            {
+                transaction.m_pageLoadState-&gt;m_mayHaveUncommittedChanges = true;
+            }
+
+#if !ASSERT_DISABLED
+            PageLoadState&amp; m_pageLoadState;
+#endif
+        };
+
+        PageLoadState* m_pageLoadState;
+    };
+
</ins><span class="cx">     void addObserver(Observer&amp;);
</span><span class="cx">     void removeObserver(Observer&amp;);
</span><span class="cx"> 
</span><del>-    void reset();
</del><ins>+    Transaction transaction() { return Transaction(*this); }
+    void commitChanges();
</ins><span class="cx"> 
</span><ins>+    void reset(const Transaction::Token&amp;);
+
</ins><span class="cx">     bool isLoading() const;
</span><span class="cx"> 
</span><del>-    const String&amp; provisionalURL() const { return m_provisionalURL; }
-    const String&amp; url() const { return m_url; }
-    const String&amp; unreachableURL() const { return m_unreachableURL; }
</del><ins>+    const String&amp; provisionalURL() const { return m_committedState.provisionalURL; }
+    const String&amp; url() const { return m_committedState.url; }
+    const String&amp; unreachableURL() const { return m_committedState.unreachableURL; }
</ins><span class="cx"> 
</span><span class="cx">     String activeURL() const;
</span><span class="cx"> 
</span><span class="cx">     double estimatedProgress() const;
</span><span class="cx"> 
</span><span class="cx">     const String&amp; pendingAPIRequestURL() const;
</span><del>-    void setPendingAPIRequestURL(const String&amp;);
-    void clearPendingAPIRequestURL();
</del><ins>+    void setPendingAPIRequestURL(const Transaction::Token&amp;, const String&amp;);
+    void clearPendingAPIRequestURL(const Transaction::Token&amp;);
</ins><span class="cx"> 
</span><del>-    void didStartProvisionalLoad(const String&amp; url, const String&amp; unreachableURL);
-    void didReceiveServerRedirectForProvisionalLoad(const String&amp; url);
-    void didFailProvisionalLoad();
</del><ins>+    void didStartProvisionalLoad(const Transaction::Token&amp;, const String&amp; url, const String&amp; unreachableURL);
+    void didReceiveServerRedirectForProvisionalLoad(const Transaction::Token&amp;, const String&amp; url);
+    void didFailProvisionalLoad(const Transaction::Token&amp;);
</ins><span class="cx"> 
</span><del>-    void didCommitLoad();
-    void didFinishLoad();
-    void didFailLoad();
</del><ins>+    void didCommitLoad(const Transaction::Token&amp;);
+    void didFinishLoad(const Transaction::Token&amp;);
+    void didFailLoad(const Transaction::Token&amp;);
</ins><span class="cx"> 
</span><del>-    void didSameDocumentNavigation(const String&amp; url);
</del><ins>+    void didSameDocumentNavigation(const Transaction::Token&amp;, const String&amp; url);
</ins><span class="cx"> 
</span><del>-    void setUnreachableURL(const String&amp;);
</del><ins>+    void setUnreachableURL(const Transaction::Token&amp;, const String&amp;);
</ins><span class="cx"> 
</span><span class="cx">     const String&amp; title() const;
</span><del>-    void setTitle(const String&amp;);
</del><ins>+    void setTitle(const Transaction::Token&amp;, const String&amp;);
</ins><span class="cx"> 
</span><del>-    void didStartProgress();
-    void didChangeProgress(double);
-    void didFinishProgress();
</del><ins>+    void didStartProgress(const Transaction::Token&amp;);
+    void didChangeProgress(const Transaction::Token&amp;, double);
+    void didFinishProgress(const Transaction::Token&amp;);
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     static bool isLoadingState(State);
</span><del>-    void setState(State);
</del><span class="cx"> 
</span><ins>+    void beginTransaction() { ++m_outstandingTransactionCount; }
+    void endTransaction();
+
</ins><span class="cx">     void callObserverCallback(void (Observer::*)());
</span><span class="cx"> 
</span><span class="cx">     Vector&lt;Observer*&gt; m_observers;
</span><span class="cx"> 
</span><del>-    State m_state;
</del><ins>+    struct Data {
+        Data()
+            : state(State::Finished)
+            , estimatedProgress(0)
+        {
+        }
</ins><span class="cx"> 
</span><del>-    String m_pendingAPIRequestURL;
</del><ins>+        State state;
</ins><span class="cx"> 
</span><del>-    String m_provisionalURL;
-    String m_url;
</del><ins>+        String pendingAPIRequestURL;
</ins><span class="cx"> 
</span><del>-    String m_unreachableURL;
</del><ins>+        String provisionalURL;
+        String url;
+
+        String unreachableURL;
+
+        String title;
+
+        double estimatedProgress;
+    };
+
+    static String activeURL(const Data&amp;);
+    static double estimatedProgress(const Data&amp;);
+
+    Data m_committedState;
+    Data m_uncommittedState;
+
</ins><span class="cx">     String m_lastUnreachableURL;
</span><span class="cx"> 
</span><del>-    String m_title;
-
-    double m_estimatedProgress;
</del><ins>+    bool m_mayHaveUncommittedChanges;
+    unsigned m_outstandingTransactionCount;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (160404 => 160405)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2013-12-11 01:28:40 UTC (rev 160404)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2013-12-11 02:07:33 UTC (rev 160405)
</span><span class="lines">@@ -600,8 +600,10 @@
</span><span class="cx"> 
</span><span class="cx"> void WebPageProxy::loadURL(const String&amp; url, API::Object* userData)
</span><span class="cx"> {
</span><del>-    m_pageLoadState.setPendingAPIRequestURL(url);
</del><ins>+    auto transaction = m_pageLoadState.transaction();
</ins><span class="cx"> 
</span><ins>+    m_pageLoadState.setPendingAPIRequestURL(transaction, url);
+
</ins><span class="cx">     if (!isValid())
</span><span class="cx">         reattachToWebProcess();
</span><span class="cx"> 
</span><span class="lines">@@ -615,8 +617,10 @@
</span><span class="cx"> 
</span><span class="cx"> void WebPageProxy::loadURLRequest(WebURLRequest* urlRequest, API::Object* userData)
</span><span class="cx"> {
</span><del>-    m_pageLoadState.setPendingAPIRequestURL(urlRequest-&gt;resourceRequest().url());
</del><ins>+    auto transaction = m_pageLoadState.transaction();
</ins><span class="cx"> 
</span><ins>+    m_pageLoadState.setPendingAPIRequestURL(transaction, urlRequest-&gt;resourceRequest().url());
+
</ins><span class="cx">     if (!isValid())
</span><span class="cx">         reattachToWebProcess();
</span><span class="cx"> 
</span><span class="lines">@@ -680,8 +684,10 @@
</span><span class="cx">     if (!isValid())
</span><span class="cx">         reattachToWebProcess();
</span><span class="cx"> 
</span><del>-    m_pageLoadState.setUnreachableURL(unreachableURL);
</del><ins>+    auto transaction = m_pageLoadState.transaction();
</ins><span class="cx"> 
</span><ins>+    m_pageLoadState.setUnreachableURL(transaction, unreachableURL);
+
</ins><span class="cx">     if (m_mainFrame)
</span><span class="cx">         m_mainFrame-&gt;setUnreachableURL(unreachableURL);
</span><span class="cx"> 
</span><span class="lines">@@ -723,7 +729,8 @@
</span><span class="cx"> 
</span><span class="cx">     if (m_backForwardList-&gt;currentItem()) {
</span><span class="cx">         String url = m_backForwardList-&gt;currentItem()-&gt;url();
</span><del>-        m_pageLoadState.setPendingAPIRequestURL(url);
</del><ins>+        auto transaction = m_pageLoadState.transaction();
+        m_pageLoadState.setPendingAPIRequestURL(transaction, url);
</ins><span class="cx"> 
</span><span class="cx">         // We may not have an extension yet if back/forward list was reinstated after a WebProcess crash or a browser relaunch
</span><span class="cx">         bool createdExtension = maybeInitializeSandboxExtensionHandle(URL(URL(), url), sandboxExtensionHandle);
</span><span class="lines">@@ -749,8 +756,10 @@
</span><span class="cx">     if (!forwardItem)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    m_pageLoadState.setPendingAPIRequestURL(forwardItem-&gt;url());
</del><ins>+    auto transaction = m_pageLoadState.transaction();
</ins><span class="cx"> 
</span><ins>+    m_pageLoadState.setPendingAPIRequestURL(transaction, forwardItem-&gt;url());
+
</ins><span class="cx">     if (!isValid()) {
</span><span class="cx">         reattachToWebProcessWithItem(forwardItem);
</span><span class="cx">         return;
</span><span class="lines">@@ -774,8 +783,10 @@
</span><span class="cx">     if (!backItem)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    m_pageLoadState.setPendingAPIRequestURL(backItem-&gt;url());
</del><ins>+    auto transaction = m_pageLoadState.transaction();
</ins><span class="cx"> 
</span><ins>+    m_pageLoadState.setPendingAPIRequestURL(transaction, backItem-&gt;url());
+
</ins><span class="cx">     if (!isValid()) {
</span><span class="cx">         reattachToWebProcessWithItem(backItem);
</span><span class="cx">         return;
</span><span class="lines">@@ -797,8 +808,10 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    m_pageLoadState.setPendingAPIRequestURL(item-&gt;url());
</del><ins>+    auto transaction = m_pageLoadState.transaction();
</ins><span class="cx"> 
</span><ins>+    m_pageLoadState.setPendingAPIRequestURL(transaction, item-&gt;url());
+
</ins><span class="cx">     m_process-&gt;send(Messages::WebPage::GoToBackForwardItem(item-&gt;itemID()), m_pageID);
</span><span class="cx">     m_process-&gt;responsivenessTimer()-&gt;start();
</span><span class="cx"> }
</span><span class="lines">@@ -1405,8 +1418,10 @@
</span><span class="cx">     if (!isValid())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    auto transaction = m_pageLoadState.transaction();
+
</ins><span class="cx">     if (action == PolicyIgnore)
</span><del>-        m_pageLoadState.clearPendingAPIRequestURL();
</del><ins>+        m_pageLoadState.clearPendingAPIRequestURL(transaction);
</ins><span class="cx"> 
</span><span class="cx">     uint64_t downloadID = 0;
</span><span class="cx">     if (action == PolicyDownload) {
</span><span class="lines">@@ -2063,29 +2078,37 @@
</span><span class="cx"> 
</span><span class="cx"> void WebPageProxy::didStartProgress()
</span><span class="cx"> {
</span><del>-    m_pageLoadState.didStartProgress();
</del><ins>+    auto transaction = m_pageLoadState.transaction();
+    m_pageLoadState.didStartProgress(transaction);
</ins><span class="cx"> 
</span><ins>+    m_pageLoadState.commitChanges();
</ins><span class="cx">     m_loaderClient.didStartProgress(this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebPageProxy::didChangeProgress(double value)
</span><span class="cx"> {
</span><del>-    m_pageLoadState.didChangeProgress(value);
</del><ins>+    auto transaction = m_pageLoadState.transaction();
+    m_pageLoadState.didChangeProgress(transaction, value);
</ins><span class="cx"> 
</span><ins>+    m_pageLoadState.commitChanges();
</ins><span class="cx">     m_loaderClient.didChangeProgress(this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebPageProxy::didFinishProgress()
</span><span class="cx"> {
</span><del>-    m_pageLoadState.didFinishProgress();
</del><ins>+    auto transaction = m_pageLoadState.transaction();
+    m_pageLoadState.didFinishProgress(transaction);
</ins><span class="cx"> 
</span><ins>+    m_pageLoadState.commitChanges();
</ins><span class="cx">     m_loaderClient.didFinishProgress(this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebPageProxy::didStartProvisionalLoadForFrame(uint64_t frameID, const String&amp; url, const String&amp; unreachableURL, CoreIPC::MessageDecoder&amp; decoder)
</span><span class="cx"> {
</span><del>-    m_pageLoadState.clearPendingAPIRequestURL();
</del><ins>+    auto transaction = m_pageLoadState.transaction();
</ins><span class="cx"> 
</span><ins>+    m_pageLoadState.clearPendingAPIRequestURL(transaction);
+
</ins><span class="cx">     RefPtr&lt;API::Object&gt; userData;
</span><span class="cx">     WebContextUserMessageDecoder messageDecoder(userData, process());
</span><span class="cx">     if (!decoder.decode(messageDecoder))
</span><span class="lines">@@ -2096,11 +2119,12 @@
</span><span class="cx">     MESSAGE_CHECK_URL(url);
</span><span class="cx"> 
</span><span class="cx">     if (frame-&gt;isMainFrame())
</span><del>-        m_pageLoadState.didStartProvisionalLoad(url, unreachableURL);
</del><ins>+        m_pageLoadState.didStartProvisionalLoad(transaction, url, unreachableURL);
</ins><span class="cx"> 
</span><span class="cx">     frame-&gt;setUnreachableURL(unreachableURL);
</span><span class="cx">     frame-&gt;didStartProvisionalLoad(url);
</span><span class="cx"> 
</span><ins>+    m_pageLoadState.commitChanges();
</ins><span class="cx">     m_loaderClient.didStartProvisionalLoadForFrame(this, frame, userData.get());
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2115,11 +2139,14 @@
</span><span class="cx">     MESSAGE_CHECK(frame);
</span><span class="cx">     MESSAGE_CHECK_URL(url);
</span><span class="cx"> 
</span><ins>+    auto transaction = m_pageLoadState.transaction();
+
</ins><span class="cx">     if (frame-&gt;isMainFrame())
</span><del>-        m_pageLoadState.didReceiveServerRedirectForProvisionalLoad(url);
</del><ins>+        m_pageLoadState.didReceiveServerRedirectForProvisionalLoad(transaction, url);
</ins><span class="cx"> 
</span><span class="cx">     frame-&gt;didReceiveServerRedirectForProvisionalLoad(url);
</span><span class="cx"> 
</span><ins>+    m_pageLoadState.commitChanges();
</ins><span class="cx">     m_loaderClient.didReceiveServerRedirectForProvisionalLoadForFrame(this, frame, userData.get());
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2133,11 +2160,14 @@
</span><span class="cx">     WebFrameProxy* frame = m_process-&gt;webFrame(frameID);
</span><span class="cx">     MESSAGE_CHECK(frame);
</span><span class="cx"> 
</span><ins>+    auto transaction = m_pageLoadState.transaction();
+
</ins><span class="cx">     if (frame-&gt;isMainFrame())
</span><del>-        m_pageLoadState.didFailProvisionalLoad();
</del><ins>+        m_pageLoadState.didFailProvisionalLoad(transaction);
</ins><span class="cx"> 
</span><span class="cx">     frame-&gt;didFailProvisionalLoad();
</span><span class="cx"> 
</span><ins>+    m_pageLoadState.commitChanges();
</ins><span class="cx">     m_loaderClient.didFailProvisionalLoadWithErrorForFrame(this, frame, error, userData.get());
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2164,8 +2194,10 @@
</span><span class="cx">     WebFrameProxy* frame = m_process-&gt;webFrame(frameID);
</span><span class="cx">     MESSAGE_CHECK(frame);
</span><span class="cx"> 
</span><ins>+    auto transaction = m_pageLoadState.transaction();
+
</ins><span class="cx">     if (frame-&gt;isMainFrame()) {
</span><del>-        m_pageLoadState.didCommitLoad();
</del><ins>+        m_pageLoadState.didCommitLoad(transaction);
</ins><span class="cx">         m_pageClient.didCommitLoadForMainFrame();
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -2188,6 +2220,7 @@
</span><span class="cx">     if (frame-&gt;isMainFrame() &amp;&amp; static_cast&lt;FrameLoadType&gt;(opaqueFrameLoadType) == FrameLoadTypeStandard)
</span><span class="cx">         m_pageScaleFactor = 1;
</span><span class="cx"> 
</span><ins>+    m_pageLoadState.commitChanges();
</ins><span class="cx">     m_loaderClient.didCommitLoadForFrame(this, frame, userData.get());
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2214,11 +2247,14 @@
</span><span class="cx">     WebFrameProxy* frame = m_process-&gt;webFrame(frameID);
</span><span class="cx">     MESSAGE_CHECK(frame);
</span><span class="cx"> 
</span><ins>+    auto transaction = m_pageLoadState.transaction();
+
</ins><span class="cx">     if (frame-&gt;isMainFrame())
</span><del>-        m_pageLoadState.didFinishLoad();
</del><ins>+        m_pageLoadState.didFinishLoad(transaction);
</ins><span class="cx"> 
</span><span class="cx">     frame-&gt;didFinishLoad();
</span><span class="cx"> 
</span><ins>+    m_pageLoadState.commitChanges();
</ins><span class="cx">     m_loaderClient.didFinishLoadForFrame(this, frame, userData.get());
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2234,11 +2270,14 @@
</span><span class="cx"> 
</span><span class="cx">     clearLoadDependentCallbacks();
</span><span class="cx"> 
</span><ins>+    auto transaction = m_pageLoadState.transaction();
+
</ins><span class="cx">     if (frame-&gt;isMainFrame())
</span><del>-        m_pageLoadState.didFailLoad();
</del><ins>+        m_pageLoadState.didFailLoad(transaction);
</ins><span class="cx"> 
</span><span class="cx">     frame-&gt;didFailLoad();
</span><span class="cx"> 
</span><ins>+    m_pageLoadState.commitChanges();
</ins><span class="cx">     m_loaderClient.didFailLoadWithErrorForFrame(this, frame, error, userData.get());
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2253,12 +2292,15 @@
</span><span class="cx">     MESSAGE_CHECK(frame);
</span><span class="cx">     MESSAGE_CHECK_URL(url);
</span><span class="cx"> 
</span><ins>+    auto transaction = m_pageLoadState.transaction();
+
</ins><span class="cx">     if (frame-&gt;isMainFrame())
</span><del>-        m_pageLoadState.didSameDocumentNavigation(url);
</del><ins>+        m_pageLoadState.didSameDocumentNavigation(transaction, url);
</ins><span class="cx"> 
</span><del>-    m_pageLoadState.clearPendingAPIRequestURL();
</del><ins>+    m_pageLoadState.clearPendingAPIRequestURL(transaction);
</ins><span class="cx">     frame-&gt;didSameDocumentNavigation(url);
</span><span class="cx"> 
</span><ins>+    m_pageLoadState.commitChanges();
</ins><span class="cx">     m_loaderClient.didSameDocumentNavigationForFrame(this, frame, static_cast&lt;SameDocumentNavigationType&gt;(opaqueSameDocumentNavigationType), userData.get());
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2272,11 +2314,14 @@
</span><span class="cx">     WebFrameProxy* frame = m_process-&gt;webFrame(frameID);
</span><span class="cx">     MESSAGE_CHECK(frame);
</span><span class="cx"> 
</span><ins>+    auto transaction = m_pageLoadState.transaction();
+
</ins><span class="cx">     if (frame-&gt;isMainFrame())
</span><del>-        m_pageLoadState.setTitle(title);
</del><ins>+        m_pageLoadState.setTitle(transaction, title);
</ins><span class="cx"> 
</span><span class="cx">     frame-&gt;didChangeTitle(title);
</span><span class="cx">     
</span><ins>+    m_pageLoadState.commitChanges();
</ins><span class="cx">     m_loaderClient.didReceiveTitleForFrame(this, title, frame, userData.get());
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2386,8 +2431,10 @@
</span><span class="cx">     if (!decoder.decode(messageDecoder))
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    auto transaction = m_pageLoadState.transaction();
+
</ins><span class="cx">     if (request.url() != m_pageLoadState.pendingAPIRequestURL())
</span><del>-        m_pageLoadState.clearPendingAPIRequestURL();
</del><ins>+        m_pageLoadState.clearPendingAPIRequestURL(transaction);
</ins><span class="cx"> 
</span><span class="cx">     WebFrameProxy* frame = m_process-&gt;webFrame(frameID);
</span><span class="cx">     MESSAGE_CHECK(frame);
</span><span class="lines">@@ -3681,11 +3728,12 @@
</span><span class="cx"> 
</span><span class="cx">     resetStateAfterProcessExited();
</span><span class="cx"> 
</span><del>-    // FIXME: Consider calling reset after calling out to the loader client,
-    // having the page load state available could be useful.
-    m_pageLoadState.reset();
</del><ins>+    auto transaction = m_pageLoadState.transaction();
</ins><span class="cx"> 
</span><ins>+    m_pageLoadState.reset(transaction);
+
</ins><span class="cx">     m_pageClient.processDidCrash();
</span><ins>+
</ins><span class="cx">     m_loaderClient.processDidCrash(this);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcesscfWebPageProxyCFcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/cf/WebPageProxyCF.cpp (160404 => 160405)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/cf/WebPageProxyCF.cpp        2013-12-11 01:28:40 UTC (rev 160404)
+++ trunk/Source/WebKit2/UIProcess/cf/WebPageProxyCF.cpp        2013-12-11 02:07:33 UTC (rev 160405)
</span><span class="lines">@@ -151,6 +151,8 @@
</span><span class="cx">             provisionalURL = static_cast&lt;CFStringRef&gt;(value);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    auto transaction = m_pageLoadState.transaction();
+
</ins><span class="cx">     if (backForwardListDictionary) {
</span><span class="cx">         if (!m_backForwardList-&gt;restoreFromCFDictionaryRepresentation(backForwardListDictionary))
</span><span class="cx">             LOG(SessionState, &quot;Failed to restore back/forward list from SessionHistory dictionary&quot;);
</span><span class="lines">@@ -165,7 +167,7 @@
</span><span class="cx">                     process().send(Messages::WebPage::RestoreSession(state), m_pageID);
</span><span class="cx">                 else {
</span><span class="cx">                     if (WebBackForwardListItem* item = m_backForwardList-&gt;currentItem())
</span><del>-                        m_pageLoadState.setPendingAPIRequestURL(item-&gt;url());
</del><ins>+                        m_pageLoadState.setPendingAPIRequestURL(transaction, item-&gt;url());
</ins><span class="cx"> 
</span><span class="cx">                     process().send(Messages::WebPage::RestoreSessionAndNavigateToCurrentItem(state), m_pageID);
</span><span class="cx">                 }
</span></span></pre>
</div>
</div>

</body>
</html>