blob: 1a09af8108053f658477b01be1cc9d3493878903 [file] [log] [blame]
// Copyright 2016 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 "base/strings/stringprintf.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/safe_browsing/safe_browsing_navigation_observer.h"
#include "chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.h"
#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/download_item.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/notification_service.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "url/gurl.h"
#include "url/url_canon.h"
namespace safe_browsing {
const char kSingleFrameTestURL[] =
"/safe_browsing/download_protection/navigation_observer/"
"navigation_observer_tests.html";
const char kMultiFrameTestURL[] =
"/safe_browsing/download_protection/navigation_observer/"
"navigation_observer_multi_frame_tests.html";
const char kRedirectURL[] =
"/safe_browsing/download_protection/navigation_observer/redirect.html";
const char kDownloadDataURL[] =
"data:application/octet-stream;base64,a2poYWxrc2hkbGtoYXNka2xoYXNsa2RoYWxra"
"GtoYWxza2hka2xzamFoZGxramhhc2xka2hhc2xrZGgKYXNrZGpoa2FzZGpoYWtzaGRrYXNoZGt"
"oYXNrZGhhc2tkaGthc2hka2Foc2RraGFrc2hka2FzaGRraGFzCmFza2pkaGFrc2hkbSxjbmtza"
"mFoZGtoYXNrZGhhc2tka2hrYXNkCjg3MzQ2ODEyNzQ2OGtqc2hka2FoZHNrZGhraApha3NqZGt"
"hc2Roa3NkaGthc2hka2FzaGtkaAohISomXkAqJl4qYWhpZGFzeWRpeWlhc1xcb1wKa2Fqc2Roa"
"2FzaGRrYXNoZGsKYWtzamRoc2tkaAplbmQK";
const char kIframeDirectDownloadURL[] =
"/safe_browsing/download_protection/navigation_observer/iframe.html";
const char kIframeRetargetingURL[] =
"/safe_browsing/download_protection/navigation_observer/"
"iframe_retargeting.html";
const char kDownloadItemURL[] = "/safe_browsing/download_protection/signed.exe";
// Test class to help create SafeBrowsingNavigationObservers for each
// WebContents before they are actually installed through AttachTabHelper.
class TestNavigationObserverManager
: public SafeBrowsingNavigationObserverManager {
public:
TestNavigationObserverManager() : SafeBrowsingNavigationObserverManager() {
registrar_.Add(this, chrome::NOTIFICATION_TAB_ADDED,
content::NotificationService::AllSources());
}
void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) override {
if (type == chrome::NOTIFICATION_TAB_ADDED) {
content::WebContents* dest_content =
content::Details<content::WebContents>(details).ptr();
DCHECK(dest_content);
observer_list_.push_back(
new SafeBrowsingNavigationObserver(dest_content, this));
DCHECK(observer_list_.back());
} else if (type == chrome::NOTIFICATION_RETARGETING) {
RecordRetargeting(details);
}
}
protected:
~TestNavigationObserverManager() override { observer_list_.clear(); }
private:
std::vector<SafeBrowsingNavigationObserver*> observer_list_;
};
class SBNavigationObserverBrowserTest : public InProcessBrowserTest {
public:
SBNavigationObserverBrowserTest() {}
void SetUpOnMainThread() override {
// Disable Safe Browsing service since it is irrelevant to this test.
browser()->profile()->GetPrefs()->SetBoolean(prefs::kSafeBrowsingEnabled,
false);
ASSERT_TRUE(embedded_test_server()->Start());
host_resolver()->AddRule("*", "127.0.0.1");
// Navigate to test page.
ui_test_utils::NavigateToURL(
browser(), embedded_test_server()->GetURL(kSingleFrameTestURL));
observer_manager_ = new TestNavigationObserverManager();
observer_ = new SafeBrowsingNavigationObserver(
browser()->tab_strip_model()->GetActiveWebContents(),
observer_manager_);
ASSERT_TRUE(observer_);
ASSERT_TRUE(InitialSetup());
}
bool InitialSetup() {
if (!browser())
return false;
if (!downloads_directory_.CreateUniqueTempDir())
return false;
// Set up default download path.
browser()->profile()->GetPrefs()->SetFilePath(
prefs::kDownloadDefaultDirectory, downloads_directory_.GetPath());
browser()->profile()->GetPrefs()->SetFilePath(
prefs::kSaveFileDefaultDirectory, downloads_directory_.GetPath());
browser()->profile()->GetPrefs()->SetBoolean(prefs::kPromptForDownload,
false);
content::DownloadManager* manager =
content::BrowserContext::GetDownloadManager(browser()->profile());
DownloadPrefs::FromDownloadManager(manager)->ResetAutoOpen();
manager->RemoveAllDownloads();
return true;
}
void TearDownOnMainThread() override { delete observer_; }
// Most test cases will trigger downloads, though we don't really care if
// download completed or not. So we cancel downloads as soon as we record
// all the navigation events we need.
void CancelDownloads() {
std::vector<content::DownloadItem*> download_items;
content::DownloadManager* manager =
content::BrowserContext::GetDownloadManager(browser()->profile());
manager->GetAllDownloads(&download_items);
for (auto item : download_items) {
if (!item->IsDone())
item->Cancel(true);
}
}
// This function needs javascript support, only works on
// navigation_observer_tests.html and
// navigation_observer_multi_frame_tests.html.
void ClickTestLink(const char* test_name,
int number_of_navigations) {
TabStripModel* tab_strip = browser()->tab_strip_model();
content::WebContents* current_web_contents =
tab_strip->GetActiveWebContents();
ASSERT_TRUE(content::WaitForLoadStop(current_web_contents));
content::TestNavigationObserver navigation_observer(
current_web_contents,
number_of_navigations);
navigation_observer.StartWatchingNewWebContents();
// Execute test.
std::string script = base::StringPrintf("clickLink('%s');", test_name);
ASSERT_TRUE(content::ExecuteScript(current_web_contents, script));
// Wait for navigations on current tab and new tab (if any) to finish.
navigation_observer.Wait();
navigation_observer.StopWatchingNewWebContents();
// Cancel unfinished download if any.
CancelDownloads();
}
void VerifyNavigationEvent(const GURL& expected_source_url,
const GURL& expected_source_main_frame_url,
const GURL& expected_original_request_url,
const GURL& expected_destination_url,
bool expected_is_user_initiated,
bool expected_has_committed,
bool expected_has_server_redirect,
const NavigationEvent& actual_nav_event) {
EXPECT_EQ(expected_source_url, actual_nav_event.source_url);
EXPECT_EQ(expected_source_main_frame_url,
actual_nav_event.source_main_frame_url);
EXPECT_EQ(expected_original_request_url,
actual_nav_event.original_request_url);
EXPECT_EQ(expected_destination_url, actual_nav_event.destination_url);
EXPECT_EQ(expected_is_user_initiated, actual_nav_event.is_user_initiated);
EXPECT_EQ(expected_has_committed, actual_nav_event.has_committed);
EXPECT_EQ(expected_has_server_redirect,
actual_nav_event.has_server_redirect);
}
void VerifyHostToIpMap() {
// Since all testing pages have the same host, there is only one entry in
// host_to_ip_map_.
SafeBrowsingNavigationObserverManager::HostToIpMap* actual_host_ip_map =
host_to_ip_map();
ASSERT_EQ(std::size_t(1), actual_host_ip_map->size());
auto ip_list =
actual_host_ip_map->at(embedded_test_server()->base_url().host());
ASSERT_EQ(std::size_t(1), ip_list.size());
EXPECT_EQ(embedded_test_server()->host_port_pair().host(),
ip_list.back().ip);
}
SafeBrowsingNavigationObserverManager::NavigationMap* navigation_map() {
return observer_manager_->navigation_map();
}
SafeBrowsingNavigationObserverManager::HostToIpMap* host_to_ip_map() {
return observer_manager_->host_to_ip_map();
}
protected:
SafeBrowsingNavigationObserverManager* observer_manager_;
SafeBrowsingNavigationObserver* observer_;
private:
base::ScopedTempDir downloads_directory_;
};
// Click on a link and start download on the same page.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest, DirectDownload) {
ClickTestLink("direct_download", 1);
GURL initial_url = embedded_test_server()->GetURL(kSingleFrameTestURL);
GURL download_url = embedded_test_server()->GetURL(kDownloadItemURL);
auto nav_map = navigation_map();
ASSERT_TRUE(nav_map);
ASSERT_EQ(std::size_t(1), nav_map->size());
ASSERT_EQ(std::size_t(1), nav_map->at(download_url).size());
// Since this test uses javascript to mimic clicking on a link (no actual user
// gesture), and DidGetUserInteraction() does not respond to ExecuteScript(),
// therefore is_user_initiated is false.
VerifyNavigationEvent(initial_url, // source_url
initial_url, // source_main_frame_url
download_url, // original_request_url
download_url, // destination_url
false, // is_user_initiated,
false, // has_committed
false, // has_server_redirect
nav_map->at(download_url).at(0));
VerifyHostToIpMap();
}
// Click on a link with rel="noreferrer" attribute, and start download on the
// same page.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
DirectDownloadNoReferrer) {
ClickTestLink("direct_download_noreferrer", 1);
GURL initial_url = embedded_test_server()->GetURL(kSingleFrameTestURL);
GURL download_url = embedded_test_server()->GetURL(kDownloadItemURL);
auto nav_map = navigation_map();
ASSERT_TRUE(nav_map);
ASSERT_EQ(std::size_t(1), nav_map->size());
ASSERT_EQ(std::size_t(1), nav_map->at(download_url).size());
VerifyNavigationEvent(initial_url, // source_url
initial_url, // source_main_frame_url
download_url, // original_request_url
download_url, // destination_url
false, // is_user_initiated,
false, // has_committed
false, // has_server_redirect
nav_map->at(download_url).at(0));
VerifyHostToIpMap();
}
// Click on a link with rel="noreferrer" attribute, and start download in a
// new tab using target=_blank.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
DirectDownloadNoReferrerTargetBlank) {
ClickTestLink("direct_download_noreferrer_target_blank", 1);
GURL initial_url = embedded_test_server()->GetURL(kSingleFrameTestURL);
GURL download_url = embedded_test_server()->GetURL(kDownloadItemURL);
auto nav_map = navigation_map();
ASSERT_TRUE(nav_map);
ASSERT_EQ(std::size_t(1), nav_map->size());
ASSERT_EQ(std::size_t(2), nav_map->at(download_url).size());
// The first NavigationEvent was obtained from NOIFICATION_RETARGETING.
// TODO(jialiul): After https://crbug.com/651895 is fixed, we'll no longer
// listen to NOTIFICATION_RETARGETING, hence only one NavigationEvent will
// be observed with the true initator URL. This applies to other new tab
// download, and target blank download test cases too.
VerifyNavigationEvent(initial_url, // source_url
initial_url, // source_main_frame_url
download_url, // original_request_url
download_url, // destination_url
false, // is_user_initiated,
false, // has_committed
false, // has_server_redirect
nav_map->at(download_url).at(0));
// The second one is the actual navigation which triggers download.
VerifyNavigationEvent(GURL(), // source_url
GURL(), // source_main_frame_url
download_url, // original_request_url
download_url, // destination_url
false, // is_user_initiated,
false, // has_committed
false, // has_server_redirect
nav_map->at(download_url).at(1));
VerifyHostToIpMap();
}
// Click on a link which navigates to a page then redirects to a download using
// META HTTP-EQUIV="refresh". All transitions happen in the same tab.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
SingleMetaRefreshRedirect) {
ClickTestLink("single_meta_refresh_redirect", 2);
GURL initial_url = embedded_test_server()->GetURL(kSingleFrameTestURL);
GURL redirect_url = embedded_test_server()->GetURL(kRedirectURL);
GURL download_url = embedded_test_server()->GetURL(kDownloadItemURL);
auto nav_map = navigation_map();
ASSERT_TRUE(nav_map);
// Since unlike server redirects client redirects commit and then generate a
// second navigation, our observer records two NavigationEvents for this test.
ASSERT_EQ(std::size_t(2), nav_map->size());
ASSERT_EQ(std::size_t(1), nav_map->at(redirect_url).size());
ASSERT_EQ(std::size_t(1), nav_map->at(download_url).size());
VerifyNavigationEvent(initial_url, // source_url
initial_url, // source_main_frame_url
redirect_url, // original_request_url
redirect_url, // destination_url
false, // is_user_initiated,
true, // has_committed
false, // has_server_redirect
nav_map->at(redirect_url).at(0));
VerifyNavigationEvent(redirect_url, // source_url
redirect_url, // source_main_frame_url
download_url, // original_request_url
download_url, // destination_url
false, // is_user_initiated,
false, // has_committed
false, // has_server_redirect
nav_map->at(download_url).at(0));
VerifyHostToIpMap();
}
// https://crbug.com/667784: The test is flaky on Linux.
#if defined(OS_LINUX)
#define MAYBE_SingleMetaRefreshRedirectTargetBlank DISABLED_SingleMetaRefreshRedirectTargetBlank
#else
#define MAYBE_SingleMetaRefreshRedirectTargetBlank SingleMetaRefreshRedirectTargetBlank
#endif
// Click on a link which navigates to a page then redirects to a download using
// META HTTP-EQUIV="refresh". First navigation happens in target blank.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
MAYBE_SingleMetaRefreshRedirectTargetBlank) {
ClickTestLink("single_meta_refresh_redirect_target_blank", 2);
GURL initial_url = embedded_test_server()->GetURL(kSingleFrameTestURL);
GURL redirect_url = embedded_test_server()->GetURL(kRedirectURL);
GURL download_url = embedded_test_server()->GetURL(kDownloadItemURL);
auto nav_map = navigation_map();
ASSERT_TRUE(nav_map);
ASSERT_EQ(std::size_t(2), nav_map->size());
ASSERT_EQ(std::size_t(2), nav_map->at(redirect_url).size());
ASSERT_EQ(std::size_t(1), nav_map->at(download_url).size());
// TODO(jialiul): After https://crbug.com/651895 is fixed, we'll no longer
// listen to NOTIFICATION_RETARGETING, hence only two NavigationEvents will
// be observed with the true initator URL.
VerifyNavigationEvent(initial_url, // source_url
initial_url, // source_main_frame_url
redirect_url, // original_request_url
redirect_url, // destination_url
false, // is_user_initiated,
false, // has_committed
false, // has_server_redirect
nav_map->at(redirect_url).at(0));
VerifyNavigationEvent(GURL(), // source_url
GURL(), // source_main_frame_url
redirect_url, // original_request_url
redirect_url, // destination_url
false, // is_user_initiated,
true, // has_committed
false, // has_server_redirect
nav_map->at(redirect_url).at(1));
VerifyNavigationEvent(redirect_url, // source_url
redirect_url, // source_main_frame_url
download_url, // original_request_url
download_url, // destination_url
false, // is_user_initiated,
false, // has_committed
false, // has_server_redirect
nav_map->at(download_url).at(0));
VerifyHostToIpMap();
}
// Click on a link which redirects twice before reaching download using
// META HTTP-EQUIV="refresh". All transitions happen in the same tab.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
MultiMetaRefreshRedirects) {
ClickTestLink("multiple_meta_refresh_redirects", 3);
GURL initial_url = embedded_test_server()->GetURL(kSingleFrameTestURL);
GURL first_redirect_url = embedded_test_server()->GetURL(
"/safe_browsing/download_protection/navigation_observer/"
"double_redirect.html");
GURL second_redirect_url = embedded_test_server()->GetURL(kRedirectURL);
GURL download_url = embedded_test_server()->GetURL(kDownloadItemURL);
auto nav_map = navigation_map();
ASSERT_TRUE(nav_map);
ASSERT_EQ(std::size_t(3), nav_map->size());
ASSERT_EQ(std::size_t(1), nav_map->at(first_redirect_url).size());
ASSERT_EQ(std::size_t(1), nav_map->at(second_redirect_url).size());
ASSERT_EQ(std::size_t(1), nav_map->at(download_url).size());
VerifyNavigationEvent(initial_url, // source_url
initial_url, // source_main_frame_url
first_redirect_url, // original_request_url
first_redirect_url, // destination_url
false, // is_user_initiated,
true, // has_committed
false, // has_server_redirect
nav_map->at(first_redirect_url).at(0));
VerifyNavigationEvent(first_redirect_url, // source_url
first_redirect_url, // source_main_frame_url
second_redirect_url, // original_request_url
second_redirect_url, // destination_url
false, // is_user_initiated,
true, // has_committed
false, // has_server_redirect
nav_map->at(second_redirect_url).at(0));
VerifyNavigationEvent(second_redirect_url, // source_url
second_redirect_url, // source_main_frame_url
download_url, // original_request_url
download_url, // destination_url
false, // is_user_initiated,
false, // has_committed
false, // has_server_redirect
nav_map->at(download_url).at(0));
VerifyHostToIpMap();
}
// Click on a link which redirects to download using window.location.
// All transitions happen in the same tab.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
WindowLocationRedirect) {
ClickTestLink("window_location_redirection", 1);
GURL initial_url = embedded_test_server()->GetURL(kSingleFrameTestURL);
GURL download_url = embedded_test_server()->GetURL(kDownloadItemURL);
auto nav_map = navigation_map();
ASSERT_TRUE(nav_map);
ASSERT_EQ(std::size_t(1), nav_map->size());
ASSERT_EQ(std::size_t(1), nav_map->at(download_url).size());
VerifyNavigationEvent(initial_url, // source_url
initial_url, // source_main_frame_url
download_url, // original_request_url
download_url, // destination_url
false, // is_user_initiated,
false, // has_committed
false, // has_server_redirect
nav_map->at(download_url).at(0));
}
// Click on a link which redirects twice until it reaches download using a
// mixture of meta refresh and window.location. All transitions happen in the
// same tab.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest, MixRedirects) {
ClickTestLink("mix_redirects", 2);
GURL redirect_url = embedded_test_server()->GetURL(kRedirectURL);
GURL initial_url = embedded_test_server()->GetURL(kSingleFrameTestURL);
GURL download_url = embedded_test_server()->GetURL(kDownloadItemURL);
auto nav_map = navigation_map();
ASSERT_TRUE(nav_map);
ASSERT_EQ(std::size_t(2), nav_map->size());
ASSERT_EQ(std::size_t(1), nav_map->at(redirect_url).size());
ASSERT_EQ(std::size_t(1), nav_map->at(download_url).size());
VerifyNavigationEvent(initial_url, // source_url
initial_url, // source_main_frame_url
redirect_url, // original_request_url
redirect_url, // destination_url
false, // is_user_initiated,
true, // has_committed
false, // has_server_redirect
nav_map->at(redirect_url).at(0));
VerifyNavigationEvent(redirect_url, // source_url
redirect_url, // source_main_frame_url
download_url, // original_request_url
download_url, // destination_url
false, // is_user_initiated,
false, // has_committed
false, // has_server_redirect
nav_map->at(download_url).at(0));
VerifyHostToIpMap();
}
// Use javascript to open download in a new tab.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest, NewTabDownload) {
ClickTestLink("new_tab_download", 2);
GURL initial_url = embedded_test_server()->GetURL(kSingleFrameTestURL);
GURL download_url = embedded_test_server()->GetURL(kDownloadItemURL);
GURL blank_url = GURL(url::kAboutBlankURL);
auto nav_map = navigation_map();
ASSERT_TRUE(nav_map);
ASSERT_EQ(std::size_t(2), nav_map->size());
ASSERT_EQ(std::size_t(2), nav_map->at(blank_url).size());
ASSERT_EQ(std::size_t(1), nav_map->at(download_url).size());
VerifyNavigationEvent(initial_url, // source_url
initial_url, // source_main_frame_url
blank_url, // original_request_url
blank_url, // destination_url
false, // is_user_initiated,
false, // has_committed
false, // has_server_redirect
nav_map->at(blank_url).at(0));
// Source and target are at different tabs.
EXPECT_NE(nav_map->at(blank_url).at(0).source_tab_id,
nav_map->at(blank_url).at(0).target_tab_id);
VerifyNavigationEvent(GURL(), // source_url
GURL(), // source_main_frame_url
blank_url, // original_request_url
blank_url, // destination_url
false, // is_user_initiated,
false, // has_committed
false, // has_server_redirect
nav_map->at(blank_url).at(1));
EXPECT_EQ(nav_map->at(blank_url).at(1).source_tab_id,
nav_map->at(blank_url).at(1).target_tab_id);
VerifyNavigationEvent(blank_url, // source_url
blank_url, // source_main_frame_url
download_url, // original_request_url
download_url, // destination_url
false, // is_user_initiated,
false, // has_committed
false, // has_server_redirect
nav_map->at(download_url).at(0));
EXPECT_EQ(nav_map->at(download_url).at(0).source_tab_id,
nav_map->at(download_url).at(0).target_tab_id);
VerifyHostToIpMap();
}
// Use javascript to open download in a new tab and download has a data url.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
NewTabDownloadWithDataURL) {
ClickTestLink("new_tab_download_with_data_url", 2);
GURL initial_url = embedded_test_server()->GetURL(kSingleFrameTestURL);
GURL download_url = GURL(kDownloadDataURL);
GURL blank_url = GURL("about:blank");
auto nav_map = navigation_map();
ASSERT_TRUE(nav_map);
ASSERT_EQ(std::size_t(2), nav_map->size());
ASSERT_EQ(std::size_t(2), nav_map->at(blank_url).size());
ASSERT_EQ(std::size_t(1), nav_map->at(download_url).size());
// The first one comes from NOTIFICATION_RETARGETING.
VerifyNavigationEvent(initial_url, // source_url
initial_url, // source_main_frame_url
blank_url, // original_request_url
blank_url, // destination_url
false, // is_user_initiated,
false, // has_committed
false, // has_server_redirect
nav_map->at(blank_url).at(0));
// Source and target are at different tabs.
EXPECT_FALSE(nav_map->at(blank_url).at(0).source_tab_id ==
nav_map->at(blank_url).at(0).target_tab_id);
VerifyNavigationEvent(GURL(), // source_url
GURL(), // source_main_frame_url
blank_url, // original_request_url
blank_url, // destination_url
false, // is_user_initiated,
false, // has_committed
false, // has_server_redirect
nav_map->at(blank_url).at(1));
EXPECT_EQ(nav_map->at(blank_url).at(1).source_tab_id,
nav_map->at(blank_url).at(1).target_tab_id);
VerifyNavigationEvent(blank_url, // source_url
blank_url, // source_main_frame_url
download_url, // original_request_url
download_url, // destination_url
false, // is_user_initiated,
false, // has_committed
false, // has_server_redirect
nav_map->at(download_url).at(0));
EXPECT_TRUE(nav_map->at(download_url).at(0).source_tab_id ==
nav_map->at(download_url).at(0).target_tab_id);
// Since data url does does not have IP, host_to_ip_map_ should be empty.
EXPECT_EQ(std::size_t(0), host_to_ip_map()->size());
}
// TODO(jialiul): Need to figure out why this test is failing on Windows and
// flaky on other platforms.
#define MAYBE_DownloadViaHTML5FileApi DISABLED_DownloadViaHTML5FileApi
// Download via html5 file API.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
MAYBE_DownloadViaHTML5FileApi) {
ClickTestLink("html5_file_api", 1);
GURL initial_url = embedded_test_server()->GetURL(kSingleFrameTestURL);
std::string download_url_str =
base::StringPrintf("filesystem:%stemporary/test.exe",
embedded_test_server()->base_url().spec().c_str());
GURL download_url = GURL(download_url_str);
auto nav_map = navigation_map();
ASSERT_TRUE(nav_map);
ASSERT_EQ(std::size_t(1), nav_map->size());
ASSERT_EQ(std::size_t(1), nav_map->at(download_url).size());
VerifyNavigationEvent(initial_url, // source_url
initial_url, // source_main_frame_url
download_url, // original_request_url
download_url, // destination_url
false, // is_user_initiated,
false, // has_committed
false, // has_server_redirect
nav_map->at(download_url).at(0));
VerifyHostToIpMap();
}
// Click a link in a subframe and start download.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
SubFrameDirectDownload) {
ui_test_utils::NavigateToURL(
browser(), embedded_test_server()->GetURL(kMultiFrameTestURL));
std::string test_name =
base::StringPrintf("%s', '%s", "iframe1", "iframe_direct_download");
ClickTestLink(test_name.c_str(), 1);
GURL initial_url = embedded_test_server()->GetURL(kSingleFrameTestURL);
GURL multi_frame_test_url =
embedded_test_server()->GetURL(kMultiFrameTestURL);
GURL iframe_url = embedded_test_server()->GetURL(kIframeDirectDownloadURL);
GURL iframe_retargeting_url =
embedded_test_server()->GetURL(kIframeRetargetingURL);
GURL download_url = embedded_test_server()->GetURL(kDownloadItemURL);
auto nav_map = navigation_map();
ASSERT_TRUE(nav_map);
ASSERT_EQ(std::size_t(4), nav_map->size());
ASSERT_EQ(std::size_t(1), nav_map->at(multi_frame_test_url).size());
ASSERT_EQ(std::size_t(1), nav_map->at(iframe_url).size());
ASSERT_EQ(std::size_t(1), nav_map->at(iframe_retargeting_url).size());
ASSERT_EQ(std::size_t(1), nav_map->at(download_url).size());
VerifyNavigationEvent(initial_url, // source_url
initial_url, // source_main_frame_url
multi_frame_test_url, // original_request_url
multi_frame_test_url, // destination_url
true, // is_user_initiated,
true, // has_committed
false, // has_server_redirect
nav_map->at(multi_frame_test_url).at(0));
VerifyNavigationEvent(GURL(), // source_url
multi_frame_test_url, // source_main_frame_url
iframe_url, // original_request_url
iframe_url, // destination_url
false, // is_user_initiated,
true, // has_committed
false, // has_server_redirect
nav_map->at(iframe_url).at(0));
VerifyNavigationEvent(GURL(), // source_url
multi_frame_test_url, // source_main_frame_url
iframe_retargeting_url, // original_request_url
iframe_retargeting_url, // destination_url
false, // is_user_initiated,
true, // has_committed
false, // has_server_redirect
nav_map->at(iframe_retargeting_url).at(0));
VerifyNavigationEvent(iframe_url, // source_url
multi_frame_test_url, // source_main_frame_url
download_url, // original_request_url
download_url, // destination_url
false, // is_user_initiated,
false, // has_committed
false, // has_server_redirect
nav_map->at(download_url).at(0));
VerifyHostToIpMap();
}
// Click a link in a subframe and open download in a new tab.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
SubFrameNewTabDownload) {
ui_test_utils::NavigateToURL(
browser(), embedded_test_server()->GetURL(kMultiFrameTestURL));
std::string test_name =
base::StringPrintf("%s', '%s", "iframe2", "iframe_new_tab_download");
ClickTestLink(test_name.c_str(), 2);
GURL initial_url = embedded_test_server()->GetURL(kSingleFrameTestURL);
GURL multi_frame_test_url =
embedded_test_server()->GetURL(kMultiFrameTestURL);
GURL iframe_url = embedded_test_server()->GetURL(kIframeDirectDownloadURL);
GURL iframe_retargeting_url =
embedded_test_server()->GetURL(kIframeRetargetingURL);
GURL blank_url = GURL(url::kAboutBlankURL);
GURL download_url = embedded_test_server()->GetURL(kDownloadItemURL);
auto nav_map = navigation_map();
ASSERT_TRUE(nav_map);
ASSERT_EQ(std::size_t(5), nav_map->size());
ASSERT_EQ(std::size_t(1), nav_map->at(multi_frame_test_url).size());
ASSERT_EQ(std::size_t(1), nav_map->at(iframe_url).size());
ASSERT_EQ(std::size_t(1), nav_map->at(iframe_retargeting_url).size());
ASSERT_EQ(std::size_t(2), nav_map->at(blank_url).size());
ASSERT_EQ(std::size_t(1), nav_map->at(download_url).size());
VerifyNavigationEvent(initial_url, // source_url
initial_url, // source_main_frame_url
multi_frame_test_url, // original_request_url
multi_frame_test_url, // destination_url
true, // is_user_initiated,
true, // has_committed
false, // has_server_redirect
nav_map->at(multi_frame_test_url).at(0));
VerifyNavigationEvent(GURL(), // source_url
multi_frame_test_url, // source_main_frame_url
iframe_url, // original_request_url
iframe_url, // destination_url
false, // is_user_initiated,
true, // has_committed
false, // has_server_redirect
nav_map->at(iframe_url).at(0));
VerifyNavigationEvent(GURL(), // source_url
multi_frame_test_url, // source_main_frame_url
iframe_retargeting_url, // original_request_url
iframe_retargeting_url, // destination_url
false, // is_user_initiated,
true, // has_committed
false, // has_server_redirect
nav_map->at(iframe_retargeting_url).at(0));
VerifyNavigationEvent(iframe_retargeting_url, // source_url
multi_frame_test_url, // source_main_frame_url
blank_url, // original_request_url
blank_url, // destination_url
false, // is_user_initiated,
false, // has_committed
false, // has_server_redirect
nav_map->at(blank_url).at(0));
VerifyNavigationEvent(GURL(), // source_url
GURL(), // source_main_frame_url
blank_url, // original_request_url
blank_url, // destination_url
false, // is_user_initiated,
false, // has_committed
false, // has_server_redirect
nav_map->at(blank_url).at(1));
VerifyNavigationEvent(blank_url, // source_url
blank_url, // source_main_frame_url
download_url, // original_request_url
download_url, // destination_url
false, // is_user_initiated,
false, // has_committed
false, // has_server_redirect
nav_map->at(download_url).at(0));
VerifyHostToIpMap();
}
// Server-side redirect.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest, ServerRedirect) {
GURL initial_url = embedded_test_server()->GetURL(kSingleFrameTestURL);
GURL download_url = embedded_test_server()->GetURL(kDownloadItemURL);
GURL request_url =
embedded_test_server()->GetURL("/server-redirect?" + download_url.spec());
ui_test_utils::NavigateToURL(browser(), request_url);
CancelDownloads();
auto nav_map = navigation_map();
ASSERT_TRUE(nav_map);
ASSERT_EQ(std::size_t(1), nav_map->size());
ASSERT_EQ(std::size_t(1), nav_map->at(download_url).size());
VerifyNavigationEvent(initial_url, // source_url
initial_url, // source_main_frame_url
request_url, // original_request_url
download_url, // destination_url
true, // is_user_initiated,
false, // has_committed
true, // has_server_redirect
nav_map->at(download_url).at(0));
}
// host_to_ip_map_ size should increase by one after a new navigation.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest, AddIPMapping) {
auto ip_map = host_to_ip_map();
std::string test_server_host(embedded_test_server()->base_url().host());
ip_map->insert(
std::make_pair(test_server_host, std::vector<ResolvedIPAddress>()));
ASSERT_EQ(std::size_t(0), ip_map->at(test_server_host).size());
ClickTestLink("direct_download", 1);
EXPECT_EQ(std::size_t(1), ip_map->at(test_server_host).size());
EXPECT_EQ(embedded_test_server()->host_port_pair().host(),
ip_map->at(test_server_host).back().ip);
}
// If we have already seen an IP associated with a host, update its timestamp.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest, IPListDedup) {
auto ip_map = host_to_ip_map();
std::string test_server_host(embedded_test_server()->base_url().host());
ip_map->insert(
std::make_pair(test_server_host, std::vector<ResolvedIPAddress>()));
base::Time yesterday(base::Time::Now() - base::TimeDelta::FromDays(1));
ip_map->at(test_server_host)
.push_back(ResolvedIPAddress(
yesterday, embedded_test_server()->host_port_pair().host()));
ASSERT_EQ(std::size_t(1), ip_map->at(test_server_host).size());
ClickTestLink("direct_download", 1);
EXPECT_EQ(std::size_t(1), ip_map->at(test_server_host).size());
EXPECT_EQ(embedded_test_server()->host_port_pair().host(),
ip_map->at(test_server_host).back().ip);
EXPECT_NE(yesterday, ip_map->at(test_server_host).front().timestamp);
}
} // namespace safe_browsing