blob: 2a7b31f47705f2ed66c36b069079e080f679935e [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/test/mock_commit_deferring_condition.h"
#include "content/browser/renderer_host/navigation_request.h"
namespace content {
class MockCommitDeferringCondition : public CommitDeferringCondition {
using WillCommitCallback = base::OnceCallback<void(base::OnceClosure)>;
public:
// |is_ready_to_commit| specifies whether the condition is ready to commit at
// the time WillCommitNavigation is called. If false, the runner will block
// asynchronously until the closure passed into WillCommitNavigation is
// invoked. |on_will_commit_navigation_| is invoked when WillCommitNavigation
// is called by the delegate. It will receive the |resume| callback which can
// be used to unblock an asynchronously deferred condition.
MockCommitDeferringCondition(NavigationHandle& handle,
bool is_ready_to_commit,
WillCommitCallback on_will_commit_navigation)
: CommitDeferringCondition(handle),
is_ready_to_commit_(is_ready_to_commit),
on_will_commit_navigation_(std::move(on_will_commit_navigation)) {}
~MockCommitDeferringCondition() override = default;
MockCommitDeferringCondition(const MockCommitDeferringCondition&) = delete;
MockCommitDeferringCondition& operator=(const MockCommitDeferringCondition&) =
delete;
Result WillCommitNavigation(base::OnceClosure resume) override {
if (on_will_commit_navigation_)
std::move(on_will_commit_navigation_).Run(std::move(resume));
return is_ready_to_commit_ ? Result::kProceed : Result::kDefer;
}
base::WeakPtr<MockCommitDeferringCondition> AsWeakPtr() {
return weak_factory_.GetWeakPtr();
}
private:
const bool is_ready_to_commit_;
WillCommitCallback on_will_commit_navigation_;
base::WeakPtrFactory<MockCommitDeferringCondition> weak_factory_{this};
};
MockCommitDeferringConditionWrapper::MockCommitDeferringConditionWrapper(
NavigationHandle& handle,
bool is_ready_to_commit) {
condition_ = std::make_unique<MockCommitDeferringCondition>(
handle, is_ready_to_commit,
base::BindOnce(
&MockCommitDeferringConditionWrapper::WillCommitNavigationCalled,
weak_factory_.GetWeakPtr()));
weak_condition_ = condition_->AsWeakPtr();
}
MockCommitDeferringConditionWrapper::~MockCommitDeferringConditionWrapper() =
default;
std::unique_ptr<CommitDeferringCondition>
MockCommitDeferringConditionWrapper::PassToDelegate() {
DCHECK(condition_);
std::unique_ptr<MockCommitDeferringCondition> ret = std::move(condition_);
return ret;
}
void MockCommitDeferringConditionWrapper::CallResumeClosure() {
DCHECK(WasInvoked());
DCHECK(resume_closure_);
std::move(resume_closure_).Run();
}
bool MockCommitDeferringConditionWrapper::WasInvoked() const {
return did_call_will_commit_navigation_;
}
bool MockCommitDeferringConditionWrapper::IsDestroyed() const {
return !static_cast<bool>(weak_condition_);
}
void MockCommitDeferringConditionWrapper::WaitUntilInvoked() {
if (WasInvoked())
return;
base::RunLoop loop;
invoked_closure_ = loop.QuitClosure();
loop.Run();
}
base::OnceClosure MockCommitDeferringConditionWrapper::TakeResumeClosure() {
DCHECK(resume_closure_);
return std::move(resume_closure_);
}
void MockCommitDeferringConditionWrapper::WillCommitNavigationCalled(
base::OnceClosure resume_closure) {
did_call_will_commit_navigation_ = true;
resume_closure_ = std::move(resume_closure);
if (invoked_closure_)
std::move(invoked_closure_).Run();
}
MockCommitDeferringConditionInstaller::MockCommitDeferringConditionInstaller(
const GURL& url,
bool is_ready_to_commit,
CommitDeferringConditionRunner::InsertOrder order)
: url_(url),
is_ready_to_commit_(is_ready_to_commit),
generator_id_(
CommitDeferringConditionRunner::InstallConditionGeneratorForTesting(
base::BindRepeating(
&MockCommitDeferringConditionInstaller::Install,
base::Unretained(this)),
order)) {}
MockCommitDeferringConditionInstaller::
~MockCommitDeferringConditionInstaller() {
CommitDeferringConditionRunner::UninstallConditionGeneratorForTesting(
generator_id_);
}
void MockCommitDeferringConditionInstaller::WaitUntilInstalled() {
if (installed_condition_)
return;
base::RunLoop loop;
was_installed_closure_ = loop.QuitClosure();
loop.Run();
}
std::unique_ptr<CommitDeferringCondition>
MockCommitDeferringConditionInstaller::Install(
NavigationHandle& handle,
CommitDeferringCondition::NavigationType /*type*/) {
DCHECK(!installed_condition_)
<< "MockCommitDeferringConditionInstaller can only be used on a single "
"navigation, received second navigation to: "
<< url_;
installed_condition_ = std::make_unique<MockCommitDeferringConditionWrapper>(
handle, is_ready_to_commit_);
if (was_installed_closure_)
std::move(was_installed_closure_).Run();
return installed_condition_->PassToDelegate();
}
} // namespace content