navigation_browsertest.cc 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include <memory>
  5. #include "weblayer/test/weblayer_browser_test.h"
  6. #include "base/callback.h"
  7. #include "base/callback_helpers.h"
  8. #include "base/command_line.h"
  9. #include "base/files/file_path.h"
  10. #include "base/memory/raw_ptr.h"
  11. #include "base/strings/stringprintf.h"
  12. #include "base/strings/utf_string_conversions.h"
  13. #include "base/test/bind.h"
  14. #include "base/test/metrics/histogram_tester.h"
  15. #include "base/test/scoped_feature_list.h"
  16. #include "build/build_config.h"
  17. #include "components/variations/net/variations_http_headers.h"
  18. #include "components/variations/variations_ids_provider.h"
  19. #include "content/public/browser/web_contents_observer.h"
  20. #include "content/public/test/browser_test_utils.h"
  21. #include "content/public/test/url_loader_interceptor.h"
  22. #include "net/dns/mock_host_resolver.h"
  23. #include "net/test/embedded_test_server/controllable_http_response.h"
  24. #include "net/test/embedded_test_server/embedded_test_server.h"
  25. #include "net/test/embedded_test_server/http_response.h"
  26. #include "third_party/blink/public/common/features.h"
  27. #include "third_party/blink/public/common/web_preferences/web_preferences.h"
  28. #include "weblayer/browser/tab_impl.h"
  29. #include "weblayer/public/browser.h"
  30. #include "weblayer/public/browser_observer.h"
  31. #include "weblayer/public/navigation.h"
  32. #include "weblayer/public/navigation_controller.h"
  33. #include "weblayer/public/navigation_observer.h"
  34. #include "weblayer/public/new_tab_delegate.h"
  35. #include "weblayer/shell/browser/shell.h"
  36. #include "weblayer/test/interstitial_utils.h"
  37. #include "weblayer/test/test_navigation_observer.h"
  38. #include "weblayer/test/weblayer_browser_test_utils.h"
  39. namespace weblayer {
  40. namespace {
  41. // NavigationObserver that allows registering a callback for various
  42. // NavigationObserver functions.
  43. class NavigationObserverImpl : public NavigationObserver {
  44. public:
  45. explicit NavigationObserverImpl(NavigationController* controller)
  46. : controller_(controller) {
  47. controller_->AddObserver(this);
  48. }
  49. ~NavigationObserverImpl() override { controller_->RemoveObserver(this); }
  50. using Callback = base::RepeatingCallback<void(Navigation*)>;
  51. using PageLanguageDeterminedCallback =
  52. base::RepeatingCallback<void(Page*, std::string)>;
  53. void SetStartedCallback(Callback callback) {
  54. started_callback_ = std::move(callback);
  55. }
  56. void SetRedirectedCallback(Callback callback) {
  57. redirected_callback_ = std::move(callback);
  58. }
  59. void SetFailedCallback(Callback callback) {
  60. failed_callback_ = std::move(callback);
  61. }
  62. void SetCompletedClosure(Callback callback) {
  63. completed_callback_ = std::move(callback);
  64. }
  65. void SetOnPageLanguageDeterminedCallback(
  66. PageLanguageDeterminedCallback callback) {
  67. on_page_language_determined_callback_ = std::move(callback);
  68. }
  69. // NavigationObserver:
  70. void NavigationStarted(Navigation* navigation) override {
  71. if (started_callback_)
  72. started_callback_.Run(navigation);
  73. }
  74. void NavigationRedirected(Navigation* navigation) override {
  75. if (redirected_callback_)
  76. redirected_callback_.Run(navigation);
  77. }
  78. void NavigationCompleted(Navigation* navigation) override {
  79. if (completed_callback_)
  80. completed_callback_.Run(navigation);
  81. }
  82. void NavigationFailed(Navigation* navigation) override {
  83. // As |this| may be deleted when running the callback, the callback must be
  84. // copied before running. To do otherwise results in use-after-free.
  85. auto callback = failed_callback_;
  86. if (callback)
  87. callback.Run(navigation);
  88. }
  89. void OnPageLanguageDetermined(Page* page,
  90. const std::string& language) override {
  91. if (on_page_language_determined_callback_)
  92. on_page_language_determined_callback_.Run(page, language);
  93. }
  94. private:
  95. raw_ptr<NavigationController> controller_;
  96. Callback started_callback_;
  97. Callback redirected_callback_;
  98. Callback completed_callback_;
  99. Callback failed_callback_;
  100. PageLanguageDeterminedCallback on_page_language_determined_callback_;
  101. };
  102. } // namespace
  103. class NavigationBrowserTest : public WebLayerBrowserTest {
  104. public:
  105. NavigationController* GetNavigationController() {
  106. return shell()->tab()->GetNavigationController();
  107. }
  108. void SetUpOnMainThread() override {
  109. host_resolver()->AddRule("*", "127.0.0.1");
  110. content::SetupCrossSiteRedirector(embedded_test_server());
  111. }
  112. };
  113. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, NoError) {
  114. EXPECT_TRUE(embedded_test_server()->Start());
  115. OneShotNavigationObserver observer(shell());
  116. GetNavigationController()->Navigate(
  117. embedded_test_server()->GetURL("/simple_page.html"));
  118. observer.WaitForNavigation();
  119. EXPECT_TRUE(observer.completed());
  120. EXPECT_FALSE(observer.is_error_page());
  121. EXPECT_FALSE(observer.is_download());
  122. EXPECT_FALSE(observer.is_reload());
  123. EXPECT_FALSE(observer.was_stop_called());
  124. EXPECT_EQ(observer.load_error(), Navigation::kNoError);
  125. EXPECT_EQ(observer.http_status_code(), 200);
  126. EXPECT_EQ(observer.navigation_state(), NavigationState::kComplete);
  127. }
  128. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
  129. IsPageInitiatedTrueForWindowHistoryBack) {
  130. EXPECT_TRUE(embedded_test_server()->Start());
  131. std::unique_ptr<OneShotNavigationObserver> observer =
  132. std::make_unique<OneShotNavigationObserver>(shell());
  133. GetNavigationController()->Navigate(
  134. embedded_test_server()->GetURL("a.com", "/simple_page.html"));
  135. observer->WaitForNavigation();
  136. ASSERT_TRUE(observer->completed());
  137. EXPECT_FALSE(observer->is_page_initiated());
  138. observer = std::make_unique<OneShotNavigationObserver>(shell());
  139. GetNavigationController()->Navigate(
  140. embedded_test_server()->GetURL("b.com", "/simple_page.html"));
  141. observer->WaitForNavigation();
  142. ASSERT_TRUE(observer->completed());
  143. EXPECT_FALSE(observer->is_page_initiated());
  144. observer = std::make_unique<OneShotNavigationObserver>(shell());
  145. shell()->tab()->ExecuteScript(
  146. u"window.history.back();", false,
  147. base::BindLambdaForTesting(
  148. [&](base::Value value) { LOG(ERROR) << "executescript result"; }));
  149. observer->WaitForNavigation();
  150. ASSERT_TRUE(observer->completed());
  151. EXPECT_TRUE(observer->is_page_initiated());
  152. }
  153. // Http client error when the server returns a non-empty response.
  154. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, HttpClientError) {
  155. EXPECT_TRUE(embedded_test_server()->Start());
  156. OneShotNavigationObserver observer(shell());
  157. GetNavigationController()->Navigate(
  158. embedded_test_server()->GetURL("/non_empty404.html"));
  159. observer.WaitForNavigation();
  160. EXPECT_TRUE(observer.completed());
  161. EXPECT_FALSE(observer.is_error_page());
  162. EXPECT_EQ(observer.load_error(), Navigation::kHttpClientError);
  163. EXPECT_EQ(observer.http_status_code(), 404);
  164. EXPECT_EQ(observer.navigation_state(), NavigationState::kComplete);
  165. }
  166. // Http client error when the server returns an empty response.
  167. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, HttpClientErrorEmptyResponse) {
  168. EXPECT_TRUE(embedded_test_server()->Start());
  169. OneShotNavigationObserver observer(shell());
  170. GetNavigationController()->Navigate(
  171. embedded_test_server()->GetURL("/empty404.html"));
  172. observer.WaitForNavigation();
  173. EXPECT_FALSE(observer.completed());
  174. EXPECT_TRUE(observer.is_error_page());
  175. EXPECT_EQ(observer.load_error(), Navigation::kHttpClientError);
  176. EXPECT_EQ(observer.http_status_code(), 404);
  177. EXPECT_EQ(observer.navigation_state(), NavigationState::kFailed);
  178. }
  179. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, HttpServerError) {
  180. EXPECT_TRUE(embedded_test_server()->Start());
  181. OneShotNavigationObserver observer(shell());
  182. GetNavigationController()->Navigate(
  183. embedded_test_server()->GetURL("/echo?status=500"));
  184. observer.WaitForNavigation();
  185. EXPECT_TRUE(observer.completed());
  186. EXPECT_FALSE(observer.is_error_page());
  187. EXPECT_EQ(observer.load_error(), Navigation::kHttpServerError);
  188. EXPECT_EQ(observer.http_status_code(), 500);
  189. EXPECT_EQ(observer.navigation_state(), NavigationState::kComplete);
  190. }
  191. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, SSLError) {
  192. net::EmbeddedTestServer https_server_mismatched(
  193. net::EmbeddedTestServer::TYPE_HTTPS);
  194. https_server_mismatched.SetSSLConfig(
  195. net::EmbeddedTestServer::CERT_MISMATCHED_NAME);
  196. https_server_mismatched.AddDefaultHandlers(
  197. base::FilePath(FILE_PATH_LITERAL("weblayer/test/data")));
  198. ASSERT_TRUE(https_server_mismatched.Start());
  199. OneShotNavigationObserver observer(shell());
  200. GetNavigationController()->Navigate(
  201. https_server_mismatched.GetURL("/simple_page.html"));
  202. observer.WaitForNavigation();
  203. EXPECT_FALSE(observer.completed());
  204. EXPECT_TRUE(observer.is_error_page());
  205. EXPECT_EQ(observer.load_error(), Navigation::kSSLError);
  206. EXPECT_EQ(observer.navigation_state(), NavigationState::kFailed);
  207. }
  208. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, HttpConnectivityError) {
  209. GURL url("http://doesntexist.com/foo");
  210. auto interceptor = content::URLLoaderInterceptor::SetupRequestFailForURL(
  211. url, net::ERR_NAME_NOT_RESOLVED);
  212. OneShotNavigationObserver observer(shell());
  213. GetNavigationController()->Navigate(url);
  214. observer.WaitForNavigation();
  215. EXPECT_FALSE(observer.completed());
  216. EXPECT_TRUE(observer.is_error_page());
  217. EXPECT_EQ(observer.load_error(), Navigation::kConnectivityError);
  218. EXPECT_EQ(observer.navigation_state(), NavigationState::kFailed);
  219. }
  220. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  221. // https://crbug.com/1296643
  222. #define MAYBE_Download DISABLED_Download
  223. #else
  224. #define MAYBE_Download Download
  225. #endif
  226. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, MAYBE_Download) {
  227. EXPECT_TRUE(embedded_test_server()->Start());
  228. GURL url(embedded_test_server()->GetURL("/content-disposition.html"));
  229. OneShotNavigationObserver observer(shell());
  230. GetNavigationController()->Navigate(url);
  231. observer.WaitForNavigation();
  232. EXPECT_FALSE(observer.completed());
  233. EXPECT_FALSE(observer.is_error_page());
  234. EXPECT_TRUE(observer.is_download());
  235. EXPECT_FALSE(observer.was_stop_called());
  236. EXPECT_EQ(observer.load_error(), Navigation::kOtherError);
  237. EXPECT_EQ(observer.navigation_state(), NavigationState::kFailed);
  238. }
  239. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, StopInOnStart) {
  240. ASSERT_TRUE(embedded_test_server()->Start());
  241. base::RunLoop run_loop;
  242. NavigationObserverImpl observer(GetNavigationController());
  243. observer.SetStartedCallback(base::BindLambdaForTesting(
  244. [&](Navigation*) { GetNavigationController()->Stop(); }));
  245. observer.SetFailedCallback(
  246. base::BindLambdaForTesting([&](Navigation* navigation) {
  247. ASSERT_TRUE(navigation->WasStopCalled());
  248. run_loop.Quit();
  249. }));
  250. GetNavigationController()->Navigate(
  251. embedded_test_server()->GetURL("/simple_page.html"));
  252. run_loop.Run();
  253. }
  254. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, DestroyTabInNavigation) {
  255. ASSERT_TRUE(embedded_test_server()->Start());
  256. Tab* new_tab = shell()->browser()->CreateTab();
  257. base::RunLoop run_loop;
  258. std::unique_ptr<NavigationObserverImpl> observer =
  259. std::make_unique<NavigationObserverImpl>(
  260. new_tab->GetNavigationController());
  261. observer->SetFailedCallback(
  262. base::BindLambdaForTesting([&](Navigation* navigation) {
  263. observer.reset();
  264. shell()->browser()->DestroyTab(new_tab);
  265. // Destroying the tab posts a task to delete the WebContents, which must
  266. // be run before the test shuts down lest it access deleted state.
  267. base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
  268. run_loop.QuitClosure());
  269. }));
  270. new_tab->GetNavigationController()->Navigate(
  271. embedded_test_server()->GetURL("/simple_pageX.html"));
  272. run_loop.Run();
  273. }
  274. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, StopInOnRedirect) {
  275. ASSERT_TRUE(embedded_test_server()->Start());
  276. base::RunLoop run_loop;
  277. NavigationObserverImpl observer(GetNavigationController());
  278. observer.SetRedirectedCallback(base::BindLambdaForTesting(
  279. [&](Navigation*) { GetNavigationController()->Stop(); }));
  280. observer.SetFailedCallback(
  281. base::BindLambdaForTesting([&](Navigation* navigation) {
  282. ASSERT_TRUE(navigation->WasStopCalled());
  283. run_loop.Quit();
  284. }));
  285. const GURL original_url = embedded_test_server()->GetURL("/simple_page.html");
  286. GetNavigationController()->Navigate(embedded_test_server()->GetURL(
  287. "/server-redirect?" + original_url.spec()));
  288. run_loop.Run();
  289. }
  290. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
  291. NavigateFromRendererInitiatedNavigation) {
  292. ASSERT_TRUE(embedded_test_server()->Start());
  293. NavigationController* controller = shell()->tab()->GetNavigationController();
  294. const GURL final_url = embedded_test_server()->GetURL("/simple_page2.html");
  295. int failed_count = 0;
  296. int completed_count = 0;
  297. NavigationObserverImpl observer(controller);
  298. base::RunLoop run_loop;
  299. observer.SetFailedCallback(
  300. base::BindLambdaForTesting([&](Navigation*) { failed_count++; }));
  301. observer.SetCompletedClosure(
  302. base::BindLambdaForTesting([&](Navigation* navigation) {
  303. completed_count++;
  304. if (navigation->GetURL().path() == "/simple_page2.html")
  305. run_loop.Quit();
  306. }));
  307. observer.SetStartedCallback(
  308. base::BindLambdaForTesting([&](Navigation* navigation) {
  309. if (navigation->GetURL().path() == "/simple_page.html")
  310. controller->Navigate(final_url);
  311. }));
  312. controller->Navigate(embedded_test_server()->GetURL("/simple_page4.html"));
  313. run_loop.Run();
  314. EXPECT_EQ(1, failed_count);
  315. EXPECT_EQ(2, completed_count);
  316. ASSERT_EQ(2, controller->GetNavigationListSize());
  317. EXPECT_EQ(final_url, controller->GetNavigationEntryDisplayURL(1));
  318. }
  319. class BrowserObserverImpl : public BrowserObserver {
  320. public:
  321. explicit BrowserObserverImpl(Browser* browser) : browser_(browser) {
  322. browser->AddObserver(this);
  323. }
  324. ~BrowserObserverImpl() override { browser_->RemoveObserver(this); }
  325. void SetNewTabCallback(base::RepeatingCallback<void(Tab*)> callback) {
  326. new_tab_callback_ = callback;
  327. }
  328. // BrowserObserver:
  329. void OnTabAdded(Tab* tab) override { new_tab_callback_.Run(tab); }
  330. private:
  331. base::RepeatingCallback<void(Tab*)> new_tab_callback_;
  332. raw_ptr<Browser> browser_;
  333. };
  334. class NewTabDelegateImpl : public NewTabDelegate {
  335. public:
  336. // NewTabDelegate:
  337. void OnNewTab(Tab* new_tab, NewTabType type) override {}
  338. };
  339. // Ensures calling Navigate() from within NavigationStarted() for a popup does
  340. // not crash.
  341. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, NavigateFromNewWindow) {
  342. ASSERT_TRUE(embedded_test_server()->Start());
  343. NavigateAndWaitForCompletion(
  344. embedded_test_server()->GetURL("/simple_page2.html"), shell());
  345. NewTabDelegate* old_new_tab_delegate =
  346. static_cast<TabImpl*>(shell()->tab())->new_tab_delegate();
  347. NewTabDelegateImpl new_tab_delegate;
  348. shell()->tab()->SetNewTabDelegate(&new_tab_delegate);
  349. BrowserObserverImpl browser_observer(shell()->tab()->GetBrowser());
  350. std::unique_ptr<NavigationObserverImpl> popup_navigation_observer;
  351. base::RunLoop run_loop;
  352. Tab* popup_tab = nullptr;
  353. auto popup_started_navigation = [&](Navigation* navigation) {
  354. if (navigation->GetURL().path() == "/simple_page.html") {
  355. popup_tab->GetNavigationController()->Navigate(
  356. embedded_test_server()->GetURL("/simple_page3.html"));
  357. } else if (navigation->GetURL().path() == "/simple_page3.html") {
  358. run_loop.Quit();
  359. }
  360. };
  361. browser_observer.SetNewTabCallback(base::BindLambdaForTesting([&](Tab* tab) {
  362. popup_tab = tab;
  363. popup_navigation_observer = std::make_unique<NavigationObserverImpl>(
  364. tab->GetNavigationController());
  365. popup_navigation_observer->SetStartedCallback(
  366. base::BindLambdaForTesting(popup_started_navigation));
  367. }));
  368. // 'noopener' is key to triggering the problematic case.
  369. const std::string window_open = base::StringPrintf(
  370. "window.open('%s', '', 'noopener')",
  371. embedded_test_server()->GetURL("/simple_page.html").spec().c_str());
  372. ExecuteScriptWithUserGesture(shell()->tab(), window_open);
  373. run_loop.Run();
  374. // Restore the old delegate to make sure it is cleaned up on Android.
  375. shell()->tab()->SetNewTabDelegate(old_new_tab_delegate);
  376. }
  377. // Verifies calling Navigate() from NavigationRedirected() works.
  378. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, NavigateFromRedirect) {
  379. net::test_server::ControllableHttpResponse response_1(embedded_test_server(),
  380. "", true);
  381. net::test_server::ControllableHttpResponse response_2(embedded_test_server(),
  382. "", true);
  383. ASSERT_TRUE(embedded_test_server()->Start());
  384. NavigationObserverImpl observer(GetNavigationController());
  385. bool got_redirect = false;
  386. const GURL url_to_load_on_redirect =
  387. embedded_test_server()->GetURL("/url_to_load_on_redirect.html");
  388. observer.SetRedirectedCallback(
  389. base::BindLambdaForTesting([&](Navigation* navigation) {
  390. shell()->LoadURL(url_to_load_on_redirect);
  391. got_redirect = true;
  392. }));
  393. shell()->LoadURL(embedded_test_server()->GetURL("/initial_url.html"));
  394. response_1.WaitForRequest();
  395. response_1.Send(
  396. "HTTP/1.1 302 Moved Temporarily\r\nLocation: /redirect_dest_url\r\n\r\n");
  397. response_1.Done();
  398. response_2.WaitForRequest();
  399. response_2.Done();
  400. EXPECT_EQ(url_to_load_on_redirect, response_2.http_request()->GetURL());
  401. EXPECT_TRUE(got_redirect);
  402. }
  403. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, SetRequestHeader) {
  404. net::test_server::ControllableHttpResponse response_1(embedded_test_server(),
  405. "", true);
  406. net::test_server::ControllableHttpResponse response_2(embedded_test_server(),
  407. "", true);
  408. ASSERT_TRUE(embedded_test_server()->Start());
  409. const std::string header_name = "header";
  410. const std::string header_value = "value";
  411. NavigationObserverImpl observer(GetNavigationController());
  412. observer.SetStartedCallback(
  413. base::BindLambdaForTesting([&](Navigation* navigation) {
  414. navigation->SetRequestHeader(header_name, header_value);
  415. }));
  416. shell()->LoadURL(embedded_test_server()->GetURL("/simple_page.html"));
  417. response_1.WaitForRequest();
  418. // Header should be present in initial request.
  419. EXPECT_EQ(header_value, response_1.http_request()->headers.at(header_name));
  420. response_1.Send(
  421. "HTTP/1.1 302 Moved Temporarily\r\nLocation: /new_doc\r\n\r\n");
  422. response_1.Done();
  423. // Header should carry through to redirect.
  424. response_2.WaitForRequest();
  425. EXPECT_EQ(header_value, response_2.http_request()->headers.at(header_name));
  426. }
  427. // Verifies setting the 'referer' via SetRequestHeader() works as expected.
  428. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, SetRequestHeaderWithReferer) {
  429. net::test_server::ControllableHttpResponse response(embedded_test_server(),
  430. "", true);
  431. ASSERT_TRUE(embedded_test_server()->Start());
  432. const std::string header_name = "Referer";
  433. const std::string header_value = "http://request.com";
  434. NavigationObserverImpl observer(GetNavigationController());
  435. observer.SetStartedCallback(
  436. base::BindLambdaForTesting([&](Navigation* navigation) {
  437. navigation->SetRequestHeader(header_name, header_value);
  438. }));
  439. shell()->LoadURL(embedded_test_server()->GetURL("/simple_page.html"));
  440. response.WaitForRequest();
  441. // Verify 'referer' matches expected value.
  442. EXPECT_EQ(GURL(header_value),
  443. GURL(response.http_request()->headers.at(header_name)));
  444. }
  445. // Like above but checks that referer isn't sent when it's https and the target
  446. // url is http.
  447. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
  448. SetRequestHeaderWithRefererDowngrade) {
  449. net::test_server::ControllableHttpResponse response(embedded_test_server(),
  450. "", true);
  451. ASSERT_TRUE(embedded_test_server()->Start());
  452. const std::string header_name = "Referer";
  453. const std::string header_value = "https://request.com";
  454. NavigationObserverImpl observer(GetNavigationController());
  455. observer.SetStartedCallback(
  456. base::BindLambdaForTesting([&](Navigation* navigation) {
  457. navigation->SetRequestHeader(header_name, header_value);
  458. }));
  459. shell()->LoadURL(embedded_test_server()->GetURL("/simple_page.html"));
  460. response.WaitForRequest();
  461. EXPECT_EQ(0u, response.http_request()->headers.count(header_name));
  462. }
  463. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, SetRequestHeaderInRedirect) {
  464. net::test_server::ControllableHttpResponse response_1(embedded_test_server(),
  465. "", true);
  466. net::test_server::ControllableHttpResponse response_2(embedded_test_server(),
  467. "", true);
  468. ASSERT_TRUE(embedded_test_server()->Start());
  469. const std::string header_name = "header";
  470. const std::string header_value = "value";
  471. NavigationObserverImpl observer(GetNavigationController());
  472. observer.SetRedirectedCallback(
  473. base::BindLambdaForTesting([&](Navigation* navigation) {
  474. navigation->SetRequestHeader(header_name, header_value);
  475. }));
  476. shell()->LoadURL(embedded_test_server()->GetURL("/simple_page.html"));
  477. response_1.WaitForRequest();
  478. // Header should not be present in initial request.
  479. EXPECT_FALSE(base::Contains(response_1.http_request()->headers, header_name));
  480. response_1.Send(
  481. "HTTP/1.1 302 Moved Temporarily\r\nLocation: /new_doc\r\n\r\n");
  482. response_1.Done();
  483. response_2.WaitForRequest();
  484. // Header should be in redirect.
  485. ASSERT_TRUE(base::Contains(response_2.http_request()->headers, header_name));
  486. EXPECT_EQ(header_value, response_2.http_request()->headers.at(header_name));
  487. }
  488. class NavigationBrowserTestUserAgentOverrideSubstring
  489. : public NavigationBrowserTest {
  490. public:
  491. void SetUp() override {
  492. scoped_feature_list_.InitWithFeatures(
  493. {blink::features::kUserAgentOverrideExperiment,
  494. blink::features::kUACHOverrideBlank},
  495. {});
  496. NavigationBrowserTest::SetUp();
  497. }
  498. private:
  499. base::test::ScopedFeatureList scoped_feature_list_;
  500. };
  501. IN_PROC_BROWSER_TEST_F(NavigationBrowserTestUserAgentOverrideSubstring,
  502. PageSeesUserAgentString) {
  503. net::test_server::EmbeddedTestServer https_server(
  504. net::test_server::EmbeddedTestServer::TYPE_HTTPS);
  505. https_server.AddDefaultHandlers(
  506. base::FilePath(FILE_PATH_LITERAL("weblayer/test/data")));
  507. ASSERT_TRUE(https_server.Start());
  508. const std::string custom_ua = "custom";
  509. NavigationObserverImpl observer(GetNavigationController());
  510. observer.SetStartedCallback(
  511. base::BindLambdaForTesting([&](Navigation* navigation) {
  512. navigation->SetUserAgentString(custom_ua);
  513. }));
  514. base::HistogramTester histogram;
  515. OneShotNavigationObserver navigation_observer(shell());
  516. shell()->LoadURL(https_server.GetURL("/simple_page.html"));
  517. navigation_observer.WaitForNavigation();
  518. histogram.ExpectBucketCount(
  519. blink::UserAgentOverride::kUserAgentOverrideHistogram,
  520. blink::UserAgentOverride::UserAgentOverriden, 1);
  521. base::RunLoop run_loop;
  522. shell()->tab()->ExecuteScript(
  523. u"navigator.userAgent;", false,
  524. base::BindLambdaForTesting([&](base::Value value) {
  525. ASSERT_TRUE(value.is_string());
  526. EXPECT_EQ(custom_ua, value.GetString());
  527. run_loop.Quit();
  528. }));
  529. run_loop.Run();
  530. // Ensure that userAgentData is blank when custom user agent is set.
  531. base::RunLoop run_loop2;
  532. shell()->tab()->ExecuteScript(
  533. u"navigator.userAgentData.platform;", false,
  534. base::BindLambdaForTesting([&](base::Value value) {
  535. ASSERT_TRUE(value.is_string());
  536. EXPECT_EQ("", value.GetString());
  537. run_loop2.Quit();
  538. }));
  539. run_loop2.Run();
  540. }
  541. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, Reload) {
  542. ASSERT_TRUE(embedded_test_server()->Start());
  543. OneShotNavigationObserver observer(shell());
  544. GetNavigationController()->Navigate(
  545. embedded_test_server()->GetURL("/simple_page.html"));
  546. observer.WaitForNavigation();
  547. OneShotNavigationObserver observer2(shell());
  548. shell()->tab()->ExecuteScript(u"location.reload();", false,
  549. base::DoNothing());
  550. observer2.WaitForNavigation();
  551. EXPECT_TRUE(observer2.completed());
  552. EXPECT_TRUE(observer2.is_reload());
  553. }
  554. IN_PROC_BROWSER_TEST_F(NavigationBrowserTestUserAgentOverrideSubstring,
  555. SetUserAgentString) {
  556. std::unique_ptr<net::test_server::EmbeddedTestServer> https_server =
  557. std::make_unique<net::test_server::EmbeddedTestServer>(
  558. net::test_server::EmbeddedTestServer::TYPE_HTTPS);
  559. https_server->AddDefaultHandlers(
  560. base::FilePath(FILE_PATH_LITERAL("weblayer/test/data")));
  561. net::test_server::ControllableHttpResponse response_1(https_server.get(), "",
  562. true);
  563. net::test_server::ControllableHttpResponse response_2(https_server.get(), "",
  564. true);
  565. ASSERT_TRUE(https_server->Start());
  566. const std::string custom_ua = "CUSTOM";
  567. NavigationObserverImpl observer(GetNavigationController());
  568. observer.SetStartedCallback(
  569. base::BindLambdaForTesting([&](Navigation* navigation) {
  570. navigation->SetUserAgentString(custom_ua);
  571. }));
  572. base::HistogramTester histogram;
  573. shell()->LoadURL(https_server->GetURL("/simple_page.html"));
  574. response_1.WaitForRequest();
  575. // |custom_ua| should be present in initial request.
  576. ASSERT_TRUE(base::Contains(response_1.http_request()->headers,
  577. net::HttpRequestHeaders::kUserAgent));
  578. const std::string new_header = response_1.http_request()->headers.at(
  579. net::HttpRequestHeaders::kUserAgent);
  580. EXPECT_EQ(custom_ua, new_header);
  581. ASSERT_TRUE(base::Contains(response_1.http_request()->headers, "sec-ch-ua"));
  582. const std::string new_ch_header =
  583. response_1.http_request()->headers.at("Sec-CH-UA");
  584. EXPECT_EQ("", new_ch_header);
  585. content::FetchHistogramsFromChildProcesses();
  586. histogram.ExpectBucketCount(
  587. blink::UserAgentOverride::kUserAgentOverrideHistogram,
  588. blink::UserAgentOverride::UserAgentOverriden, 1);
  589. // Header should carry through to redirect.
  590. response_1.Send(
  591. "HTTP/1.1 302 Moved Temporarily\r\nLocation: /new_doc\r\n\r\n");
  592. response_1.Done();
  593. response_2.WaitForRequest();
  594. EXPECT_EQ(custom_ua, response_2.http_request()->headers.at(
  595. net::HttpRequestHeaders::kUserAgent));
  596. EXPECT_EQ("", response_2.http_request()->headers.at("Sec-CH-UA"));
  597. }
  598. #if BUILDFLAG(IS_ANDROID)
  599. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
  600. SetUserAgentStringDoesntChangeViewportMetaTag) {
  601. ASSERT_TRUE(embedded_test_server()->Start());
  602. NavigationObserverImpl observer(GetNavigationController());
  603. const std::string custom_ua = "custom-ua";
  604. observer.SetStartedCallback(
  605. base::BindLambdaForTesting([&](Navigation* navigation) {
  606. navigation->SetUserAgentString(custom_ua);
  607. }));
  608. OneShotNavigationObserver load_observer(shell());
  609. shell()->LoadURL(embedded_test_server()->GetURL("/simple_page.html"));
  610. load_observer.WaitForNavigation();
  611. // Just because we set a custom user agent doesn't mean we should ignore
  612. // viewport meta tags.
  613. auto* tab = static_cast<TabImpl*>(shell()->tab());
  614. auto* web_contents = tab->web_contents();
  615. ASSERT_TRUE(web_contents->GetOrCreateWebPreferences().viewport_meta_enabled);
  616. }
  617. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
  618. RequestDesktopSiteChangesViewportMetaTag) {
  619. ASSERT_TRUE(embedded_test_server()->Start());
  620. OneShotNavigationObserver load_observer(shell());
  621. shell()->LoadURL(embedded_test_server()->GetURL("/simple_page.html"));
  622. load_observer.WaitForNavigation();
  623. auto* tab = static_cast<TabImpl*>(shell()->tab());
  624. OneShotNavigationObserver load_observer2(shell());
  625. tab->SetDesktopUserAgentEnabled(nullptr, true);
  626. load_observer2.WaitForNavigation();
  627. auto* web_contents = tab->web_contents();
  628. ASSERT_FALSE(web_contents->GetOrCreateWebPreferences().viewport_meta_enabled);
  629. }
  630. #endif
  631. // Verifies changing the user agent twice in a row works.
  632. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, UserAgentDoesntCarryThrough1) {
  633. net::test_server::ControllableHttpResponse response_1(embedded_test_server(),
  634. "", true);
  635. net::test_server::ControllableHttpResponse response_2(embedded_test_server(),
  636. "", true);
  637. ASSERT_TRUE(embedded_test_server()->Start());
  638. const std::string custom_ua1 = "my ua1";
  639. const std::string custom_ua2 = "my ua2";
  640. NavigationObserverImpl observer(GetNavigationController());
  641. observer.SetStartedCallback(
  642. base::BindLambdaForTesting([&](Navigation* navigation) {
  643. navigation->SetUserAgentString(custom_ua1);
  644. }));
  645. shell()->LoadURL(embedded_test_server()->GetURL("/simple_page.html"));
  646. response_1.WaitForRequest();
  647. EXPECT_EQ(custom_ua1, response_1.http_request()->headers.at(
  648. net::HttpRequestHeaders::kUserAgent));
  649. // Before the request is done, start another navigation.
  650. observer.SetStartedCallback(
  651. base::BindLambdaForTesting([&](Navigation* navigation) {
  652. navigation->SetUserAgentString(custom_ua2);
  653. }));
  654. shell()->LoadURL(embedded_test_server()->GetURL("/simple_page2.html"));
  655. response_2.WaitForRequest();
  656. EXPECT_EQ(custom_ua2, response_2.http_request()->headers.at(
  657. net::HttpRequestHeaders::kUserAgent));
  658. }
  659. // Verifies changing the user agent doesn't bleed through to next navigation.
  660. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, UserAgentDoesntCarryThrough2) {
  661. net::test_server::ControllableHttpResponse response_1(embedded_test_server(),
  662. "", true);
  663. net::test_server::ControllableHttpResponse response_2(embedded_test_server(),
  664. "", true);
  665. ASSERT_TRUE(embedded_test_server()->Start());
  666. const std::string custom_ua = "my ua1";
  667. NavigationObserverImpl observer(GetNavigationController());
  668. observer.SetStartedCallback(
  669. base::BindLambdaForTesting([&](Navigation* navigation) {
  670. navigation->SetUserAgentString(custom_ua);
  671. }));
  672. shell()->LoadURL(embedded_test_server()->GetURL("/simple_page.html"));
  673. response_1.WaitForRequest();
  674. EXPECT_EQ(custom_ua, response_1.http_request()->headers.at(
  675. net::HttpRequestHeaders::kUserAgent));
  676. // Before the request is done, start another navigation.
  677. observer.SetStartedCallback(base::DoNothing());
  678. shell()->LoadURL(embedded_test_server()->GetURL("/simple_page2.html"));
  679. response_2.WaitForRequest();
  680. EXPECT_NE(custom_ua, response_2.http_request()->headers.at(
  681. net::HttpRequestHeaders::kUserAgent));
  682. EXPECT_FALSE(response_2.http_request()
  683. ->headers.at(net::HttpRequestHeaders::kUserAgent)
  684. .empty());
  685. }
  686. // Verifies changing the user-agent applies to child resources, such as an
  687. // <img>.
  688. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
  689. UserAgentAppliesToChildResources) {
  690. net::test_server::ControllableHttpResponse response_1(embedded_test_server(),
  691. "", true);
  692. net::test_server::ControllableHttpResponse response_2(embedded_test_server(),
  693. "", true);
  694. ASSERT_TRUE(embedded_test_server()->Start());
  695. const std::string custom_ua = "custom-ua";
  696. NavigationObserverImpl observer(GetNavigationController());
  697. observer.SetStartedCallback(
  698. base::BindLambdaForTesting([&](Navigation* navigation) {
  699. navigation->SetUserAgentString(custom_ua);
  700. }));
  701. shell()->LoadURL(embedded_test_server()->GetURL("/foo.html"));
  702. response_1.WaitForRequest();
  703. response_1.Send(net::HTTP_OK, "text/html", "<img src=\"image.png\">");
  704. response_1.Done();
  705. EXPECT_EQ(custom_ua, response_1.http_request()->headers.at(
  706. net::HttpRequestHeaders::kUserAgent));
  707. observer.SetStartedCallback(base::DoNothing());
  708. response_2.WaitForRequest();
  709. EXPECT_EQ(custom_ua, response_2.http_request()->headers.at(
  710. net::HttpRequestHeaders::kUserAgent));
  711. }
  712. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
  713. SetUserAgentStringRendererInitiated) {
  714. net::test_server::ControllableHttpResponse response_1(embedded_test_server(),
  715. "", true);
  716. net::test_server::ControllableHttpResponse response_2(embedded_test_server(),
  717. "", true);
  718. ASSERT_TRUE(embedded_test_server()->Start());
  719. OneShotNavigationObserver load_observer(shell());
  720. NavigationObserverImpl observer(GetNavigationController());
  721. shell()->LoadURL(embedded_test_server()->GetURL("/simple_page.html"));
  722. response_1.WaitForRequest();
  723. response_1.Send(net::HTTP_OK, "text/html", "<html>");
  724. response_1.Done();
  725. load_observer.WaitForNavigation();
  726. const std::string custom_ua = "custom-ua";
  727. observer.SetStartedCallback(
  728. base::BindLambdaForTesting([&](Navigation* navigation) {
  729. navigation->SetUserAgentString(custom_ua);
  730. }));
  731. const GURL target_url = embedded_test_server()->GetURL("/foo.html");
  732. shell()->tab()->ExecuteScript(
  733. u"location.href='" + base::ASCIIToUTF16(target_url.spec()) + u"';", false,
  734. base::DoNothing());
  735. response_2.WaitForRequest();
  736. // |custom_ua| should be present in the renderer initiated navigation.
  737. ASSERT_TRUE(base::Contains(response_2.http_request()->headers,
  738. net::HttpRequestHeaders::kUserAgent));
  739. const std::string new_ua = response_2.http_request()->headers.at(
  740. net::HttpRequestHeaders::kUserAgent);
  741. EXPECT_EQ(custom_ua, new_ua);
  742. }
  743. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, AutoPlayDefault) {
  744. ASSERT_TRUE(embedded_test_server()->Start());
  745. GURL url(embedded_test_server()->GetURL("/autoplay.html"));
  746. auto* tab = static_cast<TabImpl*>(shell()->tab());
  747. NavigateAndWaitForCompletion(url, tab);
  748. auto* web_contents = tab->web_contents();
  749. bool playing = false;
  750. // There's no notification to watch that would signal video wasn't autoplayed,
  751. // so instead check once through javascript.
  752. EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
  753. web_contents,
  754. "window.domAutomationController.send(!document.getElementById('vid')."
  755. "paused)",
  756. &playing));
  757. ASSERT_FALSE(playing);
  758. }
  759. namespace {
  760. class WaitForMediaPlaying : public content::WebContentsObserver {
  761. public:
  762. explicit WaitForMediaPlaying(content::WebContents* web_contents)
  763. : WebContentsObserver(web_contents) {}
  764. WaitForMediaPlaying(const WaitForMediaPlaying&) = delete;
  765. WaitForMediaPlaying& operator=(const WaitForMediaPlaying&) = delete;
  766. // WebContentsObserver override.
  767. void MediaStartedPlaying(const MediaPlayerInfo& info,
  768. const content::MediaPlayerId&) final {
  769. run_loop_.Quit();
  770. CHECK(info.has_audio);
  771. CHECK(info.has_video);
  772. }
  773. void Wait() { run_loop_.Run(); }
  774. private:
  775. base::RunLoop run_loop_;
  776. };
  777. } // namespace
  778. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, AutoPlayEnabled) {
  779. ASSERT_TRUE(embedded_test_server()->Start());
  780. GURL url(embedded_test_server()->GetURL("/autoplay.html"));
  781. NavigationController::NavigateParams params;
  782. params.enable_auto_play = true;
  783. GetNavigationController()->Navigate(url, params);
  784. auto* tab = static_cast<TabImpl*>(shell()->tab());
  785. WaitForMediaPlaying wait_for_media(tab->web_contents());
  786. wait_for_media.Wait();
  787. }
  788. class NavigationBrowserTest2 : public NavigationBrowserTest {
  789. public:
  790. void SetUp() override {
  791. // HTTPS server only serves a valid cert for localhost, so this is needed to
  792. // load pages from "www.google.com" without an interstitial.
  793. base::CommandLine::ForCurrentProcess()->AppendSwitch(
  794. "ignore-certificate-errors");
  795. NavigationBrowserTest::SetUp();
  796. }
  797. void SetUpOnMainThread() override {
  798. NavigationBrowserTest::SetUpOnMainThread();
  799. https_server_ = std::make_unique<net::EmbeddedTestServer>(
  800. net::EmbeddedTestServer::TYPE_HTTPS);
  801. // The test makes requests to google.com which we want to redirect to the
  802. // test server.
  803. host_resolver()->AddRule("*", "127.0.0.1");
  804. // Forces variations code to set the header.
  805. auto* variations_provider =
  806. variations::VariationsIdsProvider::GetInstance();
  807. variations_provider->ForceVariationIds({"12", "456", "t789"}, "");
  808. }
  809. net::EmbeddedTestServer* https_server() { return https_server_.get(); }
  810. private:
  811. std::unique_ptr<net::EmbeddedTestServer> https_server_;
  812. };
  813. // This test verifies the embedder can replace the X-Client-Data header that
  814. // is also set by //components/variations.
  815. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest2, ReplaceXClientDataHeader) {
  816. std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
  817. std::string last_header_value;
  818. auto main_task_runner = base::SequencedTaskRunnerHandle::Get();
  819. https_server()->RegisterRequestHandler(base::BindLambdaForTesting(
  820. [&, main_task_runner](const net::test_server::HttpRequest& request)
  821. -> std::unique_ptr<net::test_server::HttpResponse> {
  822. auto iter = request.headers.find(variations::kClientDataHeader);
  823. if (iter != request.headers.end()) {
  824. main_task_runner->PostTask(
  825. FROM_HERE, base::BindOnce(base::BindLambdaForTesting(
  826. [&](const std::string& value) {
  827. last_header_value = value;
  828. run_loop->Quit();
  829. }),
  830. iter->second));
  831. }
  832. return std::make_unique<net::test_server::BasicHttpResponse>();
  833. }));
  834. ASSERT_TRUE(https_server()->Start());
  835. // Verify the header is set by default.
  836. const GURL url = https_server()->GetURL("www.google.com", "/");
  837. shell()->LoadURL(url);
  838. run_loop->Run();
  839. EXPECT_FALSE(last_header_value.empty());
  840. // Repeat, but clobber the header when navigating.
  841. const std::string header_value = "value";
  842. EXPECT_NE(last_header_value, header_value);
  843. last_header_value.clear();
  844. run_loop = std::make_unique<base::RunLoop>();
  845. NavigationObserverImpl observer(GetNavigationController());
  846. observer.SetStartedCallback(
  847. base::BindLambdaForTesting([&](Navigation* navigation) {
  848. navigation->SetRequestHeader(variations::kClientDataHeader,
  849. header_value);
  850. }));
  851. shell()->LoadURL(https_server()->GetURL("www.google.com", "/foo"));
  852. run_loop->Run();
  853. EXPECT_EQ(header_value, last_header_value);
  854. }
  855. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest2,
  856. SetXClientDataHeaderCarriesThroughToRedirect) {
  857. std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
  858. std::string last_header_value;
  859. bool should_redirect = true;
  860. auto main_task_runner = base::SequencedTaskRunnerHandle::Get();
  861. https_server()->RegisterRequestHandler(base::BindLambdaForTesting(
  862. [&, main_task_runner](const net::test_server::HttpRequest& request)
  863. -> std::unique_ptr<net::test_server::HttpResponse> {
  864. auto response = std::make_unique<net::test_server::BasicHttpResponse>();
  865. if (should_redirect) {
  866. should_redirect = false;
  867. response->set_code(net::HTTP_MOVED_PERMANENTLY);
  868. response->AddCustomHeader(
  869. "Location",
  870. https_server()->GetURL("www.google.com", "/redirect").spec());
  871. } else {
  872. auto iter = request.headers.find(variations::kClientDataHeader);
  873. main_task_runner->PostTask(
  874. FROM_HERE, base::BindOnce(base::BindLambdaForTesting(
  875. [&](const std::string& value) {
  876. last_header_value = value;
  877. run_loop->Quit();
  878. }),
  879. iter->second));
  880. }
  881. return response;
  882. }));
  883. ASSERT_TRUE(https_server()->Start());
  884. const std::string header_value = "value";
  885. run_loop = std::make_unique<base::RunLoop>();
  886. NavigationObserverImpl observer(GetNavigationController());
  887. observer.SetStartedCallback(
  888. base::BindLambdaForTesting([&](Navigation* navigation) {
  889. navigation->SetRequestHeader(variations::kClientDataHeader,
  890. header_value);
  891. }));
  892. shell()->LoadURL(https_server()->GetURL("www.google.com", "/foo"));
  893. run_loop->Run();
  894. EXPECT_EQ(header_value, last_header_value);
  895. }
  896. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest2, SetXClientDataHeaderInRedirect) {
  897. std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
  898. std::string last_header_value;
  899. bool should_redirect = true;
  900. auto main_task_runner = base::SequencedTaskRunnerHandle::Get();
  901. https_server()->RegisterRequestHandler(base::BindLambdaForTesting(
  902. [&, main_task_runner](const net::test_server::HttpRequest& request)
  903. -> std::unique_ptr<net::test_server::HttpResponse> {
  904. auto response = std::make_unique<net::test_server::BasicHttpResponse>();
  905. if (should_redirect) {
  906. should_redirect = false;
  907. response->set_code(net::HTTP_MOVED_PERMANENTLY);
  908. response->AddCustomHeader(
  909. "Location",
  910. https_server()->GetURL("www.google.com", "/redirect").spec());
  911. } else {
  912. auto iter = request.headers.find(variations::kClientDataHeader);
  913. main_task_runner->PostTask(
  914. FROM_HERE, base::BindOnce(base::BindLambdaForTesting(
  915. [&](const std::string& value) {
  916. last_header_value = value;
  917. run_loop->Quit();
  918. }),
  919. iter->second));
  920. }
  921. return response;
  922. }));
  923. ASSERT_TRUE(https_server()->Start());
  924. const std::string header_value = "value";
  925. NavigationObserverImpl observer(GetNavigationController());
  926. observer.SetRedirectedCallback(
  927. base::BindLambdaForTesting([&](Navigation* navigation) {
  928. navigation->SetRequestHeader(variations::kClientDataHeader,
  929. header_value);
  930. }));
  931. shell()->LoadURL(https_server()->GetURL("www.google.com", "/foo"));
  932. run_loop->Run();
  933. EXPECT_EQ(header_value, last_header_value);
  934. }
  935. #if BUILDFLAG(IS_ANDROID)
  936. // Verifies setting the 'referer' to an android-app url works.
  937. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, AndroidAppReferer) {
  938. net::test_server::ControllableHttpResponse response(embedded_test_server(),
  939. "", true);
  940. ASSERT_TRUE(embedded_test_server()->Start());
  941. const std::string header_name = "Referer";
  942. const std::string header_value = "android-app://google.com/";
  943. NavigationObserverImpl observer(GetNavigationController());
  944. observer.SetStartedCallback(
  945. base::BindLambdaForTesting([&](Navigation* navigation) {
  946. navigation->SetRequestHeader(header_name, header_value);
  947. }));
  948. shell()->LoadURL(embedded_test_server()->GetURL("/simple_page.html"));
  949. response.WaitForRequest();
  950. // Verify 'referer' matches expected value.
  951. EXPECT_EQ(header_value, response.http_request()->headers.at(header_name));
  952. }
  953. #endif
  954. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
  955. OnPageLanguageDeterminedCallback) {
  956. ASSERT_TRUE(embedded_test_server()->Start());
  957. NavigationController* controller = shell()->tab()->GetNavigationController();
  958. NavigationObserverImpl observer(controller);
  959. Page* committed_page = nullptr;
  960. Page* page_with_language_determined = nullptr;
  961. std::string determined_language = "";
  962. base::RunLoop navigation_run_loop1;
  963. base::RunLoop page_language_determination_run_loop1;
  964. base::RunLoop* navigation_run_loop = &navigation_run_loop1;
  965. base::RunLoop* page_language_determination_run_loop =
  966. &page_language_determination_run_loop1;
  967. observer.SetCompletedClosure(
  968. base::BindLambdaForTesting([&](Navigation* navigation) {
  969. committed_page = navigation->GetPage();
  970. navigation_run_loop->Quit();
  971. }));
  972. observer.SetOnPageLanguageDeterminedCallback(
  973. base::BindLambdaForTesting([&](Page* page, std::string language) {
  974. page_with_language_determined = page;
  975. determined_language = language;
  976. page_language_determination_run_loop->Quit();
  977. }));
  978. // Navigate to a page in English.
  979. controller->Navigate(embedded_test_server()->GetURL("/english_page.html"));
  980. navigation_run_loop1.Run();
  981. EXPECT_TRUE(committed_page);
  982. // Verify that the language determined event fires as expected.
  983. page_language_determination_run_loop1.Run();
  984. EXPECT_EQ(committed_page, page_with_language_determined);
  985. EXPECT_EQ("en", determined_language);
  986. // Now navigate to a page in French.
  987. committed_page = nullptr;
  988. page_with_language_determined = nullptr;
  989. base::RunLoop navigation_run_loop2;
  990. base::RunLoop page_language_determination_run_loop2;
  991. navigation_run_loop = &navigation_run_loop2;
  992. page_language_determination_run_loop = &page_language_determination_run_loop2;
  993. controller->Navigate(embedded_test_server()->GetURL("/french_page.html"));
  994. navigation_run_loop2.Run();
  995. EXPECT_TRUE(committed_page);
  996. // Verify that the language determined event fires as expected.
  997. page_language_determination_run_loop2.Run();
  998. EXPECT_EQ(committed_page, page_with_language_determined);
  999. EXPECT_EQ("fr", determined_language);
  1000. }
  1001. // Verifies that closing a tab when a navigation is waiting for a response
  1002. // causes the navigation to be marked as failed to the embedder.
  1003. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
  1004. CloseTabWithNavigationWaitingForResponse) {
  1005. net::test_server::ControllableHttpResponse response(embedded_test_server(),
  1006. "", true);
  1007. ASSERT_TRUE(embedded_test_server()->Start());
  1008. GURL url = embedded_test_server()->GetURL("/initial_url.html");
  1009. base::RunLoop run_loop;
  1010. Navigation* ongoing_navigation = nullptr;
  1011. auto observer =
  1012. std::make_unique<NavigationObserverImpl>(GetNavigationController());
  1013. observer->SetStartedCallback(base::BindLambdaForTesting(
  1014. [&](Navigation* navigation) { ongoing_navigation = navigation; }));
  1015. observer->SetFailedCallback(
  1016. base::BindLambdaForTesting([&](Navigation* navigation) {
  1017. EXPECT_EQ(url, navigation->GetURL());
  1018. EXPECT_EQ(NavigationState::kFailed, navigation->GetState());
  1019. run_loop.Quit();
  1020. // The NavigationControllerImpl that |observer| is observing will
  1021. // be destroyed before control returns to the test, so destroy
  1022. // |observer| now to avoid UaF.
  1023. observer.reset();
  1024. }));
  1025. shell()->LoadURL(url);
  1026. response.WaitForRequest();
  1027. EXPECT_EQ(NavigationState::kWaitingResponse, ongoing_navigation->GetState());
  1028. shell()->browser()->DestroyTab(shell()->tab());
  1029. run_loop.Run();
  1030. }
  1031. // Verifies that closing a tab when a navigation is in the middle of receiving a
  1032. // response causes the navigation to be marked as failed to the embedder.
  1033. IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
  1034. CloseTabWithNavigationReceivingBytes) {
  1035. net::test_server::ControllableHttpResponse response(embedded_test_server(),
  1036. "", true);
  1037. ASSERT_TRUE(embedded_test_server()->Start());
  1038. GURL url = embedded_test_server()->GetURL("/initial_url.html");
  1039. base::RunLoop run_loop;
  1040. Navigation* ongoing_navigation = nullptr;
  1041. auto observer =
  1042. std::make_unique<NavigationObserverImpl>(GetNavigationController());
  1043. observer->SetStartedCallback(base::BindLambdaForTesting(
  1044. [&](Navigation* navigation) { ongoing_navigation = navigation; }));
  1045. observer->SetFailedCallback(
  1046. base::BindLambdaForTesting([&](Navigation* navigation) {
  1047. EXPECT_EQ(url, navigation->GetURL());
  1048. EXPECT_EQ(NavigationState::kFailed, navigation->GetState());
  1049. run_loop.Quit();
  1050. // The NavigationControllerImpl that |observer| is observing will
  1051. // be destroyed before control returns to the test, so destroy
  1052. // |observer| now to avoid UaF.
  1053. observer.reset();
  1054. }));
  1055. auto* tab = static_cast<TabImpl*>(shell()->tab());
  1056. auto wait_for_response_start =
  1057. std::make_unique<content::TestNavigationManager>(tab->web_contents(),
  1058. url);
  1059. shell()->LoadURL(url);
  1060. // Wait until request is ready to start.
  1061. EXPECT_TRUE(wait_for_response_start->WaitForRequestStart());
  1062. // Start the request.
  1063. wait_for_response_start->ResumeNavigation();
  1064. // Wait for the request to arrive to ControllableHttpResponse.
  1065. response.WaitForRequest();
  1066. response.Send(net::HTTP_OK, "text/html", "<html>");
  1067. ASSERT_TRUE(wait_for_response_start->WaitForResponse());
  1068. EXPECT_EQ(NavigationState::kReceivingBytes, ongoing_navigation->GetState());
  1069. // Destroy |wait_for_response_start| before we indirectly destroy the
  1070. // WebContents it's observing.
  1071. wait_for_response_start.reset();
  1072. shell()->browser()->DestroyTab(tab);
  1073. run_loop.Run();
  1074. }
  1075. } // namespace weblayer