blob: ab1fa25190c4eca1f99111fd7ce196af62b53f7c [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/public/test/test_navigation_observer.h"
#include "base/bind.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/browser/frame_host/navigation_request.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/web_contents_observer.h"
namespace content {
class TestNavigationObserver::TestWebContentsObserver
: public WebContentsObserver {
public:
TestWebContentsObserver(TestNavigationObserver* parent,
WebContents* web_contents)
: WebContentsObserver(web_contents),
parent_(parent) {
}
private:
// WebContentsObserver:
void NavigationEntryCommitted(
const LoadCommittedDetails& load_details) override {
parent_->OnNavigationEntryCommitted(this, web_contents(), load_details);
}
void DidAttachInterstitialPage() override {
parent_->OnDidAttachInterstitialPage(web_contents());
}
void WebContentsDestroyed() override {
parent_->OnWebContentsDestroyed(this, web_contents());
}
void DidStartLoading() override {
parent_->OnDidStartLoading(web_contents());
}
void DidStopLoading() override {
parent_->OnDidStopLoading(web_contents());
}
void DidStartNavigation(NavigationHandle* navigation_handle) override {
if (navigation_handle->IsSameDocument())
return;
parent_->OnDidStartNavigation(navigation_handle);
}
void DidFinishNavigation(NavigationHandle* navigation_handle) override {
if (!navigation_handle->HasCommitted())
return;
parent_->OnDidFinishNavigation(navigation_handle);
}
TestNavigationObserver* parent_;
DISALLOW_COPY_AND_ASSIGN(TestWebContentsObserver);
};
TestNavigationObserver::TestNavigationObserver(
WebContents* web_contents,
int number_of_navigations,
MessageLoopRunner::QuitMode quit_mode)
: TestNavigationObserver(web_contents,
number_of_navigations,
GURL(),
quit_mode) {}
TestNavigationObserver::TestNavigationObserver(
WebContents* web_contents,
MessageLoopRunner::QuitMode quit_mode)
: TestNavigationObserver(web_contents, 1, quit_mode) {}
TestNavigationObserver::TestNavigationObserver(
const GURL& target_url,
MessageLoopRunner::QuitMode quit_mode)
: TestNavigationObserver(nullptr,
-1 /* num_of_navigations */,
target_url,
quit_mode) {}
TestNavigationObserver::~TestNavigationObserver() {
StopWatchingNewWebContents();
}
void TestNavigationObserver::Wait() {
message_loop_runner_->Run();
}
void TestNavigationObserver::WaitForNavigationFinished() {
wait_event_ = WaitEvent::kNavigationFinished;
message_loop_runner_->Run();
}
void TestNavigationObserver::StartWatchingNewWebContents() {
WebContentsImpl::FriendWrapper::AddCreatedCallbackForTesting(
web_contents_created_callback_);
}
void TestNavigationObserver::StopWatchingNewWebContents() {
WebContentsImpl::FriendWrapper::RemoveCreatedCallbackForTesting(
web_contents_created_callback_);
}
void TestNavigationObserver::WatchExistingWebContents() {
for (auto* web_contents : WebContentsImpl::GetAllWebContents())
RegisterAsObserver(web_contents);
}
void TestNavigationObserver::RegisterAsObserver(WebContents* web_contents) {
web_contents_observers_.insert(
std::make_unique<TestWebContentsObserver>(this, web_contents));
}
TestNavigationObserver::TestNavigationObserver(
WebContents* web_contents,
int number_of_navigations,
const GURL& target_url,
MessageLoopRunner::QuitMode quit_mode)
: wait_event_(WaitEvent::kLoadStopped),
navigation_started_(false),
navigations_completed_(0),
number_of_navigations_(number_of_navigations),
target_url_(target_url),
last_navigation_succeeded_(false),
last_net_error_code_(net::OK),
last_navigation_type_(NAVIGATION_TYPE_UNKNOWN),
message_loop_runner_(new MessageLoopRunner(quit_mode)),
web_contents_created_callback_(
base::Bind(&TestNavigationObserver::OnWebContentsCreated,
base::Unretained(this))) {
if (web_contents)
RegisterAsObserver(web_contents);
}
void TestNavigationObserver::OnWebContentsCreated(WebContents* web_contents) {
RegisterAsObserver(web_contents);
}
void TestNavigationObserver::OnWebContentsDestroyed(
TestWebContentsObserver* observer,
WebContents* web_contents) {
web_contents_observers_.erase(std::find_if(
web_contents_observers_.begin(), web_contents_observers_.end(),
[observer](const std::unique_ptr<TestWebContentsObserver>& ptr) {
return ptr.get() == observer;
}));
}
void TestNavigationObserver::OnNavigationEntryCommitted(
TestWebContentsObserver* observer,
WebContents* web_contents,
const LoadCommittedDetails& load_details) {
navigation_started_ = true;
}
void TestNavigationObserver::OnDidAttachInterstitialPage(
WebContents* web_contents) {
// Going to an interstitial page does not trigger NavigationEntryCommitted,
// but has the same meaning for us here.
navigation_started_ = true;
}
void TestNavigationObserver::OnDidStartLoading(WebContents* web_contents) {
navigation_started_ = true;
}
void TestNavigationObserver::OnDidStopLoading(WebContents* web_contents) {
if (!navigation_started_)
return;
if (wait_event_ == WaitEvent::kLoadStopped)
EventTriggered();
}
void TestNavigationObserver::OnDidStartNavigation(
NavigationHandle* navigation_handle) {
last_navigation_succeeded_ = false;
NavigationHandleImpl* nav_handle =
static_cast<NavigationHandleImpl*>(navigation_handle);
if (nav_handle->frame_tree_node()->navigation_request()) {
last_initiator_origin_ = nav_handle->frame_tree_node()
->navigation_request()
->common_params()
.initiator_origin;
} else {
last_initiator_origin_.reset();
}
}
void TestNavigationObserver::OnDidFinishNavigation(
NavigationHandle* navigation_handle) {
last_navigation_url_ = navigation_handle->GetURL();
last_navigation_succeeded_ = !navigation_handle->IsErrorPage();
last_net_error_code_ = navigation_handle->GetNetErrorCode();
last_navigation_type_ =
static_cast<NavigationHandleImpl*>(navigation_handle)->navigation_type();
if (wait_event_ == WaitEvent::kNavigationFinished)
EventTriggered();
}
void TestNavigationObserver::EventTriggered() {
if (target_url_ == GURL()) {
DCHECK_GE(navigations_completed_, 0);
++navigations_completed_;
if (navigations_completed_ != number_of_navigations_) {
return;
}
} else if (target_url_ != last_navigation_url_) {
return;
}
navigation_started_ = false;
message_loop_runner_->Quit();
}
} // namespace content