chromium/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc

// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/safe_browsing/content/browser/safe_browsing_navigation_observer.h"

#include <memory>

#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/download/download_core_service.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/safe_browsing/download_protection/download_protection_service.h"
#include "chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager_factory.h"
#include "chrome/browser/safe_browsing/test_safe_browsing_navigation_observer_manager.h"
#include "chrome/browser/safe_browsing/test_safe_browsing_service.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/download/public/common/download_item.h"
#include "components/prefs/pref_service.h"
#include "components/safe_browsing/content/browser/safe_browsing_navigation_observer_manager.h"
#include "components/sessions/content/session_tab_helper.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/download_item_utils.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/fenced_frame_test_util.h"
#include "content/public/test/prerender_test_util.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 "third_party/blink/public/common/features.h"
#include "url/gurl.h"
#include "url/url_canon.h"

DownloadManager;
DownloadItem;

namespace safe_browsing {

const char kSingleFrameTestURL[] =;
const char kMultiFrameTestURL[] =;
const char kSubFrameTestURL[] =;
const char kRedirectURL[] =;
const char kEmptyURL[] =;
const char kBasicIframeURL[] =;
// This is the src of the iframe in iframe.html above.
const char kInitialSubframeUrl[] =;
// Please update |kShortDataURL| too if you're changing |kDownloadDataURL|.
const char kDownloadDataURL[] =;
// Short data url is computed by keeping the prefix of |kDownloadDataURL| up to
// the first ",", and appending the hash (SHA256) of entire |kDownloadDataURL|.
// e.g.,
// $echo -n <kDownloadDataURL> | sha256sum |
//  awk '{print "data:application/octet-stream;base64,"toupper($1)}'
const char kShortDataURL[] =;
const char kIframeDirectDownloadURL[] =;
const char kIframeRetargetingURL[] =;
const char kDownloadItemURL[] =;
const char kRedirectToLandingURL[] =;
const char kLandingURL[] =;
const char kLandingReferrerURL[] =;
const char kLandingReferrerURLWithQuery[] =;
const char kPageBeforeLandingReferrerURL[] =;
const char kCreateIframeElementURL[] =;

class DownloadItemCreatedObserver : public DownloadManager::Observer {};

class SBNavigationObserverBrowserTest : public InProcessBrowserTest {};

// Type download URL into address bar and start download on the same page.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest, TypeInURLDownload) {}
// Click on a link and start download on the same page.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest, DirectDownload) {}

// Click on a link with rel="noreferrer" attribute, and start download on the
// same page.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       DirectDownloadNoReferrer) {}

// 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) {}

// 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) {}

// 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,
                       SingleMetaRefreshRedirectTargetBlank) {}

// 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) {}

// 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) {}

// 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) {}

// Use javascript to open download in a new tab.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest, NewTabDownload) {}

// Use javascript to open download in a new tab and download has a data url.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       NewTabDownloadWithDataURL) {}

// Click a link in a subframe and start download.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       SubFrameDirectDownload) {}

// Click a link in a subframe and open download in a new tab.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       SubFrameNewTabDownload) {}

// Click a link which redirects to the landing page, and then click on the
// landing page to trigger download.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest, CompleteReferrerChain) {}

// Click three links before reaching download.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       ReferrerAttributionWithinTwoUserGestures) {}

// Click a link which redirects to a PPAPI landing page.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       PPAPIDownloadWithUserGestureOnHostingFrame) {}

// Click a link which redirects to a page that triggers PPAPI download without
// user gesture (a.k.a not a landing page).
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       PPAPIDownloadWithoutUserGestureOnHostingFrame) {}

// Server-side redirect.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest, ServerRedirect) {}

// 2 consecutive server-side redirects.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest, TwoServerRedirects) {}

// Retargeting immediately followed by server-side redirect.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       RetargetingAndServerRedirect) {}

// host_to_ip_map_ size should increase by one after a new navigation.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest, AddIPMapping) {}

// If we have already seen an IP associated with a host, update its timestamp.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest, IPListDedup) {}

// Download via html5 file API.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       DownloadViaHTML5FileApi) {}

// Verify referrer chain when there are URL fragments.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       DownloadAttributionWithURLFragment) {}

IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       VerifySanitizeReferrerChain) {}

IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       VerifyNumberOfRecentNavigationsToCollect) {}

IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       AppendRecentNavigationsToIncompleteReferrerChain) {}

IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       NewWindowAndNavigateSubframe) {}

// This is similar to PrerenderReferrerChains, but navigates rather than
// initiating the prerender to ensure that the referrer chains match.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       ReferrerChainsMatchPrerender) {}

IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       PrerenderReferrerChains) {}

IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       FencedFrameNavigationEventsAndReferrerChain) {}

IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       NavigateBackwardForward) {}

IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest, ReloadNotRecorded) {}

IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       CreateIframeElementGetsReferrerChain) {}

IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       SetWindowLocationGetsReferrerChain) {}

// Open a new tab to some arbitrary URL, then have the opener navigate the new
// tab to the actual landing page where the user then clicks a link to start a
// download.
// TODO(drubery, mcnee): The "source" information captured in a Safe Browsing
// |NavigationEvent| does not necessarily reflect the initiator of a navigation.
// This test illustrates this behaviour. Note that |initial_popup_url| appears
// to navigate itself to the landing page, even though it was navigated by its
// opener. Investigate whether the initiator of a navigation should be reflected
// in the referrer chain.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       NewTabClientRedirectByOpener) {}

IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       IdentifyReferrerChainByPendingEventURL_TwoUserGestures) {}

IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       IdentifyReferrerChainByPendingEventURL_ServerRedirect) {}

// Verify URLs that match the Safe Browsing allowlist domains (a.k.a
// prefs::kSafeBrowsingAllowlistDomains) are removed from the referrer chain.
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       AllowlistDomainsRemoved_ReferrerChain) {}

IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       AllowlistDomainsRemoved_ServerRedirect) {}

IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       AllowlistDomainsRemoved_RecentNavigation) {}

// Test failure on macOS: crbug.com/1287901
#if BUILDFLAG(IS_MAC)
#define MAYBE_AppendRecentNavigationsToEmptyReferrerChain
#else
#define MAYBE_AppendRecentNavigationsToEmptyReferrerChain
#endif
IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
                       MAYBE_AppendRecentNavigationsToEmptyReferrerChain) {}

}  // namespace safe_browsing