Changeset 160405 in webkit


Ignore:
Timestamp:
Dec 10, 2013 6:07:33 PM (10 years ago)
Author:
mitz@apple.com
Message:

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.

Location:
trunk/Source/WebKit2
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r160404 r160405  
     12013-12-10  Dan Bernstein  <mitz@apple.com>
     2
     3        All observable PageLoadState properties should change in an atomic fashion, with properly nested change notifications
     4        https://bugs.webkit.org/show_bug.cgi?id=125431
     5
     6        Reviewed by Anders Carlsson.
     7
     8        Made PageLoadState maintain two copies of its state data members, one representing the
     9        committed state and one possibly containing uncommitted changes. When changes are committed,
     10        change notifications are sent and the uncommitted state is copied into the committed state.
     11        Changes can be committed explicitly at any time, but are also committed when the last
     12        outstanding transaction ends. Transactions are RAII objects vended by the PageLoadState.
     13        Mutating the PageLoadState requires holding a Transaction, which is enforced by making all
     14        the mutating member functions take a Transaction::Token. Passing a Token also marks the
     15        PageLoadState as possibly having uncommitted changes.
     16
     17        * UIProcess/API/Cocoa/WKBrowsingContextController.mm:
     18        Added PageLoadStateObserver::{will,did}ChangeActiveURL overrides that call
     19        -{will,did}ChangeValueForKey:.
     20
     21        * UIProcess/PageLoadState.cpp:
     22        Moved constant from the middle of the file to the beginning and reworded comment.
     23        (WebKit::PageLoadState::PageLoadState): Added initializers for new member variables, removed
     24        initialization of members that are not part of Data, which initializes them in its
     25        constructor.
     26        (WebKit::PageLoadState::endTransaction): Added. Calles when a Transaction is destructed.
     27        Decrements the outstanding transaction count, and if it is zero, commits changes.
     28        (WebKit::PageLoadState::commitChanges): Added. Checks for differences in observable
     29        properties between the committed state and the uncommitted state, then makes appropriate
     30        willChange Observer callbacks, then copies the uncommitted state into the committed state,
     31        then makes appropriate didChange Observer callbacks in reverse order. Also added active URL
     32        to the set of observable properties.
     33        (WebKit::PageLoadState::reset): Changed to take a transaction token, act on
     34        m_uncommittedState, and not make observer callbacks.
     35        (WebKit::PageLoadState::isLoading): Changed to access m_committedState.
     36        (WebKit::PageLoadState::activeURL): Changed to call a static function factored out of this.
     37        (WebKit::PageLoadState::estimatedProgress): Ditto.
     38        (WebKit::PageLoadState::pendingAPIRequestURL): Changed to access m_committedState.
     39        (WebKit::PageLoadState::setPendingAPIRequestURL): Changed to take a transaction token, act
     40        on m_uncommittedState, and not make observer callbacks.
     41        (WebKit::PageLoadState::clearPendingAPIRequestURL): Ditto.
     42        (WebKit::PageLoadState::didStartProvisionalLoad): Ditto.
     43        (WebKit::PageLoadState::didReceiveServerRedirectForProvisionalLoad): Ditto.
     44        (WebKit::PageLoadState::didFailProvisionalLoad): Ditto.
     45        (WebKit::PageLoadState::didCommitLoad): Ditto.
     46        (WebKit::PageLoadState::didFinishLoad): Ditto.
     47        (WebKit::PageLoadState::didFailLoad): Ditto.
     48        (WebKit::PageLoadState::didSameDocumentNavigation): Ditto.
     49        (WebKit::PageLoadState::setUnreachableURL): Ditto.
     50        (WebKit::PageLoadState::title): Changed to access m_committedState.
     51        (WebKit::PageLoadState::setTitle): Changed to take a transaction token, act on
     52        m_uncommittedState, and not make observer callbacks.
     53        (WebKit::PageLoadState::didStartProgress): Ditto.
     54        (WebKit::PageLoadState::didChangeProgress): Ditto.
     55        (WebKit::PageLoadState::didFinishProgress): Ditto.
     56        * UIProcess/PageLoadState.h:
     57        (WebKit::PageLoadState::Transaction::Transaction): Added. Calls
     58        PageLoadState::beginTransaction.
     59        (WebKit::PageLoadState::Transaction::~Transaction): Added. Calls
     60        PageLoadState::endTransaction.
     61        (WebKit::PageLoadState::Transaction::Token::Token): Added. Sets m_mayHaveUncommittedChanges.
     62        (WebKit::PageLoadState::transaction): Added. Returns a Transaction for this PageLoadState.
     63        (WebKit::PageLoadState::provisionalURL): Changed to access m_committedState.
     64        (WebKit::PageLoadState::url): Ditto.
     65        (WebKit::PageLoadState::unreachableURL): Ditto.
     66        (WebKit::PageLoadState::beginTransaction): Added. Increments the outstanding transaction
     67        count.
     68        (WebKit::PageLoadState::Data::Data): Added. Moved internal state members into this struct
     69        and made its constructor initialize state and estimatedProgress.
     70
     71        * UIProcess/WebPageProxy.cpp:
     72        (WebKit::WebPageProxy::loadURL): Changed to create a PageLoadState::Transaction and pass it
     73        along.
     74        (WebKit::WebPageProxy::loadURLRequest): Ditto.
     75        (WebKit::WebPageProxy::loadAlternateHTMLString): Ditto.
     76        (WebKit::WebPageProxy::reload): Ditto.
     77        (WebKit::WebPageProxy::goForward): Ditto.
     78        (WebKit::WebPageProxy::goBack): Ditto.
     79        (WebKit::WebPageProxy::goToBackForwardItem): Ditto.
     80        (WebKit::WebPageProxy::receivedPolicyDecision): Ditto.
     81        (WebKit::WebPageProxy::didStartProgress): Ditto. Also added a call to
     82        PageLoadState::commitChanges before calling the client, so that the client sees the updated
     83        state.
     84        (WebKit::WebPageProxy::didChangeProgress): Ditto.
     85        (WebKit::WebPageProxy::didFinishProgress): Ditto.
     86        (WebKit::WebPageProxy::didStartProvisionalLoadForFrame): Ditto.
     87        (WebKit::WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame): Ditto.
     88        (WebKit::WebPageProxy::didFailProvisionalLoadForFrame): Ditto.
     89        (WebKit::WebPageProxy::didCommitLoadForFrame): Ditto.
     90        (WebKit::WebPageProxy::didFinishLoadForFrame): Ditto.
     91        (WebKit::WebPageProxy::didFailLoadForFrame): Ditto.
     92        (WebKit::WebPageProxy::didSameDocumentNavigationForFrame): Ditto.
     93        (WebKit::WebPageProxy::didReceiveTitleForFrame): Ditto.
     94        (WebKit::WebPageProxy::decidePolicyForNavigationAction): Changed to create a
     95        PageLoadState::Transaction and pass it along.
     96        (WebKit::WebPageProxy::processDidCrash): Ditto. This addressed a FIXME about the client not
     97        seeing the state prior to the crash, because now the changes cuased by reset() aren’t
     98        committed until after the client callback.
     99
     100        * UIProcess/cf/WebPageProxyCF.cpp:
     101        (WebKit::WebPageProxy::restoreFromSessionStateData): Changed to create a
     102        PageLoadState::Transaction and pass it along.
     103
    11042013-12-10  Ryuan Choi  <ryuan.choi@samsung.com>
    2105
  • trunk/Source/WebKit2/UIProcess/API/Cocoa/WKBrowsingContextController.mm

    r160227 r160405  
    8585    }
    8686
     87    virtual void willChangeActiveURL() OVERRIDE
     88    {
     89        [m_controller willChangeValueForKey:@"activeURL"];
     90    }
     91
     92    virtual void didChangeActiveURL() OVERRIDE
     93    {
     94        [m_controller didChangeValueForKey:@"activeURL"];
     95    }
     96
    8797    virtual void willChangeEstimatedProgress() OVERRIDE
    8898    {
  • trunk/Source/WebKit2/UIProcess/PageLoadState.cpp

    r160137 r160405  
    2929namespace WebKit {
    3030
     31// Progress always starts at this value. This helps provide feedback as soon as a load starts.
     32static const double initialProgressValue = 0.1;
     33
    3134PageLoadState::PageLoadState()
    32     : m_state(State::Finished)
    33     , m_estimatedProgress(0)
     35    : m_mayHaveUncommittedChanges(false)
     36    , m_outstandingTransactionCount(0)
    3437{
    3538}
     
    5558}
    5659
    57 void PageLoadState::reset()
    58 {
    59     setState(State::Finished);
    60 
    61     m_pendingAPIRequestURL = String();
    62     m_provisionalURL = String();
    63     m_url = String();
    64 
    65     m_unreachableURL = String();
     60void PageLoadState::endTransaction()
     61{
     62    ASSERT(m_outstandingTransactionCount > 0);
     63
     64    if (!--m_outstandingTransactionCount)
     65        commitChanges();
     66}
     67
     68void PageLoadState::commitChanges()
     69{
     70    if (!m_mayHaveUncommittedChanges)
     71        return;
     72
     73    m_mayHaveUncommittedChanges = false;
     74
     75    bool titleChanged = m_committedState.title != m_uncommittedState.title;
     76    bool isLoadingChanged = isLoadingState(m_committedState.state) != isLoadingState(m_uncommittedState.state);
     77    bool activeURLChanged = activeURL(m_committedState) != activeURL(m_uncommittedState);
     78    bool estimatedProgressChanged = estimatedProgress(m_committedState) != estimatedProgress(m_uncommittedState);
     79
     80    if (titleChanged)
     81        callObserverCallback(&Observer::willChangeTitle);
     82    if (isLoadingChanged)
     83        callObserverCallback(&Observer::willChangeIsLoading);
     84    if (activeURLChanged)
     85        callObserverCallback(&Observer::willChangeActiveURL);
     86    if (estimatedProgressChanged)
     87        callObserverCallback(&Observer::willChangeEstimatedProgress);
     88
     89    m_committedState = m_uncommittedState;
     90
     91    // The "did" ordering is the reverse of the "will". This is a requirement of Cocoa Key-Value Observing.
     92    if (estimatedProgressChanged)
     93        callObserverCallback(&Observer::didChangeEstimatedProgress);
     94    if (activeURLChanged)
     95        callObserverCallback(&Observer::didChangeActiveURL);
     96    if (isLoadingChanged)
     97        callObserverCallback(&Observer::didChangeIsLoading);
     98    if (titleChanged)
     99        callObserverCallback(&Observer::didChangeTitle);
     100}
     101
     102void PageLoadState::reset(const Transaction::Token& token)
     103{
     104    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
     105
     106    m_uncommittedState.state = State::Finished;
     107
     108    m_uncommittedState.pendingAPIRequestURL = String();
     109    m_uncommittedState.provisionalURL = String();
     110    m_uncommittedState.url = String();
     111
     112    m_uncommittedState.unreachableURL = String();
    66113    m_lastUnreachableURL = String();
    67114
    68     callObserverCallback(&Observer::willChangeTitle);
    69     m_title = String();
    70     callObserverCallback(&Observer::didChangeTitle);
    71 
    72     callObserverCallback(&Observer::willChangeEstimatedProgress);
    73     m_estimatedProgress = 0;
    74     callObserverCallback(&Observer::didChangeEstimatedProgress);
     115    m_uncommittedState.title = String();
     116
     117    m_uncommittedState.estimatedProgress = 0;
    75118}
    76119
    77120bool PageLoadState::isLoading() const
    78121{
    79     return isLoadingState(m_state);
    80 }
    81 
    82 String PageLoadState::activeURL() const
     122    return isLoadingState(m_committedState.state);
     123}
     124
     125String PageLoadState::activeURL(const Data& data)
    83126{
    84127    // If there is a currently pending URL, it is the active URL,
    85128    // even when there's no main frame yet, as it might be the
    86129    // first API request.
    87     if (!m_pendingAPIRequestURL.isNull())
    88         return m_pendingAPIRequestURL;
    89 
    90     if (!m_unreachableURL.isEmpty())
    91         return m_unreachableURL;
    92 
    93     switch (m_state) {
     130    if (!data.pendingAPIRequestURL.isNull())
     131        return data.pendingAPIRequestURL;
     132
     133    if (!data.unreachableURL.isEmpty())
     134        return data.unreachableURL;
     135
     136    switch (data.state) {
    94137    case State::Provisional:
    95         return m_provisionalURL;
     138        return data.provisionalURL;
    96139    case State::Committed:
    97140    case State::Finished:
    98         return m_url;
     141        return data.url;
    99142    }
    100143
     
    103146}
    104147
    105 // Always start progress at initialProgressValue. This helps provide feedback as
    106 // soon as a load starts.
    107 
    108 static const double initialProgressValue = 0.1;
     148String PageLoadState::activeURL() const
     149{
     150    return activeURL(m_committedState);
     151}
     152
     153double PageLoadState::estimatedProgress(const Data& data)
     154{
     155    if (!data.pendingAPIRequestURL.isNull())
     156        return initialProgressValue;
     157
     158    return data.estimatedProgress;
     159}
    109160
    110161double PageLoadState::estimatedProgress() const
    111162{
    112     if (!m_pendingAPIRequestURL.isNull())
    113         return initialProgressValue;
    114 
    115     return m_estimatedProgress;
     163    return estimatedProgress(m_committedState);
    116164}
    117165
    118166const String& PageLoadState::pendingAPIRequestURL() const
    119167{
    120     return m_pendingAPIRequestURL;
    121 }
    122 
    123 void PageLoadState::setPendingAPIRequestURL(const String& pendingAPIRequestURL)
    124 {
    125     callObserverCallback(&Observer::willChangeEstimatedProgress);
    126     m_pendingAPIRequestURL = pendingAPIRequestURL;
    127     callObserverCallback(&Observer::didChangeEstimatedProgress);
    128 }
    129 
    130 void PageLoadState::clearPendingAPIRequestURL()
    131 {
    132     callObserverCallback(&Observer::willChangeEstimatedProgress);
    133     m_pendingAPIRequestURL = String();
    134     callObserverCallback(&Observer::didChangeEstimatedProgress);
    135 }
    136 
    137 void PageLoadState::didStartProvisionalLoad(const String& url, const String& unreachableURL)
    138 {
    139     ASSERT(m_provisionalURL.isEmpty());
    140 
    141     setState(State::Provisional);
    142 
    143     m_provisionalURL = url;
    144 
    145     setUnreachableURL(unreachableURL);
    146 }
    147 
    148 void PageLoadState::didReceiveServerRedirectForProvisionalLoad(const String& url)
    149 {
    150     ASSERT(m_state == State::Provisional);
    151 
    152     m_provisionalURL = url;
    153 }
    154 
    155 void PageLoadState::didFailProvisionalLoad()
    156 {
    157     ASSERT(m_state == State::Provisional);
    158 
    159     setState(State::Finished);
    160 
    161     m_provisionalURL = String();
    162     m_unreachableURL = m_lastUnreachableURL;
    163 }
    164 
    165 void PageLoadState::didCommitLoad()
    166 {
    167     ASSERT(m_state == State::Provisional);
    168 
    169     setState(State::Committed);
    170 
    171     m_url = m_provisionalURL;
    172     m_provisionalURL = String();
    173 
    174     m_title = String();
    175 }
    176 
    177 void PageLoadState::didFinishLoad()
    178 {
    179     ASSERT(m_state == State::Committed);
    180     ASSERT(m_provisionalURL.isEmpty());
    181 
    182     setState(State::Finished);
    183 }
    184 
    185 void PageLoadState::didFailLoad()
    186 {
    187     ASSERT(m_provisionalURL.isEmpty());
    188 
    189     setState(State::Finished);
    190 }
    191 
    192 void PageLoadState::didSameDocumentNavigation(const String& url)
    193 {
    194     ASSERT(!m_url.isEmpty());
    195 
    196     m_url = url;
    197 }
    198 
    199 void PageLoadState::setUnreachableURL(const String& unreachableURL)
    200 {
    201     m_lastUnreachableURL = m_unreachableURL;
    202     m_unreachableURL = unreachableURL;
     168    return m_committedState.pendingAPIRequestURL;
     169}
     170
     171void PageLoadState::setPendingAPIRequestURL(const Transaction::Token& token, const String& pendingAPIRequestURL)
     172{
     173    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
     174    m_uncommittedState.pendingAPIRequestURL = pendingAPIRequestURL;
     175}
     176
     177void PageLoadState::clearPendingAPIRequestURL(const Transaction::Token& token)
     178{
     179    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
     180    m_uncommittedState.pendingAPIRequestURL = String();
     181}
     182
     183void PageLoadState::didStartProvisionalLoad(const Transaction::Token& token, const String& url, const String& unreachableURL)
     184{
     185    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
     186    ASSERT(m_uncommittedState.provisionalURL.isEmpty());
     187
     188    m_uncommittedState.state = State::Provisional;
     189
     190    m_uncommittedState.provisionalURL = url;
     191
     192    setUnreachableURL(token, unreachableURL);
     193}
     194
     195void PageLoadState::didReceiveServerRedirectForProvisionalLoad(const Transaction::Token& token, const String& url)
     196{
     197    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
     198    ASSERT(m_uncommittedState.state == State::Provisional);
     199
     200    m_uncommittedState.provisionalURL = url;
     201}
     202
     203void PageLoadState::didFailProvisionalLoad(const Transaction::Token& token)
     204{
     205    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
     206    ASSERT(m_uncommittedState.state == State::Provisional);
     207
     208    m_uncommittedState.state = State::Finished;
     209
     210    m_uncommittedState.provisionalURL = String();
     211    m_uncommittedState.unreachableURL = m_lastUnreachableURL;
     212}
     213
     214void PageLoadState::didCommitLoad(const Transaction::Token& token)
     215{
     216    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
     217    ASSERT(m_uncommittedState.state == State::Provisional);
     218
     219    m_uncommittedState.state = State::Committed;
     220
     221    m_uncommittedState.url = m_uncommittedState.provisionalURL;
     222    m_uncommittedState.provisionalURL = String();
     223
     224    m_uncommittedState.title = String();
     225}
     226
     227void PageLoadState::didFinishLoad(const Transaction::Token& token)
     228{
     229    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
     230    ASSERT(m_uncommittedState.state == State::Committed);
     231    ASSERT(m_uncommittedState.provisionalURL.isEmpty());
     232
     233    m_uncommittedState.state = State::Finished;
     234}
     235
     236void PageLoadState::didFailLoad(const Transaction::Token& token)
     237{
     238    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
     239    ASSERT(m_uncommittedState.provisionalURL.isEmpty());
     240
     241    m_uncommittedState.state = State::Finished;
     242}
     243
     244void PageLoadState::didSameDocumentNavigation(const Transaction::Token& token, const String& url)
     245{
     246    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
     247    ASSERT(!m_uncommittedState.url.isEmpty());
     248
     249    m_uncommittedState.url = url;
     250}
     251
     252void PageLoadState::setUnreachableURL(const Transaction::Token& token, const String& unreachableURL)
     253{
     254    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
     255
     256    m_lastUnreachableURL = m_uncommittedState.unreachableURL;
     257    m_uncommittedState.unreachableURL = unreachableURL;
    203258}
    204259
    205260const String& PageLoadState::title() const
    206261{
    207     return m_title;
    208 }
    209 
    210 void PageLoadState::setTitle(const String& title)
    211 {
    212     callObserverCallback(&Observer::willChangeTitle);
    213     m_title = title;
    214     callObserverCallback(&Observer::didChangeTitle);
    215 }
    216 
    217 void PageLoadState::didStartProgress()
    218 {
    219     callObserverCallback(&Observer::willChangeEstimatedProgress);
    220     m_estimatedProgress = initialProgressValue;
    221     callObserverCallback(&Observer::didChangeEstimatedProgress);
    222 }
    223 
    224 void PageLoadState::didChangeProgress(double value)
    225 {
    226     callObserverCallback(&Observer::willChangeEstimatedProgress);
    227     m_estimatedProgress = value;
    228     callObserverCallback(&Observer::didChangeEstimatedProgress);
    229 }
    230 
    231 void PageLoadState::didFinishProgress()
    232 {
    233     callObserverCallback(&Observer::willChangeEstimatedProgress);
    234     m_estimatedProgress = 1;
    235     callObserverCallback(&Observer::didChangeEstimatedProgress);
     262    return m_committedState.title;
     263}
     264
     265void PageLoadState::setTitle(const Transaction::Token& token, const String& title)
     266{
     267    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
     268    m_uncommittedState.title = title;
     269}
     270
     271void PageLoadState::didStartProgress(const Transaction::Token& token)
     272{
     273    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
     274    m_uncommittedState.estimatedProgress = initialProgressValue;
     275}
     276
     277void PageLoadState::didChangeProgress(const Transaction::Token& token, double value)
     278{
     279    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
     280    m_uncommittedState.estimatedProgress = value;
     281}
     282
     283void PageLoadState::didFinishProgress(const Transaction::Token& token)
     284{
     285    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
     286    m_uncommittedState.estimatedProgress = 1;
    236287}
    237288
     
    251302}
    252303
    253 void PageLoadState::setState(State state)
    254 {
    255     if (m_state == state)
    256         return;
    257 
    258     bool isLoadingIsChanging = false;
    259 
    260     if (isLoadingState(m_state) != isLoadingState(state))
    261         isLoadingIsChanging = true;
    262 
    263     if (isLoadingIsChanging)
    264         callObserverCallback(&Observer::willChangeIsLoading);
    265 
    266     m_state = state;
    267 
    268     if (isLoadingIsChanging)
    269         callObserverCallback(&Observer::didChangeIsLoading);
    270 }
    271 
    272304void PageLoadState::callObserverCallback(void (Observer::*callback)())
    273305{
  • trunk/Source/WebKit2/UIProcess/PageLoadState.h

    r160137 r160405  
    5252        virtual void didChangeTitle() = 0;
    5353
     54        virtual void willChangeActiveURL() = 0;
     55        virtual void didChangeActiveURL() = 0;
     56
    5457        virtual void willChangeEstimatedProgress() = 0;
    5558        virtual void didChangeEstimatedProgress() = 0;
     59    };
     60
     61    class Transaction {
     62        WTF_MAKE_NONCOPYABLE(Transaction);
     63    public:
     64        Transaction(Transaction&& other)
     65            : m_pageLoadState(other.m_pageLoadState)
     66        {
     67            other.m_pageLoadState = nullptr;
     68        }
     69
     70        ~Transaction()
     71        {
     72            if (m_pageLoadState)
     73                m_pageLoadState->endTransaction();
     74        }
     75
     76    private:
     77        friend class PageLoadState;
     78
     79        explicit Transaction(PageLoadState& pageLoadState)
     80            : m_pageLoadState(&pageLoadState)
     81        {
     82            m_pageLoadState->beginTransaction();
     83        }
     84
     85        class Token {
     86        public:
     87            Token(Transaction& transaction)
     88#if !ASSERT_DISABLED
     89                : m_pageLoadState(*transaction.m_pageLoadState)
     90#endif
     91            {
     92                transaction.m_pageLoadState->m_mayHaveUncommittedChanges = true;
     93            }
     94
     95#if !ASSERT_DISABLED
     96            PageLoadState& m_pageLoadState;
     97#endif
     98        };
     99
     100        PageLoadState* m_pageLoadState;
    56101    };
    57102
     
    59104    void removeObserver(Observer&);
    60105
    61     void reset();
     106    Transaction transaction() { return Transaction(*this); }
     107    void commitChanges();
     108
     109    void reset(const Transaction::Token&);
    62110
    63111    bool isLoading() const;
    64112
    65     const String& provisionalURL() const { return m_provisionalURL; }
    66     const String& url() const { return m_url; }
    67     const String& unreachableURL() const { return m_unreachableURL; }
     113    const String& provisionalURL() const { return m_committedState.provisionalURL; }
     114    const String& url() const { return m_committedState.url; }
     115    const String& unreachableURL() const { return m_committedState.unreachableURL; }
    68116
    69117    String activeURL() const;
     
    72120
    73121    const String& pendingAPIRequestURL() const;
    74     void setPendingAPIRequestURL(const String&);
    75     void clearPendingAPIRequestURL();
     122    void setPendingAPIRequestURL(const Transaction::Token&, const String&);
     123    void clearPendingAPIRequestURL(const Transaction::Token&);
    76124
    77     void didStartProvisionalLoad(const String& url, const String& unreachableURL);
    78     void didReceiveServerRedirectForProvisionalLoad(const String& url);
    79     void didFailProvisionalLoad();
     125    void didStartProvisionalLoad(const Transaction::Token&, const String& url, const String& unreachableURL);
     126    void didReceiveServerRedirectForProvisionalLoad(const Transaction::Token&, const String& url);
     127    void didFailProvisionalLoad(const Transaction::Token&);
    80128
    81     void didCommitLoad();
    82     void didFinishLoad();
    83     void didFailLoad();
     129    void didCommitLoad(const Transaction::Token&);
     130    void didFinishLoad(const Transaction::Token&);
     131    void didFailLoad(const Transaction::Token&);
    84132
    85     void didSameDocumentNavigation(const String& url);
     133    void didSameDocumentNavigation(const Transaction::Token&, const String& url);
    86134
    87     void setUnreachableURL(const String&);
     135    void setUnreachableURL(const Transaction::Token&, const String&);
    88136
    89137    const String& title() const;
    90     void setTitle(const String&);
     138    void setTitle(const Transaction::Token&, const String&);
    91139
    92     void didStartProgress();
    93     void didChangeProgress(double);
    94     void didFinishProgress();
     140    void didStartProgress(const Transaction::Token&);
     141    void didChangeProgress(const Transaction::Token&, double);
     142    void didFinishProgress(const Transaction::Token&);
    95143
    96144private:
    97145    static bool isLoadingState(State);
    98     void setState(State);
     146
     147    void beginTransaction() { ++m_outstandingTransactionCount; }
     148    void endTransaction();
    99149
    100150    void callObserverCallback(void (Observer::*)());
     
    102152    Vector<Observer*> m_observers;
    103153
    104     State m_state;
     154    struct Data {
     155        Data()
     156            : state(State::Finished)
     157            , estimatedProgress(0)
     158        {
     159        }
    105160
    106     String m_pendingAPIRequestURL;
     161        State state;
    107162
    108     String m_provisionalURL;
    109     String m_url;
     163        String pendingAPIRequestURL;
    110164
    111     String m_unreachableURL;
     165        String provisionalURL;
     166        String url;
     167
     168        String unreachableURL;
     169
     170        String title;
     171
     172        double estimatedProgress;
     173    };
     174
     175    static String activeURL(const Data&);
     176    static double estimatedProgress(const Data&);
     177
     178    Data m_committedState;
     179    Data m_uncommittedState;
     180
    112181    String m_lastUnreachableURL;
    113182
    114     String m_title;
    115 
    116     double m_estimatedProgress;
     183    bool m_mayHaveUncommittedChanges;
     184    unsigned m_outstandingTransactionCount;
    117185};
    118186
  • trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp

    r160395 r160405  
    601601void WebPageProxy::loadURL(const String& url, API::Object* userData)
    602602{
    603     m_pageLoadState.setPendingAPIRequestURL(url);
     603    auto transaction = m_pageLoadState.transaction();
     604
     605    m_pageLoadState.setPendingAPIRequestURL(transaction, url);
    604606
    605607    if (!isValid())
     
    616618void WebPageProxy::loadURLRequest(WebURLRequest* urlRequest, API::Object* userData)
    617619{
    618     m_pageLoadState.setPendingAPIRequestURL(urlRequest->resourceRequest().url());
     620    auto transaction = m_pageLoadState.transaction();
     621
     622    m_pageLoadState.setPendingAPIRequestURL(transaction, urlRequest->resourceRequest().url());
    619623
    620624    if (!isValid())
     
    681685        reattachToWebProcess();
    682686
    683     m_pageLoadState.setUnreachableURL(unreachableURL);
     687    auto transaction = m_pageLoadState.transaction();
     688
     689    m_pageLoadState.setUnreachableURL(transaction, unreachableURL);
    684690
    685691    if (m_mainFrame)
     
    724730    if (m_backForwardList->currentItem()) {
    725731        String url = m_backForwardList->currentItem()->url();
    726         m_pageLoadState.setPendingAPIRequestURL(url);
     732        auto transaction = m_pageLoadState.transaction();
     733        m_pageLoadState.setPendingAPIRequestURL(transaction, url);
    727734
    728735        // We may not have an extension yet if back/forward list was reinstated after a WebProcess crash or a browser relaunch
     
    750757        return;
    751758
    752     m_pageLoadState.setPendingAPIRequestURL(forwardItem->url());
     759    auto transaction = m_pageLoadState.transaction();
     760
     761    m_pageLoadState.setPendingAPIRequestURL(transaction, forwardItem->url());
    753762
    754763    if (!isValid()) {
     
    775784        return;
    776785
    777     m_pageLoadState.setPendingAPIRequestURL(backItem->url());
     786    auto transaction = m_pageLoadState.transaction();
     787
     788    m_pageLoadState.setPendingAPIRequestURL(transaction, backItem->url());
    778789
    779790    if (!isValid()) {
     
    798809    }
    799810   
    800     m_pageLoadState.setPendingAPIRequestURL(item->url());
     811    auto transaction = m_pageLoadState.transaction();
     812
     813    m_pageLoadState.setPendingAPIRequestURL(transaction, item->url());
    801814
    802815    m_process->send(Messages::WebPage::GoToBackForwardItem(item->itemID()), m_pageID);
     
    14061419        return;
    14071420
     1421    auto transaction = m_pageLoadState.transaction();
     1422
    14081423    if (action == PolicyIgnore)
    1409         m_pageLoadState.clearPendingAPIRequestURL();
     1424        m_pageLoadState.clearPendingAPIRequestURL(transaction);
    14101425
    14111426    uint64_t downloadID = 0;
     
    20642079void WebPageProxy::didStartProgress()
    20652080{
    2066     m_pageLoadState.didStartProgress();
    2067 
     2081    auto transaction = m_pageLoadState.transaction();
     2082    m_pageLoadState.didStartProgress(transaction);
     2083
     2084    m_pageLoadState.commitChanges();
    20682085    m_loaderClient.didStartProgress(this);
    20692086}
     
    20712088void WebPageProxy::didChangeProgress(double value)
    20722089{
    2073     m_pageLoadState.didChangeProgress(value);
    2074 
     2090    auto transaction = m_pageLoadState.transaction();
     2091    m_pageLoadState.didChangeProgress(transaction, value);
     2092
     2093    m_pageLoadState.commitChanges();
    20752094    m_loaderClient.didChangeProgress(this);
    20762095}
     
    20782097void WebPageProxy::didFinishProgress()
    20792098{
    2080     m_pageLoadState.didFinishProgress();
    2081 
     2099    auto transaction = m_pageLoadState.transaction();
     2100    m_pageLoadState.didFinishProgress(transaction);
     2101
     2102    m_pageLoadState.commitChanges();
    20822103    m_loaderClient.didFinishProgress(this);
    20832104}
     
    20852106void WebPageProxy::didStartProvisionalLoadForFrame(uint64_t frameID, const String& url, const String& unreachableURL, CoreIPC::MessageDecoder& decoder)
    20862107{
    2087     m_pageLoadState.clearPendingAPIRequestURL();
     2108    auto transaction = m_pageLoadState.transaction();
     2109
     2110    m_pageLoadState.clearPendingAPIRequestURL(transaction);
    20882111
    20892112    RefPtr<API::Object> userData;
     
    20972120
    20982121    if (frame->isMainFrame())
    2099         m_pageLoadState.didStartProvisionalLoad(url, unreachableURL);
     2122        m_pageLoadState.didStartProvisionalLoad(transaction, url, unreachableURL);
    21002123
    21012124    frame->setUnreachableURL(unreachableURL);
    21022125    frame->didStartProvisionalLoad(url);
    21032126
     2127    m_pageLoadState.commitChanges();
    21042128    m_loaderClient.didStartProvisionalLoadForFrame(this, frame, userData.get());
    21052129}
     
    21162140    MESSAGE_CHECK_URL(url);
    21172141
     2142    auto transaction = m_pageLoadState.transaction();
     2143
    21182144    if (frame->isMainFrame())
    2119         m_pageLoadState.didReceiveServerRedirectForProvisionalLoad(url);
     2145        m_pageLoadState.didReceiveServerRedirectForProvisionalLoad(transaction, url);
    21202146
    21212147    frame->didReceiveServerRedirectForProvisionalLoad(url);
    21222148
     2149    m_pageLoadState.commitChanges();
    21232150    m_loaderClient.didReceiveServerRedirectForProvisionalLoadForFrame(this, frame, userData.get());
    21242151}
     
    21342161    MESSAGE_CHECK(frame);
    21352162
     2163    auto transaction = m_pageLoadState.transaction();
     2164
    21362165    if (frame->isMainFrame())
    2137         m_pageLoadState.didFailProvisionalLoad();
     2166        m_pageLoadState.didFailProvisionalLoad(transaction);
    21382167
    21392168    frame->didFailProvisionalLoad();
    21402169
     2170    m_pageLoadState.commitChanges();
    21412171    m_loaderClient.didFailProvisionalLoadWithErrorForFrame(this, frame, error, userData.get());
    21422172}
     
    21652195    MESSAGE_CHECK(frame);
    21662196
     2197    auto transaction = m_pageLoadState.transaction();
     2198
    21672199    if (frame->isMainFrame()) {
    2168         m_pageLoadState.didCommitLoad();
     2200        m_pageLoadState.didCommitLoad(transaction);
    21692201        m_pageClient.didCommitLoadForMainFrame();
    21702202    }
     
    21892221        m_pageScaleFactor = 1;
    21902222
     2223    m_pageLoadState.commitChanges();
    21912224    m_loaderClient.didCommitLoadForFrame(this, frame, userData.get());
    21922225}
     
    22152248    MESSAGE_CHECK(frame);
    22162249
     2250    auto transaction = m_pageLoadState.transaction();
     2251
    22172252    if (frame->isMainFrame())
    2218         m_pageLoadState.didFinishLoad();
     2253        m_pageLoadState.didFinishLoad(transaction);
    22192254
    22202255    frame->didFinishLoad();
    22212256
     2257    m_pageLoadState.commitChanges();
    22222258    m_loaderClient.didFinishLoadForFrame(this, frame, userData.get());
    22232259}
     
    22352271    clearLoadDependentCallbacks();
    22362272
     2273    auto transaction = m_pageLoadState.transaction();
     2274
    22372275    if (frame->isMainFrame())
    2238         m_pageLoadState.didFailLoad();
     2276        m_pageLoadState.didFailLoad(transaction);
    22392277
    22402278    frame->didFailLoad();
    22412279
     2280    m_pageLoadState.commitChanges();
    22422281    m_loaderClient.didFailLoadWithErrorForFrame(this, frame, error, userData.get());
    22432282}
     
    22542293    MESSAGE_CHECK_URL(url);
    22552294
     2295    auto transaction = m_pageLoadState.transaction();
     2296
    22562297    if (frame->isMainFrame())
    2257         m_pageLoadState.didSameDocumentNavigation(url);
    2258 
    2259     m_pageLoadState.clearPendingAPIRequestURL();
     2298        m_pageLoadState.didSameDocumentNavigation(transaction, url);
     2299
     2300    m_pageLoadState.clearPendingAPIRequestURL(transaction);
    22602301    frame->didSameDocumentNavigation(url);
    22612302
     2303    m_pageLoadState.commitChanges();
    22622304    m_loaderClient.didSameDocumentNavigationForFrame(this, frame, static_cast<SameDocumentNavigationType>(opaqueSameDocumentNavigationType), userData.get());
    22632305}
     
    22732315    MESSAGE_CHECK(frame);
    22742316
     2317    auto transaction = m_pageLoadState.transaction();
     2318
    22752319    if (frame->isMainFrame())
    2276         m_pageLoadState.setTitle(title);
     2320        m_pageLoadState.setTitle(transaction, title);
    22772321
    22782322    frame->didChangeTitle(title);
    22792323   
     2324    m_pageLoadState.commitChanges();
    22802325    m_loaderClient.didReceiveTitleForFrame(this, title, frame, userData.get());
    22812326}
     
    23872432        return;
    23882433
     2434    auto transaction = m_pageLoadState.transaction();
     2435
    23892436    if (request.url() != m_pageLoadState.pendingAPIRequestURL())
    2390         m_pageLoadState.clearPendingAPIRequestURL();
     2437        m_pageLoadState.clearPendingAPIRequestURL(transaction);
    23912438
    23922439    WebFrameProxy* frame = m_process->webFrame(frameID);
     
    36823729    resetStateAfterProcessExited();
    36833730
    3684     // FIXME: Consider calling reset after calling out to the loader client,
    3685     // having the page load state available could be useful.
    3686     m_pageLoadState.reset();
     3731    auto transaction = m_pageLoadState.transaction();
     3732
     3733    m_pageLoadState.reset(transaction);
    36873734
    36883735    m_pageClient.processDidCrash();
     3736
    36893737    m_loaderClient.processDidCrash(this);
    36903738}
  • trunk/Source/WebKit2/UIProcess/cf/WebPageProxyCF.cpp

    r159903 r160405  
    152152    }
    153153
     154    auto transaction = m_pageLoadState.transaction();
     155
    154156    if (backForwardListDictionary) {
    155157        if (!m_backForwardList->restoreFromCFDictionaryRepresentation(backForwardListDictionary))
     
    166168                else {
    167169                    if (WebBackForwardListItem* item = m_backForwardList->currentItem())
    168                         m_pageLoadState.setPendingAPIRequestURL(item->url());
     170                        m_pageLoadState.setPendingAPIRequestURL(transaction, item->url());
    169171
    170172                    process().send(Messages::WebPage::RestoreSessionAndNavigateToCurrentItem(state), m_pageID);
Note: See TracChangeset for help on using the changeset viewer.