| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 
|  | 2 // Use of this source code is governed by a BSD-style license that can be | 
|  | 3 // found in the LICENSE file. | 
|  | 4 | 
|  | 5 #include "components/safe_browsing/request_checker.h" | 
|  | 6 | 
|  | 7 #include <memory> | 
|  | 8 #include <set> | 
|  | 9 #include <string> | 
|  | 10 #include <utility> | 
|  | 11 | 
|  | 12 #include "base/bind.h" | 
|  | 13 #include "base/callback.h" | 
|  | 14 #include "base/location.h" | 
|  | 15 #include "base/memory/ref_counted.h" | 
|  | 16 #include "base/run_loop.h" | 
|  | 17 #include "base/time/time.h" | 
|  | 18 #include "components/safe_browsing/base_ui_manager.h" | 
|  | 19 #include "components/safe_browsing_db/database_manager.h" | 
|  | 20 #include "components/safe_browsing_db/hit_report.h" | 
|  | 21 #include "components/safe_browsing_db/v4_protocol_manager_util.h" | 
|  | 22 #include "components/security_interstitials/content/unsafe_resource.h" | 
|  | 23 #include "content/public/browser/browser_thread.h" | 
|  | 24 #include "content/public/common/resource_type.h" | 
|  | 25 #include "content/public/test/test_browser_thread_bundle.h" | 
|  | 26 #include "net/base/load_flags.h" | 
|  | 27 #include "net/url_request/url_request.h" | 
|  | 28 #include "net/url_request/url_request_test_util.h" | 
|  | 29 #include "testing/gmock/include/gmock/gmock.h" | 
|  | 30 #include "testing/gtest/include/gtest/gtest.h" | 
|  | 31 #include "url/gurl.h" | 
|  | 32 | 
|  | 33 namespace safe_browsing { | 
|  | 34 | 
|  | 35 namespace { | 
|  | 36 | 
|  | 37 using ::testing::ElementsAre; | 
|  | 38 using ::testing::InSequence; | 
|  | 39 using ::testing::Return; | 
|  | 40 using ::testing::MockFunction; | 
|  | 41 using ::testing::NiceMock; | 
|  | 42 using ::testing::SaveArg; | 
|  | 43 using ::testing::StrictMock; | 
|  | 44 using ::testing::_; | 
|  | 45 | 
|  | 46 constexpr char kTestUrl[] = "test:"; | 
|  | 47 constexpr char kTestUrl2[] = "test:2"; | 
|  | 48 constexpr char kTestUrl3[] = "test:3"; | 
|  | 49 | 
|  | 50 // A checkpoint can be used to verify the relative ordering of mocked calls and | 
|  | 51 // real calls to the code under test. | 
|  | 52 typedef StrictMock<MockFunction<void(int)>> Checkpoint; | 
|  | 53 | 
|  | 54 class StubUIManager : public BaseUIManager { | 
|  | 55  public: | 
|  | 56   StubUIManager() {} | 
|  | 57 | 
|  | 58   // Override all the methods on the base class to eliminate all side-effects. | 
|  | 59   void StopOnIOThread(bool shutdown) override {} | 
|  | 60   void DisplayBlockingPage(const UnsafeResource& resource) override {} | 
|  | 61   void LogPauseDelay(base::TimeDelta time) override {} | 
|  | 62   void SendSerializedThreatDetails(const std::string& serialized) override {} | 
|  | 63   void MaybeReportSafeBrowsingHit( | 
|  | 64       const safe_browsing::HitReport& hit_report) override {} | 
|  | 65   bool IsWhitelisted(const UnsafeResource& resource) override { return false; } | 
|  | 66   bool IsUrlWhitelistedOrPendingForWebContents( | 
|  | 67       const GURL& url, | 
|  | 68       bool is_subresource, | 
|  | 69       content::NavigationEntry* entry, | 
|  | 70       content::WebContents* web_contents, | 
|  | 71       bool whitelist_only, | 
|  | 72       SBThreatType* threat_type) override { | 
|  | 73     return false; | 
|  | 74   } | 
|  | 75   void OnBlockingPageDone(const std::vector<UnsafeResource>& resources, | 
|  | 76                           bool proceed, | 
|  | 77                           content::WebContents* web_contents, | 
|  | 78                           const GURL& main_frame_url) override {} | 
|  | 79   const std::string app_locale() const override { return "C"; } | 
|  | 80   history::HistoryService* history_service( | 
|  | 81       content::WebContents* web_contents) override { | 
|  | 82     return nullptr; | 
|  | 83   } | 
|  | 84   const GURL default_safe_page() const override { return GURL(); } | 
|  | 85 | 
|  | 86  protected: | 
|  | 87   ~StubUIManager() override {} | 
|  | 88 | 
|  | 89   // These should never be called. Override them anyway to be on the safe side. | 
|  | 90   void ReportSafeBrowsingHitOnIOThread( | 
|  | 91       const safe_browsing::HitReport& hit_report) override {} | 
|  | 92   void CreateAndSendHitReport(const UnsafeResource& resource) override {} | 
|  | 93   void ShowBlockingPageForResource(const UnsafeResource& resource) override {} | 
|  | 94 }; | 
|  | 95 | 
|  | 96 // RequestChecker only uses one method from UIManager, LogPauseDelay, so only | 
|  | 97 // mock that one. | 
|  | 98 class SemiMockUIManager : public StubUIManager { | 
|  | 99  public: | 
|  | 100   MOCK_METHOD1(LogPauseDelay, void(base::TimeDelta)); | 
|  | 101 | 
|  | 102  protected: | 
|  | 103   ~SemiMockUIManager() {} | 
|  | 104 }; | 
|  | 105 | 
|  | 106 class MockDelegate : public RequestChecker::Delegate { | 
|  | 107  public: | 
|  | 108   MOCK_METHOD1(MaybeDestroyPrerenderContents, void(const WebContentsGetter&)); | 
|  | 109   MOCK_CONST_METHOD1(GetWebContentsGetterForRequest, | 
|  | 110                      WebContentsGetter(const net::URLRequest* request)); | 
|  | 111   MOCK_METHOD2(StartDisplayingBlockingPage, | 
|  | 112                void(const security_interstitials::UnsafeResource& resource, | 
|  | 113                     scoped_refptr<BaseUIManager> ui_manager)); | 
|  | 114   MOCK_METHOD0(CancelResourceLoad, void()); | 
|  | 115   MOCK_METHOD0(ResumeResourceRequest, void()); | 
|  | 116 }; | 
|  | 117 | 
|  | 118 class MockSafeBrowsingDatabaseManager : public SafeBrowsingDatabaseManager { | 
|  | 119  public: | 
|  | 120   MOCK_METHOD1(CancelApiCheck, bool(Client* client)); | 
|  | 121   MOCK_METHOD1(CancelCheck, void(Client* client)); | 
|  | 122   MOCK_CONST_METHOD1(CanCheckResourceType, | 
|  | 123                      bool(content::ResourceType resource_type)); | 
|  | 124   MOCK_CONST_METHOD1(CanCheckUrl, bool(const GURL& url)); | 
|  | 125   MOCK_CONST_METHOD0(ChecksAreAlwaysAsync, bool()); | 
|  | 126   MOCK_METHOD2(CheckApiBlacklistUrl, bool(const GURL& url, Client* client)); | 
|  | 127   MOCK_METHOD2(CheckBrowseUrl, bool(const GURL& url, Client* client)); | 
|  | 128   MOCK_METHOD2(CheckUrlForSubresourceFilter, | 
|  | 129                bool(const GURL& url, Client* client)); | 
|  | 130   MOCK_METHOD2(CheckDownloadUrl, | 
|  | 131                bool(const std::vector<GURL>& url_chain, Client* client)); | 
|  | 132   MOCK_METHOD2(CheckExtensionIDs, | 
|  | 133                bool(const std::set<std::string>& extension_ids, | 
|  | 134                     Client* client)); | 
|  | 135   MOCK_METHOD2(CheckResourceUrl, bool(const GURL& url, Client* client)); | 
|  | 136   MOCK_METHOD1(MatchCsdWhitelistUrl, bool(const GURL& url)); | 
|  | 137   MOCK_METHOD1(MatchDownloadWhitelistString, bool(const std::string& str)); | 
|  | 138   MOCK_METHOD1(MatchDownloadWhitelistUrl, bool(const GURL& url)); | 
|  | 139   MOCK_METHOD1(MatchMalwareIP, bool(const std::string& ip_address)); | 
|  | 140   MOCK_METHOD1(MatchModuleWhitelistString, bool(const std::string& str)); | 
|  | 141   MOCK_METHOD0(GetStoresForFullHashRequests, StoresToCheck()); | 
|  | 142   MOCK_CONST_METHOD0(GetThreatSource, ThreatSource()); | 
|  | 143   MOCK_METHOD0(IsCsdWhitelistKillSwitchOn, bool()); | 
|  | 144   MOCK_CONST_METHOD0(IsDownloadProtectionEnabled, bool()); | 
|  | 145   MOCK_METHOD0(IsMalwareKillSwitchOn, bool()); | 
|  | 146   MOCK_CONST_METHOD0(IsSupported, bool()); | 
|  | 147   MOCK_METHOD2(StartOnIOThread, | 
|  | 148                void(net::URLRequestContextGetter* request_context_getter, | 
|  | 149                     const V4ProtocolConfig& config)); | 
|  | 150   MOCK_METHOD1(StopOnIOThread, void(bool shutdown)); | 
|  | 151 | 
|  | 152  protected: | 
|  | 153   ~MockSafeBrowsingDatabaseManager() {} | 
|  | 154 }; | 
|  | 155 | 
|  | 156 class RequestCheckerTest : public ::testing::Test { | 
|  | 157  protected: | 
|  | 158   RequestCheckerTest() | 
|  | 159       : request_(url_request_context_.CreateRequest(GURL(kTestUrl), | 
|  | 160                                                     net::DEFAULT_PRIORITY, | 
|  | 161                                                     nullptr)), | 
|  | 162         database_manager_(new NiceMock<MockSafeBrowsingDatabaseManager>()), | 
|  | 163         ui_manager_(new NiceMock<SemiMockUIManager>()), | 
|  | 164         delegate_(base::MakeUnique<NiceMock<MockDelegate>>()), | 
|  | 165         checker_(base::MakeUnique<RequestChecker>( | 
|  | 166             request_.get(), | 
|  | 167             content::RESOURCE_TYPE_SUB_RESOURCE, | 
|  | 168             database_manager_, | 
|  | 169             ui_manager_, | 
|  | 170             delegate_.get())) { | 
|  | 171     // CanCheckResourceType() is called by almost all tests so make it pass by | 
|  | 172     // default. | 
|  | 173     ON_CALL(*database_manager_, CanCheckResourceType(_)) | 
|  | 174         .WillByDefault(Return(true)); | 
|  | 175   } | 
|  | 176   ~RequestCheckerTest() override { | 
|  | 177     // It's possible that something could hold a reference to these objects | 
|  | 178     // after the framework is destroyed, so make sure mock expectations have | 
|  | 179     // been verified. | 
|  | 180     ::testing::Mock::VerifyAndClearExpectations(database_manager_.get()); | 
|  | 181     ::testing::Mock::VerifyAndClearExpectations(ui_manager_.get()); | 
|  | 182   } | 
|  | 183 | 
|  | 184   const content::TestBrowserThreadBundle test_browser_thread_bundle_; | 
|  | 185   net::TestURLRequestContext url_request_context_; | 
|  | 186   const std::unique_ptr<net::URLRequest> request_; | 
|  | 187   const scoped_refptr<NiceMock<MockSafeBrowsingDatabaseManager>> | 
|  | 188       database_manager_; | 
|  | 189   const scoped_refptr<NiceMock<SemiMockUIManager>> ui_manager_; | 
|  | 190   const std::unique_ptr<NiceMock<MockDelegate>> delegate_; | 
|  | 191   std::unique_ptr<RequestChecker> checker_; | 
|  | 192 }; | 
|  | 193 | 
|  | 194 TEST_F(RequestCheckerTest, Constructs) { | 
|  | 195   // The framework constructor does all the work. | 
|  | 196 } | 
|  | 197 | 
|  | 198 TEST_F(RequestCheckerTest, UncheckedResourceType) { | 
|  | 199   EXPECT_CALL(*database_manager_, | 
|  | 200               CanCheckResourceType(content::RESOURCE_TYPE_SUB_RESOURCE)) | 
|  | 201       .WillOnce(Return(false)); | 
|  | 202   EXPECT_EQ(RequestChecker::PROCEED_SKIPPED, checker_->CheckNewRequest()); | 
|  | 203 } | 
|  | 204 | 
|  | 205 TEST_F(RequestCheckerTest, SynchronousPass) { | 
|  | 206   EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(true)); | 
|  | 207   EXPECT_EQ(RequestChecker::PROCEED_SAFE, checker_->CheckNewRequest()); | 
|  | 208 } | 
|  | 209 | 
|  | 210 TEST_F(RequestCheckerTest, CorrectUrlIsPassedToDatabaseManager) { | 
|  | 211   EXPECT_CALL(*database_manager_, CheckBrowseUrl(GURL(kTestUrl), _)) | 
|  | 212       .WillOnce(Return(true)); | 
|  | 213   checker_->CheckNewRequest(); | 
|  | 214 } | 
|  | 215 | 
|  | 216 TEST_F(RequestCheckerTest, ZeroDelayIsLogged) { | 
|  | 217   EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(true)); | 
|  | 218   EXPECT_CALL(*ui_manager_, LogPauseDelay(base::TimeDelta())); | 
|  | 219   checker_->CheckNewRequest(); | 
|  | 220 } | 
|  | 221 | 
|  | 222 TEST_F(RequestCheckerTest, SyncMissAsyncProceed) { | 
|  | 223   Checkpoint checkpoint; | 
|  | 224   EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false)); | 
|  | 225   EXPECT_CALL(*database_manager_, ChecksAreAlwaysAsync()) | 
|  | 226       .WillOnce(Return(false)); | 
|  | 227   { | 
|  | 228     InSequence s; | 
|  | 229     EXPECT_CALL(checkpoint, Call(1)); | 
|  | 230     EXPECT_CALL(*delegate_, ResumeResourceRequest()); | 
|  | 231   } | 
|  | 232 | 
|  | 233   EXPECT_EQ(RequestChecker::DEFER, checker_->CheckNewRequest()); | 
|  | 234   checkpoint.Call(1); | 
|  | 235   checker_->OnCheckBrowseUrlResult(GURL(kTestUrl), SB_THREAT_TYPE_SAFE, | 
|  | 236                                    ThreatMetadata()); | 
|  | 237 } | 
|  | 238 | 
|  | 239 TEST_F(RequestCheckerTest, SyncMissAsyncUnsafe) { | 
|  | 240   security_interstitials::UnsafeResource resource; | 
|  | 241   EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false)); | 
|  | 242   EXPECT_CALL(*database_manager_, ChecksAreAlwaysAsync()) | 
|  | 243       .WillOnce(Return(false)); | 
|  | 244   EXPECT_CALL(*delegate_, StartDisplayingBlockingPage(_, _)) | 
|  | 245       .WillOnce(SaveArg<0>(&resource)); | 
|  | 246   EXPECT_CALL(*delegate_, GetWebContentsGetterForRequest(request_.get())) | 
|  | 247       .WillOnce(Return( | 
|  | 248           base::Bind([]() -> content::WebContents* { return nullptr; }))); | 
|  | 249   EXPECT_CALL(*database_manager_, GetThreatSource()) | 
|  | 250       .WillOnce(Return(ThreatSource::LOCAL_PVER4)); | 
|  | 251   EXPECT_EQ(RequestChecker::DEFER, checker_->CheckNewRequest()); | 
|  | 252   checker_->OnCheckBrowseUrlResult(GURL(kTestUrl), SB_THREAT_TYPE_URL_MALWARE, | 
|  | 253                                    ThreatMetadata()); | 
|  | 254   EXPECT_EQ(GURL(kTestUrl), resource.url); | 
|  | 255   EXPECT_EQ(request_->original_url(), resource.original_url); | 
|  | 256   EXPECT_EQ(0u, resource.redirect_urls.size()); | 
|  | 257   EXPECT_TRUE(resource.is_subresource); | 
|  | 258   EXPECT_FALSE(resource.is_subframe); | 
|  | 259   EXPECT_EQ(SB_THREAT_TYPE_URL_MALWARE, resource.threat_type); | 
|  | 260   EXPECT_EQ(ThreatMetadata(), resource.threat_metadata); | 
|  | 261   EXPECT_FALSE(resource.callback.is_null()); | 
|  | 262   EXPECT_TRUE(resource.callback_thread); | 
|  | 263   EXPECT_EQ(nullptr, resource.web_contents_getter.Run()); | 
|  | 264   EXPECT_EQ(ThreatSource::LOCAL_PVER4, resource.threat_source); | 
|  | 265 } | 
|  | 266 | 
|  | 267 TEST_F(RequestCheckerTest, SyncMissAsyncUnsafeBlockBypassed) { | 
|  | 268   security_interstitials::UnsafeResource resource; | 
|  | 269   Checkpoint checkpoint; | 
|  | 270   EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false)); | 
|  | 271   EXPECT_CALL(*database_manager_, ChecksAreAlwaysAsync()) | 
|  | 272       .WillOnce(Return(false)); | 
|  | 273   EXPECT_CALL(*delegate_, StartDisplayingBlockingPage(_, _)) | 
|  | 274       .WillOnce(SaveArg<0>(&resource)); | 
|  | 275   EXPECT_CALL(*delegate_, GetWebContentsGetterForRequest(request_.get())) | 
|  | 276       .WillOnce(Return( | 
|  | 277           base::Bind([]() -> content::WebContents* { return nullptr; }))); | 
|  | 278   EXPECT_CALL(*database_manager_, GetThreatSource()) | 
|  | 279       .WillOnce(Return(ThreatSource::LOCAL_PVER4)); | 
|  | 280   { | 
|  | 281     InSequence s; | 
|  | 282     EXPECT_CALL(checkpoint, Call(1)); | 
|  | 283     EXPECT_CALL(*delegate_, ResumeResourceRequest()); | 
|  | 284   } | 
|  | 285   EXPECT_EQ(RequestChecker::DEFER, checker_->CheckNewRequest()); | 
|  | 286   checker_->OnCheckBrowseUrlResult(GURL(kTestUrl), SB_THREAT_TYPE_URL_MALWARE, | 
|  | 287                                    ThreatMetadata()); | 
|  | 288   checkpoint.Call(1); | 
|  | 289   resource.callback.Run(true); | 
|  | 290 } | 
|  | 291 | 
|  | 292 TEST_F(RequestCheckerTest, SyncMissAsyncUnsafeBlockRejected) { | 
|  | 293   security_interstitials::UnsafeResource resource; | 
|  | 294   Checkpoint checkpoint; | 
|  | 295   EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false)); | 
|  | 296   EXPECT_CALL(*database_manager_, ChecksAreAlwaysAsync()) | 
|  | 297       .WillOnce(Return(false)); | 
|  | 298   EXPECT_CALL(*delegate_, StartDisplayingBlockingPage(_, _)) | 
|  | 299       .WillOnce(SaveArg<0>(&resource)); | 
|  | 300   EXPECT_CALL(*delegate_, GetWebContentsGetterForRequest(request_.get())) | 
|  | 301       .WillOnce(Return( | 
|  | 302           base::Bind([]() -> content::WebContents* { return nullptr; }))); | 
|  | 303   EXPECT_CALL(*database_manager_, GetThreatSource()) | 
|  | 304       .WillOnce(Return(ThreatSource::LOCAL_PVER4)); | 
|  | 305   { | 
|  | 306     InSequence s; | 
|  | 307     EXPECT_CALL(checkpoint, Call(1)); | 
|  | 308     EXPECT_CALL(*delegate_, CancelResourceLoad()); | 
|  | 309   } | 
|  | 310   EXPECT_EQ(RequestChecker::DEFER, checker_->CheckNewRequest()); | 
|  | 311   checker_->OnCheckBrowseUrlResult(GURL(kTestUrl), SB_THREAT_TYPE_URL_MALWARE, | 
|  | 312                                    ThreatMetadata()); | 
|  | 313   checkpoint.Call(1); | 
|  | 314   resource.callback.Run(false); | 
|  | 315 } | 
|  | 316 | 
|  | 317 TEST_F(RequestCheckerTest, AlwaysAsyncSafe) { | 
|  | 318   EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false)); | 
|  | 319   EXPECT_CALL(*database_manager_, ChecksAreAlwaysAsync()) | 
|  | 320       .WillRepeatedly(Return(true)); | 
|  | 321   // ResumeResourceRequest() must not be called. | 
|  | 322   EXPECT_CALL(*delegate_, ResumeResourceRequest()).Times(0); | 
|  | 323   EXPECT_EQ(RequestChecker::PROCEED_ALWAYS_ASYNC, checker_->CheckNewRequest()); | 
|  | 324   checker_->OnCheckBrowseUrlResult(GURL(kTestUrl), SB_THREAT_TYPE_SAFE, | 
|  | 325                                    ThreatMetadata()); | 
|  | 326   EXPECT_EQ(RequestChecker::PROCEED_SAFE, checker_->ShouldDeferResponse()); | 
|  | 327 } | 
|  | 328 | 
|  | 329 TEST_F(RequestCheckerTest, AlwaysAsyncLateSafe) { | 
|  | 330   Checkpoint checkpoint; | 
|  | 331   EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false)); | 
|  | 332   EXPECT_CALL(*database_manager_, ChecksAreAlwaysAsync()) | 
|  | 333       .WillRepeatedly(Return(true)); | 
|  | 334   { | 
|  | 335     InSequence s; | 
|  | 336     EXPECT_CALL(checkpoint, Call(1)); | 
|  | 337     EXPECT_CALL(*delegate_, ResumeResourceRequest()); | 
|  | 338   } | 
|  | 339   EXPECT_EQ(RequestChecker::PROCEED_ALWAYS_ASYNC, checker_->CheckNewRequest()); | 
|  | 340   EXPECT_EQ(RequestChecker::DEFER, checker_->ShouldDeferResponse()); | 
|  | 341   checkpoint.Call(1); | 
|  | 342   checker_->OnCheckBrowseUrlResult(GURL(kTestUrl), SB_THREAT_TYPE_SAFE, | 
|  | 343                                    ThreatMetadata()); | 
|  | 344 } | 
|  | 345 | 
|  | 346 TEST_F(RequestCheckerTest, AlwaysAsyncUnsafe) { | 
|  | 347   EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false)); | 
|  | 348   EXPECT_CALL(*database_manager_, ChecksAreAlwaysAsync()) | 
|  | 349       .WillRepeatedly(Return(true)); | 
|  | 350   EXPECT_CALL(*delegate_, StartDisplayingBlockingPage(_, _)); | 
|  | 351   EXPECT_CALL(*delegate_, GetWebContentsGetterForRequest(request_.get())) | 
|  | 352       .WillOnce(Return( | 
|  | 353           base::Bind([]() -> content::WebContents* { return nullptr; }))); | 
|  | 354   EXPECT_CALL(*database_manager_, GetThreatSource()) | 
|  | 355       .WillOnce(Return(ThreatSource::LOCAL_PVER4)); | 
|  | 356   // ResumeResourceRequest() must not be called. | 
|  | 357   EXPECT_CALL(*delegate_, ResumeResourceRequest()).Times(0); | 
|  | 358   EXPECT_EQ(RequestChecker::PROCEED_ALWAYS_ASYNC, checker_->CheckNewRequest()); | 
|  | 359   checker_->OnCheckBrowseUrlResult(GURL(kTestUrl), SB_THREAT_TYPE_URL_MALWARE, | 
|  | 360                                    ThreatMetadata()); | 
|  | 361   EXPECT_EQ(RequestChecker::DEFER, checker_->ShouldDeferResponse()); | 
|  | 362 } | 
|  | 363 | 
|  | 364 TEST_F(RequestCheckerTest, RedirectToSafeSync) { | 
|  | 365   EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)) | 
|  | 366       .WillRepeatedly(Return(true)); | 
|  | 367   EXPECT_EQ(RequestChecker::PROCEED_SAFE, checker_->CheckNewRequest()); | 
|  | 368   EXPECT_EQ(RequestChecker::PROCEED_SAFE, | 
|  | 369             checker_->CheckRedirect(GURL(kTestUrl2))); | 
|  | 370 } | 
|  | 371 | 
|  | 372 TEST_F(RequestCheckerTest, RedirectToSafeAsync) { | 
|  | 373   EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)) | 
|  | 374       .WillOnce(Return(true)) | 
|  | 375       .WillOnce(Return(false)); | 
|  | 376   EXPECT_CALL(*delegate_, ResumeResourceRequest()); | 
|  | 377   EXPECT_EQ(RequestChecker::PROCEED_SAFE, checker_->CheckNewRequest()); | 
|  | 378   EXPECT_EQ(RequestChecker::DEFER, checker_->CheckRedirect(GURL(kTestUrl2))); | 
|  | 379   checker_->OnCheckBrowseUrlResult(GURL(kTestUrl2), SB_THREAT_TYPE_SAFE, | 
|  | 380                                    ThreatMetadata()); | 
|  | 381 } | 
|  | 382 | 
|  | 383 TEST_F(RequestCheckerTest, RedirectToUnsafe) { | 
|  | 384   EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)) | 
|  | 385       .WillOnce(Return(true)) | 
|  | 386       .WillOnce(Return(false)); | 
|  | 387   EXPECT_CALL(*delegate_, StartDisplayingBlockingPage(_, _)); | 
|  | 388   EXPECT_EQ(RequestChecker::PROCEED_SAFE, checker_->CheckNewRequest()); | 
|  | 389   EXPECT_EQ(RequestChecker::DEFER, checker_->CheckRedirect(GURL(kTestUrl2))); | 
|  | 390   checker_->OnCheckBrowseUrlResult(GURL(kTestUrl2), SB_THREAT_TYPE_URL_MALWARE, | 
|  | 391                                    ThreatMetadata()); | 
|  | 392 } | 
|  | 393 | 
|  | 394 TEST_F(RequestCheckerTest, RedirectToSafeThenUnsafe) { | 
|  | 395   security_interstitials::UnsafeResource resource; | 
|  | 396   Checkpoint checkpoint; | 
|  | 397   EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)) | 
|  | 398       .WillOnce(Return(true)) | 
|  | 399       .WillRepeatedly(Return(false)); | 
|  | 400   { | 
|  | 401     InSequence s; | 
|  | 402     EXPECT_CALL(checkpoint, Call(1)); | 
|  | 403     EXPECT_CALL(*delegate_, ResumeResourceRequest()); | 
|  | 404     EXPECT_CALL(checkpoint, Call(2)); | 
|  | 405     EXPECT_CALL(*delegate_, StartDisplayingBlockingPage(_, _)) | 
|  | 406         .WillOnce(SaveArg<0>(&resource)); | 
|  | 407   } | 
|  | 408   EXPECT_EQ(RequestChecker::PROCEED_SAFE, checker_->CheckNewRequest()); | 
|  | 409   EXPECT_EQ(RequestChecker::DEFER, checker_->CheckRedirect(GURL(kTestUrl2))); | 
|  | 410   checkpoint.Call(1); | 
|  | 411   checker_->OnCheckBrowseUrlResult(GURL(kTestUrl2), SB_THREAT_TYPE_SAFE, | 
|  | 412                                    ThreatMetadata()); | 
|  | 413   EXPECT_EQ(RequestChecker::DEFER, checker_->CheckRedirect(GURL(kTestUrl3))); | 
|  | 414   checkpoint.Call(2); | 
|  | 415   checker_->OnCheckBrowseUrlResult(GURL(kTestUrl3), SB_THREAT_TYPE_URL_MALWARE, | 
|  | 416                                    ThreatMetadata()); | 
|  | 417   EXPECT_EQ(GURL(kTestUrl3), resource.url); | 
|  | 418   EXPECT_EQ(GURL(kTestUrl), resource.original_url); | 
|  | 419   EXPECT_THAT(resource.redirect_urls, | 
|  | 420               ElementsAre(GURL(kTestUrl2), GURL(kTestUrl3))); | 
|  | 421 } | 
|  | 422 | 
|  | 423 TEST_F(RequestCheckerTest, RedirectToSafeAlwaysAsync) { | 
|  | 424   EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)) | 
|  | 425       .WillRepeatedly(Return(false)); | 
|  | 426   EXPECT_CALL(*database_manager_, ChecksAreAlwaysAsync()) | 
|  | 427       .WillRepeatedly(Return(true)); | 
|  | 428   EXPECT_CALL(*delegate_, ResumeResourceRequest()); | 
|  | 429   EXPECT_EQ(RequestChecker::PROCEED_ALWAYS_ASYNC, checker_->CheckNewRequest()); | 
|  | 430   EXPECT_EQ(RequestChecker::DEFER, checker_->CheckRedirect(GURL(kTestUrl2))); | 
|  | 431   checker_->OnCheckBrowseUrlResult(GURL(kTestUrl), SB_THREAT_TYPE_SAFE, | 
|  | 432                                    ThreatMetadata()); | 
|  | 433   checker_->OnCheckBrowseUrlResult(GURL(kTestUrl2), SB_THREAT_TYPE_SAFE, | 
|  | 434                                    ThreatMetadata()); | 
|  | 435 } | 
|  | 436 | 
|  | 437 TEST_F(RequestCheckerTest, AsyncTimeout) { | 
|  | 438   ScopedTimeoutForTesting scoped_timeout(1); | 
|  | 439   EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false)); | 
|  | 440   EXPECT_CALL(*database_manager_, CancelCheck(_)); | 
|  | 441   EXPECT_CALL(*delegate_, ResumeResourceRequest()); | 
|  | 442   EXPECT_EQ(RequestChecker::DEFER, checker_->CheckNewRequest()); | 
|  | 443   base::RunLoop run_loop; | 
|  | 444   content::BrowserThread::PostDelayedTask(content::BrowserThread::IO, FROM_HERE, | 
|  | 445                                           run_loop.QuitClosure(), | 
|  | 446                                           base::TimeDelta::FromMilliseconds(2)); | 
|  | 447   run_loop.Run(); | 
|  | 448 } | 
|  | 449 | 
|  | 450 TEST_F(RequestCheckerTest, TimeoutIsReallyCancelled) { | 
|  | 451   // The test is not flaky because OnCheckBrowseUrlResult() is called | 
|  | 452   // synchronously, and so will always succeed in cancelling the timer before | 
|  | 453   // OnCheckUrlTimeout can be called asynchronously. | 
|  | 454   ScopedTimeoutForTesting scoped_timeout(1); | 
|  | 455   EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false)); | 
|  | 456   EXPECT_CALL(*database_manager_, CancelCheck(_)).Times(0); | 
|  | 457   EXPECT_CALL(*delegate_, ResumeResourceRequest()); | 
|  | 458   EXPECT_EQ(RequestChecker::DEFER, checker_->CheckNewRequest()); | 
|  | 459   checker_->OnCheckBrowseUrlResult(GURL(kTestUrl), SB_THREAT_TYPE_SAFE, | 
|  | 460                                    ThreatMetadata()); | 
|  | 461   base::RunLoop run_loop; | 
|  | 462   content::BrowserThread::PostDelayedTask(content::BrowserThread::IO, FROM_HERE, | 
|  | 463                                           run_loop.QuitClosure(), | 
|  | 464                                           base::TimeDelta::FromMilliseconds(2)); | 
|  | 465   run_loop.Run(); | 
|  | 466   // If we get here without hitting a DCHECK then the test passed. | 
|  | 467 } | 
|  | 468 | 
|  | 469 TEST_F(RequestCheckerTest, PrefetchCancelledOnAsyncBlock) { | 
|  | 470   request_->SetLoadFlags(request_->load_flags() | net::LOAD_PREFETCH); | 
|  | 471   EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false)); | 
|  | 472   EXPECT_CALL(*delegate_, CancelResourceLoad()); | 
|  | 473   // Blocking page is not displayed for prefetch / prerender. | 
|  | 474   EXPECT_CALL(*delegate_, StartDisplayingBlockingPage(_, _)).Times(0); | 
|  | 475   EXPECT_EQ(RequestChecker::DEFER, checker_->CheckNewRequest()); | 
|  | 476   checker_->OnCheckBrowseUrlResult(GURL(kTestUrl), SB_THREAT_TYPE_URL_MALWARE, | 
|  | 477                                    ThreatMetadata()); | 
|  | 478 } | 
|  | 479 | 
|  | 480 TEST_F(RequestCheckerTest, PrerenderContentsDestroyed) { | 
|  | 481   request_->SetLoadFlags(request_->load_flags() | net::LOAD_PREFETCH); | 
|  | 482   // Change resource type to MAIN_FRAME. | 
|  | 483   checker_.reset( | 
|  | 484       new RequestChecker(request_.get(), content::RESOURCE_TYPE_MAIN_FRAME, | 
|  | 485                          database_manager_, ui_manager_, delegate_.get())); | 
|  | 486   EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false)); | 
|  | 487   EXPECT_CALL(*delegate_, CancelResourceLoad()); | 
|  | 488   EXPECT_CALL(*delegate_, MaybeDestroyPrerenderContents(_)); | 
|  | 489   EXPECT_CALL(*delegate_, StartDisplayingBlockingPage(_, _)).Times(0); | 
|  | 490   EXPECT_EQ(RequestChecker::DEFER, checker_->CheckNewRequest()); | 
|  | 491   checker_->OnCheckBrowseUrlResult(GURL(kTestUrl), SB_THREAT_TYPE_URL_MALWARE, | 
|  | 492                                    ThreatMetadata()); | 
|  | 493 } | 
|  | 494 | 
|  | 495 TEST_F(RequestCheckerTest, CheckCancelledOnDestruction) { | 
|  | 496   EXPECT_CALL(*database_manager_, CheckBrowseUrl(_, _)).WillOnce(Return(false)); | 
|  | 497   EXPECT_CALL(*database_manager_, CancelCheck(_)); | 
|  | 498   EXPECT_EQ(RequestChecker::DEFER, checker_->CheckNewRequest()); | 
|  | 499   checker_.reset(); | 
|  | 500 } | 
|  | 501 | 
|  | 502 }  // namespace | 
|  | 503 | 
|  | 504 }  // namespace safe_browsing | 
| OLD | NEW | 
|---|