Commit 97ad28f7 authored by Justin Miron's avatar Justin Miron Committed by Commit Bot

Abusive Popups: Record UKM counting navigation redirects for popups.

This change introduces a new UKM for counting navigation redirects in
the pop up tracker. Redirects are commonly used for navigaing abusive
pop-ups to ad content from elements not tagged as ads by the ad
tagging framework. Using redirect counts as a new filter will help
us refine our abusive popup identification.

BUG=1044601

Change-Id: I68ad28a1b2965a8c1e844ec06eb42b487c6ef717
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2438669Reviewed-by: default avatarRobert Kaplow <rkaplow@chromium.org>
Reviewed-by: default avatarCharlie Harrison <csharrison@chromium.org>
Commit-Queue: Justin Miron <justinmiron@google.com>
Cr-Commit-Position: refs/heads/master@{#820261}
parent 557646fa
......@@ -55,6 +55,7 @@ const char kUkmWindowOpenDisposition[] = "WindowOpenDisposition";
const char kUkmNumActivationInteractions[] = "NumActivationInteractions";
const char kUkmNumGestureScrollBeginInteractions[] =
"NumGestureScrollBeginInteractions";
const char kUkmRedirectCount[] = "RedirectCount";
} // namespace
using UkmEntry = ukm::builders::Popup_Closed;
......@@ -570,3 +571,106 @@ IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest, PopupInWindow_IsWindowTrue) {
entry, kUkmWindowOpenDisposition,
static_cast<int>(WindowOpenDisposition::NEW_POPUP));
}
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,
PopupNoRedirect_RedirectCountZero) {
const GURL first_url = embedded_test_server()->GetURL("/title1.html");
ui_test_utils::NavigateToURL(browser(), first_url);
content::TestNavigationObserver navigation_observer(nullptr, 1);
navigation_observer.StartWatchingNewWebContents();
EXPECT_TRUE(content::ExecJs(
browser()->tab_strip_model()->GetActiveWebContents(),
"window.open('/title1.html', 'new_window', "
"'location=yes,height=570,width=520,scrollbars=yes,status=yes')"));
navigation_observer.Wait();
EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
Browser* created_browser = chrome::FindLastActive();
EXPECT_EQ(1, created_browser->tab_strip_model()->count());
content::WebContents* popup =
created_browser->tab_strip_model()->GetActiveWebContents();
EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(popup));
// Close the popup and check that the pop up did not redirect.
int active_index = created_browser->tab_strip_model()->active_index();
content::WebContentsDestroyedWatcher destroyed_watcher(popup);
created_browser->tab_strip_model()->CloseWebContentsAt(
active_index, TabStripModel::CLOSE_USER_GESTURE);
destroyed_watcher.Wait();
auto* entry = ExpectAndGetEntry(first_url);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmRedirectCount, 0);
}
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,
PopupRedirectsTwice_RedirectCountTwo) {
const GURL first_url = embedded_test_server()->GetURL("/title1.html");
ui_test_utils::NavigateToURL(browser(), first_url);
content::TestNavigationObserver navigation_observer(nullptr, 1);
navigation_observer.StartWatchingNewWebContents();
// Redirect the popup using /server-redirect twice.
EXPECT_TRUE(content::ExecJs(
browser()->tab_strip_model()->GetActiveWebContents(),
"window.open('/server-redirect?/server-redirect?/title1.html',"
"'new_window', 'location=yes,height=570,width=520,scrollbars=yes,"
"status=yes')"));
navigation_observer.Wait();
EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
Browser* created_browser = chrome::FindLastActive();
EXPECT_EQ(1, created_browser->tab_strip_model()->count());
content::WebContents* popup =
created_browser->tab_strip_model()->GetActiveWebContents();
EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(popup));
// Close the popup and check metric.
int active_index = created_browser->tab_strip_model()->active_index();
content::WebContentsDestroyedWatcher destroyed_watcher(popup);
created_browser->tab_strip_model()->CloseWebContentsAt(
active_index, TabStripModel::CLOSE_USER_GESTURE);
destroyed_watcher.Wait();
auto* entry = ExpectAndGetEntry(first_url);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmRedirectCount, 2);
}
IN_PROC_BROWSER_TEST_F(PopupTrackerBrowserTest,
PopupJavascriptRenavigation_RedirectCountZero) {
const GURL first_url = embedded_test_server()->GetURL("/title1.html");
ui_test_utils::NavigateToURL(browser(), first_url);
content::TestNavigationObserver navigation_observer(nullptr, 1);
navigation_observer.StartWatchingNewWebContents();
// Redirect the popup using /server-redirect twice.
EXPECT_TRUE(content::ExecJs(
browser()->tab_strip_model()->GetActiveWebContents(),
"var w = window.open('',"
"'new_window', 'location=yes,height=570,width=520,scrollbars=yes,"
"status=yes'); "
"w.location = '/title1.html'"));
navigation_observer.Wait();
EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
Browser* created_browser = chrome::FindLastActive();
EXPECT_EQ(1, created_browser->tab_strip_model()->count());
content::WebContents* popup =
created_browser->tab_strip_model()->GetActiveWebContents();
EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(popup));
// Close the popup and check metric.
int active_index = created_browser->tab_strip_model()->active_index();
content::WebContentsDestroyedWatcher destroyed_watcher(popup);
created_browser->tab_strip_model()->CloseWebContentsAt(
active_index, TabStripModel::CLOSE_USER_GESTURE);
destroyed_watcher.Wait();
auto* entry = ExpectAndGetEntry(first_url);
test_ukm_recorder_->ExpectEntryMetric(entry, kUkmRedirectCount, 0);
}
......@@ -102,6 +102,7 @@ void PopupTracker::WebContentsDestroyed() {
num_activation_events_, kMaxSubcatagoryInteractions))
.SetNumGestureScrollBeginInteractions(CappedUserInteractions(
num_gesture_scroll_begin_events_, kMaxSubcatagoryInteractions))
.SetRedirectCount(num_redirects_)
.Record(ukm::UkmRecorder::Get());
}
}
......@@ -113,6 +114,13 @@ void PopupTracker::DidFinishNavigation(
return;
}
if (navigation_handle->IsInMainFrame() && !first_navigation_committed_) {
first_navigation_committed_ = true;
// The last page in the redirect chain is the current page, the number of
// redirects is one less than the size of the chain.
num_redirects_ = navigation_handle->GetRedirectChain().size() - 1;
}
if (!first_load_visible_time_start_) {
first_load_visible_time_start_ =
visibility_tracker_.GetForegroundDuration();
......
......@@ -88,6 +88,10 @@ class PopupTracker : public content::WebContentsObserver,
int num_activation_events_ = 0;
int num_gesture_scroll_begin_events_ = 0;
// Number of redirects taken by the pop-up during navigation.
int num_redirects_ = 0;
bool first_navigation_committed_ = false;
// The id of the web contents that created the popup at the time of creation.
// SourceIds are permanent so it's okay to use at any point so long as it's
// not invalid.
......
......@@ -10257,6 +10257,13 @@ be describing additional metrics about the same event.
start, or raw key down event.
</summary>
</metric>
<metric name="RedirectCount">
<summary>
The number of redirects taken by the pop-up's initial navigation. This
does not include javascript navigations initiated by the opening document
for the pop-up.
</summary>
</metric>
<metric name="SafeBrowsingStatus" enum="PopupSafeBrowsingStatus">
<summary>
The site's safe browsing status if the pop-up's navigation commits.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment