Don't call OnLoadEnd for same page navigations (issue #1852)

This commit is contained in:
Marshall Greenblatt
2017-03-08 17:40:13 -05:00
parent 7b07b058a8
commit 1f1b268f4a
6 changed files with 894 additions and 122 deletions

View File

@@ -44,6 +44,7 @@
#include "chrome/browser/spellchecker/spellcheck_service.h" #include "chrome/browser/spellchecker/spellcheck_service.h"
#include "chrome/browser/ui/prefs/prefs_tab_helper.h" #include "chrome/browser/ui/prefs/prefs_tab_helper.h"
#include "components/zoom/zoom_controller.h" #include "components/zoom/zoom_controller.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/gpu/compositor_util.h" #include "content/browser/gpu/compositor_util.h"
#include "content/common/view_messages.h" #include "content/common/view_messages.h"
@@ -53,6 +54,7 @@
#include "content/public/browser/native_web_keyboard_event.h" #include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_entry.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/notification_details.h" #include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h" #include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h" #include "content/public/browser/notification_types.h"
@@ -61,6 +63,7 @@
#include "content/public/browser/render_view_host.h" #include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h" #include "content/public/browser/render_widget_host.h"
#include "content/public/browser/resource_request_info.h" #include "content/public/browser/resource_request_info.h"
#include "net/base/net_errors.h"
#include "third_party/WebKit/public/web/WebFindOptions.h" #include "third_party/WebKit/public/web/WebFindOptions.h"
#include "ui/events/base_event_utils.h" #include "ui/events/base_event_utils.h"
@@ -2499,36 +2502,51 @@ void CefBrowserHostImpl::RenderProcessGone(base::TerminationStatus status) {
} }
} }
void CefBrowserHostImpl::DidCommitProvisionalLoadForFrame( void CefBrowserHostImpl::DidFinishNavigation(
content::RenderFrameHost* render_frame_host, content::NavigationHandle* navigation_handle) {
const GURL& url, CHECK(navigation_handle->GetRenderFrameHost());
ui::PageTransition transition_type) {
const bool is_main_frame = !render_frame_host->GetParent(); const net::Error error_code = navigation_handle->GetNetErrorCode();
if (error_code == net::OK) {
// The navigation has been committed.
const bool is_main_frame = navigation_handle->IsInMainFrame();
const GURL& url = navigation_handle->GetURL();
// This also updates the URL associated with the frame.
CefRefPtr<CefFrame> frame = GetOrCreateFrame( CefRefPtr<CefFrame> frame = GetOrCreateFrame(
render_frame_host->GetRoutingID(), navigation_handle->GetRenderFrameHost()->GetRoutingID(),
CefFrameHostImpl::kUnspecifiedFrameId, CefFrameHostImpl::kUnspecifiedFrameId,
is_main_frame, is_main_frame, base::string16(), url);
base::string16(),
url); // Don't call OnLoadStart for same page navigations (fragments,
OnLoadStart(frame, url, transition_type); // history state).
if (!navigation_handle->IsSamePage())
OnLoadStart(frame, navigation_handle->GetPageTransition());
if (is_main_frame) if (is_main_frame)
OnAddressChange(frame, url); OnAddressChange(frame, url);
} else {
// The navigation failed before commit. Originates from
// RenderFrameHostImpl::OnDidFailProvisionalLoadWithError.
CefRefPtr<CefFrame> frame = GetOrCreateFrame(
navigation_handle->GetRenderFrameHost()->GetRoutingID(),
CefFrameHostImpl::kUnspecifiedFrameId,
navigation_handle->IsInMainFrame(), base::string16(), GURL());
// OnLoadStart/OnLoadEnd will not be called.
OnLoadError(frame, navigation_handle->GetURL(), error_code);
} }
void CefBrowserHostImpl::DidFailProvisionalLoad( if (!web_contents())
content::RenderFrameHost* render_frame_host, return;
const GURL& validated_url,
int error_code, CefBrowserContext* context =
const base::string16& error_description, static_cast<CefBrowserContext*>(web_contents()->GetBrowserContext());
bool was_ignored_by_handler) { if (!context)
const bool is_main_frame = !render_frame_host->GetParent(); return;
CefRefPtr<CefFrame> frame = GetOrCreateFrame(
render_frame_host->GetRoutingID(), context->AddVisitedURLs(static_cast<content::NavigationHandleImpl*>(
CefFrameHostImpl::kUnspecifiedFrameId, navigation_handle)->redirect_chain());
is_main_frame,
base::string16(),
GURL());
OnLoadError(frame, validated_url, error_code, error_description);
} }
void CefBrowserHostImpl::DocumentAvailableInMainFrame() { void CefBrowserHostImpl::DocumentAvailableInMainFrame() {
@@ -2542,6 +2560,8 @@ void CefBrowserHostImpl::DidFailLoad(
int error_code, int error_code,
const base::string16& error_description, const base::string16& error_description,
bool was_ignored_by_handler) { bool was_ignored_by_handler) {
// The navigation failed after commit. OnLoadStart was called so we also call
// OnLoadEnd.
const bool is_main_frame = !render_frame_host->GetParent(); const bool is_main_frame = !render_frame_host->GetParent();
CefRefPtr<CefFrame> frame = GetOrCreateFrame( CefRefPtr<CefFrame> frame = GetOrCreateFrame(
render_frame_host->GetRoutingID(), render_frame_host->GetRoutingID(),
@@ -2549,7 +2569,7 @@ void CefBrowserHostImpl::DidFailLoad(
is_main_frame, is_main_frame,
base::string16(), base::string16(),
validated_url); validated_url);
OnLoadError(frame, validated_url, error_code, error_description); OnLoadError(frame, validated_url, error_code);
OnLoadEnd(frame, validated_url, error_code); OnLoadEnd(frame, validated_url, error_code);
} }
@@ -2570,21 +2590,6 @@ void CefBrowserHostImpl::FrameDeleted(
focused_frame_id_ = CefFrameHostImpl::kInvalidFrameId; focused_frame_id_ = CefFrameHostImpl::kInvalidFrameId;
} }
void CefBrowserHostImpl::DidNavigateAnyFrame(
content::RenderFrameHost* render_frame_host,
const content::LoadCommittedDetails& details,
const content::FrameNavigateParams& params) {
if (!web_contents())
return;
CefBrowserContext* context =
static_cast<CefBrowserContext*>(web_contents()->GetBrowserContext());
if (!context)
return;
context->AddVisitedURLs(params.redirects);
}
void CefBrowserHostImpl::TitleWasSet(content::NavigationEntry* entry, void CefBrowserHostImpl::TitleWasSet(content::NavigationEntry* entry,
bool explicit_set) { bool explicit_set) {
// |entry| may be NULL if a popup is created via window.open and never // |entry| may be NULL if a popup is created via window.open and never
@@ -3034,7 +3039,6 @@ void CefBrowserHostImpl::OnAddressChange(CefRefPtr<CefFrame> frame,
} }
void CefBrowserHostImpl::OnLoadStart(CefRefPtr<CefFrame> frame, void CefBrowserHostImpl::OnLoadStart(CefRefPtr<CefFrame> frame,
const GURL& url,
ui::PageTransition transition_type) { ui::PageTransition transition_type) {
if (client_.get()) { if (client_.get()) {
CefRefPtr<CefLoadHandler> handler = client_->GetLoadHandler(); CefRefPtr<CefLoadHandler> handler = client_->GetLoadHandler();
@@ -3048,8 +3052,7 @@ void CefBrowserHostImpl::OnLoadStart(CefRefPtr<CefFrame> frame,
void CefBrowserHostImpl::OnLoadError(CefRefPtr<CefFrame> frame, void CefBrowserHostImpl::OnLoadError(CefRefPtr<CefFrame> frame,
const GURL& url, const GURL& url,
int error_code, int error_code) {
const base::string16& error_description) {
if (client_.get()) { if (client_.get()) {
CefRefPtr<CefLoadHandler> handler = client_->GetLoadHandler(); CefRefPtr<CefLoadHandler> handler = client_->GetLoadHandler();
if (handler.get()) { if (handler.get()) {
@@ -3057,7 +3060,7 @@ void CefBrowserHostImpl::OnLoadError(CefRefPtr<CefFrame> frame,
// Notify the handler that loading has failed. // Notify the handler that loading has failed.
handler->OnLoadError(this, frame, handler->OnLoadError(this, frame,
static_cast<cef_errorcode_t>(error_code), static_cast<cef_errorcode_t>(error_code),
CefString(error_description), net::ErrorToShortString(error_code),
url.spec()); url.spec());
frame_destruction_pending_ = false; frame_destruction_pending_ = false;
} }

View File

@@ -448,38 +448,21 @@ class CefBrowserHostImpl : public CefBrowserHost,
// content::WebContentsObserver methods. // content::WebContentsObserver methods.
using content::WebContentsObserver::BeforeUnloadFired; using content::WebContentsObserver::BeforeUnloadFired;
using content::WebContentsObserver::WasHidden; using content::WebContentsObserver::WasHidden;
void RenderFrameCreated( void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override;
content::RenderFrameHost* render_frame_host) override; void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
void RenderFrameDeleted( void RenderViewCreated(content::RenderViewHost* render_view_host) override;
content::RenderFrameHost* render_frame_host) override; void RenderViewDeleted(content::RenderViewHost* render_view_host) override;
void RenderViewCreated(
content::RenderViewHost* render_view_host) override;
void RenderViewDeleted(
content::RenderViewHost* render_view_host) override;
void RenderViewReady() override; void RenderViewReady() override;
void RenderProcessGone(base::TerminationStatus status) override; void RenderProcessGone(base::TerminationStatus status) override;
void DidCommitProvisionalLoadForFrame( void DidFinishNavigation(
content::RenderFrameHost* render_frame_host, content::NavigationHandle* navigation_handle) override;
const GURL& url,
ui::PageTransition transition_type) override;
void DidFailProvisionalLoad(
content::RenderFrameHost* render_frame_host,
const GURL& validated_url,
int error_code,
const base::string16& error_description,
bool was_ignored_by_handler) override;
void DocumentAvailableInMainFrame() override; void DocumentAvailableInMainFrame() override;
void DidFailLoad(content::RenderFrameHost* render_frame_host, void DidFailLoad(content::RenderFrameHost* render_frame_host,
const GURL& validated_url, const GURL& validated_url,
int error_code, int error_code,
const base::string16& error_description, const base::string16& error_description,
bool was_ignored_by_handler) override; bool was_ignored_by_handler) override;
void FrameDeleted( void FrameDeleted(content::RenderFrameHost* render_frame_host) override;
content::RenderFrameHost* render_frame_host) override;
void DidNavigateAnyFrame(
content::RenderFrameHost* render_frame_host,
const content::LoadCommittedDetails& details,
const content::FrameNavigateParams& params) override;
void TitleWasSet(content::NavigationEntry* entry, bool explicit_set) override; void TitleWasSet(content::NavigationEntry* entry, bool explicit_set) override;
void PluginCrashed(const base::FilePath& plugin_path, void PluginCrashed(const base::FilePath& plugin_path,
base::ProcessId plugin_pid) override; base::ProcessId plugin_pid) override;
@@ -554,12 +537,10 @@ class CefBrowserHostImpl : public CefBrowserHost,
void OnAddressChange(CefRefPtr<CefFrame> frame, void OnAddressChange(CefRefPtr<CefFrame> frame,
const GURL& url); const GURL& url);
void OnLoadStart(CefRefPtr<CefFrame> frame, void OnLoadStart(CefRefPtr<CefFrame> frame,
const GURL& url,
ui::PageTransition transition_type); ui::PageTransition transition_type);
void OnLoadError(CefRefPtr<CefFrame> frame, void OnLoadError(CefRefPtr<CefFrame> frame,
const GURL& url, const GURL& url,
int error_code, int error_code);
const base::string16& error_description);
void OnLoadEnd(CefRefPtr<CefFrame> frame, void OnLoadEnd(CefRefPtr<CefFrame> frame,
const GURL& url, const GURL& url,
int http_status_code); int http_status_code);

View File

@@ -327,4 +327,11 @@ patches = [
'name': 'views_menu_2102', 'name': 'views_menu_2102',
'path': '../', 'path': '../',
}, },
{
# Expose RFH via NavigationHandle for retrieval in DidFinishNavigation on
# network error.
# https://groups.google.com/a/chromium.org/d/msg/chromium-dev/6iAQPx_hwh8/gaTR5f1GAQAJ
'name': 'navigation_handle',
'path': '../',
},
] ]

View File

@@ -0,0 +1,42 @@
diff --git content/browser/frame_host/navigation_handle_impl.cc content/browser/frame_host/navigation_handle_impl.cc
index 30536bd..6fdb9a3 100644
--- content/browser/frame_host/navigation_handle_impl.cc
+++ content/browser/frame_host/navigation_handle_impl.cc
@@ -223,12 +223,6 @@ net::Error NavigationHandleImpl::GetNetErrorCode() {
}
RenderFrameHostImpl* NavigationHandleImpl::GetRenderFrameHost() {
- // TODO(mkwst): Change this to check against 'READY_TO_COMMIT' once
- // ReadyToCommitNavigation is available whether or not PlzNavigate is
- // enabled. https://crbug.com/621856
- CHECK_GE(state_, WILL_PROCESS_RESPONSE)
- << "This accessor should only be called after a response has been "
- "delivered for processing.";
return render_frame_host_;
}
diff --git content/browser/frame_host/navigation_handle_impl.h content/browser/frame_host/navigation_handle_impl.h
index 19b6871..6e85c69 100644
--- content/browser/frame_host/navigation_handle_impl.h
+++ content/browser/frame_host/navigation_handle_impl.h
@@ -300,6 +300,8 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
searchable_form_encoding_ = encoding;
}
+ const std::vector<GURL>& redirect_chain() const { return redirect_chain_; }
+
private:
friend class NavigationHandleImplTest;
diff --git content/browser/frame_host/render_frame_host_impl.cc content/browser/frame_host/render_frame_host_impl.cc
index e496ce3..de019a8 100644
--- content/browser/frame_host/render_frame_host_impl.cc
+++ content/browser/frame_host/render_frame_host_impl.cc
@@ -1139,6 +1139,7 @@ void RenderFrameHostImpl::OnDidFailProvisionalLoadWithError(
if (navigation_handle_) {
navigation_handle_->set_net_error_code(
static_cast<net::Error>(params.error_code));
+ navigation_handle_->set_render_frame_host(this);
}
frame_tree_node_->navigator()->DidFailProvisionalLoadWithError(this, params);

View File

@@ -1058,6 +1058,8 @@ class MultiQueryManager : public CefMessageRouterBrowserSide::Handler {
virtual ~MultiQueryManager() {} virtual ~MultiQueryManager() {}
std::string label() const { return label_; }
void AddObserver(Observer* observer) { void AddObserver(Observer* observer) {
EXPECT_FALSE(running_); EXPECT_FALSE(running_);
observer_set_.insert(observer); observer_set_.insert(observer);
@@ -2274,15 +2276,12 @@ class MultiQueryManagerMap :
MultiQueryManager* CreateManager(const std::string& url, bool synchronous) { MultiQueryManager* CreateManager(const std::string& url, bool synchronous) {
EXPECT_FALSE(finalized_); EXPECT_FALSE(finalized_);
// The sub-frame resource should not already exist.
URLManagerMap::const_iterator it = manager_map_.find(url);
EXPECT_EQ(it, manager_map_.end());
MultiQueryManager* manager = MultiQueryManager* manager =
new MultiQueryManager(url, synchronous, new MultiQueryManager(url, synchronous,
static_cast<int>(manager_map_.size()) * 1000); static_cast<int>(manager_map_.size()) * 1000);
manager->AddObserver(this); manager->AddObserver(this);
manager_map_.insert(std::make_pair(url, manager)); all_managers_.push_back(manager);
pending_managers_.push_back(manager);
return manager; return manager;
} }
@@ -2298,11 +2297,10 @@ class MultiQueryManagerMap :
std::string html = "<html><body>\n"; std::string html = "<html><body>\n";
URLManagerMap::const_iterator it = manager_map_.begin(); for (size_t i = 0; i < all_managers_.size(); ++i) {
for (; it != manager_map_.end(); ++it) { const std::string& url = all_managers_[i]->label();
const std::string& name = GetNameForURL(it->first); const std::string& name = GetNameForURL(url);
html += "<iframe id=\"" + name + "\" src=\"" + it->first + html += "<iframe id=\"" + name + "\" src=\"" + url + "\"></iframe>\n";
"\"></iframe>\n";
} }
html += "</body></html>"; html += "</body></html>";
@@ -2347,7 +2345,7 @@ class MultiQueryManagerMap :
} }
void OnManualQueriesCompleted(MultiQueryManager* manager) override { void OnManualQueriesCompleted(MultiQueryManager* manager) override {
const int size = static_cast<int>(manager_map_.size()); const int size = static_cast<int>(all_managers_.size());
EXPECT_LT(manual_complete_count_, size); EXPECT_LT(manual_complete_count_, size);
if (++manual_complete_count_ == size) { if (++manual_complete_count_ == size) {
running_ = false; running_ = false;
@@ -2367,7 +2365,7 @@ class MultiQueryManagerMap :
} }
void OnAllQueriesCompleted(MultiQueryManager* manager) override { void OnAllQueriesCompleted(MultiQueryManager* manager) override {
const int size = static_cast<int>(manager_map_.size()); const int size = static_cast<int>(all_managers_.size());
EXPECT_LT(total_complete_count_, size); EXPECT_LT(total_complete_count_, size);
if (++total_complete_count_ == size) { if (++total_complete_count_ == size) {
running_ = false; running_ = false;
@@ -2389,9 +2387,8 @@ class MultiQueryManagerMap :
bool AllComplete() const { bool AllComplete() const {
EXPECT_TRUE(finalized_); EXPECT_TRUE(finalized_);
URLManagerMap::const_iterator it = manager_map_.begin(); for (size_t i = 0; i < all_managers_.size(); ++i) {
for (; it != manager_map_.end(); ++it) { if (!all_managers_[i]->IsAllComplete())
if (!it->second->IsAllComplete())
return false; return false;
} }
return true; return true;
@@ -2399,55 +2396,84 @@ class MultiQueryManagerMap :
void AssertAllComplete() const { void AssertAllComplete() const {
EXPECT_TRUE(finalized_); EXPECT_TRUE(finalized_);
EXPECT_TRUE(pending_managers_.empty());
EXPECT_FALSE(running_); EXPECT_FALSE(running_);
URLManagerMap::const_iterator it = manager_map_.begin(); for (size_t i = 0; i < all_managers_.size(); ++i) {
for (; it != manager_map_.end(); ++it) all_managers_[i]->AssertAllComplete();
it->second->AssertAllComplete(); }
} }
bool HasAutoQueries() const { bool HasAutoQueries() const {
if (manager_map_.empty()) for (size_t i = 0; i < all_managers_.size(); ++i) {
return false; if (all_managers_[i]->HasAutoQueries())
URLManagerMap::const_iterator it = manager_map_.begin();
for (; it != manager_map_.end(); ++it) {
if (it->second->HasAutoQueries())
return true; return true;
} }
return false; return false;
} }
void OnLoadStart(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame) {
if (pending_managers_.empty())
return;
const std::string& expected_url = frame->GetURL();
MultiQueryManager* next_manager = nullptr;
// Find the pending manager that matches the expected URL.
ManagerList::iterator it = pending_managers_.begin();
for (; it != pending_managers_.end(); ++it) {
if ((*it)->label() == expected_url) {
next_manager = *it;
pending_managers_.erase(it);
break;
}
}
EXPECT_TRUE(next_manager);
const int browser_id = browser->GetIdentifier();
// Always use the same ID for the main frame.
const int64 frame_id = frame->IsMain() ? -1 : frame->GetIdentifier();
const std::pair<int, int64>& id = std::make_pair(browser_id, frame_id);
// Remove the currently active manager, if any.
ManagerMap::iterator it2 = manager_map_.find(id);
if (it2 != manager_map_.end())
manager_map_.erase(it2);
// Add the next manager to the active map.
manager_map_.insert(std::make_pair(id, next_manager));
}
MultiQueryManager* GetManager(CefRefPtr<CefBrowser> browser, MultiQueryManager* GetManager(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame) const { CefRefPtr<CefFrame> frame) const {
const std::string& url = frame->GetURL(); const int browser_id = browser->GetIdentifier();
URLManagerMap::const_iterator it = manager_map_.find(url); // Always use the same ID for the main frame.
EXPECT_NE(it, manager_map_.end()); const int64 frame_id = frame->IsMain() ? -1 : frame->GetIdentifier();
// Find the manager in the active map.
ManagerMap::const_iterator it =
manager_map_.find(std::make_pair(browser_id, frame_id));
EXPECT_NE(it, manager_map_.end()) <<
"browser_id = " << browser_id << ", frame_id = " << frame_id;
return it->second; return it->second;
} }
void RemoveAllManagers() { void RemoveAllManagers() {
if (manager_map_.empty()) EXPECT_TRUE(pending_managers_.empty());
if (all_managers_.empty())
return; return;
URLManagerMap::const_iterator it = manager_map_.begin(); for (size_t i = 0; i < all_managers_.size(); ++i) {
for (; it != manager_map_.end(); ++it) delete all_managers_[i];
delete it->second; }
all_managers_.clear();
manager_map_.clear(); manager_map_.clear();
} }
std::string GetURLForManager(MultiQueryManager* manager) const {
if (!manager_map_.empty()) {
URLManagerMap::const_iterator it = manager_map_.begin();
for (; it != manager_map_.end(); ++it) {
if (it->second == manager)
return it->first;
}
}
return std::string();
}
static std::string GetNameForURL(const std::string& url) { static std::string GetNameForURL(const std::string& url) {
// Extract the file name without extension. // Extract the file name without extension.
int pos1 = static_cast<int>(url.rfind("/")); int pos1 = static_cast<int>(url.rfind("/"));
@@ -2457,9 +2483,16 @@ class MultiQueryManagerMap :
} }
private: private:
// Map of page URL to MultiQueryManager instance. typedef std::vector<MultiQueryManager*> ManagerList;
typedef std::map<std::string, MultiQueryManager*> URLManagerMap; // Map of (browser ID, frame ID) to manager.
URLManagerMap manager_map_; typedef std::map<std::pair<int, int64>, MultiQueryManager*> ManagerMap;
// All managers that have been created.
ManagerList all_managers_;
// Managers that have not yet associated with a frame.
ManagerList pending_managers_;
// Managers that are currently active.
ManagerMap manager_map_;
typedef std::set<Observer*> ObserverSet; typedef std::set<Observer*> ObserverSet;
ObserverSet observer_set_; ObserverSet observer_set_;
@@ -2501,6 +2534,14 @@ class MultiQueryMultiFrameTestHandler :
return manager_map_.GetMainHTML(); return manager_map_.GetMainHTML();
} }
void OnLoadStart(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
TransitionType transition_type) override {
AssertMainBrowser(browser);
if (!frame->IsMain())
manager_map_.OnLoadStart(browser, frame);
}
void OnNotify(CefRefPtr<CefBrowser> browser, void OnNotify(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame, CefRefPtr<CefFrame> frame,
const std::string& message) override { const std::string& message) override {
@@ -2637,6 +2678,12 @@ class MultiQueryMultiLoadTestHandler :
manager_map_.AddObserver(this); manager_map_.AddObserver(this);
} }
void OnLoadStart(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
TransitionType transition_type) override {
manager_map_.OnLoadStart(browser, frame);
}
void OnNotify(CefRefPtr<CefBrowser> browser, void OnNotify(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame, CefRefPtr<CefFrame> frame,
const std::string& message) override { const std::string& message) override {
@@ -2797,7 +2844,7 @@ class MultiQueryMultiNavigateTestHandler : public MultiQueryMultiLoadTestHandler
} }
void OnManualQueriesCompleted(MultiQueryManager* manager) override { void OnManualQueriesCompleted(MultiQueryManager* manager) override {
const std::string& url = manager_map_.GetURLForManager(manager); const std::string& url = manager->label();
if (url == url1_) // 2. Load the 2nd url. if (url == url1_) // 2. Load the 2nd url.
GetBrowser()->GetMainFrame()->LoadURL(url2_); GetBrowser()->GetMainFrame()->LoadURL(url2_);
else if (url == url2_) // 3. Load the 3rd url. else if (url == url2_) // 3. Load the 3rd url.

View File

@@ -2325,6 +2325,23 @@ class PopupNavTestHandler : public TestHandler {
} }
} }
void OnLoadError(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) override {
if (failedUrl == kPopupNavPageUrl) {
EXPECT_FALSE(got_load_error_);
got_load_error_.yes();
} else if (failedUrl == kPopupNavPopupUrl) {
EXPECT_FALSE(got_popup_load_error_);
got_popup_load_error_.yes();
} else if (failedUrl == kPopupNavPopupUrl2) {
EXPECT_FALSE(got_popup_load_error2_);
got_popup_load_error2_.yes();
}
}
void OnLoadEnd(CefRefPtr<CefBrowser> browser, void OnLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame, CefRefPtr<CefFrame> frame,
int httpStatusCode) override { int httpStatusCode) override {
@@ -2370,22 +2387,29 @@ class PopupNavTestHandler : public TestHandler {
private: private:
void DestroyTest() override { void DestroyTest() override {
EXPECT_TRUE(got_load_start_); EXPECT_TRUE(got_load_start_);
EXPECT_FALSE(got_load_error_);
EXPECT_TRUE(got_load_end_); EXPECT_TRUE(got_load_end_);
EXPECT_TRUE(got_on_before_popup_); EXPECT_TRUE(got_on_before_popup_);
if (mode_ == ALLOW) { if (mode_ == ALLOW) {
EXPECT_TRUE(got_popup_load_start_); EXPECT_TRUE(got_popup_load_start_);
EXPECT_FALSE(got_popup_load_error_);
EXPECT_TRUE(got_popup_load_end_); EXPECT_TRUE(got_popup_load_end_);
EXPECT_FALSE(got_popup_load_start2_); EXPECT_FALSE(got_popup_load_start2_);
EXPECT_FALSE(got_popup_load_error2_);
EXPECT_FALSE(got_popup_load_end2_); EXPECT_FALSE(got_popup_load_end2_);
} else if (mode_ == DENY) { } else if (mode_ == DENY) {
EXPECT_FALSE(got_popup_load_start_); EXPECT_FALSE(got_popup_load_start_);
EXPECT_FALSE(got_popup_load_error_);
EXPECT_FALSE(got_popup_load_end_); EXPECT_FALSE(got_popup_load_end_);
EXPECT_FALSE(got_popup_load_start2_); EXPECT_FALSE(got_popup_load_start2_);
EXPECT_FALSE(got_popup_load_error2_);
EXPECT_FALSE(got_popup_load_end2_); EXPECT_FALSE(got_popup_load_end2_);
} else if (mode_ == NAVIGATE_AFTER_CREATION) { } else if (mode_ == NAVIGATE_AFTER_CREATION) {
EXPECT_FALSE(got_popup_load_start_); EXPECT_FALSE(got_popup_load_start_);
EXPECT_TRUE(got_popup_load_error_);
EXPECT_FALSE(got_popup_load_end_); EXPECT_FALSE(got_popup_load_end_);
EXPECT_TRUE(got_popup_load_start2_); EXPECT_TRUE(got_popup_load_start2_);
EXPECT_FALSE(got_popup_load_error2_);
EXPECT_TRUE(got_popup_load_end2_); EXPECT_TRUE(got_popup_load_end2_);
} }
@@ -2396,10 +2420,13 @@ class PopupNavTestHandler : public TestHandler {
TrackCallback got_on_before_popup_; TrackCallback got_on_before_popup_;
TrackCallback got_load_start_; TrackCallback got_load_start_;
TrackCallback got_load_error_;
TrackCallback got_load_end_; TrackCallback got_load_end_;
TrackCallback got_popup_load_start_; TrackCallback got_popup_load_start_;
TrackCallback got_popup_load_error_;
TrackCallback got_popup_load_end_; TrackCallback got_popup_load_end_;
TrackCallback got_popup_load_start2_; TrackCallback got_popup_load_start2_;
TrackCallback got_popup_load_error2_;
TrackCallback got_popup_load_end2_; TrackCallback got_popup_load_end2_;
IMPLEMENT_REFCOUNTING(PopupNavTestHandler); IMPLEMENT_REFCOUNTING(PopupNavTestHandler);
@@ -2865,6 +2892,671 @@ TEST(NavigationTest, BrowseDeny) {
ReleaseAndWaitForDestructor(handler); ReleaseAndWaitForDestructor(handler);
} }
namespace {
const char kSameNavPageUrl[] = "http://tests-samenav/nav.html";
// Browser side.
class SameNavTestHandler : public TestHandler {
public:
SameNavTestHandler()
: destroyed_(false),
step_(0) {}
void RunTest() override {
AddResource(kSameNavPageUrl, "<html>Test</html>", "text/html");
// Create the browser.
expected_url_ = kSameNavPageUrl;
CreateBrowser(kSameNavPageUrl);
// Time out the test after a reasonable period of time.
SetTestTimeout();
}
bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
bool is_redirect) override {
const std::string& url = request->GetURL();
EXPECT_STREQ(expected_url_.c_str(), url.c_str());
EXPECT_EQ(GetBrowserId(), browser->GetIdentifier());
EXPECT_TRUE(frame->IsMain());
got_before_browse_.yes();
return false;
}
void OnLoadStart(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
TransitionType transition_type) override {
const std::string& url = frame->GetURL();
EXPECT_STREQ(expected_url_.c_str(), url.c_str());
EXPECT_EQ(GetBrowserId(), browser->GetIdentifier());
EXPECT_TRUE(frame->IsMain());
got_load_start_.yes();
}
void OnLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int httpStatusCode) override {
const std::string& url = frame->GetURL();
EXPECT_STREQ(expected_url_.c_str(), url.c_str());
EXPECT_EQ(GetBrowserId(), browser->GetIdentifier());
EXPECT_TRUE(frame->IsMain());
got_load_end_.yes();
ContinueTestIfDone();
}
void OnLoadError(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) override {
got_load_error_.yes();
}
void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
bool isLoading,
bool canGoBack,
bool canGoForward) override {
const std::string& url = browser->GetMainFrame()->GetURL();
EXPECT_EQ(GetBrowserId(), browser->GetIdentifier());
if (isLoading) {
// Verify the previous URL.
if (step_ == 0)
EXPECT_TRUE(url.empty());
else
EXPECT_STREQ(kSameNavPageUrl, url.c_str());
got_loading_state_changed_start_.yes();
} else {
EXPECT_STREQ(expected_url_.c_str(), url.c_str());
got_loading_state_changed_end_.yes();
ContinueTestIfDone();
}
}
private:
void ContinueTestIfDone() {
if (step_ == 0) {
// First navigation should trigger all callbacks except OnLoadError.
if (got_loading_state_changed_end_ && got_load_end_) {
EXPECT_TRUE(got_before_browse_);
EXPECT_TRUE(got_loading_state_changed_start_);
EXPECT_TRUE(got_load_start_);
EXPECT_FALSE(got_load_error_);
got_before_browse_.reset();
got_loading_state_changed_start_.reset();
got_loading_state_changed_end_.reset();
got_load_start_.reset();
got_load_end_.reset();
step_++;
expected_url_ = kSameNavPageUrl + std::string("#fragment");
GetBrowser()->GetMainFrame()->LoadURL(expected_url_);
}
} else if (step_ == 1) {
step_++;
DestroyTest();
} else {
EXPECT_TRUE(false); // Not reached.
}
}
void DestroyTest() override {
if (destroyed_)
return;
destroyed_ = true;
EXPECT_EQ(2, step_);
// Second (fragment) navigation should only trigger OnLoadingStateChange.
EXPECT_FALSE(got_before_browse_);
EXPECT_TRUE(got_loading_state_changed_start_);
EXPECT_TRUE(got_loading_state_changed_end_);
EXPECT_FALSE(got_load_start_);
EXPECT_FALSE(got_load_end_);
EXPECT_FALSE(got_load_error_);
TestHandler::DestroyTest();
}
bool destroyed_;
int step_;
std::string expected_url_;
TrackCallback got_before_browse_;
TrackCallback got_load_start_;
TrackCallback got_load_end_;
TrackCallback got_load_error_;
TrackCallback got_loading_state_changed_start_;
TrackCallback got_loading_state_changed_end_;
IMPLEMENT_REFCOUNTING(SameNavTestHandler);
};
} // namespace
// Test that same page navigation does not call OnLoadStart/OnLoadEnd.
TEST(NavigationTest, SamePage) {
CefRefPtr<SameNavTestHandler> handler = new SameNavTestHandler();
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
namespace {
const char kCancelPageUrl[] = "http://tests-cancelnav/nav.html";
// A scheme handler that never starts sending data.
class UnstartedSchemeHandler : public CefResourceHandler {
public:
UnstartedSchemeHandler() {}
bool ProcessRequest(CefRefPtr<CefRequest> request,
CefRefPtr<CefCallback> callback) override {
callback->Continue();
return true;
}
void GetResponseHeaders(CefRefPtr<CefResponse> response,
int64& response_length,
CefString& redirectUrl) override {
response->SetStatus(200);
response->SetMimeType("text/html");
response_length = 100;
}
void Cancel() override {
callback_ = nullptr;
}
bool ReadResponse(void* data_out,
int bytes_to_read,
int& bytes_read,
CefRefPtr<CefCallback> callback) override {
callback_ = callback;
// Pretend that we'll provide the data later.
bytes_read = 0;
return true;
}
protected:
CefRefPtr<CefCallback> callback_;
IMPLEMENT_REFCOUNTING(UnstartedSchemeHandler);
};
// Browser side.
class CancelBeforeNavTestHandler : public TestHandler {
public:
CancelBeforeNavTestHandler()
: destroyed_(false) {}
void RunTest() override {
// Create the browser.
CreateBrowser(kCancelPageUrl);
// Time out the test after a reasonable period of time.
SetTestTimeout();
}
bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
bool is_redirect) override {
EXPECT_TRUE(got_loading_state_changed_start_);
EXPECT_FALSE(got_before_browse_);
EXPECT_FALSE(got_get_resource_handler_);
EXPECT_FALSE(got_load_start_);
EXPECT_FALSE(got_cancel_load_);
EXPECT_FALSE(got_load_error_);
EXPECT_FALSE(got_load_end_);
EXPECT_FALSE(got_loading_state_changed_end_);
const std::string& url = request->GetURL();
EXPECT_STREQ(kCancelPageUrl, url.c_str());
EXPECT_EQ(GetBrowserId(), browser->GetIdentifier());
EXPECT_TRUE(frame->IsMain());
got_before_browse_.yes();
return false;
}
CefRefPtr<CefResourceHandler> GetResourceHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request) override {
EXPECT_TRUE(got_loading_state_changed_start_);
EXPECT_TRUE(got_before_browse_);
EXPECT_FALSE(got_get_resource_handler_);
EXPECT_FALSE(got_load_start_);
EXPECT_FALSE(got_cancel_load_);
EXPECT_FALSE(got_load_error_);
EXPECT_FALSE(got_load_end_);
EXPECT_FALSE(got_loading_state_changed_end_);
const std::string& url = request->GetURL();
EXPECT_STREQ(kCancelPageUrl, url.c_str());
EXPECT_EQ(GetBrowserId(), browser->GetIdentifier());
EXPECT_TRUE(frame->IsMain());
got_get_resource_handler_.yes();
CefPostDelayedTask(TID_UI,
base::Bind(&CancelBeforeNavTestHandler::CancelLoad, this), 100);
return new UnstartedSchemeHandler();
}
void OnLoadStart(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
TransitionType transition_type) override {
EXPECT_TRUE(false); // Not reached.
got_load_start_.yes();
}
void OnLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int httpStatusCode) override {
EXPECT_TRUE(false); // Not reached.
got_load_end_.yes();
}
void OnLoadError(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) override {
EXPECT_TRUE(got_loading_state_changed_start_);
EXPECT_TRUE(got_before_browse_);
EXPECT_TRUE(got_get_resource_handler_);
EXPECT_FALSE(got_load_start_);
EXPECT_TRUE(got_cancel_load_);
EXPECT_FALSE(got_load_error_);
EXPECT_FALSE(got_load_end_);
EXPECT_FALSE(got_loading_state_changed_end_);
const std::string& url = failedUrl;
EXPECT_STREQ(kCancelPageUrl, url.c_str());
EXPECT_EQ(GetBrowserId(), browser->GetIdentifier());
EXPECT_TRUE(frame->IsMain());
got_load_error_.yes();
}
void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
bool isLoading,
bool canGoBack,
bool canGoForward) override {
const std::string& url = browser->GetMainFrame()->GetURL();
EXPECT_EQ(GetBrowserId(), browser->GetIdentifier());
EXPECT_TRUE(url.empty());
if (isLoading) {
EXPECT_FALSE(got_loading_state_changed_start_);
EXPECT_FALSE(got_before_browse_);
EXPECT_FALSE(got_get_resource_handler_);
EXPECT_FALSE(got_load_start_);
EXPECT_FALSE(got_cancel_load_);
EXPECT_FALSE(got_load_error_);
EXPECT_FALSE(got_load_end_);
EXPECT_FALSE(got_loading_state_changed_end_);
got_loading_state_changed_start_.yes();
} else {
EXPECT_TRUE(got_loading_state_changed_start_);
EXPECT_TRUE(got_before_browse_);
EXPECT_TRUE(got_get_resource_handler_);
EXPECT_FALSE(got_load_start_);
EXPECT_TRUE(got_cancel_load_);
EXPECT_TRUE(got_load_error_);
EXPECT_FALSE(got_load_end_);
EXPECT_FALSE(got_loading_state_changed_end_);
got_loading_state_changed_end_.yes();
DestroyTest();
}
}
private:
void CancelLoad() {
got_cancel_load_.yes();
GetBrowser()->StopLoad();
}
void DestroyTest() override {
if (destroyed_)
return;
destroyed_ = true;
EXPECT_TRUE(got_loading_state_changed_start_);
EXPECT_TRUE(got_before_browse_);
EXPECT_TRUE(got_get_resource_handler_);
EXPECT_FALSE(got_load_start_);
EXPECT_TRUE(got_cancel_load_);
EXPECT_TRUE(got_load_error_);
EXPECT_FALSE(got_load_end_);
EXPECT_TRUE(got_loading_state_changed_end_);
TestHandler::DestroyTest();
}
bool destroyed_;
TrackCallback got_loading_state_changed_start_;
TrackCallback got_before_browse_;
TrackCallback got_get_resource_handler_;
TrackCallback got_load_start_;
TrackCallback got_cancel_load_;
TrackCallback got_load_error_;
TrackCallback got_load_end_;
TrackCallback got_loading_state_changed_end_;
IMPLEMENT_REFCOUNTING(CancelBeforeNavTestHandler);
};
} // namespace
// Test that navigation canceled before commit does not call
// OnLoadStart/OnLoadEnd.
TEST(NavigationTest, CancelBeforeCommit) {
CefRefPtr<CancelBeforeNavTestHandler> handler =
new CancelBeforeNavTestHandler();
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
namespace {
// A scheme handler that stalls after writing some data.
class StalledSchemeHandler : public CefResourceHandler {
public:
StalledSchemeHandler() : offset_(0), write_size_(0) {}
bool ProcessRequest(CefRefPtr<CefRequest> request,
CefRefPtr<CefCallback> callback) override {
callback->Continue();
return true;
}
void GetResponseHeaders(CefRefPtr<CefResponse> response,
int64& response_length,
CefString& redirectUrl) override {
response->SetStatus(200);
response->SetMimeType("text/html");
content_ = "<html><body>Test</body></html>";
// Write this number of bytes and then stall.
write_size_ = content_.size() / 2U;
response_length = content_.size();
}
void Cancel() override {
callback_ = nullptr;
}
bool ReadResponse(void* data_out,
int bytes_to_read,
int& bytes_read,
CefRefPtr<CefCallback> callback) override {
size_t size = content_.size();
if (offset_ >= write_size_) {
// Now stall.
bytes_read = 0;
callback_ = callback;
return true;
}
if (offset_ < size) {
// Write up to |write_size_| bytes.
int transfer_size =
std::min(bytes_to_read, std::min(static_cast<int>(write_size_),
static_cast<int>(size - offset_)));
memcpy(data_out, content_.c_str() + offset_, transfer_size);
offset_ += transfer_size;
bytes_read = transfer_size;
return true;
}
return false;
}
protected:
std::string content_;
size_t offset_;
size_t write_size_;
CefRefPtr<CefCallback> callback_;
IMPLEMENT_REFCOUNTING(StalledSchemeHandler);
};
// Browser side.
class CancelAfterNavTestHandler : public TestHandler {
public:
CancelAfterNavTestHandler()
: destroyed_(false) {}
void RunTest() override {
// Create the browser.
CreateBrowser(kCancelPageUrl);
// Time out the test after a reasonable period of time.
SetTestTimeout();
}
bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
bool is_redirect) override {
EXPECT_TRUE(got_loading_state_changed_start_);
EXPECT_FALSE(got_before_browse_);
EXPECT_FALSE(got_get_resource_handler_);
EXPECT_FALSE(got_load_start_);
EXPECT_FALSE(got_cancel_load_);
EXPECT_FALSE(got_load_error_);
EXPECT_FALSE(got_load_end_);
EXPECT_FALSE(got_loading_state_changed_end_);
const std::string& url = request->GetURL();
EXPECT_STREQ(kCancelPageUrl, url.c_str());
EXPECT_EQ(GetBrowserId(), browser->GetIdentifier());
EXPECT_TRUE(frame->IsMain());
got_before_browse_.yes();
return false;
}
CefRefPtr<CefResourceHandler> GetResourceHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request) override {
EXPECT_TRUE(got_loading_state_changed_start_);
EXPECT_TRUE(got_before_browse_);
EXPECT_FALSE(got_get_resource_handler_);
EXPECT_FALSE(got_load_start_);
EXPECT_FALSE(got_cancel_load_);
EXPECT_FALSE(got_load_error_);
EXPECT_FALSE(got_load_end_);
EXPECT_FALSE(got_loading_state_changed_end_);
const std::string& url = request->GetURL();
EXPECT_STREQ(kCancelPageUrl, url.c_str());
EXPECT_EQ(GetBrowserId(), browser->GetIdentifier());
EXPECT_TRUE(frame->IsMain());
got_get_resource_handler_.yes();
CefPostDelayedTask(TID_UI,
base::Bind(&CancelAfterNavTestHandler::CancelLoad, this), 100);
return new StalledSchemeHandler();
}
void OnLoadStart(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
TransitionType transition_type) override {
EXPECT_TRUE(got_loading_state_changed_start_);
EXPECT_TRUE(got_before_browse_);
EXPECT_TRUE(got_get_resource_handler_);
EXPECT_FALSE(got_load_start_);
EXPECT_FALSE(got_cancel_load_);
EXPECT_FALSE(got_load_error_);
EXPECT_FALSE(got_load_end_);
EXPECT_FALSE(got_loading_state_changed_end_);
const std::string& url = frame->GetURL();
EXPECT_STREQ(kCancelPageUrl, url.c_str());
EXPECT_EQ(GetBrowserId(), browser->GetIdentifier());
EXPECT_TRUE(frame->IsMain());
got_load_start_.yes();
}
void OnLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int httpStatusCode) override {
EXPECT_TRUE(got_loading_state_changed_start_);
EXPECT_TRUE(got_before_browse_);
EXPECT_TRUE(got_get_resource_handler_);
EXPECT_TRUE(got_load_start_);
EXPECT_TRUE(got_cancel_load_);
EXPECT_TRUE(got_load_error_);
EXPECT_FALSE(got_load_end_);
EXPECT_FALSE(got_loading_state_changed_end_);
const std::string& url = frame->GetURL();
EXPECT_STREQ(kCancelPageUrl, url.c_str());
EXPECT_EQ(GetBrowserId(), browser->GetIdentifier());
EXPECT_TRUE(frame->IsMain());
got_load_end_.yes();
DestroyTestIfDone();
}
void OnLoadError(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) override {
EXPECT_TRUE(got_loading_state_changed_start_);
EXPECT_TRUE(got_before_browse_);
EXPECT_TRUE(got_get_resource_handler_);
EXPECT_TRUE(got_load_start_);
EXPECT_TRUE(got_cancel_load_);
EXPECT_FALSE(got_load_error_);
EXPECT_FALSE(got_load_end_);
EXPECT_FALSE(got_loading_state_changed_end_);
const std::string& url = failedUrl;
EXPECT_STREQ(kCancelPageUrl, url.c_str());
EXPECT_EQ(GetBrowserId(), browser->GetIdentifier());
EXPECT_TRUE(frame->IsMain());
got_load_error_.yes();
}
void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
bool isLoading,
bool canGoBack,
bool canGoForward) override {
const std::string& url = browser->GetMainFrame()->GetURL();
EXPECT_EQ(GetBrowserId(), browser->GetIdentifier());
if (isLoading) {
EXPECT_FALSE(got_loading_state_changed_start_);
EXPECT_FALSE(got_before_browse_);
EXPECT_FALSE(got_get_resource_handler_);
EXPECT_FALSE(got_load_start_);
EXPECT_FALSE(got_cancel_load_);
EXPECT_FALSE(got_load_error_);
EXPECT_FALSE(got_load_end_);
EXPECT_FALSE(got_loading_state_changed_end_);
EXPECT_TRUE(url.empty());
got_loading_state_changed_start_.yes();
} else {
EXPECT_TRUE(got_loading_state_changed_start_);
EXPECT_TRUE(got_before_browse_);
EXPECT_TRUE(got_get_resource_handler_);
EXPECT_TRUE(got_load_start_);
EXPECT_TRUE(got_cancel_load_);
EXPECT_TRUE(got_load_error_);
EXPECT_TRUE(got_load_end_);
EXPECT_FALSE(got_loading_state_changed_end_);
EXPECT_STREQ(kCancelPageUrl, url.c_str());
got_loading_state_changed_end_.yes();
DestroyTestIfDone();
}
}
private:
void CancelLoad() {
got_cancel_load_.yes();
GetBrowser()->StopLoad();
}
void DestroyTestIfDone() {
if (got_loading_state_changed_end_ && got_load_end_)
DestroyTest();
}
void DestroyTest() override {
if (destroyed_)
return;
destroyed_ = true;
EXPECT_TRUE(got_loading_state_changed_start_);
EXPECT_TRUE(got_before_browse_);
EXPECT_TRUE(got_get_resource_handler_);
EXPECT_TRUE(got_load_start_);
EXPECT_TRUE(got_cancel_load_);
EXPECT_TRUE(got_load_error_);
EXPECT_TRUE(got_load_end_);
EXPECT_TRUE(got_loading_state_changed_end_);
TestHandler::DestroyTest();
}
bool destroyed_;
TrackCallback got_loading_state_changed_start_;
TrackCallback got_before_browse_;
TrackCallback got_get_resource_handler_;
TrackCallback got_load_start_;
TrackCallback got_cancel_load_;
TrackCallback got_load_error_;
TrackCallback got_load_end_;
TrackCallback got_loading_state_changed_end_;
IMPLEMENT_REFCOUNTING(CancelAfterNavTestHandler);
};
} // namespace
// Test that navigation canceled after commit calls everything.
TEST(NavigationTest, CancelAfterCommit) {
CefRefPtr<CancelAfterNavTestHandler> handler =
new CancelAfterNavTestHandler();
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
// Entry point for creating navigation browser test objects. // Entry point for creating navigation browser test objects.
// Called from client_app_delegates.cc. // Called from client_app_delegates.cc.