popup_blocker_browsertest.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. // Copyright 2020 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 "base/memory/raw_ptr.h"
  5. #include "base/strings/stringprintf.h"
  6. #include "build/build_config.h"
  7. #include "components/blocked_content/popup_blocker_tab_helper.h"
  8. #include "third_party/blink/public/common/switches.h"
  9. #include "ui/base/page_transition_types.h"
  10. #include "ui/base/window_open_disposition.h"
  11. #include "weblayer/browser/browser_impl.h"
  12. #include "weblayer/browser/host_content_settings_map_factory.h"
  13. #include "weblayer/browser/profile_impl.h"
  14. #include "weblayer/browser/tab_impl.h"
  15. #include "weblayer/public/browser.h"
  16. #include "weblayer/public/browser_observer.h"
  17. #include "weblayer/public/navigation_controller.h"
  18. #include "weblayer/public/new_tab_delegate.h"
  19. #include "weblayer/shell/browser/shell.h"
  20. #include "weblayer/test/test_navigation_observer.h"
  21. #include "weblayer/test/weblayer_browser_test.h"
  22. #include "weblayer/test/weblayer_browser_test_utils.h"
  23. namespace weblayer {
  24. class PopupBlockerBrowserTest : public WebLayerBrowserTest,
  25. public NewTabDelegate,
  26. public BrowserObserver {
  27. public:
  28. // WebLayerBrowserTest:
  29. void SetUpOnMainThread() override {
  30. ASSERT_TRUE(embedded_test_server()->Start());
  31. original_tab_ = shell()->tab();
  32. #if !BUILDFLAG(IS_ANDROID)
  33. // Android does this in Java.
  34. original_tab_->SetNewTabDelegate(this);
  35. #endif
  36. shell()->browser()->AddObserver(this);
  37. NavigateAndWaitForCompletion(embedded_test_server()->GetURL("/echo"),
  38. original_tab_);
  39. }
  40. void TearDownOnMainThread() override {
  41. shell()->browser()->RemoveObserver(this);
  42. }
  43. void SetUpCommandLine(base::CommandLine* command_line) override {
  44. WebLayerBrowserTest::SetUpCommandLine(command_line);
  45. // Some bots are flaky due to slower loading interacting with
  46. // deferred commits.
  47. command_line->AppendSwitch(blink::switches::kAllowPreCommitInput);
  48. }
  49. // NewTabDelegate:
  50. void OnNewTab(Tab* new_tab, NewTabType type) override {}
  51. // BrowserObserver:
  52. void OnTabAdded(Tab* tab) override {
  53. new_tab_ = tab;
  54. if (new_tab_run_loop_)
  55. new_tab_run_loop_->Quit();
  56. }
  57. void OnTabRemoved(Tab* tab, bool active_tab_changed) override {
  58. ASSERT_EQ(tab, new_tab_);
  59. new_tab_ = nullptr;
  60. if (close_tab_run_loop_)
  61. close_tab_run_loop_->Quit();
  62. }
  63. size_t GetBlockedPopupCount() {
  64. return blocked_content::PopupBlockerTabHelper::FromWebContents(
  65. GetWebContents(original_tab_))
  66. ->GetBlockedPopupsCount();
  67. }
  68. content::WebContents* GetWebContents(Tab* tab) {
  69. return static_cast<TabImpl*>(tab)->web_contents();
  70. }
  71. Tab* WaitForNewTab() {
  72. if (!new_tab_) {
  73. new_tab_run_loop_ = std::make_unique<base::RunLoop>();
  74. new_tab_run_loop_->Run();
  75. new_tab_run_loop_ = nullptr;
  76. }
  77. return new_tab_;
  78. }
  79. void WaitForCloseTab() {
  80. if (new_tab_) {
  81. close_tab_run_loop_ = std::make_unique<base::RunLoop>();
  82. close_tab_run_loop_->Run();
  83. close_tab_run_loop_ = nullptr;
  84. }
  85. ASSERT_FALSE(new_tab_);
  86. }
  87. void ExpectTabURL(Tab* tab, const GURL& url) {
  88. if (tab->GetNavigationController()->GetNavigationListSize() > 0) {
  89. EXPECT_EQ(tab->GetNavigationController()->GetNavigationEntryDisplayURL(0),
  90. url);
  91. } else {
  92. TestNavigationObserver(
  93. url, TestNavigationObserver::NavigationEvent::kCompletion, tab)
  94. .Wait();
  95. }
  96. }
  97. Tab* ShowPopup(const GURL& url) {
  98. auto* popup_blocker =
  99. blocked_content::PopupBlockerTabHelper::FromWebContents(
  100. GetWebContents(original_tab_));
  101. popup_blocker->ShowBlockedPopup(
  102. popup_blocker->GetBlockedPopupRequests().begin()->first,
  103. WindowOpenDisposition::NEW_FOREGROUND_TAB);
  104. Tab* new_tab = WaitForNewTab();
  105. ExpectTabURL(new_tab, url);
  106. EXPECT_EQ(GetBlockedPopupCount(), 0u);
  107. return new_tab;
  108. }
  109. Tab* original_tab() { return original_tab_; }
  110. private:
  111. std::unique_ptr<base::RunLoop> new_tab_run_loop_;
  112. std::unique_ptr<base::RunLoop> close_tab_run_loop_;
  113. raw_ptr<Tab> original_tab_ = nullptr;
  114. raw_ptr<Tab> new_tab_ = nullptr;
  115. };
  116. IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest, BlocksPopup) {
  117. ExecuteScript(original_tab(), "window.open('https://google.com')", true);
  118. EXPECT_EQ(GetBlockedPopupCount(), 1u);
  119. }
  120. IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest, BlocksMultiplePopups) {
  121. ExecuteScript(original_tab(), "window.open('https://google.com')", true);
  122. ExecuteScript(original_tab(), "window.open('https://google.com')", true);
  123. EXPECT_EQ(GetBlockedPopupCount(), 2u);
  124. }
  125. IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest, DoesNotBlockUserGesture) {
  126. GURL popup_url = embedded_test_server()->GetURL("/echo?popup");
  127. ExecuteScriptWithUserGesture(
  128. original_tab(),
  129. base::StringPrintf("window.open('%s')", popup_url.spec().c_str()));
  130. Tab* new_tab = WaitForNewTab();
  131. ExpectTabURL(new_tab, popup_url);
  132. EXPECT_EQ(GetBlockedPopupCount(), 0u);
  133. }
  134. IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest, OpensBlockedPopup) {
  135. GURL popup_url = embedded_test_server()->GetURL("/echo?popup");
  136. ExecuteScript(
  137. original_tab(),
  138. base::StringPrintf("window.open('%s')", popup_url.spec().c_str()), true);
  139. EXPECT_EQ(GetBlockedPopupCount(), 1u);
  140. Tab* new_tab = ShowPopup(popup_url);
  141. // Blocked popups should no longer have the opener set to match Chrome
  142. // behavior.
  143. EXPECT_FALSE(GetWebContents(new_tab)->HasOpener());
  144. // Make sure we can cleanly close the popup, and there's no crash.
  145. ExecuteScriptWithUserGesture(new_tab, "window.close()");
  146. WaitForCloseTab();
  147. }
  148. IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest,
  149. AllowsPopupThroughContentSettingException) {
  150. GURL popup_url = embedded_test_server()->GetURL("/echo?popup");
  151. HostContentSettingsMapFactory::GetForBrowserContext(
  152. GetWebContents(original_tab())->GetBrowserContext())
  153. ->SetContentSettingDefaultScope(popup_url, GURL(),
  154. ContentSettingsType::POPUPS,
  155. CONTENT_SETTING_ALLOW);
  156. ExecuteScript(
  157. original_tab(),
  158. base::StringPrintf("window.open('%s')", popup_url.spec().c_str()), true);
  159. Tab* new_tab = WaitForNewTab();
  160. ExpectTabURL(new_tab, popup_url);
  161. EXPECT_EQ(GetBlockedPopupCount(), 0u);
  162. }
  163. IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest,
  164. AllowsPopupThroughContentSettingDefaultValue) {
  165. GURL popup_url = embedded_test_server()->GetURL("/echo?popup");
  166. HostContentSettingsMapFactory::GetForBrowserContext(
  167. GetWebContents(original_tab())->GetBrowserContext())
  168. ->SetDefaultContentSetting(ContentSettingsType::POPUPS,
  169. CONTENT_SETTING_ALLOW);
  170. ExecuteScript(
  171. original_tab(),
  172. base::StringPrintf("window.open('%s')", popup_url.spec().c_str()), true);
  173. Tab* new_tab = WaitForNewTab();
  174. ExpectTabURL(new_tab, popup_url);
  175. EXPECT_EQ(GetBlockedPopupCount(), 0u);
  176. }
  177. IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest,
  178. BlockPopupThroughContentSettingException) {
  179. GURL popup_url = embedded_test_server()->GetURL("/echo?popup");
  180. HostContentSettingsMapFactory::GetForBrowserContext(
  181. GetWebContents(original_tab())->GetBrowserContext())
  182. ->SetDefaultContentSetting(ContentSettingsType::POPUPS,
  183. CONTENT_SETTING_ALLOW);
  184. HostContentSettingsMapFactory::GetForBrowserContext(
  185. GetWebContents(original_tab())->GetBrowserContext())
  186. ->SetContentSettingDefaultScope(popup_url, GURL(),
  187. ContentSettingsType::POPUPS,
  188. CONTENT_SETTING_BLOCK);
  189. ExecuteScript(
  190. original_tab(),
  191. base::StringPrintf("window.open('%s')", popup_url.spec().c_str()), true);
  192. EXPECT_EQ(GetBlockedPopupCount(), 1u);
  193. }
  194. IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest,
  195. BlocksAndOpensPopupFromOpenURL) {
  196. GURL popup_url = embedded_test_server()->GetURL("/echo?popup");
  197. content::OpenURLParams params(popup_url, content::Referrer(),
  198. WindowOpenDisposition::NEW_FOREGROUND_TAB,
  199. ui::PAGE_TRANSITION_LINK, true);
  200. params.initiator_origin = url::Origin::Create(popup_url);
  201. GetWebContents(original_tab())->OpenURL(params);
  202. EXPECT_EQ(GetBlockedPopupCount(), 1u);
  203. ShowPopup(popup_url);
  204. }
  205. IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest,
  206. DoesNotOpenPopupWithoutNewTabDelegate) {
  207. NewTabDelegate* old_delegate =
  208. static_cast<TabImpl*>(original_tab())->new_tab_delegate();
  209. original_tab()->SetNewTabDelegate(nullptr);
  210. GURL popup_url = embedded_test_server()->GetURL("/echo?popup");
  211. ExecuteScriptWithUserGesture(
  212. original_tab(),
  213. base::StringPrintf("window.open('%s')", popup_url.spec().c_str()));
  214. EXPECT_EQ(GetBlockedPopupCount(), 0u);
  215. // Navigate the original tab, then make sure we still only have a single tab.
  216. NavigateAndWaitForCompletion(embedded_test_server()->GetURL("/echo"),
  217. original_tab());
  218. EXPECT_EQ(shell()->browser()->GetTabs().size(), 1u);
  219. // Restore the old delegate to make sure it is cleaned up on Android.
  220. original_tab()->SetNewTabDelegate(old_delegate);
  221. }
  222. IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest,
  223. DoesNotOpenBlockedPopupWithoutNewTabDelegate) {
  224. NewTabDelegate* old_delegate =
  225. static_cast<TabImpl*>(original_tab())->new_tab_delegate();
  226. original_tab()->SetNewTabDelegate(nullptr);
  227. GURL popup_url = embedded_test_server()->GetURL("/echo?popup");
  228. ExecuteScript(
  229. original_tab(),
  230. base::StringPrintf("window.open('%s')", popup_url.spec().c_str()), true);
  231. EXPECT_EQ(GetBlockedPopupCount(), 0u);
  232. // Navigate the original tab, then make sure we still only have a single tab.
  233. NavigateAndWaitForCompletion(embedded_test_server()->GetURL("/echo"),
  234. original_tab());
  235. EXPECT_EQ(shell()->browser()->GetTabs().size(), 1u);
  236. // Restore the old delegate to make sure it is cleaned up on Android.
  237. original_tab()->SetNewTabDelegate(old_delegate);
  238. }
  239. } // namespace weblayer