1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Use of this source code is governed by a BSD-style license that can be 3dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// found in the LICENSE file. 4dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 5dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/command_line.h" 6dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/file_path.h" 7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/ref_counted.h" 8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h" 9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_temp_dir.h" 10dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/task.h" 11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/safe_browsing/client_side_detection_host.h" 12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/safe_browsing/client_side_detection_service.h" 13dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/safe_browsing/safe_browsing_service.h" 14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/common/chrome_switches.h" 15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/safe_browsing/csd.pb.h" 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/safe_browsing/safebrowsing_messages.h" 17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/test/testing_profile.h" 18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/test/ui_test_utils.h" 19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h" 20dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/test_render_view_host.h" 21dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/test_tab_contents.h" 22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "googleurl/src/gurl.h" 23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "ipc/ipc_test_sink.h" 24dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "testing/gmock/include/gmock/gmock.h" 25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "testing/gtest/include/gtest/gtest.h" 26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing ::testing::_; 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing ::testing::DeleteArg; 29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing ::testing::DoAll; 30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing ::testing::Eq; 31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing ::testing::Mock; 32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing ::testing::NiceMock; 33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing ::testing::NotNull; 34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing ::testing::Pointee; 35dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing ::testing::Return; 36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing ::testing::SaveArg; 37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing ::testing::SetArgumentPointee; 38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing ::testing::StrictMock; 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace { 41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst bool kFalse = false; 42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst bool kTrue = true; 43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 44dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 45dc0f95d653279beabeb9817299e2902918ba123eKristian Monsennamespace safe_browsing { 46dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenMATCHER_P(EqualsProto, other, "") { 48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return other.SerializeAsString() == arg.SerializeAsString(); 49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 51dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenclass MockClientSideDetectionService : public ClientSideDetectionService { 52dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen public: 53dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen explicit MockClientSideDetectionService(const FilePath& model_path) 54dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen : ClientSideDetectionService(model_path, NULL) {} 55dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen virtual ~MockClientSideDetectionService() {}; 56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MOCK_METHOD2(SendClientReportPhishingRequest, 58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void(ClientPhishingRequest*, 59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ClientReportPhishingRequestCallback*)); 60dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen MOCK_CONST_METHOD1(IsPrivateIPAddress, bool(const std::string&)); 61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MOCK_METHOD2(GetValidCachedResult, bool(const GURL&, bool*)); 62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MOCK_METHOD1(IsInCache, bool(const GURL&)); 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MOCK_METHOD0(OverReportLimit, bool()); 64dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 65dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen private: 66dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DISALLOW_COPY_AND_ASSIGN(MockClientSideDetectionService); 67dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}; 68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 69dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenclass MockSafeBrowsingService : public SafeBrowsingService { 70dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen public: 71dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen MockSafeBrowsingService() {} 72dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen virtual ~MockSafeBrowsingService() {} 73dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 74dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen MOCK_METHOD8(DisplayBlockingPage, 75dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen void(const GURL&, const GURL&, const std::vector<GURL>&, 76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ResourceType::Type, UrlCheckResult, Client*, int, int)); 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MOCK_METHOD1(MatchCsdWhitelistUrl, bool(const GURL&)); 78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 79dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Helper function which calls OnBlockingPageComplete for this client 80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // object. 81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen void InvokeOnBlockingPageComplete(SafeBrowsingService::Client* client) { 82dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 83dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(client); 84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Note: this will delete the client object in the case of the CsdClient 85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // implementation. 86dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen client->OnBlockingPageComplete(false); 87dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 88dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 89dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen private: 90dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DISALLOW_COPY_AND_ASSIGN(MockSafeBrowsingService); 91dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}; 92dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass MockTestingProfile : public TestingProfile { 94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public: 95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MockTestingProfile() {} 96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual ~MockTestingProfile() {} 97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MOCK_METHOD0(IsOffTheRecord, bool()); 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Helper function which quits the UI message loop from the IO message loop. 102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid QuitUIMessageLoop() { 103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen BrowserThread::PostTask(BrowserThread::UI, 105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FROM_HERE, 106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen new MessageLoop::QuitTask()); 107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 108dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 109dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenclass ClientSideDetectionHostTest : public RenderViewHostTestHarness { 110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen public: 111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen virtual void SetUp() { 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Set custom profile object so that we can mock calls to IsOffTheRecord. 113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // This needs to happen before we call the parent SetUp() function. We use 114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // a nice mock because other parts of the code are calling IsOffTheRecord. 115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen mock_profile_ = new NiceMock<MockTestingProfile>(); 116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen profile_.reset(mock_profile_); 117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 118dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen RenderViewHostTestHarness::SetUp(); 119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ui_thread_.reset(new BrowserThread(BrowserThread::UI, &message_loop_)); 120dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Note: we're starting a real IO thread to make sure our DCHECKs that 121dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // verify which thread is running are actually tested. 122dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen io_thread_.reset(new BrowserThread(BrowserThread::IO)); 123dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ASSERT_TRUE(io_thread_->Start()); 124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Inject service classes. 126dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ScopedTempDir tmp_dir; 127dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ASSERT_TRUE(tmp_dir.CreateUniqueTempDir()); 128dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FilePath model_path = tmp_dir.path().AppendASCII("model"); 129dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen csd_service_.reset(new StrictMock<MockClientSideDetectionService>( 131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_path)); 132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sb_service_ = new StrictMock<MockSafeBrowsingService>(); 133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen csd_host_ = contents()->safebrowsing_detection_host(); 134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen csd_host_->set_client_side_detection_service(csd_service_.get()); 135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen csd_host_->set_safe_browsing_service(sb_service_.get()); 136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Save command-line so that it can be restored for every test. 138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen original_cmd_line_.reset( 139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new CommandLine(*CommandLine::ForCurrentProcess())); 140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen virtual void TearDown() { 143dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen io_thread_.reset(); 144dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ui_thread_.reset(); 145dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen RenderViewHostTestHarness::TearDown(); 146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Restore the command-line like it was before we ran the test. 147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *CommandLine::ForCurrentProcess() = *original_cmd_line_; 148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 149dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void OnDetectedPhishingSite(const std::string& verdict_str) { 151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen csd_host_->OnDetectedPhishingSite(verdict_str); 152dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 153dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 154dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen void FlushIOMessageLoop() { 155dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // If there was a message posted on the IO thread to display the 156dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // interstitial page we know that it would have been posted before 157dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // we put the quit message there. 158dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen BrowserThread::PostTask(BrowserThread::IO, 159dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FROM_HERE, 160dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NewRunnableFunction(&QuitUIMessageLoop)); 161dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen MessageLoop::current()->Run(); 162dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 163dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void ExpectPreClassificationChecks(const GURL& url, 165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const bool* is_private, 166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const bool* is_incognito, 167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const bool* match_csd_whitelist, 168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const bool* get_valid_cached_result, 169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const bool* is_in_cache, 170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const bool* over_report_limit) { 171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (is_private) { 172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_CALL(*csd_service_, IsPrivateIPAddress(_)) 173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen .WillOnce(Return(*is_private)); 174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (is_incognito) { 176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_CALL(*mock_profile_, IsOffTheRecord()) 177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen .WillRepeatedly(Return(*is_incognito)); 178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (match_csd_whitelist) { 180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_CALL(*sb_service_, MatchCsdWhitelistUrl(url)) 181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen .WillOnce(Return(*match_csd_whitelist)); 182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (get_valid_cached_result) { 184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_CALL(*csd_service_, GetValidCachedResult(url, NotNull())) 185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen .WillOnce(DoAll(SetArgumentPointee<1>(true), 186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Return(*get_valid_cached_result))); 187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (is_in_cache) { 189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_CALL(*csd_service_, IsInCache(url)).WillOnce(Return(*is_in_cache)); 190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (over_report_limit) { 192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_CALL(*csd_service_, OverReportLimit()) 193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen .WillOnce(Return(*over_report_limit)); 194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void WaitAndCheckPreClassificationChecks() { 198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Wait for CheckCsdWhitelist to be called if at all. 199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FlushIOMessageLoop(); 200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Checks for CheckCache() to be called if at all. 201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MessageLoop::current()->RunAllPending(); 202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get())); 203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get())); 204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(Mock::VerifyAndClear(mock_profile_)); 205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 207dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen protected: 208dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ClientSideDetectionHost* csd_host_; 209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_ptr<StrictMock<MockClientSideDetectionService> > csd_service_; 210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_refptr<StrictMock<MockSafeBrowsingService> > sb_service_; 211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MockTestingProfile* mock_profile_; // We don't own this object 212dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 213dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen private: 214dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen scoped_ptr<BrowserThread> ui_thread_; 215dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen scoped_ptr<BrowserThread> io_thread_; 216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_ptr<CommandLine> original_cmd_line_; 217dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}; 218dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteInvalidVerdict) { 220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Case 0: renderer sends an invalid verdict string that we're unable to 221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // parse. 222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_CALL(*csd_service_, SendClientReportPhishingRequest(_, _)).Times(0); 223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnDetectedPhishingSite("Invalid Protocol Buffer"); 224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get())); 225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 227dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteNotPhishing) { 228dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Case 1: client thinks the page is phishing. The server does not agree. 229dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // No interstitial is shown. 230dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ClientSideDetectionService::ClientReportPhishingRequestCallback* cb; 231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ClientPhishingRequest verdict; 232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen verdict.set_url("http://phishingurl.com/"); 233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen verdict.set_client_score(1.0f); 234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen verdict.set_is_phishing(true); 235dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 236dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EXPECT_CALL(*csd_service_, 237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SendClientReportPhishingRequest(Pointee(EqualsProto(verdict)), _)) 238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen .WillOnce(DoAll(DeleteArg<0>(), SaveArg<1>(&cb))); 239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnDetectedPhishingSite(verdict.SerializeAsString()); 240dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get())); 241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(cb); 242dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 243dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Make sure DisplayBlockingPage is not going to be called. 244dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EXPECT_CALL(*sb_service_, 245dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DisplayBlockingPage(_, _, _, _, _, _, _, _)).Times(0); 246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen cb->Run(GURL(verdict.url()), false); 247dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delete cb; 248dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // If there was a message posted on the IO thread to display the 249dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // interstitial page we know that it would have been posted before 250dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // we put the quit message there. 251dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen BrowserThread::PostTask(BrowserThread::IO, 252dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FROM_HERE, 253dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NewRunnableFunction(&QuitUIMessageLoop)); 254dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen MessageLoop::current()->Run(); 255dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get())); 256dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 257dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 258dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteDisabled) { 259dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Case 2: client thinks the page is phishing and so does the server but 260dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // showing the interstitial is disabled => no interstitial is shown. 261dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ClientSideDetectionService::ClientReportPhishingRequestCallback* cb; 262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ClientPhishingRequest verdict; 263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen verdict.set_url("http://phishingurl.com/"); 264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen verdict.set_client_score(1.0f); 265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen verdict.set_is_phishing(true); 266dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 267dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EXPECT_CALL(*csd_service_, 268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SendClientReportPhishingRequest(Pointee(EqualsProto(verdict)), _)) 269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen .WillOnce(DoAll(DeleteArg<0>(), SaveArg<1>(&cb))); 270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnDetectedPhishingSite(verdict.SerializeAsString()); 271dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get())); 272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(cb); 273dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 274dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Make sure DisplayBlockingPage is not going to be called. 275dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EXPECT_CALL(*sb_service_, 276dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DisplayBlockingPage(_, _, _, _, _, _, _, _)).Times(0); 277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen cb->Run(GURL(verdict.url()), false); 278dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delete cb; 279dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 280dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FlushIOMessageLoop(); 281dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get())); 282dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 283dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 284dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteShowInterstitial) { 285dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Case 3: client thinks the page is phishing and so does the server. 286dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // We show an interstitial. 287dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ClientSideDetectionService::ClientReportPhishingRequestCallback* cb; 288dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GURL phishing_url("http://phishingurl.com/"); 289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ClientPhishingRequest verdict; 290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen verdict.set_url(phishing_url.spec()); 291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen verdict.set_client_score(1.0f); 292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen verdict.set_is_phishing(true); 293dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 294dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen CommandLine::ForCurrentProcess()->AppendSwitch( 295dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen switches::kEnableClientSidePhishingInterstitial); 296dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 297dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EXPECT_CALL(*csd_service_, 298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SendClientReportPhishingRequest(Pointee(EqualsProto(verdict)), _)) 299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen .WillOnce(DoAll(DeleteArg<0>(), SaveArg<1>(&cb))); 300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnDetectedPhishingSite(verdict.SerializeAsString()); 301dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get())); 302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(cb); 303dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 304dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SafeBrowsingService::Client* client; 305dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EXPECT_CALL(*sb_service_, 306dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DisplayBlockingPage( 307dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen phishing_url, 308dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen phishing_url, 309dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen _, 310dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ResourceType::MAIN_FRAME, 311dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SafeBrowsingService::URL_PHISHING, 312dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen _ /* a CsdClient object */, 313dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen contents()->GetRenderProcessHost()->id(), 314dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen contents()->render_view_host()->routing_id())) 315dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen .WillOnce(SaveArg<5>(&client)); 316dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 317dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen cb->Run(phishing_url, true); 318dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delete cb; 319dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 320dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FlushIOMessageLoop(); 321dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get())); 322dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 323dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Make sure the client object will be deleted. 324dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen BrowserThread::PostTask( 325dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen BrowserThread::IO, 326dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FROM_HERE, 327dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NewRunnableMethod( 328dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen sb_service_.get(), 329dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen &MockSafeBrowsingService::InvokeOnBlockingPageComplete, 330dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen client)); 331dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Since the CsdClient object will be deleted on the UI thread I need 332dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // to run the UI message loop. Post a task to stop the UI message loop 333dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // after the client object destructor is called. 334dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FlushIOMessageLoop(); 335dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 336dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 337dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_F(ClientSideDetectionHostTest, OnDetectedPhishingSiteMultiplePings) { 338dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Case 4 & 5: client thinks a page is phishing then navigates to 339dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // another page which is also considered phishing by the client 340dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // before the server responds with a verdict. After a while the 341dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // server responds for both requests with a phishing verdict. Only 342dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // a single interstitial is shown for the second URL. 343dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ClientSideDetectionService::ClientReportPhishingRequestCallback* cb; 344dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GURL phishing_url("http://phishingurl.com/"); 345ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ClientPhishingRequest verdict; 346ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen verdict.set_url(phishing_url.spec()); 347ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen verdict.set_client_score(1.0f); 348ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen verdict.set_is_phishing(true); 349dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 350dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen CommandLine::ForCurrentProcess()->AppendSwitch( 351dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen switches::kEnableClientSidePhishingInterstitial); 352dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 353dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EXPECT_CALL(*csd_service_, 354ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SendClientReportPhishingRequest(Pointee(EqualsProto(verdict)), _)) 355ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen .WillOnce(DoAll(DeleteArg<0>(), SaveArg<1>(&cb))); 356ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnDetectedPhishingSite(verdict.SerializeAsString()); 357dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get())); 358ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(cb); 359dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GURL other_phishing_url("http://other_phishing_url.com/bla"); 360ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectPreClassificationChecks(other_phishing_url, &kFalse, &kFalse, &kFalse, 361ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &kFalse, &kFalse, &kFalse); 362dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // We navigate away. The callback cb should be revoked. 363dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NavigateAndCommit(other_phishing_url); 364dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Wait for the pre-classification checks to finish for other_phishing_url. 365ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WaitAndCheckPreClassificationChecks(); 366dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 367dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ClientSideDetectionService::ClientReportPhishingRequestCallback* cb_other; 368ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen verdict.set_url(other_phishing_url.spec()); 369ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen verdict.set_client_score(0.8f); 370dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EXPECT_CALL(*csd_service_, 371ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SendClientReportPhishingRequest(Pointee(EqualsProto(verdict)), _)) 372ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen .WillOnce(DoAll(DeleteArg<0>(), SaveArg<1>(&cb_other))); 373ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnDetectedPhishingSite(verdict.SerializeAsString()); 374dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get())); 375dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ASSERT_TRUE(cb_other); 376dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 377dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // We expect that the interstitial is shown for the second phishing URL and 378dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // not for the first phishing URL. 379dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EXPECT_CALL(*sb_service_, 380dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DisplayBlockingPage(phishing_url, phishing_url,_, _, _, _, _, _)) 381dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen .Times(0); 382dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SafeBrowsingService::Client* client; 383dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EXPECT_CALL(*sb_service_, 384dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DisplayBlockingPage( 385dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen other_phishing_url, 386dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen other_phishing_url, 387dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen _, 388dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ResourceType::MAIN_FRAME, 389dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SafeBrowsingService::URL_PHISHING, 390dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen _ /* a CsdClient object */, 391dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen contents()->GetRenderProcessHost()->id(), 392dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen contents()->render_view_host()->routing_id())) 393dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen .WillOnce(SaveArg<5>(&client)); 394dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 395dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen cb->Run(phishing_url, true); // Should have no effect. 396dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delete cb; 397dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen cb_other->Run(other_phishing_url, true); // Should show interstitial. 398dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delete cb_other; 399dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 400dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FlushIOMessageLoop(); 401dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get())); 402dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 403dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Make sure the client object will be deleted. 404dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen BrowserThread::PostTask( 405dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen BrowserThread::IO, 406dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FROM_HERE, 407dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NewRunnableMethod( 408dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen sb_service_.get(), 409dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen &MockSafeBrowsingService::InvokeOnBlockingPageComplete, 410dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen client)); 411dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Since the CsdClient object will be deleted on the UI thread I need 412dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // to run the UI message loop. Post a task to stop the UI message loop 413dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // after the client object destructor is called. 414dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FlushIOMessageLoop(); 415dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 416dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 417ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(ClientSideDetectionHostTest, NavigationCancelsShouldClassifyUrl) { 418ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Test that canceling pending should classify requests works as expected. 419ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 420ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GURL first_url("http://first.phishy.url.com"); 421ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The proxy checks is done synchronously so check that it has been done 422ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // for the first URL. 423ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectPreClassificationChecks(first_url, &kFalse, &kFalse, &kFalse, NULL, 424ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NULL, NULL); 425ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NavigateAndCommit(first_url); 426ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 427ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Don't flush the message loop, as we want to navigate to a different 428ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // url before the final pre-classification checks are run. 429ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GURL second_url("http://second.url.com/"); 430ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectPreClassificationChecks(second_url, &kFalse, &kFalse, &kFalse, &kFalse, 431ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &kFalse, &kFalse); 432ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NavigateAndCommit(second_url); 433ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WaitAndCheckPreClassificationChecks(); 434ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 435ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 436dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_F(ClientSideDetectionHostTest, ShouldClassifyUrl) { 437dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Navigate the tab to a page. We should see a StartPhishingDetection IPC. 438ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GURL url("http://host.com/"); 439ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse, 440ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &kFalse, &kFalse); 441ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NavigateAndCommit(url); 442ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WaitAndCheckPreClassificationChecks(); 443ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 444dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const IPC::Message* msg = process()->sink().GetFirstMessageMatching( 445ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SafeBrowsingMsg_StartPhishingDetection::ID); 446dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ASSERT_TRUE(msg); 447ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Tuple1<GURL> actual_url; 448ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SafeBrowsingMsg_StartPhishingDetection::Read(msg, &actual_url); 449ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(url, actual_url.a); 450dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EXPECT_EQ(rvh()->routing_id(), msg->routing_id()); 451dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen process()->sink().ClearMessages(); 452dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 453dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Now try an in-page navigation. This should not trigger an IPC. 454dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EXPECT_CALL(*csd_service_, IsPrivateIPAddress(_)).Times(0); 455ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen url = GURL("http://host.com/#foo"); 456ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectPreClassificationChecks(url, NULL, NULL, NULL, NULL, NULL, NULL); 457ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NavigateAndCommit(url); 458ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WaitAndCheckPreClassificationChecks(); 459ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 460dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen msg = process()->sink().GetFirstMessageMatching( 461ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SafeBrowsingMsg_StartPhishingDetection::ID); 462dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ASSERT_FALSE(msg); 463dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 464ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Check that XHTML is supported, in addition to the default HTML type. 465ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Note: for this test to work correctly, the new URL must be on the 466ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // same domain as the previous URL, otherwise it will create a new 467ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // RenderViewHost that won't have the mime type set. 468ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen url = GURL("http://host.com/xhtml"); 469ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen rvh()->set_contents_mime_type("application/xhtml+xml"); 470ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse, 471ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &kFalse, &kFalse); 472ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NavigateAndCommit(url); 473ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WaitAndCheckPreClassificationChecks(); 474ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen msg = process()->sink().GetFirstMessageMatching( 475ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SafeBrowsingMsg_StartPhishingDetection::ID); 476ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(msg); 477ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SafeBrowsingMsg_StartPhishingDetection::Read(msg, &actual_url); 478ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(url, actual_url.a); 479ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(rvh()->routing_id(), msg->routing_id()); 480ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen process()->sink().ClearMessages(); 481ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 482dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Navigate to a new host, which should cause another IPC. 483ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen url = GURL("http://host2.com/"); 484ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse, 485ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &kFalse, &kFalse); 486ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NavigateAndCommit(url); 487ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WaitAndCheckPreClassificationChecks(); 488dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen msg = process()->sink().GetFirstMessageMatching( 489ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SafeBrowsingMsg_StartPhishingDetection::ID); 490dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ASSERT_TRUE(msg); 491ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SafeBrowsingMsg_StartPhishingDetection::Read(msg, &actual_url); 492ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(url, actual_url.a); 493dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EXPECT_EQ(rvh()->routing_id(), msg->routing_id()); 494dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen process()->sink().ClearMessages(); 495dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 496ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If the mime type is not one that we support, no IPC should be triggered. 497ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Note: for this test to work correctly, the new URL must be on the 498ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // same domain as the previous URL, otherwise it will create a new 499ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // RenderViewHost that won't have the mime type set. 500ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen url = GURL("http://host2.com/image.jpg"); 501ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen rvh()->set_contents_mime_type("image/jpeg"); 502ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectPreClassificationChecks(url, NULL, NULL, NULL, NULL, NULL, NULL); 503ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NavigateAndCommit(url); 504ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WaitAndCheckPreClassificationChecks(); 505ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen msg = process()->sink().GetFirstMessageMatching( 506ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SafeBrowsingMsg_StartPhishingDetection::ID); 507ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_FALSE(msg); 508ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 509dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // If IsPrivateIPAddress returns true, no IPC should be triggered. 510ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen url = GURL("http://host3.com/"); 511ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectPreClassificationChecks(url, &kTrue, NULL, NULL, NULL, NULL, NULL); 512ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NavigateAndCommit(url); 513ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WaitAndCheckPreClassificationChecks(); 514dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen msg = process()->sink().GetFirstMessageMatching( 515ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SafeBrowsingMsg_StartPhishingDetection::ID); 516dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ASSERT_FALSE(msg); 517dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 518dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // If the connection is proxied, no IPC should be triggered. 519dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Note: for this test to work correctly, the new URL must be on the 520dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // same domain as the previous URL, otherwise it will create a new 521dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // RenderViewHost that won't have simulate_fetch_via_proxy set. 522ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen url = GURL("http://host3.com/abc"); 523dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen rvh()->set_simulate_fetch_via_proxy(true); 524ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectPreClassificationChecks(url, NULL, NULL, NULL, NULL, NULL, NULL); 525ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NavigateAndCommit(url); 526ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WaitAndCheckPreClassificationChecks(); 527ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen msg = process()->sink().GetFirstMessageMatching( 528ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SafeBrowsingMsg_StartPhishingDetection::ID); 529ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_FALSE(msg); 530ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 531ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If the tab is incognito there should be no IPC. Also, we shouldn't 532ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // even check the csd-whitelist. 533ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen url = GURL("http://host4.com/"); 534ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectPreClassificationChecks(url, &kFalse, &kTrue, NULL, NULL, NULL, NULL); 535ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NavigateAndCommit(url); 536ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WaitAndCheckPreClassificationChecks(); 537ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen msg = process()->sink().GetFirstMessageMatching( 538ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SafeBrowsingMsg_StartPhishingDetection::ID); 539ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_FALSE(msg); 540ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 541ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If the URL is on the csd whitelist, no IPC should be triggered. 542ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen url = GURL("http://host5.com/"); 543ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kTrue, NULL, NULL, 544ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NULL); 545ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NavigateAndCommit(url); 546ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WaitAndCheckPreClassificationChecks(); 547ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen msg = process()->sink().GetFirstMessageMatching( 548ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SafeBrowsingMsg_StartPhishingDetection::ID); 549ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_FALSE(msg); 550ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 551ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If item is in the cache but it isn't valid, we will classify regardless 552ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // of whether we are over the reporting limit. 553ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen url = GURL("http://host6.com/"); 554ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse, &kTrue, 555ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NULL); 556ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NavigateAndCommit(url); 557ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WaitAndCheckPreClassificationChecks(); 558ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen msg = process()->sink().GetFirstMessageMatching( 559ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SafeBrowsingMsg_StartPhishingDetection::ID); 560ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_TRUE(msg); 561ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SafeBrowsingMsg_StartPhishingDetection::Read(msg, &actual_url); 562ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(url, actual_url.a); 563ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(rvh()->routing_id(), msg->routing_id()); 564ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen process()->sink().ClearMessages(); 565ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 566ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If the url isn't in the cache and we are over the reporting limit, we 567ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // don't do classification. 568ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen url = GURL("http://host7.com/"); 569ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse, 570ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &kFalse, &kTrue); 571ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NavigateAndCommit(url); 572ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WaitAndCheckPreClassificationChecks(); 573ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen msg = process()->sink().GetFirstMessageMatching( 574ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SafeBrowsingMsg_StartPhishingDetection::ID); 575ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ASSERT_FALSE(msg); 576ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 577ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If result is cached, we will try and display the blocking page directly 578ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // with no start classification message. 579ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CommandLine::ForCurrentProcess()->AppendSwitch( 580ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen switches::kEnableClientSidePhishingInterstitial); 581ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen url = GURL("http://host8.com/"); 582ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kTrue, NULL, 583ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NULL); 584ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_CALL(*sb_service_, 585ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DisplayBlockingPage(Eq(url), Eq(url), _, _, _, _, _, _)) 586ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen .WillOnce(DeleteArg<5>()); 587ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NavigateAndCommit(url); 588ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Wait for CheckCsdWhitelist to be called on the IO thread. 589ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FlushIOMessageLoop(); 590ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Wait for CheckCache() to be called on the UI thread. 591ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MessageLoop::current()->RunAllPending(); 592ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Wait for DisplayBlockingPage to be called on the IO thread. 593dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FlushIOMessageLoop(); 594ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Now we check that all expected functions were indeed called on the two 595ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // service objects. 596ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get())); 597ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(Mock::VerifyAndClear(sb_service_.get())); 598dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen msg = process()->sink().GetFirstMessageMatching( 599ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SafeBrowsingMsg_StartPhishingDetection::ID); 600dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ASSERT_FALSE(msg); 601dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 602dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 603dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} // namespace safe_browsing 604