Commit b974887c authored by Meredith Lane's avatar Meredith Lane Committed by Commit Bot

Revert "weblayer: allow calling Navigate() from onNavigationStarted"

This reverts commit c462e4b7.

Reason for revert: Causes a heap-use-after-free on win-asan. First failure: https://ci.chromium.org/p/chromium/builders/ci/win-asan/11631

Original change's description:
> weblayer: allow calling Navigate() from onNavigationStarted
> 
> At the time OnNavigationStarted() is called it's not safe to call
> Navigate(). This patch delays the navigate until it is safe (when
> NavigationThrottleImpl::WillStartRequest() is called).
> 
> BUG=1070569
> TEST=NavigationBrowserTest.NavigateFromRendererInitiatedNavigation
> 
> Change-Id: Ia110bb94e64d6551c9db302ae41b735ad5a8a5e5
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2153758
> Reviewed-by: John Abd-El-Malek <jam@chromium.org>
> Commit-Queue: Scott Violet <sky@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#759872}

TBR=sky@chromium.org,jam@chromium.org

Change-Id: I67a8b8d121ea1223650ee35a013068da20de6fb9
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 1070569
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2154348Reviewed-by: default avatarMeredith Lane <meredithl@chromium.org>
Commit-Queue: Meredith Lane <meredithl@chromium.org>
Cr-Commit-Position: refs/heads/master@{#759943}
parent 8ba3bf9a
...@@ -32,7 +32,7 @@ class NavigationObserverImpl : public NavigationObserver { ...@@ -32,7 +32,7 @@ class NavigationObserverImpl : public NavigationObserver {
} }
~NavigationObserverImpl() override { controller_->RemoveObserver(this); } ~NavigationObserverImpl() override { controller_->RemoveObserver(this); }
using Callback = base::RepeatingCallback<void(Navigation*)>; using Callback = base::OnceCallback<void(Navigation*)>;
void SetStartedCallback(Callback callback) { void SetStartedCallback(Callback callback) {
started_callback_ = std::move(callback); started_callback_ = std::move(callback);
...@@ -42,38 +42,29 @@ class NavigationObserverImpl : public NavigationObserver { ...@@ -42,38 +42,29 @@ class NavigationObserverImpl : public NavigationObserver {
redirected_callback_ = std::move(callback); redirected_callback_ = std::move(callback);
} }
void SetFailedClosure(base::RepeatingClosure closure) { void SetFailedClosure(base::OnceClosure closure) {
failed_closure_ = std::move(closure); failed_closure_ = std::move(closure);
} }
void SetCompletedClosure(Callback closure) {
completed_closure_ = std::move(closure);
}
// NavigationObserver: // NavigationObserver:
void NavigationStarted(Navigation* navigation) override { void NavigationStarted(Navigation* navigation) override {
if (started_callback_) if (started_callback_)
started_callback_.Run(navigation); std::move(started_callback_).Run(navigation);
} }
void NavigationRedirected(Navigation* navigation) override { void NavigationRedirected(Navigation* navigation) override {
if (redirected_callback_) if (redirected_callback_)
redirected_callback_.Run(navigation); std::move(redirected_callback_).Run(navigation);
}
void NavigationCompleted(Navigation* navigation) override {
if (completed_closure_)
completed_closure_.Run(navigation);
} }
void NavigationFailed(Navigation* navigation) override { void NavigationFailed(Navigation* navigation) override {
if (failed_closure_) if (failed_closure_)
failed_closure_.Run(); std::move(failed_closure_).Run();
} }
private: private:
NavigationController* controller_; NavigationController* controller_;
Callback started_callback_; Callback started_callback_;
Callback redirected_callback_; Callback redirected_callback_;
Callback completed_closure_; base::OnceClosure failed_closure_;
base::RepeatingClosure failed_closure_;
}; };
class OneShotNavigationObserver : public NavigationObserver { class OneShotNavigationObserver : public NavigationObserver {
...@@ -217,7 +208,7 @@ IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, StopInOnStart) { ...@@ -217,7 +208,7 @@ IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, StopInOnStart) {
observer.SetStartedCallback(base::BindLambdaForTesting( observer.SetStartedCallback(base::BindLambdaForTesting(
[&](Navigation*) { GetNavigationController()->Stop(); })); [&](Navigation*) { GetNavigationController()->Stop(); }));
observer.SetFailedClosure( observer.SetFailedClosure(
base::BindRepeating(&base::RunLoop::Quit, base::Unretained(&run_loop))); base::BindOnce(&base::RunLoop::Quit, base::Unretained(&run_loop)));
GetNavigationController()->Navigate( GetNavigationController()->Navigate(
embedded_test_server()->GetURL("/simple_page.html")); embedded_test_server()->GetURL("/simple_page.html"));
...@@ -231,7 +222,7 @@ IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, StopInOnRedirect) { ...@@ -231,7 +222,7 @@ IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, StopInOnRedirect) {
observer.SetRedirectedCallback(base::BindLambdaForTesting( observer.SetRedirectedCallback(base::BindLambdaForTesting(
[&](Navigation*) { GetNavigationController()->Stop(); })); [&](Navigation*) { GetNavigationController()->Stop(); }));
observer.SetFailedClosure( observer.SetFailedClosure(
base::BindRepeating(&base::RunLoop::Quit, base::Unretained(&run_loop))); base::BindOnce(&base::RunLoop::Quit, base::Unretained(&run_loop)));
const GURL original_url = embedded_test_server()->GetURL("/simple_page.html"); const GURL original_url = embedded_test_server()->GetURL("/simple_page.html");
GetNavigationController()->Navigate(embedded_test_server()->GetURL( GetNavigationController()->Navigate(embedded_test_server()->GetURL(
"/server-redirect?" + original_url.spec())); "/server-redirect?" + original_url.spec()));
...@@ -239,36 +230,6 @@ IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, StopInOnRedirect) { ...@@ -239,36 +230,6 @@ IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, StopInOnRedirect) {
run_loop.Run(); run_loop.Run();
} }
IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
NavigateFromRendererInitiatedNavigation) {
ASSERT_TRUE(embedded_test_server()->Start());
NavigationController* controller = shell()->tab()->GetNavigationController();
const GURL final_url = embedded_test_server()->GetURL("/simple_page2.html");
int failed_count = 0;
int completed_count = 0;
NavigationObserverImpl observer(controller);
base::RunLoop run_loop;
observer.SetFailedClosure(
base::BindLambdaForTesting([&]() { failed_count++; }));
observer.SetCompletedClosure(
base::BindLambdaForTesting([&](Navigation* navigation) {
completed_count++;
if (navigation->GetURL().path() == "/simple_page2.html")
run_loop.Quit();
}));
observer.SetStartedCallback(
base::BindLambdaForTesting([&](Navigation* navigation) {
if (navigation->GetURL().path() == "/simple_page.html")
controller->Navigate(final_url);
}));
controller->Navigate(embedded_test_server()->GetURL("/simple_page4.html"));
run_loop.Run();
EXPECT_EQ(1, failed_count);
EXPECT_EQ(2, completed_count);
ASSERT_EQ(2, controller->GetNavigationListSize());
EXPECT_EQ(final_url, controller->GetNavigationEntryDisplayURL(1));
}
IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, SetRequestHeader) { IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, SetRequestHeader) {
net::test_server::ControllableHttpResponse response_1(embedded_test_server(), net::test_server::ControllableHttpResponse response_1(embedded_test_server(),
"", true); "", true);
......
...@@ -29,19 +29,25 @@ using base::android::ScopedJavaLocalRef; ...@@ -29,19 +29,25 @@ using base::android::ScopedJavaLocalRef;
namespace weblayer { namespace weblayer {
// NavigationThrottle implementation responsible for delaying certain // NavigationThrottle implementation responsible for stopping the navigation in
// operations and performing them when safe. This is necessary as content // certain situations. In particular, WebContents::Stop() can not be called from
// does allow certain operations to be called at certain times. For example, // WebContentsObserver::DidStartNavigation() or
// content does not allow calling WebContents::Stop() from // WebContentsObserver::DidRedirectNavigation() (to do so crashes). To work
// WebContentsObserver::DidStartNavigation() (to do so crashes). To work around // around this NavigationControllerImpl detects if Stop() is called while
// this NavigationControllerImpl detects these scenarios and delays processing // processing DidStartNavigation() or DidRedirectNavigation() and sets state in
// until safe. // NavigationThrottleImpl such that the navigation is canceled.
// //
// Most of the support for these scenarios is handled by a custom // The call order for starting is WebContents::DidStartNavigation() followed
// NavigationThrottle. To make things interesting, the NavigationThrottle is // by NavigationThrottle::WillStartRequest(). To make things interesting,
// created after some of the scenarios this code wants to handle. As such, // the NavigationThrottle is created *after* DidStartNavigation(). OTOH,
// NavigationImpl does some amount of caching until the NavigationThrottle is // the call order for redirect is NavigationThrottle::WillRedirectRequest()
// created. // followed by WebContentsObserver::DidRedirectNavigation(). To ensure the
// right call order NavigationControllerImpl does nothing in
// DidRedirectNavigation(), instead this class calls to the
// NavigationController and then returns cancel if necessary. While redirect
// handling is initiated from this class, start must be handled from the
// WebContentsObserver call. This is necessary as some code paths do *not*
// call to NavigationThrottle::WillStartRequest().
class NavigationControllerImpl::NavigationThrottleImpl class NavigationControllerImpl::NavigationThrottleImpl
: public content::NavigationThrottle { : public content::NavigationThrottle {
public: public:
...@@ -53,15 +59,9 @@ class NavigationControllerImpl::NavigationThrottleImpl ...@@ -53,15 +59,9 @@ class NavigationControllerImpl::NavigationThrottleImpl
~NavigationThrottleImpl() override = default; ~NavigationThrottleImpl() override = default;
void ScheduleCancel() { should_cancel_ = true; } void ScheduleCancel() { should_cancel_ = true; }
void ScheduleNavigate(
std::unique_ptr<content::NavigationController::LoadURLParams> params) {
load_params_ = std::move(params);
}
// content::NavigationThrottle: // content::NavigationThrottle:
ThrottleCheckResult WillStartRequest() override { ThrottleCheckResult WillStartRequest() override {
if (load_params_)
controller_->DoNavigate(std::move(load_params_));
return should_cancel_ ? CANCEL : PROCEED; return should_cancel_ ? CANCEL : PROCEED;
} }
...@@ -77,7 +77,6 @@ class NavigationControllerImpl::NavigationThrottleImpl ...@@ -77,7 +77,6 @@ class NavigationControllerImpl::NavigationThrottleImpl
private: private:
NavigationControllerImpl* controller_; NavigationControllerImpl* controller_;
bool should_cancel_ = false; bool should_cancel_ = false;
std::unique_ptr<content::NavigationController::LoadURLParams> load_params_;
}; };
NavigationControllerImpl::NavigationControllerImpl(TabImpl* tab) NavigationControllerImpl::NavigationControllerImpl(TabImpl* tab)
...@@ -96,9 +95,6 @@ NavigationControllerImpl::CreateNavigationThrottle( ...@@ -96,9 +95,6 @@ NavigationControllerImpl::CreateNavigationThrottle(
auto* navigation = navigation_map_[handle].get(); auto* navigation = navigation_map_[handle].get();
if (navigation->should_stop_when_throttle_created()) if (navigation->should_stop_when_throttle_created())
throttle->ScheduleCancel(); throttle->ScheduleCancel();
auto load_params = navigation->TakeParamsToLoadWhenSafe();
if (load_params)
throttle->ScheduleNavigate(std::move(load_params));
return throttle; return throttle;
} }
...@@ -126,9 +122,9 @@ void NavigationControllerImpl::NavigateWithParams( ...@@ -126,9 +122,9 @@ void NavigationControllerImpl::NavigateWithParams(
const JavaParamRef<jobject>& obj, const JavaParamRef<jobject>& obj,
const JavaParamRef<jstring>& url, const JavaParamRef<jstring>& url,
jboolean should_replace_current_entry) { jboolean should_replace_current_entry) {
auto params = std::make_unique<content::NavigationController::LoadURLParams>( content::NavigationController::LoadURLParams params(
GURL(base::android::ConvertJavaStringToUTF8(env, url))); GURL(base::android::ConvertJavaStringToUTF8(env, url)));
params->should_replace_current_entry = should_replace_current_entry; params.should_replace_current_entry = should_replace_current_entry;
DoNavigate(std::move(params)); DoNavigate(std::move(params));
} }
...@@ -182,16 +178,14 @@ void NavigationControllerImpl::RemoveObserver(NavigationObserver* observer) { ...@@ -182,16 +178,14 @@ void NavigationControllerImpl::RemoveObserver(NavigationObserver* observer) {
} }
void NavigationControllerImpl::Navigate(const GURL& url) { void NavigationControllerImpl::Navigate(const GURL& url) {
DoNavigate( DoNavigate(content::NavigationController::LoadURLParams(url));
std::make_unique<content::NavigationController::LoadURLParams>(url));
} }
void NavigationControllerImpl::Navigate( void NavigationControllerImpl::Navigate(
const GURL& url, const GURL& url,
const NavigationController::NavigateParams& params) { const NavigationController::NavigateParams& params) {
auto load_params = content::NavigationController::LoadURLParams load_params(url);
std::make_unique<content::NavigationController::LoadURLParams>(url); load_params.should_replace_current_entry =
load_params->should_replace_current_entry =
params.should_replace_current_entry; params.should_replace_current_entry;
DoNavigate(std::move(load_params)); DoNavigate(std::move(load_params));
} }
...@@ -397,18 +391,10 @@ void NavigationControllerImpl::NotifyLoadStateChanged() { ...@@ -397,18 +391,10 @@ void NavigationControllerImpl::NotifyLoadStateChanged() {
} }
void NavigationControllerImpl::DoNavigate( void NavigationControllerImpl::DoNavigate(
std::unique_ptr<content::NavigationController::LoadURLParams> params) { content::NavigationController::LoadURLParams&& params) {
if (navigation_starting_) { params.transition_type = ui::PageTransitionFromInt(
// DoNavigate() is being called reentrantly. Delay processing until it's
// safe.
Stop();
navigation_starting_->SetParamsToLoadWhenSafe(std::move(params));
return;
}
params->transition_type = ui::PageTransitionFromInt(
ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR); ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
web_contents()->GetController().LoadURLWithParams(*params); web_contents()->GetController().LoadURLWithParams(params);
// So that if the user had entered the UI in a bar it stops flashing the // So that if the user had entered the UI in a bar it stops flashing the
// caret. // caret.
web_contents()->Focus(); web_contents()->Focus();
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include <map> #include <map>
#include <memory>
#include "base/macros.h" #include "base/macros.h"
#include "base/observer_list.h" #include "base/observer_list.h"
#include "build/build_config.h" #include "build/build_config.h"
...@@ -131,8 +130,7 @@ class NavigationControllerImpl : public NavigationController, ...@@ -131,8 +130,7 @@ class NavigationControllerImpl : public NavigationController,
void NotifyLoadStateChanged(); void NotifyLoadStateChanged();
void DoNavigate( void DoNavigate(content::NavigationController::LoadURLParams&& params);
std::unique_ptr<content::NavigationController::LoadURLParams> params);
base::ObserverList<NavigationObserver>::Unchecked observers_; base::ObserverList<NavigationObserver>::Unchecked observers_;
std::map<content::NavigationHandle*, std::unique_ptr<NavigationImpl>> std::map<content::NavigationHandle*, std::unique_ptr<NavigationImpl>>
......
...@@ -33,16 +33,6 @@ NavigationImpl::~NavigationImpl() { ...@@ -33,16 +33,6 @@ NavigationImpl::~NavigationImpl() {
#endif #endif
} }
void NavigationImpl::SetParamsToLoadWhenSafe(
std::unique_ptr<content::NavigationController::LoadURLParams> params) {
scheduled_load_params_ = std::move(params);
}
std::unique_ptr<content::NavigationController::LoadURLParams>
NavigationImpl::TakeParamsToLoadWhenSafe() {
return std::move(scheduled_load_params_);
}
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
void NavigationImpl::SetJavaNavigation( void NavigationImpl::SetJavaNavigation(
JNIEnv* env, JNIEnv* env,
......
...@@ -5,11 +5,8 @@ ...@@ -5,11 +5,8 @@
#ifndef WEBLAYER_BROWSER_NAVIGATION_IMPL_H_ #ifndef WEBLAYER_BROWSER_NAVIGATION_IMPL_H_
#define WEBLAYER_BROWSER_NAVIGATION_IMPL_H_ #define WEBLAYER_BROWSER_NAVIGATION_IMPL_H_
#include <memory>
#include "base/macros.h" #include "base/macros.h"
#include "base/optional.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "content/public/browser/navigation_controller.h"
#include "weblayer/public/navigation.h" #include "weblayer/public/navigation.h"
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
...@@ -38,11 +35,6 @@ class NavigationImpl : public Navigation { ...@@ -38,11 +35,6 @@ class NavigationImpl : public Navigation {
safe_to_set_request_headers_ = value; safe_to_set_request_headers_ = value;
} }
void SetParamsToLoadWhenSafe(
std::unique_ptr<content::NavigationController::LoadURLParams> params);
std::unique_ptr<content::NavigationController::LoadURLParams>
TakeParamsToLoadWhenSafe();
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
void SetJavaNavigation( void SetJavaNavigation(
JNIEnv* env, JNIEnv* env,
...@@ -107,13 +99,6 @@ class NavigationImpl : public Navigation { ...@@ -107,13 +99,6 @@ class NavigationImpl : public Navigation {
base::android::ScopedJavaGlobalRef<jobject> java_navigation_; base::android::ScopedJavaGlobalRef<jobject> java_navigation_;
#endif #endif
// Used to delay loading until safe. In particular, if Navigate() is called
// from NavigationStarted(), then the parameters are captured and the
// navigation started later on. The delaying is necessary as content is not
// reentrant, and this triggers some amount of reentrancy.
std::unique_ptr<content::NavigationController::LoadURLParams>
scheduled_load_params_;
DISALLOW_COPY_AND_ASSIGN(NavigationImpl); DISALLOW_COPY_AND_ASSIGN(NavigationImpl);
}; };
......
<html>
<head><title>OK</title></head>
<body>
<meta http-equiv = "refresh" content = "2; url = /simple_page.html" />
</body>
</html>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment