12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262 |
- // Copyright 2019 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 <memory>
- #include "weblayer/test/weblayer_browser_test.h"
- #include "base/callback.h"
- #include "base/callback_helpers.h"
- #include "base/command_line.h"
- #include "base/files/file_path.h"
- #include "base/memory/raw_ptr.h"
- #include "base/strings/stringprintf.h"
- #include "base/strings/utf_string_conversions.h"
- #include "base/test/bind.h"
- #include "base/test/metrics/histogram_tester.h"
- #include "base/test/scoped_feature_list.h"
- #include "build/build_config.h"
- #include "components/variations/net/variations_http_headers.h"
- #include "components/variations/variations_ids_provider.h"
- #include "content/public/browser/web_contents_observer.h"
- #include "content/public/test/browser_test_utils.h"
- #include "content/public/test/url_loader_interceptor.h"
- #include "net/dns/mock_host_resolver.h"
- #include "net/test/embedded_test_server/controllable_http_response.h"
- #include "net/test/embedded_test_server/embedded_test_server.h"
- #include "net/test/embedded_test_server/http_response.h"
- #include "third_party/blink/public/common/features.h"
- #include "third_party/blink/public/common/web_preferences/web_preferences.h"
- #include "weblayer/browser/tab_impl.h"
- #include "weblayer/public/browser.h"
- #include "weblayer/public/browser_observer.h"
- #include "weblayer/public/navigation.h"
- #include "weblayer/public/navigation_controller.h"
- #include "weblayer/public/navigation_observer.h"
- #include "weblayer/public/new_tab_delegate.h"
- #include "weblayer/shell/browser/shell.h"
- #include "weblayer/test/interstitial_utils.h"
- #include "weblayer/test/test_navigation_observer.h"
- #include "weblayer/test/weblayer_browser_test_utils.h"
- namespace weblayer {
- namespace {
- // NavigationObserver that allows registering a callback for various
- // NavigationObserver functions.
- class NavigationObserverImpl : public NavigationObserver {
- public:
- explicit NavigationObserverImpl(NavigationController* controller)
- : controller_(controller) {
- controller_->AddObserver(this);
- }
- ~NavigationObserverImpl() override { controller_->RemoveObserver(this); }
- using Callback = base::RepeatingCallback<void(Navigation*)>;
- using PageLanguageDeterminedCallback =
- base::RepeatingCallback<void(Page*, std::string)>;
- void SetStartedCallback(Callback callback) {
- started_callback_ = std::move(callback);
- }
- void SetRedirectedCallback(Callback callback) {
- redirected_callback_ = std::move(callback);
- }
- void SetFailedCallback(Callback callback) {
- failed_callback_ = std::move(callback);
- }
- void SetCompletedClosure(Callback callback) {
- completed_callback_ = std::move(callback);
- }
- void SetOnPageLanguageDeterminedCallback(
- PageLanguageDeterminedCallback callback) {
- on_page_language_determined_callback_ = std::move(callback);
- }
- // NavigationObserver:
- void NavigationStarted(Navigation* navigation) override {
- if (started_callback_)
- started_callback_.Run(navigation);
- }
- void NavigationRedirected(Navigation* navigation) override {
- if (redirected_callback_)
- redirected_callback_.Run(navigation);
- }
- void NavigationCompleted(Navigation* navigation) override {
- if (completed_callback_)
- completed_callback_.Run(navigation);
- }
- void NavigationFailed(Navigation* navigation) override {
- // As |this| may be deleted when running the callback, the callback must be
- // copied before running. To do otherwise results in use-after-free.
- auto callback = failed_callback_;
- if (callback)
- callback.Run(navigation);
- }
- void OnPageLanguageDetermined(Page* page,
- const std::string& language) override {
- if (on_page_language_determined_callback_)
- on_page_language_determined_callback_.Run(page, language);
- }
- private:
- raw_ptr<NavigationController> controller_;
- Callback started_callback_;
- Callback redirected_callback_;
- Callback completed_callback_;
- Callback failed_callback_;
- PageLanguageDeterminedCallback on_page_language_determined_callback_;
- };
- } // namespace
- class NavigationBrowserTest : public WebLayerBrowserTest {
- public:
- NavigationController* GetNavigationController() {
- return shell()->tab()->GetNavigationController();
- }
- void SetUpOnMainThread() override {
- host_resolver()->AddRule("*", "127.0.0.1");
- content::SetupCrossSiteRedirector(embedded_test_server());
- }
- };
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, NoError) {
- EXPECT_TRUE(embedded_test_server()->Start());
- OneShotNavigationObserver observer(shell());
- GetNavigationController()->Navigate(
- embedded_test_server()->GetURL("/simple_page.html"));
- observer.WaitForNavigation();
- EXPECT_TRUE(observer.completed());
- EXPECT_FALSE(observer.is_error_page());
- EXPECT_FALSE(observer.is_download());
- EXPECT_FALSE(observer.is_reload());
- EXPECT_FALSE(observer.was_stop_called());
- EXPECT_EQ(observer.load_error(), Navigation::kNoError);
- EXPECT_EQ(observer.http_status_code(), 200);
- EXPECT_EQ(observer.navigation_state(), NavigationState::kComplete);
- }
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
- IsPageInitiatedTrueForWindowHistoryBack) {
- EXPECT_TRUE(embedded_test_server()->Start());
- std::unique_ptr<OneShotNavigationObserver> observer =
- std::make_unique<OneShotNavigationObserver>(shell());
- GetNavigationController()->Navigate(
- embedded_test_server()->GetURL("a.com", "/simple_page.html"));
- observer->WaitForNavigation();
- ASSERT_TRUE(observer->completed());
- EXPECT_FALSE(observer->is_page_initiated());
- observer = std::make_unique<OneShotNavigationObserver>(shell());
- GetNavigationController()->Navigate(
- embedded_test_server()->GetURL("b.com", "/simple_page.html"));
- observer->WaitForNavigation();
- ASSERT_TRUE(observer->completed());
- EXPECT_FALSE(observer->is_page_initiated());
- observer = std::make_unique<OneShotNavigationObserver>(shell());
- shell()->tab()->ExecuteScript(
- u"window.history.back();", false,
- base::BindLambdaForTesting(
- [&](base::Value value) { LOG(ERROR) << "executescript result"; }));
- observer->WaitForNavigation();
- ASSERT_TRUE(observer->completed());
- EXPECT_TRUE(observer->is_page_initiated());
- }
- // Http client error when the server returns a non-empty response.
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, HttpClientError) {
- EXPECT_TRUE(embedded_test_server()->Start());
- OneShotNavigationObserver observer(shell());
- GetNavigationController()->Navigate(
- embedded_test_server()->GetURL("/non_empty404.html"));
- observer.WaitForNavigation();
- EXPECT_TRUE(observer.completed());
- EXPECT_FALSE(observer.is_error_page());
- EXPECT_EQ(observer.load_error(), Navigation::kHttpClientError);
- EXPECT_EQ(observer.http_status_code(), 404);
- EXPECT_EQ(observer.navigation_state(), NavigationState::kComplete);
- }
- // Http client error when the server returns an empty response.
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, HttpClientErrorEmptyResponse) {
- EXPECT_TRUE(embedded_test_server()->Start());
- OneShotNavigationObserver observer(shell());
- GetNavigationController()->Navigate(
- embedded_test_server()->GetURL("/empty404.html"));
- observer.WaitForNavigation();
- EXPECT_FALSE(observer.completed());
- EXPECT_TRUE(observer.is_error_page());
- EXPECT_EQ(observer.load_error(), Navigation::kHttpClientError);
- EXPECT_EQ(observer.http_status_code(), 404);
- EXPECT_EQ(observer.navigation_state(), NavigationState::kFailed);
- }
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, HttpServerError) {
- EXPECT_TRUE(embedded_test_server()->Start());
- OneShotNavigationObserver observer(shell());
- GetNavigationController()->Navigate(
- embedded_test_server()->GetURL("/echo?status=500"));
- observer.WaitForNavigation();
- EXPECT_TRUE(observer.completed());
- EXPECT_FALSE(observer.is_error_page());
- EXPECT_EQ(observer.load_error(), Navigation::kHttpServerError);
- EXPECT_EQ(observer.http_status_code(), 500);
- EXPECT_EQ(observer.navigation_state(), NavigationState::kComplete);
- }
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, SSLError) {
- net::EmbeddedTestServer https_server_mismatched(
- net::EmbeddedTestServer::TYPE_HTTPS);
- https_server_mismatched.SetSSLConfig(
- net::EmbeddedTestServer::CERT_MISMATCHED_NAME);
- https_server_mismatched.AddDefaultHandlers(
- base::FilePath(FILE_PATH_LITERAL("weblayer/test/data")));
- ASSERT_TRUE(https_server_mismatched.Start());
- OneShotNavigationObserver observer(shell());
- GetNavigationController()->Navigate(
- https_server_mismatched.GetURL("/simple_page.html"));
- observer.WaitForNavigation();
- EXPECT_FALSE(observer.completed());
- EXPECT_TRUE(observer.is_error_page());
- EXPECT_EQ(observer.load_error(), Navigation::kSSLError);
- EXPECT_EQ(observer.navigation_state(), NavigationState::kFailed);
- }
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, HttpConnectivityError) {
- GURL url("http://doesntexist.com/foo");
- auto interceptor = content::URLLoaderInterceptor::SetupRequestFailForURL(
- url, net::ERR_NAME_NOT_RESOLVED);
- OneShotNavigationObserver observer(shell());
- GetNavigationController()->Navigate(url);
- observer.WaitForNavigation();
- EXPECT_FALSE(observer.completed());
- EXPECT_TRUE(observer.is_error_page());
- EXPECT_EQ(observer.load_error(), Navigation::kConnectivityError);
- EXPECT_EQ(observer.navigation_state(), NavigationState::kFailed);
- }
- #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
- // https://crbug.com/1296643
- #define MAYBE_Download DISABLED_Download
- #else
- #define MAYBE_Download Download
- #endif
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, MAYBE_Download) {
- EXPECT_TRUE(embedded_test_server()->Start());
- GURL url(embedded_test_server()->GetURL("/content-disposition.html"));
- OneShotNavigationObserver observer(shell());
- GetNavigationController()->Navigate(url);
- observer.WaitForNavigation();
- EXPECT_FALSE(observer.completed());
- EXPECT_FALSE(observer.is_error_page());
- EXPECT_TRUE(observer.is_download());
- EXPECT_FALSE(observer.was_stop_called());
- EXPECT_EQ(observer.load_error(), Navigation::kOtherError);
- EXPECT_EQ(observer.navigation_state(), NavigationState::kFailed);
- }
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, StopInOnStart) {
- ASSERT_TRUE(embedded_test_server()->Start());
- base::RunLoop run_loop;
- NavigationObserverImpl observer(GetNavigationController());
- observer.SetStartedCallback(base::BindLambdaForTesting(
- [&](Navigation*) { GetNavigationController()->Stop(); }));
- observer.SetFailedCallback(
- base::BindLambdaForTesting([&](Navigation* navigation) {
- ASSERT_TRUE(navigation->WasStopCalled());
- run_loop.Quit();
- }));
- GetNavigationController()->Navigate(
- embedded_test_server()->GetURL("/simple_page.html"));
- run_loop.Run();
- }
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, DestroyTabInNavigation) {
- ASSERT_TRUE(embedded_test_server()->Start());
- Tab* new_tab = shell()->browser()->CreateTab();
- base::RunLoop run_loop;
- std::unique_ptr<NavigationObserverImpl> observer =
- std::make_unique<NavigationObserverImpl>(
- new_tab->GetNavigationController());
- observer->SetFailedCallback(
- base::BindLambdaForTesting([&](Navigation* navigation) {
- observer.reset();
- shell()->browser()->DestroyTab(new_tab);
- // Destroying the tab posts a task to delete the WebContents, which must
- // be run before the test shuts down lest it access deleted state.
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- run_loop.QuitClosure());
- }));
- new_tab->GetNavigationController()->Navigate(
- embedded_test_server()->GetURL("/simple_pageX.html"));
- run_loop.Run();
- }
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, StopInOnRedirect) {
- ASSERT_TRUE(embedded_test_server()->Start());
- base::RunLoop run_loop;
- NavigationObserverImpl observer(GetNavigationController());
- observer.SetRedirectedCallback(base::BindLambdaForTesting(
- [&](Navigation*) { GetNavigationController()->Stop(); }));
- observer.SetFailedCallback(
- base::BindLambdaForTesting([&](Navigation* navigation) {
- ASSERT_TRUE(navigation->WasStopCalled());
- run_loop.Quit();
- }));
- const GURL original_url = embedded_test_server()->GetURL("/simple_page.html");
- GetNavigationController()->Navigate(embedded_test_server()->GetURL(
- "/server-redirect?" + original_url.spec()));
- 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.SetFailedCallback(
- base::BindLambdaForTesting([&](Navigation*) { 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));
- }
- class BrowserObserverImpl : public BrowserObserver {
- public:
- explicit BrowserObserverImpl(Browser* browser) : browser_(browser) {
- browser->AddObserver(this);
- }
- ~BrowserObserverImpl() override { browser_->RemoveObserver(this); }
- void SetNewTabCallback(base::RepeatingCallback<void(Tab*)> callback) {
- new_tab_callback_ = callback;
- }
- // BrowserObserver:
- void OnTabAdded(Tab* tab) override { new_tab_callback_.Run(tab); }
- private:
- base::RepeatingCallback<void(Tab*)> new_tab_callback_;
- raw_ptr<Browser> browser_;
- };
- class NewTabDelegateImpl : public NewTabDelegate {
- public:
- // NewTabDelegate:
- void OnNewTab(Tab* new_tab, NewTabType type) override {}
- };
- // Ensures calling Navigate() from within NavigationStarted() for a popup does
- // not crash.
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, NavigateFromNewWindow) {
- ASSERT_TRUE(embedded_test_server()->Start());
- NavigateAndWaitForCompletion(
- embedded_test_server()->GetURL("/simple_page2.html"), shell());
- NewTabDelegate* old_new_tab_delegate =
- static_cast<TabImpl*>(shell()->tab())->new_tab_delegate();
- NewTabDelegateImpl new_tab_delegate;
- shell()->tab()->SetNewTabDelegate(&new_tab_delegate);
- BrowserObserverImpl browser_observer(shell()->tab()->GetBrowser());
- std::unique_ptr<NavigationObserverImpl> popup_navigation_observer;
- base::RunLoop run_loop;
- Tab* popup_tab = nullptr;
- auto popup_started_navigation = [&](Navigation* navigation) {
- if (navigation->GetURL().path() == "/simple_page.html") {
- popup_tab->GetNavigationController()->Navigate(
- embedded_test_server()->GetURL("/simple_page3.html"));
- } else if (navigation->GetURL().path() == "/simple_page3.html") {
- run_loop.Quit();
- }
- };
- browser_observer.SetNewTabCallback(base::BindLambdaForTesting([&](Tab* tab) {
- popup_tab = tab;
- popup_navigation_observer = std::make_unique<NavigationObserverImpl>(
- tab->GetNavigationController());
- popup_navigation_observer->SetStartedCallback(
- base::BindLambdaForTesting(popup_started_navigation));
- }));
- // 'noopener' is key to triggering the problematic case.
- const std::string window_open = base::StringPrintf(
- "window.open('%s', '', 'noopener')",
- embedded_test_server()->GetURL("/simple_page.html").spec().c_str());
- ExecuteScriptWithUserGesture(shell()->tab(), window_open);
- run_loop.Run();
- // Restore the old delegate to make sure it is cleaned up on Android.
- shell()->tab()->SetNewTabDelegate(old_new_tab_delegate);
- }
- // Verifies calling Navigate() from NavigationRedirected() works.
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, NavigateFromRedirect) {
- net::test_server::ControllableHttpResponse response_1(embedded_test_server(),
- "", true);
- net::test_server::ControllableHttpResponse response_2(embedded_test_server(),
- "", true);
- ASSERT_TRUE(embedded_test_server()->Start());
- NavigationObserverImpl observer(GetNavigationController());
- bool got_redirect = false;
- const GURL url_to_load_on_redirect =
- embedded_test_server()->GetURL("/url_to_load_on_redirect.html");
- observer.SetRedirectedCallback(
- base::BindLambdaForTesting([&](Navigation* navigation) {
- shell()->LoadURL(url_to_load_on_redirect);
- got_redirect = true;
- }));
- shell()->LoadURL(embedded_test_server()->GetURL("/initial_url.html"));
- response_1.WaitForRequest();
- response_1.Send(
- "HTTP/1.1 302 Moved Temporarily\r\nLocation: /redirect_dest_url\r\n\r\n");
- response_1.Done();
- response_2.WaitForRequest();
- response_2.Done();
- EXPECT_EQ(url_to_load_on_redirect, response_2.http_request()->GetURL());
- EXPECT_TRUE(got_redirect);
- }
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, SetRequestHeader) {
- net::test_server::ControllableHttpResponse response_1(embedded_test_server(),
- "", true);
- net::test_server::ControllableHttpResponse response_2(embedded_test_server(),
- "", true);
- ASSERT_TRUE(embedded_test_server()->Start());
- const std::string header_name = "header";
- const std::string header_value = "value";
- NavigationObserverImpl observer(GetNavigationController());
- observer.SetStartedCallback(
- base::BindLambdaForTesting([&](Navigation* navigation) {
- navigation->SetRequestHeader(header_name, header_value);
- }));
- shell()->LoadURL(embedded_test_server()->GetURL("/simple_page.html"));
- response_1.WaitForRequest();
- // Header should be present in initial request.
- EXPECT_EQ(header_value, response_1.http_request()->headers.at(header_name));
- response_1.Send(
- "HTTP/1.1 302 Moved Temporarily\r\nLocation: /new_doc\r\n\r\n");
- response_1.Done();
- // Header should carry through to redirect.
- response_2.WaitForRequest();
- EXPECT_EQ(header_value, response_2.http_request()->headers.at(header_name));
- }
- // Verifies setting the 'referer' via SetRequestHeader() works as expected.
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, SetRequestHeaderWithReferer) {
- net::test_server::ControllableHttpResponse response(embedded_test_server(),
- "", true);
- ASSERT_TRUE(embedded_test_server()->Start());
- const std::string header_name = "Referer";
- const std::string header_value = "http://request.com";
- NavigationObserverImpl observer(GetNavigationController());
- observer.SetStartedCallback(
- base::BindLambdaForTesting([&](Navigation* navigation) {
- navigation->SetRequestHeader(header_name, header_value);
- }));
- shell()->LoadURL(embedded_test_server()->GetURL("/simple_page.html"));
- response.WaitForRequest();
- // Verify 'referer' matches expected value.
- EXPECT_EQ(GURL(header_value),
- GURL(response.http_request()->headers.at(header_name)));
- }
- // Like above but checks that referer isn't sent when it's https and the target
- // url is http.
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
- SetRequestHeaderWithRefererDowngrade) {
- net::test_server::ControllableHttpResponse response(embedded_test_server(),
- "", true);
- ASSERT_TRUE(embedded_test_server()->Start());
- const std::string header_name = "Referer";
- const std::string header_value = "https://request.com";
- NavigationObserverImpl observer(GetNavigationController());
- observer.SetStartedCallback(
- base::BindLambdaForTesting([&](Navigation* navigation) {
- navigation->SetRequestHeader(header_name, header_value);
- }));
- shell()->LoadURL(embedded_test_server()->GetURL("/simple_page.html"));
- response.WaitForRequest();
- EXPECT_EQ(0u, response.http_request()->headers.count(header_name));
- }
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, SetRequestHeaderInRedirect) {
- net::test_server::ControllableHttpResponse response_1(embedded_test_server(),
- "", true);
- net::test_server::ControllableHttpResponse response_2(embedded_test_server(),
- "", true);
- ASSERT_TRUE(embedded_test_server()->Start());
- const std::string header_name = "header";
- const std::string header_value = "value";
- NavigationObserverImpl observer(GetNavigationController());
- observer.SetRedirectedCallback(
- base::BindLambdaForTesting([&](Navigation* navigation) {
- navigation->SetRequestHeader(header_name, header_value);
- }));
- shell()->LoadURL(embedded_test_server()->GetURL("/simple_page.html"));
- response_1.WaitForRequest();
- // Header should not be present in initial request.
- EXPECT_FALSE(base::Contains(response_1.http_request()->headers, header_name));
- response_1.Send(
- "HTTP/1.1 302 Moved Temporarily\r\nLocation: /new_doc\r\n\r\n");
- response_1.Done();
- response_2.WaitForRequest();
- // Header should be in redirect.
- ASSERT_TRUE(base::Contains(response_2.http_request()->headers, header_name));
- EXPECT_EQ(header_value, response_2.http_request()->headers.at(header_name));
- }
- class NavigationBrowserTestUserAgentOverrideSubstring
- : public NavigationBrowserTest {
- public:
- void SetUp() override {
- scoped_feature_list_.InitWithFeatures(
- {blink::features::kUserAgentOverrideExperiment,
- blink::features::kUACHOverrideBlank},
- {});
- NavigationBrowserTest::SetUp();
- }
- private:
- base::test::ScopedFeatureList scoped_feature_list_;
- };
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTestUserAgentOverrideSubstring,
- PageSeesUserAgentString) {
- net::test_server::EmbeddedTestServer https_server(
- net::test_server::EmbeddedTestServer::TYPE_HTTPS);
- https_server.AddDefaultHandlers(
- base::FilePath(FILE_PATH_LITERAL("weblayer/test/data")));
- ASSERT_TRUE(https_server.Start());
- const std::string custom_ua = "custom";
- NavigationObserverImpl observer(GetNavigationController());
- observer.SetStartedCallback(
- base::BindLambdaForTesting([&](Navigation* navigation) {
- navigation->SetUserAgentString(custom_ua);
- }));
- base::HistogramTester histogram;
- OneShotNavigationObserver navigation_observer(shell());
- shell()->LoadURL(https_server.GetURL("/simple_page.html"));
- navigation_observer.WaitForNavigation();
- histogram.ExpectBucketCount(
- blink::UserAgentOverride::kUserAgentOverrideHistogram,
- blink::UserAgentOverride::UserAgentOverriden, 1);
- base::RunLoop run_loop;
- shell()->tab()->ExecuteScript(
- u"navigator.userAgent;", false,
- base::BindLambdaForTesting([&](base::Value value) {
- ASSERT_TRUE(value.is_string());
- EXPECT_EQ(custom_ua, value.GetString());
- run_loop.Quit();
- }));
- run_loop.Run();
- // Ensure that userAgentData is blank when custom user agent is set.
- base::RunLoop run_loop2;
- shell()->tab()->ExecuteScript(
- u"navigator.userAgentData.platform;", false,
- base::BindLambdaForTesting([&](base::Value value) {
- ASSERT_TRUE(value.is_string());
- EXPECT_EQ("", value.GetString());
- run_loop2.Quit();
- }));
- run_loop2.Run();
- }
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, Reload) {
- ASSERT_TRUE(embedded_test_server()->Start());
- OneShotNavigationObserver observer(shell());
- GetNavigationController()->Navigate(
- embedded_test_server()->GetURL("/simple_page.html"));
- observer.WaitForNavigation();
- OneShotNavigationObserver observer2(shell());
- shell()->tab()->ExecuteScript(u"location.reload();", false,
- base::DoNothing());
- observer2.WaitForNavigation();
- EXPECT_TRUE(observer2.completed());
- EXPECT_TRUE(observer2.is_reload());
- }
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTestUserAgentOverrideSubstring,
- SetUserAgentString) {
- std::unique_ptr<net::test_server::EmbeddedTestServer> https_server =
- std::make_unique<net::test_server::EmbeddedTestServer>(
- net::test_server::EmbeddedTestServer::TYPE_HTTPS);
- https_server->AddDefaultHandlers(
- base::FilePath(FILE_PATH_LITERAL("weblayer/test/data")));
- net::test_server::ControllableHttpResponse response_1(https_server.get(), "",
- true);
- net::test_server::ControllableHttpResponse response_2(https_server.get(), "",
- true);
- ASSERT_TRUE(https_server->Start());
- const std::string custom_ua = "CUSTOM";
- NavigationObserverImpl observer(GetNavigationController());
- observer.SetStartedCallback(
- base::BindLambdaForTesting([&](Navigation* navigation) {
- navigation->SetUserAgentString(custom_ua);
- }));
- base::HistogramTester histogram;
- shell()->LoadURL(https_server->GetURL("/simple_page.html"));
- response_1.WaitForRequest();
- // |custom_ua| should be present in initial request.
- ASSERT_TRUE(base::Contains(response_1.http_request()->headers,
- net::HttpRequestHeaders::kUserAgent));
- const std::string new_header = response_1.http_request()->headers.at(
- net::HttpRequestHeaders::kUserAgent);
- EXPECT_EQ(custom_ua, new_header);
- ASSERT_TRUE(base::Contains(response_1.http_request()->headers, "sec-ch-ua"));
- const std::string new_ch_header =
- response_1.http_request()->headers.at("Sec-CH-UA");
- EXPECT_EQ("", new_ch_header);
- content::FetchHistogramsFromChildProcesses();
- histogram.ExpectBucketCount(
- blink::UserAgentOverride::kUserAgentOverrideHistogram,
- blink::UserAgentOverride::UserAgentOverriden, 1);
- // Header should carry through to redirect.
- response_1.Send(
- "HTTP/1.1 302 Moved Temporarily\r\nLocation: /new_doc\r\n\r\n");
- response_1.Done();
- response_2.WaitForRequest();
- EXPECT_EQ(custom_ua, response_2.http_request()->headers.at(
- net::HttpRequestHeaders::kUserAgent));
- EXPECT_EQ("", response_2.http_request()->headers.at("Sec-CH-UA"));
- }
- #if BUILDFLAG(IS_ANDROID)
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
- SetUserAgentStringDoesntChangeViewportMetaTag) {
- ASSERT_TRUE(embedded_test_server()->Start());
- NavigationObserverImpl observer(GetNavigationController());
- const std::string custom_ua = "custom-ua";
- observer.SetStartedCallback(
- base::BindLambdaForTesting([&](Navigation* navigation) {
- navigation->SetUserAgentString(custom_ua);
- }));
- OneShotNavigationObserver load_observer(shell());
- shell()->LoadURL(embedded_test_server()->GetURL("/simple_page.html"));
- load_observer.WaitForNavigation();
- // Just because we set a custom user agent doesn't mean we should ignore
- // viewport meta tags.
- auto* tab = static_cast<TabImpl*>(shell()->tab());
- auto* web_contents = tab->web_contents();
- ASSERT_TRUE(web_contents->GetOrCreateWebPreferences().viewport_meta_enabled);
- }
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
- RequestDesktopSiteChangesViewportMetaTag) {
- ASSERT_TRUE(embedded_test_server()->Start());
- OneShotNavigationObserver load_observer(shell());
- shell()->LoadURL(embedded_test_server()->GetURL("/simple_page.html"));
- load_observer.WaitForNavigation();
- auto* tab = static_cast<TabImpl*>(shell()->tab());
- OneShotNavigationObserver load_observer2(shell());
- tab->SetDesktopUserAgentEnabled(nullptr, true);
- load_observer2.WaitForNavigation();
- auto* web_contents = tab->web_contents();
- ASSERT_FALSE(web_contents->GetOrCreateWebPreferences().viewport_meta_enabled);
- }
- #endif
- // Verifies changing the user agent twice in a row works.
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, UserAgentDoesntCarryThrough1) {
- net::test_server::ControllableHttpResponse response_1(embedded_test_server(),
- "", true);
- net::test_server::ControllableHttpResponse response_2(embedded_test_server(),
- "", true);
- ASSERT_TRUE(embedded_test_server()->Start());
- const std::string custom_ua1 = "my ua1";
- const std::string custom_ua2 = "my ua2";
- NavigationObserverImpl observer(GetNavigationController());
- observer.SetStartedCallback(
- base::BindLambdaForTesting([&](Navigation* navigation) {
- navigation->SetUserAgentString(custom_ua1);
- }));
- shell()->LoadURL(embedded_test_server()->GetURL("/simple_page.html"));
- response_1.WaitForRequest();
- EXPECT_EQ(custom_ua1, response_1.http_request()->headers.at(
- net::HttpRequestHeaders::kUserAgent));
- // Before the request is done, start another navigation.
- observer.SetStartedCallback(
- base::BindLambdaForTesting([&](Navigation* navigation) {
- navigation->SetUserAgentString(custom_ua2);
- }));
- shell()->LoadURL(embedded_test_server()->GetURL("/simple_page2.html"));
- response_2.WaitForRequest();
- EXPECT_EQ(custom_ua2, response_2.http_request()->headers.at(
- net::HttpRequestHeaders::kUserAgent));
- }
- // Verifies changing the user agent doesn't bleed through to next navigation.
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, UserAgentDoesntCarryThrough2) {
- net::test_server::ControllableHttpResponse response_1(embedded_test_server(),
- "", true);
- net::test_server::ControllableHttpResponse response_2(embedded_test_server(),
- "", true);
- ASSERT_TRUE(embedded_test_server()->Start());
- const std::string custom_ua = "my ua1";
- NavigationObserverImpl observer(GetNavigationController());
- observer.SetStartedCallback(
- base::BindLambdaForTesting([&](Navigation* navigation) {
- navigation->SetUserAgentString(custom_ua);
- }));
- shell()->LoadURL(embedded_test_server()->GetURL("/simple_page.html"));
- response_1.WaitForRequest();
- EXPECT_EQ(custom_ua, response_1.http_request()->headers.at(
- net::HttpRequestHeaders::kUserAgent));
- // Before the request is done, start another navigation.
- observer.SetStartedCallback(base::DoNothing());
- shell()->LoadURL(embedded_test_server()->GetURL("/simple_page2.html"));
- response_2.WaitForRequest();
- EXPECT_NE(custom_ua, response_2.http_request()->headers.at(
- net::HttpRequestHeaders::kUserAgent));
- EXPECT_FALSE(response_2.http_request()
- ->headers.at(net::HttpRequestHeaders::kUserAgent)
- .empty());
- }
- // Verifies changing the user-agent applies to child resources, such as an
- // <img>.
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
- UserAgentAppliesToChildResources) {
- net::test_server::ControllableHttpResponse response_1(embedded_test_server(),
- "", true);
- net::test_server::ControllableHttpResponse response_2(embedded_test_server(),
- "", true);
- ASSERT_TRUE(embedded_test_server()->Start());
- const std::string custom_ua = "custom-ua";
- NavigationObserverImpl observer(GetNavigationController());
- observer.SetStartedCallback(
- base::BindLambdaForTesting([&](Navigation* navigation) {
- navigation->SetUserAgentString(custom_ua);
- }));
- shell()->LoadURL(embedded_test_server()->GetURL("/foo.html"));
- response_1.WaitForRequest();
- response_1.Send(net::HTTP_OK, "text/html", "<img src=\"image.png\">");
- response_1.Done();
- EXPECT_EQ(custom_ua, response_1.http_request()->headers.at(
- net::HttpRequestHeaders::kUserAgent));
- observer.SetStartedCallback(base::DoNothing());
- response_2.WaitForRequest();
- EXPECT_EQ(custom_ua, response_2.http_request()->headers.at(
- net::HttpRequestHeaders::kUserAgent));
- }
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
- SetUserAgentStringRendererInitiated) {
- net::test_server::ControllableHttpResponse response_1(embedded_test_server(),
- "", true);
- net::test_server::ControllableHttpResponse response_2(embedded_test_server(),
- "", true);
- ASSERT_TRUE(embedded_test_server()->Start());
- OneShotNavigationObserver load_observer(shell());
- NavigationObserverImpl observer(GetNavigationController());
- shell()->LoadURL(embedded_test_server()->GetURL("/simple_page.html"));
- response_1.WaitForRequest();
- response_1.Send(net::HTTP_OK, "text/html", "<html>");
- response_1.Done();
- load_observer.WaitForNavigation();
- const std::string custom_ua = "custom-ua";
- observer.SetStartedCallback(
- base::BindLambdaForTesting([&](Navigation* navigation) {
- navigation->SetUserAgentString(custom_ua);
- }));
- const GURL target_url = embedded_test_server()->GetURL("/foo.html");
- shell()->tab()->ExecuteScript(
- u"location.href='" + base::ASCIIToUTF16(target_url.spec()) + u"';", false,
- base::DoNothing());
- response_2.WaitForRequest();
- // |custom_ua| should be present in the renderer initiated navigation.
- ASSERT_TRUE(base::Contains(response_2.http_request()->headers,
- net::HttpRequestHeaders::kUserAgent));
- const std::string new_ua = response_2.http_request()->headers.at(
- net::HttpRequestHeaders::kUserAgent);
- EXPECT_EQ(custom_ua, new_ua);
- }
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, AutoPlayDefault) {
- ASSERT_TRUE(embedded_test_server()->Start());
- GURL url(embedded_test_server()->GetURL("/autoplay.html"));
- auto* tab = static_cast<TabImpl*>(shell()->tab());
- NavigateAndWaitForCompletion(url, tab);
- auto* web_contents = tab->web_contents();
- bool playing = false;
- // There's no notification to watch that would signal video wasn't autoplayed,
- // so instead check once through javascript.
- EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
- web_contents,
- "window.domAutomationController.send(!document.getElementById('vid')."
- "paused)",
- &playing));
- ASSERT_FALSE(playing);
- }
- namespace {
- class WaitForMediaPlaying : public content::WebContentsObserver {
- public:
- explicit WaitForMediaPlaying(content::WebContents* web_contents)
- : WebContentsObserver(web_contents) {}
- WaitForMediaPlaying(const WaitForMediaPlaying&) = delete;
- WaitForMediaPlaying& operator=(const WaitForMediaPlaying&) = delete;
- // WebContentsObserver override.
- void MediaStartedPlaying(const MediaPlayerInfo& info,
- const content::MediaPlayerId&) final {
- run_loop_.Quit();
- CHECK(info.has_audio);
- CHECK(info.has_video);
- }
- void Wait() { run_loop_.Run(); }
- private:
- base::RunLoop run_loop_;
- };
- } // namespace
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, AutoPlayEnabled) {
- ASSERT_TRUE(embedded_test_server()->Start());
- GURL url(embedded_test_server()->GetURL("/autoplay.html"));
- NavigationController::NavigateParams params;
- params.enable_auto_play = true;
- GetNavigationController()->Navigate(url, params);
- auto* tab = static_cast<TabImpl*>(shell()->tab());
- WaitForMediaPlaying wait_for_media(tab->web_contents());
- wait_for_media.Wait();
- }
- class NavigationBrowserTest2 : public NavigationBrowserTest {
- public:
- void SetUp() override {
- // HTTPS server only serves a valid cert for localhost, so this is needed to
- // load pages from "www.google.com" without an interstitial.
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- "ignore-certificate-errors");
- NavigationBrowserTest::SetUp();
- }
- void SetUpOnMainThread() override {
- NavigationBrowserTest::SetUpOnMainThread();
- https_server_ = std::make_unique<net::EmbeddedTestServer>(
- net::EmbeddedTestServer::TYPE_HTTPS);
- // The test makes requests to google.com which we want to redirect to the
- // test server.
- host_resolver()->AddRule("*", "127.0.0.1");
- // Forces variations code to set the header.
- auto* variations_provider =
- variations::VariationsIdsProvider::GetInstance();
- variations_provider->ForceVariationIds({"12", "456", "t789"}, "");
- }
- net::EmbeddedTestServer* https_server() { return https_server_.get(); }
- private:
- std::unique_ptr<net::EmbeddedTestServer> https_server_;
- };
- // This test verifies the embedder can replace the X-Client-Data header that
- // is also set by //components/variations.
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest2, ReplaceXClientDataHeader) {
- std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
- std::string last_header_value;
- auto main_task_runner = base::SequencedTaskRunnerHandle::Get();
- https_server()->RegisterRequestHandler(base::BindLambdaForTesting(
- [&, main_task_runner](const net::test_server::HttpRequest& request)
- -> std::unique_ptr<net::test_server::HttpResponse> {
- auto iter = request.headers.find(variations::kClientDataHeader);
- if (iter != request.headers.end()) {
- main_task_runner->PostTask(
- FROM_HERE, base::BindOnce(base::BindLambdaForTesting(
- [&](const std::string& value) {
- last_header_value = value;
- run_loop->Quit();
- }),
- iter->second));
- }
- return std::make_unique<net::test_server::BasicHttpResponse>();
- }));
- ASSERT_TRUE(https_server()->Start());
- // Verify the header is set by default.
- const GURL url = https_server()->GetURL("www.google.com", "/");
- shell()->LoadURL(url);
- run_loop->Run();
- EXPECT_FALSE(last_header_value.empty());
- // Repeat, but clobber the header when navigating.
- const std::string header_value = "value";
- EXPECT_NE(last_header_value, header_value);
- last_header_value.clear();
- run_loop = std::make_unique<base::RunLoop>();
- NavigationObserverImpl observer(GetNavigationController());
- observer.SetStartedCallback(
- base::BindLambdaForTesting([&](Navigation* navigation) {
- navigation->SetRequestHeader(variations::kClientDataHeader,
- header_value);
- }));
- shell()->LoadURL(https_server()->GetURL("www.google.com", "/foo"));
- run_loop->Run();
- EXPECT_EQ(header_value, last_header_value);
- }
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest2,
- SetXClientDataHeaderCarriesThroughToRedirect) {
- std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
- std::string last_header_value;
- bool should_redirect = true;
- auto main_task_runner = base::SequencedTaskRunnerHandle::Get();
- https_server()->RegisterRequestHandler(base::BindLambdaForTesting(
- [&, main_task_runner](const net::test_server::HttpRequest& request)
- -> std::unique_ptr<net::test_server::HttpResponse> {
- auto response = std::make_unique<net::test_server::BasicHttpResponse>();
- if (should_redirect) {
- should_redirect = false;
- response->set_code(net::HTTP_MOVED_PERMANENTLY);
- response->AddCustomHeader(
- "Location",
- https_server()->GetURL("www.google.com", "/redirect").spec());
- } else {
- auto iter = request.headers.find(variations::kClientDataHeader);
- main_task_runner->PostTask(
- FROM_HERE, base::BindOnce(base::BindLambdaForTesting(
- [&](const std::string& value) {
- last_header_value = value;
- run_loop->Quit();
- }),
- iter->second));
- }
- return response;
- }));
- ASSERT_TRUE(https_server()->Start());
- const std::string header_value = "value";
- run_loop = std::make_unique<base::RunLoop>();
- NavigationObserverImpl observer(GetNavigationController());
- observer.SetStartedCallback(
- base::BindLambdaForTesting([&](Navigation* navigation) {
- navigation->SetRequestHeader(variations::kClientDataHeader,
- header_value);
- }));
- shell()->LoadURL(https_server()->GetURL("www.google.com", "/foo"));
- run_loop->Run();
- EXPECT_EQ(header_value, last_header_value);
- }
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest2, SetXClientDataHeaderInRedirect) {
- std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
- std::string last_header_value;
- bool should_redirect = true;
- auto main_task_runner = base::SequencedTaskRunnerHandle::Get();
- https_server()->RegisterRequestHandler(base::BindLambdaForTesting(
- [&, main_task_runner](const net::test_server::HttpRequest& request)
- -> std::unique_ptr<net::test_server::HttpResponse> {
- auto response = std::make_unique<net::test_server::BasicHttpResponse>();
- if (should_redirect) {
- should_redirect = false;
- response->set_code(net::HTTP_MOVED_PERMANENTLY);
- response->AddCustomHeader(
- "Location",
- https_server()->GetURL("www.google.com", "/redirect").spec());
- } else {
- auto iter = request.headers.find(variations::kClientDataHeader);
- main_task_runner->PostTask(
- FROM_HERE, base::BindOnce(base::BindLambdaForTesting(
- [&](const std::string& value) {
- last_header_value = value;
- run_loop->Quit();
- }),
- iter->second));
- }
- return response;
- }));
- ASSERT_TRUE(https_server()->Start());
- const std::string header_value = "value";
- NavigationObserverImpl observer(GetNavigationController());
- observer.SetRedirectedCallback(
- base::BindLambdaForTesting([&](Navigation* navigation) {
- navigation->SetRequestHeader(variations::kClientDataHeader,
- header_value);
- }));
- shell()->LoadURL(https_server()->GetURL("www.google.com", "/foo"));
- run_loop->Run();
- EXPECT_EQ(header_value, last_header_value);
- }
- #if BUILDFLAG(IS_ANDROID)
- // Verifies setting the 'referer' to an android-app url works.
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, AndroidAppReferer) {
- net::test_server::ControllableHttpResponse response(embedded_test_server(),
- "", true);
- ASSERT_TRUE(embedded_test_server()->Start());
- const std::string header_name = "Referer";
- const std::string header_value = "android-app://google.com/";
- NavigationObserverImpl observer(GetNavigationController());
- observer.SetStartedCallback(
- base::BindLambdaForTesting([&](Navigation* navigation) {
- navigation->SetRequestHeader(header_name, header_value);
- }));
- shell()->LoadURL(embedded_test_server()->GetURL("/simple_page.html"));
- response.WaitForRequest();
- // Verify 'referer' matches expected value.
- EXPECT_EQ(header_value, response.http_request()->headers.at(header_name));
- }
- #endif
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
- OnPageLanguageDeterminedCallback) {
- ASSERT_TRUE(embedded_test_server()->Start());
- NavigationController* controller = shell()->tab()->GetNavigationController();
- NavigationObserverImpl observer(controller);
- Page* committed_page = nullptr;
- Page* page_with_language_determined = nullptr;
- std::string determined_language = "";
- base::RunLoop navigation_run_loop1;
- base::RunLoop page_language_determination_run_loop1;
- base::RunLoop* navigation_run_loop = &navigation_run_loop1;
- base::RunLoop* page_language_determination_run_loop =
- &page_language_determination_run_loop1;
- observer.SetCompletedClosure(
- base::BindLambdaForTesting([&](Navigation* navigation) {
- committed_page = navigation->GetPage();
- navigation_run_loop->Quit();
- }));
- observer.SetOnPageLanguageDeterminedCallback(
- base::BindLambdaForTesting([&](Page* page, std::string language) {
- page_with_language_determined = page;
- determined_language = language;
- page_language_determination_run_loop->Quit();
- }));
- // Navigate to a page in English.
- controller->Navigate(embedded_test_server()->GetURL("/english_page.html"));
- navigation_run_loop1.Run();
- EXPECT_TRUE(committed_page);
- // Verify that the language determined event fires as expected.
- page_language_determination_run_loop1.Run();
- EXPECT_EQ(committed_page, page_with_language_determined);
- EXPECT_EQ("en", determined_language);
- // Now navigate to a page in French.
- committed_page = nullptr;
- page_with_language_determined = nullptr;
- base::RunLoop navigation_run_loop2;
- base::RunLoop page_language_determination_run_loop2;
- navigation_run_loop = &navigation_run_loop2;
- page_language_determination_run_loop = &page_language_determination_run_loop2;
- controller->Navigate(embedded_test_server()->GetURL("/french_page.html"));
- navigation_run_loop2.Run();
- EXPECT_TRUE(committed_page);
- // Verify that the language determined event fires as expected.
- page_language_determination_run_loop2.Run();
- EXPECT_EQ(committed_page, page_with_language_determined);
- EXPECT_EQ("fr", determined_language);
- }
- // Verifies that closing a tab when a navigation is waiting for a response
- // causes the navigation to be marked as failed to the embedder.
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
- CloseTabWithNavigationWaitingForResponse) {
- net::test_server::ControllableHttpResponse response(embedded_test_server(),
- "", true);
- ASSERT_TRUE(embedded_test_server()->Start());
- GURL url = embedded_test_server()->GetURL("/initial_url.html");
- base::RunLoop run_loop;
- Navigation* ongoing_navigation = nullptr;
- auto observer =
- std::make_unique<NavigationObserverImpl>(GetNavigationController());
- observer->SetStartedCallback(base::BindLambdaForTesting(
- [&](Navigation* navigation) { ongoing_navigation = navigation; }));
- observer->SetFailedCallback(
- base::BindLambdaForTesting([&](Navigation* navigation) {
- EXPECT_EQ(url, navigation->GetURL());
- EXPECT_EQ(NavigationState::kFailed, navigation->GetState());
- run_loop.Quit();
- // The NavigationControllerImpl that |observer| is observing will
- // be destroyed before control returns to the test, so destroy
- // |observer| now to avoid UaF.
- observer.reset();
- }));
- shell()->LoadURL(url);
- response.WaitForRequest();
- EXPECT_EQ(NavigationState::kWaitingResponse, ongoing_navigation->GetState());
- shell()->browser()->DestroyTab(shell()->tab());
- run_loop.Run();
- }
- // Verifies that closing a tab when a navigation is in the middle of receiving a
- // response causes the navigation to be marked as failed to the embedder.
- IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
- CloseTabWithNavigationReceivingBytes) {
- net::test_server::ControllableHttpResponse response(embedded_test_server(),
- "", true);
- ASSERT_TRUE(embedded_test_server()->Start());
- GURL url = embedded_test_server()->GetURL("/initial_url.html");
- base::RunLoop run_loop;
- Navigation* ongoing_navigation = nullptr;
- auto observer =
- std::make_unique<NavigationObserverImpl>(GetNavigationController());
- observer->SetStartedCallback(base::BindLambdaForTesting(
- [&](Navigation* navigation) { ongoing_navigation = navigation; }));
- observer->SetFailedCallback(
- base::BindLambdaForTesting([&](Navigation* navigation) {
- EXPECT_EQ(url, navigation->GetURL());
- EXPECT_EQ(NavigationState::kFailed, navigation->GetState());
- run_loop.Quit();
- // The NavigationControllerImpl that |observer| is observing will
- // be destroyed before control returns to the test, so destroy
- // |observer| now to avoid UaF.
- observer.reset();
- }));
- auto* tab = static_cast<TabImpl*>(shell()->tab());
- auto wait_for_response_start =
- std::make_unique<content::TestNavigationManager>(tab->web_contents(),
- url);
- shell()->LoadURL(url);
- // Wait until request is ready to start.
- EXPECT_TRUE(wait_for_response_start->WaitForRequestStart());
- // Start the request.
- wait_for_response_start->ResumeNavigation();
- // Wait for the request to arrive to ControllableHttpResponse.
- response.WaitForRequest();
- response.Send(net::HTTP_OK, "text/html", "<html>");
- ASSERT_TRUE(wait_for_response_start->WaitForResponse());
- EXPECT_EQ(NavigationState::kReceivingBytes, ongoing_navigation->GetState());
- // Destroy |wait_for_response_start| before we indirectly destroy the
- // WebContents it's observing.
- wait_for_response_start.reset();
- shell()->browser()->DestroyTab(tab);
- run_loop.Run();
- }
- } // namespace weblayer
|