summaryrefslogtreecommitdiffstats
path: root/Source/WebKit2/UIProcess/PageLoadState.cpp
diff options
context:
space:
mode:
authorKonstantin Tokarev <annulen@yandex.ru>2016-08-25 19:20:41 +0300
committerKonstantin Tokarev <annulen@yandex.ru>2017-02-02 12:30:55 +0000
commit6882a04fb36642862b11efe514251d32070c3d65 (patch)
treeb7959826000b061fd5ccc7512035c7478742f7b0 /Source/WebKit2/UIProcess/PageLoadState.cpp
parentab6df191029eeeb0b0f16f127d553265659f739e (diff)
Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443)
Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/WebKit2/UIProcess/PageLoadState.cpp')
-rw-r--r--Source/WebKit2/UIProcess/PageLoadState.cpp421
1 files changed, 421 insertions, 0 deletions
diff --git a/Source/WebKit2/UIProcess/PageLoadState.cpp b/Source/WebKit2/UIProcess/PageLoadState.cpp
new file mode 100644
index 000000000..8b501bf11
--- /dev/null
+++ b/Source/WebKit2/UIProcess/PageLoadState.cpp
@@ -0,0 +1,421 @@
+/*
+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "PageLoadState.h"
+
+#include "WebPageProxy.h"
+
+namespace WebKit {
+
+// Progress always starts at this value. This helps provide feedback as soon as a load starts.
+static const double initialProgressValue = 0.1;
+
+PageLoadState::PageLoadState(WebPageProxy& webPageProxy)
+ : m_webPageProxy(webPageProxy)
+ , m_mayHaveUncommittedChanges(false)
+ , m_outstandingTransactionCount(0)
+{
+}
+
+PageLoadState::~PageLoadState()
+{
+ ASSERT(m_observers.isEmpty());
+}
+
+PageLoadState::Transaction::Transaction(PageLoadState& pageLoadState)
+ : m_webPageProxy(&pageLoadState.m_webPageProxy)
+ , m_pageLoadState(&pageLoadState)
+{
+ m_pageLoadState->beginTransaction();
+}
+
+PageLoadState::Transaction::Transaction(Transaction&& other)
+ : m_webPageProxy(WTFMove(other.m_webPageProxy))
+ , m_pageLoadState(other.m_pageLoadState)
+{
+ other.m_pageLoadState = nullptr;
+}
+
+PageLoadState::Transaction::~Transaction()
+{
+ if (m_pageLoadState)
+ m_pageLoadState->endTransaction();
+}
+
+void PageLoadState::addObserver(Observer& observer)
+{
+ ASSERT(!m_observers.contains(&observer));
+
+ m_observers.append(&observer);
+}
+
+void PageLoadState::removeObserver(Observer& observer)
+{
+ bool removed = m_observers.removeFirst(&observer);
+ ASSERT_UNUSED(removed, removed);
+}
+
+void PageLoadState::endTransaction()
+{
+ ASSERT(m_outstandingTransactionCount > 0);
+
+ if (!--m_outstandingTransactionCount)
+ commitChanges();
+}
+
+void PageLoadState::commitChanges()
+{
+ if (!m_mayHaveUncommittedChanges)
+ return;
+
+ m_mayHaveUncommittedChanges = false;
+
+ bool canGoBackChanged = m_committedState.canGoBack != m_uncommittedState.canGoBack;
+ bool canGoForwardChanged = m_committedState.canGoForward != m_uncommittedState.canGoForward;
+ bool titleChanged = m_committedState.title != m_uncommittedState.title;
+ bool isLoadingChanged = isLoading(m_committedState) != isLoading(m_uncommittedState);
+ bool activeURLChanged = activeURL(m_committedState) != activeURL(m_uncommittedState);
+ bool hasOnlySecureContentChanged = hasOnlySecureContent(m_committedState) != hasOnlySecureContent(m_uncommittedState);
+ bool estimatedProgressChanged = estimatedProgress(m_committedState) != estimatedProgress(m_uncommittedState);
+ bool networkRequestsInProgressChanged = m_committedState.networkRequestsInProgress != m_uncommittedState.networkRequestsInProgress;
+ bool certificateInfoChanged = m_committedState.certificateInfo != m_uncommittedState.certificateInfo;
+
+ if (canGoBackChanged)
+ callObserverCallback(&Observer::willChangeCanGoBack);
+ if (canGoForwardChanged)
+ callObserverCallback(&Observer::willChangeCanGoForward);
+ if (titleChanged)
+ callObserverCallback(&Observer::willChangeTitle);
+ if (isLoadingChanged)
+ callObserverCallback(&Observer::willChangeIsLoading);
+ if (activeURLChanged)
+ callObserverCallback(&Observer::willChangeActiveURL);
+ if (hasOnlySecureContentChanged)
+ callObserverCallback(&Observer::willChangeHasOnlySecureContent);
+ if (estimatedProgressChanged)
+ callObserverCallback(&Observer::willChangeEstimatedProgress);
+ if (networkRequestsInProgressChanged)
+ callObserverCallback(&Observer::willChangeNetworkRequestsInProgress);
+ if (certificateInfoChanged)
+ callObserverCallback(&Observer::willChangeCertificateInfo);
+
+ m_committedState = m_uncommittedState;
+
+ // The "did" ordering is the reverse of the "will". This is a requirement of Cocoa Key-Value Observing.
+ if (certificateInfoChanged)
+ callObserverCallback(&Observer::didChangeCertificateInfo);
+ if (networkRequestsInProgressChanged)
+ callObserverCallback(&Observer::didChangeNetworkRequestsInProgress);
+ if (estimatedProgressChanged)
+ callObserverCallback(&Observer::didChangeEstimatedProgress);
+ if (hasOnlySecureContentChanged)
+ callObserverCallback(&Observer::didChangeHasOnlySecureContent);
+ if (activeURLChanged)
+ callObserverCallback(&Observer::didChangeActiveURL);
+ if (isLoadingChanged)
+ callObserverCallback(&Observer::didChangeIsLoading);
+ if (titleChanged)
+ callObserverCallback(&Observer::didChangeTitle);
+ if (canGoForwardChanged)
+ callObserverCallback(&Observer::didChangeCanGoForward);
+ if (canGoBackChanged)
+ callObserverCallback(&Observer::didChangeCanGoBack);
+}
+
+void PageLoadState::reset(const Transaction::Token& token)
+{
+ ASSERT_UNUSED(token, &token.m_pageLoadState == this);
+
+ m_uncommittedState.state = State::Finished;
+ m_uncommittedState.hasInsecureContent = false;
+
+ m_uncommittedState.pendingAPIRequestURL = String();
+ m_uncommittedState.provisionalURL = String();
+ m_uncommittedState.url = String();
+
+ m_uncommittedState.unreachableURL = String();
+ m_lastUnreachableURL = String();
+
+ m_uncommittedState.title = String();
+
+ m_uncommittedState.estimatedProgress = 0;
+ m_uncommittedState.networkRequestsInProgress = false;
+}
+
+bool PageLoadState::isLoading() const
+{
+ return isLoading(m_committedState);
+}
+
+String PageLoadState::activeURL(const Data& data)
+{
+ // If there is a currently pending URL, it is the active URL,
+ // even when there's no main frame yet, as it might be the
+ // first API request.
+ if (!data.pendingAPIRequestURL.isNull())
+ return data.pendingAPIRequestURL;
+
+ if (!data.unreachableURL.isEmpty())
+ return data.unreachableURL;
+
+ switch (data.state) {
+ case State::Provisional:
+ return data.provisionalURL;
+ case State::Committed:
+ case State::Finished:
+ return data.url;
+ }
+
+ ASSERT_NOT_REACHED();
+ return String();
+}
+
+String PageLoadState::activeURL() const
+{
+ return activeURL(m_committedState);
+}
+
+bool PageLoadState::hasOnlySecureContent(const Data& data)
+{
+ if (data.hasInsecureContent)
+ return false;
+
+ return WebCore::protocolIs(data.url, "https");
+}
+
+bool PageLoadState::hasOnlySecureContent() const
+{
+ return hasOnlySecureContent(m_committedState);
+}
+
+double PageLoadState::estimatedProgress(const Data& data)
+{
+ if (!data.pendingAPIRequestURL.isNull())
+ return initialProgressValue;
+
+ return data.estimatedProgress;
+}
+
+double PageLoadState::estimatedProgress() const
+{
+ return estimatedProgress(m_committedState);
+}
+
+const String& PageLoadState::pendingAPIRequestURL() const
+{
+ return m_committedState.pendingAPIRequestURL;
+}
+
+void PageLoadState::setPendingAPIRequestURL(const Transaction::Token& token, const String& pendingAPIRequestURL)
+{
+ ASSERT_UNUSED(token, &token.m_pageLoadState == this);
+ m_uncommittedState.pendingAPIRequestURL = pendingAPIRequestURL;
+}
+
+void PageLoadState::clearPendingAPIRequestURL(const Transaction::Token& token)
+{
+ ASSERT_UNUSED(token, &token.m_pageLoadState == this);
+ m_uncommittedState.pendingAPIRequestURL = String();
+}
+
+void PageLoadState::didStartProvisionalLoad(const Transaction::Token& token, const String& url, const String& unreachableURL)
+{
+ ASSERT_UNUSED(token, &token.m_pageLoadState == this);
+ ASSERT(m_uncommittedState.provisionalURL.isEmpty());
+
+ m_uncommittedState.state = State::Provisional;
+
+ m_uncommittedState.provisionalURL = url;
+
+ setUnreachableURL(token, unreachableURL);
+}
+
+void PageLoadState::didReceiveServerRedirectForProvisionalLoad(const Transaction::Token& token, const String& url)
+{
+ ASSERT_UNUSED(token, &token.m_pageLoadState == this);
+ ASSERT(m_uncommittedState.state == State::Provisional);
+
+ m_uncommittedState.provisionalURL = url;
+}
+
+void PageLoadState::didFailProvisionalLoad(const Transaction::Token& token)
+{
+ ASSERT_UNUSED(token, &token.m_pageLoadState == this);
+ ASSERT(m_uncommittedState.state == State::Provisional);
+
+ m_uncommittedState.state = State::Finished;
+
+ m_uncommittedState.provisionalURL = String();
+ m_uncommittedState.unreachableURL = m_lastUnreachableURL;
+}
+
+void PageLoadState::didCommitLoad(const Transaction::Token& token, WebCertificateInfo& certificateInfo, bool hasInsecureContent)
+{
+ ASSERT_UNUSED(token, &token.m_pageLoadState == this);
+ ASSERT(m_uncommittedState.state == State::Provisional);
+
+ m_uncommittedState.state = State::Committed;
+ m_uncommittedState.hasInsecureContent = hasInsecureContent;
+ m_uncommittedState.certificateInfo = &certificateInfo;
+
+ m_uncommittedState.url = m_uncommittedState.provisionalURL;
+ m_uncommittedState.provisionalURL = String();
+
+ m_uncommittedState.title = String();
+}
+
+void PageLoadState::didFinishLoad(const Transaction::Token& token)
+{
+ ASSERT_UNUSED(token, &token.m_pageLoadState == this);
+ ASSERT(m_uncommittedState.state == State::Committed);
+ ASSERT(m_uncommittedState.provisionalURL.isEmpty());
+
+ m_uncommittedState.state = State::Finished;
+}
+
+void PageLoadState::didFailLoad(const Transaction::Token& token)
+{
+ ASSERT_UNUSED(token, &token.m_pageLoadState == this);
+ ASSERT(m_uncommittedState.provisionalURL.isEmpty());
+
+ m_uncommittedState.state = State::Finished;
+}
+
+void PageLoadState::didSameDocumentNavigation(const Transaction::Token& token, const String& url)
+{
+ ASSERT_UNUSED(token, &token.m_pageLoadState == this);
+ ASSERT(!m_uncommittedState.url.isEmpty());
+
+ m_uncommittedState.url = url;
+}
+
+void PageLoadState::didDisplayOrRunInsecureContent(const Transaction::Token& token)
+{
+ ASSERT_UNUSED(token, &token.m_pageLoadState == this);
+
+ m_uncommittedState.hasInsecureContent = true;
+}
+
+void PageLoadState::setUnreachableURL(const Transaction::Token& token, const String& unreachableURL)
+{
+ ASSERT_UNUSED(token, &token.m_pageLoadState == this);
+
+ m_lastUnreachableURL = m_uncommittedState.unreachableURL;
+ m_uncommittedState.unreachableURL = unreachableURL;
+}
+
+const String& PageLoadState::title() const
+{
+ return m_committedState.title;
+}
+
+void PageLoadState::setTitle(const Transaction::Token& token, const String& title)
+{
+ ASSERT_UNUSED(token, &token.m_pageLoadState == this);
+ m_uncommittedState.title = title;
+}
+
+bool PageLoadState::canGoBack() const
+{
+ return m_committedState.canGoBack;
+}
+
+void PageLoadState::setCanGoBack(const Transaction::Token& token, bool canGoBack)
+{
+ ASSERT_UNUSED(token, &token.m_pageLoadState == this);
+ m_uncommittedState.canGoBack = canGoBack;
+}
+
+bool PageLoadState::canGoForward() const
+{
+ return m_committedState.canGoForward;
+}
+
+void PageLoadState::setCanGoForward(const Transaction::Token& token, bool canGoForward)
+{
+ ASSERT_UNUSED(token, &token.m_pageLoadState == this);
+ m_uncommittedState.canGoForward = canGoForward;
+}
+
+void PageLoadState::didStartProgress(const Transaction::Token& token)
+{
+ ASSERT_UNUSED(token, &token.m_pageLoadState == this);
+ m_uncommittedState.estimatedProgress = initialProgressValue;
+}
+
+void PageLoadState::didChangeProgress(const Transaction::Token& token, double value)
+{
+ ASSERT_UNUSED(token, &token.m_pageLoadState == this);
+ m_uncommittedState.estimatedProgress = value;
+}
+
+void PageLoadState::didFinishProgress(const Transaction::Token& token)
+{
+ ASSERT_UNUSED(token, &token.m_pageLoadState == this);
+ m_uncommittedState.estimatedProgress = 1;
+}
+
+void PageLoadState::setNetworkRequestsInProgress(const Transaction::Token& token, bool networkRequestsInProgress)
+{
+ ASSERT_UNUSED(token, &token.m_pageLoadState == this);
+ m_uncommittedState.networkRequestsInProgress = networkRequestsInProgress;
+}
+
+bool PageLoadState::isLoading(const Data& data)
+{
+ if (!data.pendingAPIRequestURL.isNull())
+ return true;
+
+ switch (data.state) {
+ case State::Provisional:
+ case State::Committed:
+ return true;
+
+ case State::Finished:
+ return false;
+ }
+
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+void PageLoadState::willChangeProcessIsResponsive()
+{
+ callObserverCallback(&Observer::willChangeWebProcessIsResponsive);
+}
+
+void PageLoadState::didChangeProcessIsResponsive()
+{
+ callObserverCallback(&Observer::didChangeWebProcessIsResponsive);
+}
+
+void PageLoadState::callObserverCallback(void (Observer::*callback)())
+{
+ for (auto* observer : m_observers)
+ (observer->*callback)();
+}
+
+} // namespace WebKit