Index: chrome/browser/subresource_filter/subresource_filter_browsertest.cc |
diff --git a/chrome/browser/subresource_filter/subresource_filter_browsertest.cc b/chrome/browser/subresource_filter/subresource_filter_browsertest.cc |
index c2941ea73ee82bb0d4c07dcc4f9f28691c13e61c..51fde64e3adb1db8c4631fee874a634d48528538 100644 |
--- a/chrome/browser/subresource_filter/subresource_filter_browsertest.cc |
+++ b/chrome/browser/subresource_filter/subresource_filter_browsertest.cc |
@@ -58,6 +58,7 @@ |
#include "content/public/browser/notification_types.h" |
#include "content/public/browser/render_frame_host.h" |
#include "content/public/browser/web_contents.h" |
+#include "content/public/common/browser_side_navigation_policy.h" |
#include "content/public/common/content_switches.h" |
#include "content/public/test/browser_test_utils.h" |
#include "content/public/test/test_navigation_observer.h" |
@@ -318,6 +319,24 @@ class SubresourceFilterBrowserTest : public InProcessBrowserTest { |
} |
} |
+ void ExpectFramesIncludedInLayout(const std::vector<const char*>& frame_names, |
+ const std::vector<bool>& expect_displayed) { |
+ const char kScript[] = |
+ "window.domAutomationController.send(" |
+ " document.getElementsByName(\"%s\")[0].clientWidth" |
+ ");"; |
+ |
+ ASSERT_EQ(expect_displayed.size(), frame_names.size()); |
+ for (size_t i = 0; i < frame_names.size(); ++i) { |
+ SCOPED_TRACE(frame_names[i]); |
+ int client_width = 0; |
+ EXPECT_TRUE(content::ExecuteScriptAndExtractInt( |
+ web_contents()->GetMainFrame(), |
+ base::StringPrintf(kScript, frame_names[i]), &client_width)); |
+ EXPECT_EQ(expect_displayed[i], !!client_width) << client_width; |
+ } |
+ } |
+ |
bool IsDynamicScriptElementLoaded(content::RenderFrameHost* rfh) { |
DCHECK(rfh); |
bool script_resource_was_loaded = false; |
@@ -336,9 +355,21 @@ class SubresourceFilterBrowserTest : public InProcessBrowserTest { |
} |
void NavigateFromRendererSide(const GURL& url) { |
+ content::TestNavigationObserver navigation_observer(web_contents(), 1); |
ASSERT_TRUE(content::ExecuteScript( |
web_contents()->GetMainFrame(), |
base::StringPrintf("window.location = \"%s\";", url.spec().c_str()))); |
+ navigation_observer.Wait(); |
+ } |
+ |
+ void NavigateFrame(const char* frame_name, const GURL& url) { |
+ content::TestNavigationObserver navigation_observer(web_contents(), 1); |
+ ASSERT_TRUE(content::ExecuteScript( |
+ web_contents()->GetMainFrame(), |
+ base::StringPrintf( |
+ "document.getElementsByName(\"%s\")[0].src = \"%s\";", frame_name, |
+ url.spec().c_str()))); |
+ navigation_observer.Wait(); |
} |
void SetRulesetToDisallowURLsWithPathSuffix(const std::string& suffix) { |
@@ -518,31 +549,71 @@ IN_PROC_BROWSER_TEST_F(SubresourceFilterBrowserTest, SubFrameActivation) { |
IN_PROC_BROWSER_TEST_F(SubresourceFilterBrowserTest, |
SubframeDocumentLoadFiltering) { |
+ base::HistogramTester histogram_tester; |
GURL url(GetTestUrl(kTestFrameSetPath)); |
ConfigureAsPhishingURL(url); |
- // Disallow all the subframes that end up loading included_script.js. |
- ASSERT_NO_FATAL_FAILURE( |
- SetRulesetToDisallowURLsWithPathSuffix("included_script.html")); |
- base::HistogramTester tester; |
+ // Disallow loading subframe documents that in turn would end up loading |
+ // included_script.js, unless the document is loaded from a whitelisted |
+ // domain. This enables the third part of this test disallowing a load only |
+ // after the first redirect. |
+ const char kWhitelistedDomain[] = "whitelisted.com"; |
+ proto::UrlRule rule = testing::CreateSuffixRule("included_script.html"); |
+ proto::UrlRule whitelist_rule = testing::CreateSuffixRule(kWhitelistedDomain); |
+ whitelist_rule.set_anchor_right(proto::ANCHOR_TYPE_NONE); |
+ whitelist_rule.set_semantics(proto::RULE_SEMANTICS_WHITELIST); |
+ ASSERT_NO_FATAL_FAILURE(SetRulesetWithRules({rule, whitelist_rule})); |
+ |
ui_test_utils::NavigateToURL(browser(), url); |
const std::vector<const char*> kSubframeNames{"one", "two", "three"}; |
- const std::vector<bool> kExpectScriptInFrameToLoad{false, true, false}; |
+ const std::vector<bool> kExpectOnlySecondSubframe{false, true, false}; |
ASSERT_NO_FATAL_FAILURE(ExpectParsedScriptElementLoadedStatusInFrames( |
- kSubframeNames, kExpectScriptInFrameToLoad)); |
+ kSubframeNames, kExpectOnlySecondSubframe)); |
+ ExpectFramesIncludedInLayout(kSubframeNames, kExpectOnlySecondSubframe); |
+ histogram_tester.ExpectBucketCount(kSubresourceFilterActionsHistogram, |
+ kActionUIShown, 1); |
+ |
+ // Now navigate the first subframe to an allowed URL and ensure that the load |
+ // successfully commits and the frame gets restored (no longer collapsed). |
+ GURL allowed_subdocument_url( |
+ GetTestUrl("subresource_filter/frame_with_allowed_script.html")); |
+ NavigateFrame(kSubframeNames[0], allowed_subdocument_url); |
+ |
+ const std::vector<bool> kExpectFirstAndSecondSubframe{true, true, false}; |
+ ASSERT_NO_FATAL_FAILURE(ExpectParsedScriptElementLoadedStatusInFrames( |
+ kSubframeNames, kExpectFirstAndSecondSubframe)); |
+ ExpectFramesIncludedInLayout(kSubframeNames, kExpectFirstAndSecondSubframe); |
+ |
+ // Navigate the first subframe to a document that does not load the probe JS. |
+ GURL allowed_empty_subdocument_url( |
+ GetTestUrl("subresource_filter/frame_with_no_subresources.html")); |
+ NavigateFrame(kSubframeNames[0], allowed_empty_subdocument_url); |
+ |
+ // Finally, navigate the first subframe to an allowed URL that redirects to a |
+ // disallowed URL, and verify that: |
+ // -- The navigation gets blocked and the frame collapsed (with PlzNavigate). |
+ // -- The navigation is cancelled, but the frame is not collapsed (without |
+ // PlzNavigate, where BLOCK_REQUEST_AND_COLLAPSE is not supported). |
+ GURL disallowed_subdocument_url( |
+ GetTestUrl("subresource_filter/frame_with_included_script.html")); |
+ GURL redirect_to_disallowed_subdocument_url(embedded_test_server()->GetURL( |
+ kWhitelistedDomain, |
+ "/server-redirect?" + disallowed_subdocument_url.spec())); |
+ NavigateFrame(kSubframeNames[0], redirect_to_disallowed_subdocument_url); |
- // The subframe navigations never commit. |
- for (size_t i = 0; i < kSubframeNames.size(); ++i) { |
- const char* subframe_name = kSubframeNames[i]; |
- bool expect_loaded = kExpectScriptInFrameToLoad[i]; |
- content::RenderFrameHost* frame = FindFrameByName(subframe_name); |
- if (!expect_loaded) |
- EXPECT_EQ(GURL(), frame->GetLastCommittedURL()); |
- } |
+ ASSERT_NO_FATAL_FAILURE(ExpectParsedScriptElementLoadedStatusInFrames( |
+ kSubframeNames, kExpectOnlySecondSubframe)); |
- tester.ExpectBucketCount(kSubresourceFilterActionsHistogram, kActionUIShown, |
- 1); |
+ content::RenderFrameHost* frame = FindFrameByName(kSubframeNames[0]); |
+ ASSERT_TRUE(frame); |
+ if (content::IsBrowserSideNavigationEnabled()) { |
+ EXPECT_EQ(disallowed_subdocument_url, frame->GetLastCommittedURL()); |
+ ExpectFramesIncludedInLayout(kSubframeNames, kExpectOnlySecondSubframe); |
+ } else { |
+ EXPECT_EQ(allowed_empty_subdocument_url, frame->GetLastCommittedURL()); |
+ ExpectFramesIncludedInLayout(kSubframeNames, kExpectFirstAndSecondSubframe); |
+ } |
} |
IN_PROC_BROWSER_TEST_F(SubresourceFilterBrowserTest, |