| Index: components/safe_browsing/request_checker_unittest.cc
|
| diff --git a/components/safe_browsing/request_checker_unittest.cc b/components/safe_browsing/request_checker_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a593ca15e8107f0338e81c444e0b0f6d77273b68
|
| --- /dev/null
|
| +++ b/components/safe_browsing/request_checker_unittest.cc
|
| @@ -0,0 +1,505 @@
|
| +// Copyright 2017 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 "components/safe_browsing/request_checker.h"
|
| +
|
| +#include <memory>
|
| +#include <set>
|
| +#include <string>
|
| +#include <utility>
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/callback.h"
|
| +#include "base/location.h"
|
| +#include "base/memory/ref_counted.h"
|
| +#include "base/run_loop.h"
|
| +#include "base/time/time.h"
|
| +#include "components/safe_browsing/base_ui_manager.h"
|
| +#include "components/safe_browsing_db/database_manager.h"
|
| +#include "components/safe_browsing_db/hit_report.h"
|
| +#include "components/safe_browsing_db/v4_protocol_manager_util.h"
|
| +#include "components/security_interstitials/content/unsafe_resource.h"
|
| +#include "content/public/browser/browser_thread.h"
|
| +#include "content/public/common/resource_type.h"
|
| +#include "content/public/test/test_browser_thread_bundle.h"
|
| +#include "net/base/load_flags.h"
|
| +#include "net/url_request/url_request.h"
|
| +#include "net/url_request/url_request_test_util.h"
|
| +#include "testing/gmock/include/gmock/gmock.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +#include "url/gurl.h"
|
| +
|
| +namespace safe_browsing {
|
| +
|
| +namespace {
|
| +
|
| +using ::testing::ElementsAre;
|
| +using ::testing::InSequence;
|
| +using ::testing::Return;
|
| +using ::testing::MockFunction;
|
| +using ::testing::NiceMock;
|
| +using ::testing::SaveArg;
|
| +using ::testing::StrictMock;
|
| +using ::testing::_;
|
| +
|
| +constexpr char kTestUrl[] = "test:";
|
| +constexpr char kTestUrl2[] = "test:2";
|
| +constexpr char kTestUrl3[] = "test:3";
|
| +
|
| +// A checkpoint can be used to verify the relative ordering of mocked calls and
|
| +// real calls to the code under test.
|
| +typedef StrictMock<MockFunction<void(int)>> Checkpoint;
|
| +
|
| +class StubUIManager : public BaseUIManager {
|
| + public:
|
| + StubUIManager() {}
|
| +
|
| + // Override all the methods on the base class to eliminate all side-effects.
|
| + void StopOnIOThread(bool shutdown) override {}
|
| + void DisplayBlockingPage(const UnsafeResource& resource) override {}
|
| + void LogPauseDelay(base::TimeDelta time) override {}
|
| + void SendSerializedThreatDetails(const std::string& serialized) override {}
|
| + void MaybeReportSafeBrowsingHit(
|
| + const safe_browsing::HitReport& hit_report) override {}
|
| + bool IsWhitelisted(const UnsafeResource& resource) override { return false; }
|
| + bool IsUrlWhitelistedOrPendingForWebContents(
|
| + const GURL& url,
|
| + bool is_subresource,
|
| + content::NavigationEntry* entry,
|
| + content::WebContents* web_contents,
|
| + bool whitelist_only,
|
| + SBThreatType* threat_type) override {
|
| + return false;
|
| + }
|
| + void OnBlockingPageDone(const std::vector<UnsafeResource>& resources,
|
| + bool proceed,
|
| + content::WebContents* web_contents,
|
| + const GURL& main_frame_url) override {}
|
| + const std::string app_locale() const override { return "C"; }
|
| + history::HistoryService* history_service(
|
| + content::WebContents* web_contents) override {
|
| + return nullptr;
|
| + }
|
| + const GURL default_safe_page() const override { return GURL(); }
|
| +
|
| + protected:
|
| + ~StubUIManager() override {}
|
| +
|
| + // These should never be called. Override them anyway to be on the safe side.
|
| + void ReportSafeBrowsingHitOnIOThread(
|
| + const safe_browsing::HitReport& hit_report) override {}
|
| + void CreateAndSendHitReport(const UnsafeResource& resource) override {}
|
| + void ShowBlockingPageForResource(const UnsafeResource& resource) override {}
|
| +};
|
| +
|
| +// RequestChecker only uses one method from UIManager, LogPauseDelay, so only
|
| +// mock that one.
|
| +class SemiMockUIManager : public StubUIManager {
|
| + public:
|
| + MOCK_METHOD1(LogPauseDelay, void(base::TimeDelta));
|
| +
|
| + protected:
|
| + ~SemiMockUIManager() {}
|
| +};
|
| +
|
| +class MockDelegate : public RequestChecker::Delegate {
|
| + public:
|
| + MOCK_METHOD1(MaybeDestroyPrerenderContents,
|
| + void(const net::URLRequest* request));
|
| + MOCK_CONST_METHOD1(GetWebContentsGetterForRequest,
|
| + WebContentsGetter(const net::URLRequest* request));
|
| + MOCK_METHOD2(StartDisplayingBlockingPage,
|
| + void(const security_interstitials::UnsafeResource& resource,
|
| + scoped_refptr<BaseUIManager> ui_manager));
|
| + MOCK_METHOD0(CancelResourceLoad, void());
|
| + MOCK_METHOD0(ResumeResourceRequest, void());
|
| +};
|
| +
|
| +class MockSafeBrowsingDatabaseManager : public SafeBrowsingDatabaseManager {
|
| + public:
|
| + MOCK_METHOD1(CancelApiCheck, bool(Client* client));
|
| + MOCK_METHOD1(CancelCheck, void(Client* client));
|
| + MOCK_CONST_METHOD1(CanCheckResourceType,
|
| + bool(content::ResourceType resource_type));
|
| + MOCK_CONST_METHOD1(CanCheckUrl, bool(const GURL& url));
|
| + MOCK_CONST_METHOD0(ChecksAreAlwaysAsync, bool());
|
| + MOCK_METHOD2(CheckApiBlacklistUrl, bool(const GURL& url, Client* client));
|
| + MOCK_METHOD2(CheckBrowseUrl, bool(const GURL& url, Client* client));
|
| + MOCK_METHOD2(CheckUrlForSubresourceFilter,
|
| + bool(const GURL& url, Client* client));
|
| + MOCK_METHOD2(CheckDownloadUrl,
|
| + bool(const std::vector<GURL>& url_chain, Client* client));
|
| + MOCK_METHOD2(CheckExtensionIDs,
|
| + bool(const std::set<std::string>& extension_ids,
|
| + Client* client));
|
| + MOCK_METHOD2(CheckResourceUrl, bool(const GURL& url, Client* client));
|
| + MOCK_METHOD1(MatchCsdWhitelistUrl, bool(const GURL& url));
|
| + MOCK_METHOD1(MatchDownloadWhitelistString, bool(const std::string& str));
|
| + MOCK_METHOD1(MatchDownloadWhitelistUrl, bool(const GURL& url));
|
| + MOCK_METHOD1(MatchMalwareIP, bool(const std::string& ip_address));
|
| + MOCK_METHOD1(MatchModuleWhitelistString, bool(const std::string& str));
|
| + MOCK_METHOD0(GetStoresForFullHashRequests, StoresToCheck());
|
| + MOCK_CONST_METHOD0(GetThreatSource, ThreatSource());
|
| + MOCK_METHOD0(IsCsdWhitelistKillSwitchOn, bool());
|
| + MOCK_CONST_METHOD0(IsDownloadProtectionEnabled, bool());
|
| + MOCK_METHOD0(IsMalwareKillSwitchOn, bool());
|
| + MOCK_CONST_METHOD0(IsSupported, bool());
|
| + MOCK_METHOD2(StartOnIOThread,
|
| + void(net::URLRequestContextGetter* request_context_getter,
|
| + const V4ProtocolConfig& config));
|
| + MOCK_METHOD1(StopOnIOThread, void(bool shutdown));
|
| +
|
| + protected:
|
| + ~MockSafeBrowsingDatabaseManager() {}
|
| +};
|
| +
|
| +class RequestCheckerTest : public ::testing::Test {
|
| + protected:
|
| + RequestCheckerTest()
|
| + : request_(url_request_context_.CreateRequest(GURL(kTestUrl),
|
| + net::DEFAULT_PRIORITY,
|
| + nullptr)),
|
| + database_manager_(new NiceMock<MockSafeBrowsingDatabaseManager>()),
|
| + ui_manager_(new NiceMock<SemiMockUIManager>()),
|
| + delegate_(base::MakeUnique<NiceMock<MockDelegate>>()),
|
| + checker_(base::MakeUnique<RequestChecker>(
|
| + request_.get(),
|
| + content::RESOURCE_TYPE_SUB_RESOURCE,
|
| + database_manager_,
|
| + ui_manager_,
|
| + delegate_.get())) {
|
| + // CanCheckResourceType() is called by almost all tests so make it pass by
|
| + // default.
|
| + ON_CALL(*database_manager_, CanCheckResourceType(_))
|
| + .WillByDefault(Return(true));
|
| + }
|
| + ~RequestCheckerTest() override {
|
| + // It's possible that something could hold a reference to these objects
|
| + // after the framework is destroyed, so make sure mock expectations have
|
| + // been verified.
|
| + ::testing::Mock::VerifyAndClearExpectations(database_manager_.get());
|
| + ::testing::Mock::VerifyAndClearExpectations(ui_manager_.get());
|
| + }
|
| +
|
| + const content::TestBrowserThreadBundle test_browser_thread_bundle_;
|
| + net::TestURLRequestContext url_request_context_;
|
| + const std::unique_ptr<net::URLRequest> request_;
|
| + const scoped_refptr<NiceMock<MockSafeBrowsingDatabaseManager>>
|
| + database_manager_;
|
| + const scoped_refptr<NiceMock<SemiMockUIManager>> ui_manager_;
|
| + const std::unique_ptr<NiceMock<MockDelegate>> delegate_;
|
| + std::unique_ptr<RequestChecker> checker_;
|
| +};
|
| +
|
| +TEST_F(RequestCheckerTest, Constructs) {
|
| + // The framework constructor does all the work.
|
| +}
|
| +
|
| +TEST_F(RequestCheckerTest, UncheckedResourceType) {
|
| + EXPECT_CALL(*database_manager_,
|
| + CanCheckResourceType(content::RESOURCE_TYPE_SUB_RESOURCE))
|
| + .WillOnce(Return(false));
|
| + EXPECT_EQ(RequestChecker::PROCEED_SKIPPED, checker_->CheckNewRequest());
|
| +}
|
| +
|
| +TEST_F(RequestCheckerTest, SynchronousPass) {
|
| + EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(true));
|
| + EXPECT_EQ(RequestChecker::PROCEED_SAFE, checker_->CheckNewRequest());
|
| +}
|
| +
|
| +TEST_F(RequestCheckerTest, CorrectUrlIsPassedToDatabaseManager) {
|
| + EXPECT_CALL(*database_manager_, CheckBrowseUrl(GURL(kTestUrl), _))
|
| + .WillOnce(Return(true));
|
| + checker_->CheckNewRequest();
|
| +}
|
| +
|
| +TEST_F(RequestCheckerTest, ZeroDelayIsLogged) {
|
| + EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(true));
|
| + EXPECT_CALL(*ui_manager_, LogPauseDelay(base::TimeDelta()));
|
| + checker_->CheckNewRequest();
|
| +}
|
| +
|
| +TEST_F(RequestCheckerTest, SyncMissAsyncProceed) {
|
| + Checkpoint checkpoint;
|
| + EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false));
|
| + EXPECT_CALL(*database_manager_, ChecksAreAlwaysAsync())
|
| + .WillOnce(Return(false));
|
| + {
|
| + InSequence s;
|
| + EXPECT_CALL(checkpoint, Call(1));
|
| + EXPECT_CALL(*delegate_, ResumeResourceRequest());
|
| + }
|
| +
|
| + EXPECT_EQ(RequestChecker::DEFER, checker_->CheckNewRequest());
|
| + checkpoint.Call(1);
|
| + checker_->OnCheckBrowseUrlResult(GURL(kTestUrl), SB_THREAT_TYPE_SAFE,
|
| + ThreatMetadata());
|
| +}
|
| +
|
| +TEST_F(RequestCheckerTest, SyncMissAsyncUnsafe) {
|
| + security_interstitials::UnsafeResource resource;
|
| + EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false));
|
| + EXPECT_CALL(*database_manager_, ChecksAreAlwaysAsync())
|
| + .WillOnce(Return(false));
|
| + EXPECT_CALL(*delegate_, StartDisplayingBlockingPage(_, _))
|
| + .WillOnce(SaveArg<0>(&resource));
|
| + EXPECT_CALL(*delegate_, GetWebContentsGetterForRequest(request_.get()))
|
| + .WillOnce(Return(
|
| + base::Bind([]() -> content::WebContents* { return nullptr; })));
|
| + EXPECT_CALL(*database_manager_, GetThreatSource())
|
| + .WillOnce(Return(ThreatSource::LOCAL_PVER4));
|
| + EXPECT_EQ(RequestChecker::DEFER, checker_->CheckNewRequest());
|
| + checker_->OnCheckBrowseUrlResult(GURL(kTestUrl), SB_THREAT_TYPE_URL_MALWARE,
|
| + ThreatMetadata());
|
| + EXPECT_EQ(GURL(kTestUrl), resource.url);
|
| + EXPECT_EQ(request_->original_url(), resource.original_url);
|
| + EXPECT_EQ(0u, resource.redirect_urls.size());
|
| + EXPECT_TRUE(resource.is_subresource);
|
| + EXPECT_FALSE(resource.is_subframe);
|
| + EXPECT_EQ(SB_THREAT_TYPE_URL_MALWARE, resource.threat_type);
|
| + EXPECT_EQ(ThreatMetadata(), resource.threat_metadata);
|
| + EXPECT_FALSE(resource.callback.is_null());
|
| + EXPECT_TRUE(resource.callback_thread);
|
| + EXPECT_EQ(nullptr, resource.web_contents_getter.Run());
|
| + EXPECT_EQ(ThreatSource::LOCAL_PVER4, resource.threat_source);
|
| +}
|
| +
|
| +TEST_F(RequestCheckerTest, SyncMissAsyncUnsafeBlockBypassed) {
|
| + security_interstitials::UnsafeResource resource;
|
| + Checkpoint checkpoint;
|
| + EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false));
|
| + EXPECT_CALL(*database_manager_, ChecksAreAlwaysAsync())
|
| + .WillOnce(Return(false));
|
| + EXPECT_CALL(*delegate_, StartDisplayingBlockingPage(_, _))
|
| + .WillOnce(SaveArg<0>(&resource));
|
| + EXPECT_CALL(*delegate_, GetWebContentsGetterForRequest(request_.get()))
|
| + .WillOnce(Return(
|
| + base::Bind([]() -> content::WebContents* { return nullptr; })));
|
| + EXPECT_CALL(*database_manager_, GetThreatSource())
|
| + .WillOnce(Return(ThreatSource::LOCAL_PVER4));
|
| + {
|
| + InSequence s;
|
| + EXPECT_CALL(checkpoint, Call(1));
|
| + EXPECT_CALL(*delegate_, ResumeResourceRequest());
|
| + }
|
| + EXPECT_EQ(RequestChecker::DEFER, checker_->CheckNewRequest());
|
| + checker_->OnCheckBrowseUrlResult(GURL(kTestUrl), SB_THREAT_TYPE_URL_MALWARE,
|
| + ThreatMetadata());
|
| + checkpoint.Call(1);
|
| + resource.callback.Run(true);
|
| +}
|
| +
|
| +TEST_F(RequestCheckerTest, SyncMissAsyncUnsafeBlockRejected) {
|
| + security_interstitials::UnsafeResource resource;
|
| + Checkpoint checkpoint;
|
| + EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false));
|
| + EXPECT_CALL(*database_manager_, ChecksAreAlwaysAsync())
|
| + .WillOnce(Return(false));
|
| + EXPECT_CALL(*delegate_, StartDisplayingBlockingPage(_, _))
|
| + .WillOnce(SaveArg<0>(&resource));
|
| + EXPECT_CALL(*delegate_, GetWebContentsGetterForRequest(request_.get()))
|
| + .WillOnce(Return(
|
| + base::Bind([]() -> content::WebContents* { return nullptr; })));
|
| + EXPECT_CALL(*database_manager_, GetThreatSource())
|
| + .WillOnce(Return(ThreatSource::LOCAL_PVER4));
|
| + {
|
| + InSequence s;
|
| + EXPECT_CALL(checkpoint, Call(1));
|
| + EXPECT_CALL(*delegate_, CancelResourceLoad());
|
| + }
|
| + EXPECT_EQ(RequestChecker::DEFER, checker_->CheckNewRequest());
|
| + checker_->OnCheckBrowseUrlResult(GURL(kTestUrl), SB_THREAT_TYPE_URL_MALWARE,
|
| + ThreatMetadata());
|
| + checkpoint.Call(1);
|
| + resource.callback.Run(false);
|
| +}
|
| +
|
| +TEST_F(RequestCheckerTest, AlwaysAsyncSafe) {
|
| + EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false));
|
| + EXPECT_CALL(*database_manager_, ChecksAreAlwaysAsync())
|
| + .WillRepeatedly(Return(true));
|
| + // ResumeResourceRequest() must not be called.
|
| + EXPECT_CALL(*delegate_, ResumeResourceRequest()).Times(0);
|
| + EXPECT_EQ(RequestChecker::PROCEED_ALWAYS_ASYNC, checker_->CheckNewRequest());
|
| + checker_->OnCheckBrowseUrlResult(GURL(kTestUrl), SB_THREAT_TYPE_SAFE,
|
| + ThreatMetadata());
|
| + EXPECT_EQ(RequestChecker::PROCEED_SAFE, checker_->ShouldDeferResponse());
|
| +}
|
| +
|
| +TEST_F(RequestCheckerTest, AlwaysAsyncLateSafe) {
|
| + Checkpoint checkpoint;
|
| + EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false));
|
| + EXPECT_CALL(*database_manager_, ChecksAreAlwaysAsync())
|
| + .WillRepeatedly(Return(true));
|
| + {
|
| + InSequence s;
|
| + EXPECT_CALL(checkpoint, Call(1));
|
| + EXPECT_CALL(*delegate_, ResumeResourceRequest());
|
| + }
|
| + EXPECT_EQ(RequestChecker::PROCEED_ALWAYS_ASYNC, checker_->CheckNewRequest());
|
| + EXPECT_EQ(RequestChecker::DEFER, checker_->ShouldDeferResponse());
|
| + checkpoint.Call(1);
|
| + checker_->OnCheckBrowseUrlResult(GURL(kTestUrl), SB_THREAT_TYPE_SAFE,
|
| + ThreatMetadata());
|
| +}
|
| +
|
| +TEST_F(RequestCheckerTest, AlwaysAsyncUnsafe) {
|
| + EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false));
|
| + EXPECT_CALL(*database_manager_, ChecksAreAlwaysAsync())
|
| + .WillRepeatedly(Return(true));
|
| + EXPECT_CALL(*delegate_, StartDisplayingBlockingPage(_, _));
|
| + EXPECT_CALL(*delegate_, GetWebContentsGetterForRequest(request_.get()))
|
| + .WillOnce(Return(
|
| + base::Bind([]() -> content::WebContents* { return nullptr; })));
|
| + EXPECT_CALL(*database_manager_, GetThreatSource())
|
| + .WillOnce(Return(ThreatSource::LOCAL_PVER4));
|
| + // ResumeResourceRequest() must not be called.
|
| + EXPECT_CALL(*delegate_, ResumeResourceRequest()).Times(0);
|
| + EXPECT_EQ(RequestChecker::PROCEED_ALWAYS_ASYNC, checker_->CheckNewRequest());
|
| + checker_->OnCheckBrowseUrlResult(GURL(kTestUrl), SB_THREAT_TYPE_URL_MALWARE,
|
| + ThreatMetadata());
|
| + EXPECT_EQ(RequestChecker::DEFER, checker_->ShouldDeferResponse());
|
| +}
|
| +
|
| +TEST_F(RequestCheckerTest, RedirectToSafeSync) {
|
| + EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _))
|
| + .WillRepeatedly(Return(true));
|
| + EXPECT_EQ(RequestChecker::PROCEED_SAFE, checker_->CheckNewRequest());
|
| + EXPECT_EQ(RequestChecker::PROCEED_SAFE,
|
| + checker_->CheckRedirect(GURL(kTestUrl2)));
|
| +}
|
| +
|
| +TEST_F(RequestCheckerTest, RedirectToSafeAsync) {
|
| + EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _))
|
| + .WillOnce(Return(true))
|
| + .WillOnce(Return(false));
|
| + EXPECT_CALL(*delegate_, ResumeResourceRequest());
|
| + EXPECT_EQ(RequestChecker::PROCEED_SAFE, checker_->CheckNewRequest());
|
| + EXPECT_EQ(RequestChecker::DEFER, checker_->CheckRedirect(GURL(kTestUrl2)));
|
| + checker_->OnCheckBrowseUrlResult(GURL(kTestUrl2), SB_THREAT_TYPE_SAFE,
|
| + ThreatMetadata());
|
| +}
|
| +
|
| +TEST_F(RequestCheckerTest, RedirectToUnsafe) {
|
| + EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _))
|
| + .WillOnce(Return(true))
|
| + .WillOnce(Return(false));
|
| + EXPECT_CALL(*delegate_, StartDisplayingBlockingPage(_, _));
|
| + EXPECT_EQ(RequestChecker::PROCEED_SAFE, checker_->CheckNewRequest());
|
| + EXPECT_EQ(RequestChecker::DEFER, checker_->CheckRedirect(GURL(kTestUrl2)));
|
| + checker_->OnCheckBrowseUrlResult(GURL(kTestUrl2), SB_THREAT_TYPE_URL_MALWARE,
|
| + ThreatMetadata());
|
| +}
|
| +
|
| +TEST_F(RequestCheckerTest, RedirectToSafeThenUnsafe) {
|
| + security_interstitials::UnsafeResource resource;
|
| + Checkpoint checkpoint;
|
| + EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _))
|
| + .WillOnce(Return(true))
|
| + .WillRepeatedly(Return(false));
|
| + {
|
| + InSequence s;
|
| + EXPECT_CALL(checkpoint, Call(1));
|
| + EXPECT_CALL(*delegate_, ResumeResourceRequest());
|
| + EXPECT_CALL(checkpoint, Call(2));
|
| + EXPECT_CALL(*delegate_, StartDisplayingBlockingPage(_, _))
|
| + .WillOnce(SaveArg<0>(&resource));
|
| + }
|
| + EXPECT_EQ(RequestChecker::PROCEED_SAFE, checker_->CheckNewRequest());
|
| + EXPECT_EQ(RequestChecker::DEFER, checker_->CheckRedirect(GURL(kTestUrl2)));
|
| + checkpoint.Call(1);
|
| + checker_->OnCheckBrowseUrlResult(GURL(kTestUrl2), SB_THREAT_TYPE_SAFE,
|
| + ThreatMetadata());
|
| + EXPECT_EQ(RequestChecker::DEFER, checker_->CheckRedirect(GURL(kTestUrl3)));
|
| + checkpoint.Call(2);
|
| + checker_->OnCheckBrowseUrlResult(GURL(kTestUrl3), SB_THREAT_TYPE_URL_MALWARE,
|
| + ThreatMetadata());
|
| + EXPECT_EQ(GURL(kTestUrl3), resource.url);
|
| + EXPECT_EQ(GURL(kTestUrl), resource.original_url);
|
| + EXPECT_THAT(resource.redirect_urls,
|
| + ElementsAre(GURL(kTestUrl2), GURL(kTestUrl3)));
|
| +}
|
| +
|
| +TEST_F(RequestCheckerTest, RedirectToSafeAlwaysAsync) {
|
| + EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _))
|
| + .WillRepeatedly(Return(false));
|
| + EXPECT_CALL(*database_manager_, ChecksAreAlwaysAsync())
|
| + .WillRepeatedly(Return(true));
|
| + EXPECT_CALL(*delegate_, ResumeResourceRequest());
|
| + EXPECT_EQ(RequestChecker::PROCEED_ALWAYS_ASYNC, checker_->CheckNewRequest());
|
| + EXPECT_EQ(RequestChecker::DEFER, checker_->CheckRedirect(GURL(kTestUrl2)));
|
| + checker_->OnCheckBrowseUrlResult(GURL(kTestUrl), SB_THREAT_TYPE_SAFE,
|
| + ThreatMetadata());
|
| + checker_->OnCheckBrowseUrlResult(GURL(kTestUrl2), SB_THREAT_TYPE_SAFE,
|
| + ThreatMetadata());
|
| +}
|
| +
|
| +TEST_F(RequestCheckerTest, AsyncTimeout) {
|
| + ScopedTimeoutForTesting scoped_timeout(1);
|
| + EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false));
|
| + EXPECT_CALL(*database_manager_, CancelCheck(_));
|
| + EXPECT_CALL(*delegate_, ResumeResourceRequest());
|
| + EXPECT_EQ(RequestChecker::DEFER, checker_->CheckNewRequest());
|
| + base::RunLoop run_loop;
|
| + content::BrowserThread::PostDelayedTask(content::BrowserThread::IO, FROM_HERE,
|
| + run_loop.QuitClosure(),
|
| + base::TimeDelta::FromMilliseconds(2));
|
| + run_loop.Run();
|
| +}
|
| +
|
| +TEST_F(RequestCheckerTest, TimeoutIsReallyCancelled) {
|
| + // The test is not flaky because OnCheckBrowseUrlResult() is called
|
| + // synchronously, and so will always succeed in cancelling the timer before
|
| + // OnCheckUrlTimeout can be called asynchronously.
|
| + ScopedTimeoutForTesting scoped_timeout(1);
|
| + EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false));
|
| + EXPECT_CALL(*database_manager_, CancelCheck(_)).Times(0);
|
| + EXPECT_CALL(*delegate_, ResumeResourceRequest());
|
| + EXPECT_EQ(RequestChecker::DEFER, checker_->CheckNewRequest());
|
| + checker_->OnCheckBrowseUrlResult(GURL(kTestUrl), SB_THREAT_TYPE_SAFE,
|
| + ThreatMetadata());
|
| + base::RunLoop run_loop;
|
| + content::BrowserThread::PostDelayedTask(content::BrowserThread::IO, FROM_HERE,
|
| + run_loop.QuitClosure(),
|
| + base::TimeDelta::FromMilliseconds(2));
|
| + run_loop.Run();
|
| + // If we get here without hitting a DCHECK then the test passed.
|
| +}
|
| +
|
| +TEST_F(RequestCheckerTest, PrefetchCancelledOnAsyncBlock) {
|
| + request_->SetLoadFlags(request_->load_flags() | net::LOAD_PREFETCH);
|
| + EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false));
|
| + EXPECT_CALL(*delegate_, CancelResourceLoad());
|
| + // Blocking page is not displayed for prefetch / prerender.
|
| + EXPECT_CALL(*delegate_, StartDisplayingBlockingPage(_, _)).Times(0);
|
| + EXPECT_EQ(RequestChecker::DEFER, checker_->CheckNewRequest());
|
| + checker_->OnCheckBrowseUrlResult(GURL(kTestUrl), SB_THREAT_TYPE_URL_MALWARE,
|
| + ThreatMetadata());
|
| +}
|
| +
|
| +TEST_F(RequestCheckerTest, PrerenderContentsDestroyed) {
|
| + request_->SetLoadFlags(request_->load_flags() | net::LOAD_PREFETCH);
|
| + // Change resource type to MAIN_FRAME.
|
| + checker_.reset(
|
| + new RequestChecker(request_.get(), content::RESOURCE_TYPE_MAIN_FRAME,
|
| + database_manager_, ui_manager_, delegate_.get()));
|
| + EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false));
|
| + EXPECT_CALL(*delegate_, CancelResourceLoad());
|
| + EXPECT_CALL(*delegate_, MaybeDestroyPrerenderContents(_));
|
| + EXPECT_CALL(*delegate_, StartDisplayingBlockingPage(_, _)).Times(0);
|
| + EXPECT_EQ(RequestChecker::DEFER, checker_->CheckNewRequest());
|
| + checker_->OnCheckBrowseUrlResult(GURL(kTestUrl), SB_THREAT_TYPE_URL_MALWARE,
|
| + ThreatMetadata());
|
| +}
|
| +
|
| +TEST_F(RequestCheckerTest, CheckCancelledOnDestruction) {
|
| + EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false));
|
| + EXPECT_CALL(*database_manager_, CancelCheck(_));
|
| + EXPECT_EQ(RequestChecker::DEFER, checker_->CheckNewRequest());
|
| + checker_.reset();
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +} // namespace safe_browsing
|
|
|