| Index: chrome/browser/safe_browsing/protocol_manager_unittest.cc
|
| diff --git a/chrome/browser/safe_browsing/protocol_manager_unittest.cc b/chrome/browser/safe_browsing/protocol_manager_unittest.cc
|
| index 75f4097b89681bcfa7b62eedd9b55abfabcb2637..460ab49a23a1092d1000d2c9a0b13926cc1d2147 100644
|
| --- a/chrome/browser/safe_browsing/protocol_manager_unittest.cc
|
| +++ b/chrome/browser/safe_browsing/protocol_manager_unittest.cc
|
| @@ -253,7 +253,8 @@ class MockProtocolDelegate : public SafeBrowsingProtocolManagerDelegate {
|
| MOCK_METHOD1(UpdateFinished, void(bool));
|
| MOCK_METHOD0(ResetDatabase, void());
|
| MOCK_METHOD1(GetChunks, void(GetChunksCallback));
|
| - MOCK_METHOD2(AddChunks, void(const std::string&, SBChunkList*));
|
| + MOCK_METHOD3(AddChunks, void(const std::string&, SBChunkList*,
|
| + AddChunksCallback));
|
| MOCK_METHOD1(DeleteChunks, void(std::vector<SBChunkDelete>*));
|
| };
|
|
|
| @@ -312,6 +313,18 @@ void InvokeGetChunksCallback(
|
| callback.Run(ranges, database_error);
|
| }
|
|
|
| +// |DeferAddChunksCallback| is used to asynchronously invoke |callback|,
|
| +// since SafeBrowsingProtocolManager is not re-entrant at that point. This
|
| +// guarantee is part of the SafeBrowsingProtocolManagerDelegate contract.
|
| +void DeferAddChunksCallback(
|
| + SafeBrowsingProtocolManagerDelegate::AddChunksCallback callback) {
|
| + scoped_refptr<base::SingleThreadTaskRunner> task_runner(
|
| + base::ThreadTaskRunnerHandle::Get());
|
| + if (!task_runner)
|
| + return;
|
| + task_runner->PostTask(FROM_HERE, callback);
|
| +}
|
| +
|
| } // namespace
|
|
|
| // Tests that the Update protocol will be skipped if there are problems
|
| @@ -334,10 +347,12 @@ TEST_F(SafeBrowsingProtocolManagerTest, ProblemAccessingDatabase) {
|
|
|
| pm->ForceScheduleNextUpdate(base::TimeDelta());
|
| runner->RunTasks();
|
| +
|
| + EXPECT_TRUE(pm->IsUpdateScheduled());
|
| }
|
|
|
| -// Tests the contents of the POST body when the local database is empty.
|
| -TEST_F(SafeBrowsingProtocolManagerTest, EmptyDatabase) {
|
| +// Tests what happens when there is a response with no chunks.
|
| +TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseEmptyBody) {
|
| scoped_refptr<ImmediateSingleThreadTaskRunner> runner(
|
| new ImmediateSingleThreadTaskRunner());
|
| base::ThreadTaskRunnerHandle runner_handler(runner);
|
| @@ -349,6 +364,7 @@ TEST_F(SafeBrowsingProtocolManagerTest, EmptyDatabase) {
|
| Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
|
| std::vector<SBListChunkRanges>(),
|
| false)));
|
| + EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
|
|
|
| scoped_ptr<SafeBrowsingProtocolManager> pm(
|
| CreateProtocolManager(&test_delegate));
|
| @@ -360,6 +376,14 @@ TEST_F(SafeBrowsingProtocolManagerTest, EmptyDatabase) {
|
| // We should have an URLFetcher at this point in time.
|
| net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
|
| ValidateUpdateFetcherRequest(url_fetcher);
|
| +
|
| + // The update response is successful, but an empty body.
|
| + url_fetcher->set_status(net::URLRequestStatus());
|
| + url_fetcher->set_response_code(200);
|
| + url_fetcher->SetResponseString("");
|
| + url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
|
| +
|
| + EXPECT_TRUE(pm->IsUpdateScheduled());
|
| }
|
|
|
| // Tests the contents of the POST body when there are contents in the
|
| @@ -388,6 +412,7 @@ TEST_F(SafeBrowsingProtocolManagerTest, ExistingDatabase) {
|
| Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
|
| ranges,
|
| false)));
|
| + EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
|
|
|
| scoped_ptr<SafeBrowsingProtocolManager> pm(
|
| CreateProtocolManager(&test_delegate));
|
| @@ -407,10 +432,16 @@ TEST_F(SafeBrowsingProtocolManagerTest, ExistingDatabase) {
|
| EXPECT_EQ(GURL("https://prefix.com/foo/downloads?client=unittest&appver=1.0"
|
| "&pver=2.2" + key_param_),
|
| url_fetcher->GetOriginalURL());
|
| + url_fetcher->set_status(net::URLRequestStatus());
|
| + url_fetcher->set_response_code(200);
|
| + url_fetcher->SetResponseString("");
|
| + url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
|
| +
|
| + EXPECT_TRUE(pm->IsUpdateScheduled());
|
| }
|
|
|
| -// Tests what happens when there is a response with no chunks.
|
| -TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseEmptyBody) {
|
| +
|
| +TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseBadBody) {
|
| scoped_refptr<ImmediateSingleThreadTaskRunner> runner(
|
| new ImmediateSingleThreadTaskRunner());
|
| base::ThreadTaskRunnerHandle runner_handler(runner);
|
| @@ -422,7 +453,7 @@ TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseEmptyBody) {
|
| Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
|
| std::vector<SBListChunkRanges>(),
|
| false)));
|
| - EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
|
| + EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
|
|
|
| scoped_ptr<SafeBrowsingProtocolManager> pm(
|
| CreateProtocolManager(&test_delegate));
|
| @@ -435,14 +466,17 @@ TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseEmptyBody) {
|
| net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
|
| ValidateUpdateFetcherRequest(url_fetcher);
|
|
|
| - // The update response is successful, but an empty body.
|
| + // The update response is successful, but an invalid body.
|
| url_fetcher->set_status(net::URLRequestStatus());
|
| url_fetcher->set_response_code(200);
|
| - url_fetcher->SetResponseString("");
|
| + url_fetcher->SetResponseString("THIS_IS_A_BAD_RESPONSE");
|
| url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
|
| +
|
| + EXPECT_TRUE(pm->IsUpdateScheduled());
|
| }
|
|
|
| -TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseBadBody) {
|
| +// Tests what happens when there is an error in the update response.
|
| +TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseHttpError) {
|
| scoped_refptr<ImmediateSingleThreadTaskRunner> runner(
|
| new ImmediateSingleThreadTaskRunner());
|
| base::ThreadTaskRunnerHandle runner_handler(runner);
|
| @@ -467,15 +501,17 @@ TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseBadBody) {
|
| net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
|
| ValidateUpdateFetcherRequest(url_fetcher);
|
|
|
| - // The update response is successful, but an invalid body.
|
| + // Go ahead and respond to it.
|
| url_fetcher->set_status(net::URLRequestStatus());
|
| - url_fetcher->set_response_code(200);
|
| - url_fetcher->SetResponseString("THIS_IS_A_BAD_RESPONSE");
|
| + url_fetcher->set_response_code(404);
|
| + url_fetcher->SetResponseString("");
|
| url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
|
| +
|
| + EXPECT_TRUE(pm->IsUpdateScheduled());
|
| }
|
|
|
| -// Tests what happens when there is an error in the update response.
|
| -TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseHttpError) {
|
| +// Tests what happens when there is an error with the connection.
|
| +TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseConnectionError) {
|
| scoped_refptr<ImmediateSingleThreadTaskRunner> runner(
|
| new ImmediateSingleThreadTaskRunner());
|
| base::ThreadTaskRunnerHandle runner_handler(runner);
|
| @@ -501,14 +537,15 @@ TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseHttpError) {
|
| ValidateUpdateFetcherRequest(url_fetcher);
|
|
|
| // Go ahead and respond to it.
|
| - url_fetcher->set_status(net::URLRequestStatus());
|
| - url_fetcher->set_response_code(404);
|
| - url_fetcher->SetResponseString("");
|
| + url_fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED,
|
| + net::ERR_CONNECTION_RESET));
|
| url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
|
| +
|
| + EXPECT_TRUE(pm->IsUpdateScheduled());
|
| }
|
|
|
| -// Tests what happens when there is an error with the connection.
|
| -TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseConnectionError) {
|
| +// Tests what happens when there is a timeout before an update response.
|
| +TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseTimeout) {
|
| scoped_refptr<ImmediateSingleThreadTaskRunner> runner(
|
| new ImmediateSingleThreadTaskRunner());
|
| base::ThreadTaskRunnerHandle runner_handler(runner);
|
| @@ -533,14 +570,99 @@ TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseConnectionError) {
|
| net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
|
| ValidateUpdateFetcherRequest(url_fetcher);
|
|
|
| - // Go ahead and respond to it.
|
| - url_fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED,
|
| - net::ERR_CONNECTION_RESET));
|
| + // The first time RunTasks is called above, the update timeout timer is not
|
| + // handled. This call of RunTasks will handle the update.
|
| + runner->RunTasks();
|
| +
|
| + EXPECT_TRUE(pm->IsUpdateScheduled());
|
| +}
|
| +
|
| +// Tests what happens when there is a reset command in the response.
|
| +TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseReset) {
|
| + scoped_refptr<ImmediateSingleThreadTaskRunner> runner(
|
| + new ImmediateSingleThreadTaskRunner());
|
| + base::ThreadTaskRunnerHandle runner_handler(runner);
|
| + net::TestURLFetcherFactory url_fetcher_factory;
|
| +
|
| + testing::StrictMock<MockProtocolDelegate> test_delegate;
|
| + EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
|
| + EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
|
| + Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
|
| + std::vector<SBListChunkRanges>(),
|
| + false)));
|
| + EXPECT_CALL(test_delegate, ResetDatabase()).Times(1);
|
| + EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
|
| +
|
| + scoped_ptr<SafeBrowsingProtocolManager> pm(
|
| + CreateProtocolManager(&test_delegate));
|
| +
|
| + // Kick off initialization. This returns chunks from the DB synchronously.
|
| + pm->ForceScheduleNextUpdate(base::TimeDelta());
|
| + runner->RunTasks();
|
| +
|
| + // We should have an URLFetcher at this point in time.
|
| + net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
|
| + ValidateUpdateFetcherRequest(url_fetcher);
|
| +
|
| + // The update response is successful, and has a reset command.
|
| + url_fetcher->set_status(net::URLRequestStatus());
|
| + url_fetcher->set_response_code(200);
|
| + url_fetcher->SetResponseString("r:pleasereset\n");
|
| url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
|
| +
|
| + EXPECT_TRUE(pm->IsUpdateScheduled());
|
| }
|
|
|
| -// Tests what happens when there is a timeout before an update response.
|
| -TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseTimeout) {
|
| +// Tests a single valid update response, followed by a single redirect response
|
| +// that has an valid, but empty body.
|
| +TEST_F(SafeBrowsingProtocolManagerTest, EmptyRedirectResponse) {
|
| + scoped_refptr<ImmediateSingleThreadTaskRunner> runner(
|
| + new ImmediateSingleThreadTaskRunner());
|
| + base::ThreadTaskRunnerHandle runner_handler(runner);
|
| + net::TestURLFetcherFactory url_fetcher_factory;
|
| +
|
| + testing::StrictMock<MockProtocolDelegate> test_delegate;
|
| + EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
|
| + EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
|
| + Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
|
| + std::vector<SBListChunkRanges>(),
|
| + false)));
|
| + EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
|
| +
|
| + scoped_ptr<SafeBrowsingProtocolManager> pm(
|
| + CreateProtocolManager(&test_delegate));
|
| +
|
| + // Kick off initialization. This returns chunks from the DB synchronously.
|
| + pm->ForceScheduleNextUpdate(base::TimeDelta());
|
| + runner->RunTasks();
|
| +
|
| + // We should have an URLFetcher at this point in time.
|
| + net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
|
| + ValidateUpdateFetcherRequest(url_fetcher);
|
| +
|
| + // The update response is successful, and has a reset command.
|
| + url_fetcher->set_status(net::URLRequestStatus());
|
| + url_fetcher->set_response_code(200);
|
| + url_fetcher->SetResponseString(
|
| + "i:goog-phish-shavar\n"
|
| + "u:redirect-server.example.com/path\n");
|
| + url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
|
| +
|
| + // We should have another request.
|
| + net::TestURLFetcher* chunk_url_fetcher =
|
| + url_fetcher_factory.GetFetcherByID(1);
|
| + ASSERT_TRUE(chunk_url_fetcher != NULL);
|
| + chunk_url_fetcher->set_status(net::URLRequestStatus());
|
| + chunk_url_fetcher->set_response_code(200);
|
| + chunk_url_fetcher->SetResponseString("");
|
| + chunk_url_fetcher->delegate()->OnURLFetchComplete(chunk_url_fetcher);
|
| +
|
| + EXPECT_TRUE(pm->IsUpdateScheduled());
|
| +}
|
| +
|
| +// Tests a single valid update response, followed by a single redirect response
|
| +// that has an invalid body.
|
| +TEST_F(SafeBrowsingProtocolManagerTest, InvalidRedirectResponse) {
|
| scoped_refptr<ImmediateSingleThreadTaskRunner> runner(
|
| new ImmediateSingleThreadTaskRunner());
|
| base::ThreadTaskRunnerHandle runner_handler(runner);
|
| @@ -565,13 +687,84 @@ TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseTimeout) {
|
| net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
|
| ValidateUpdateFetcherRequest(url_fetcher);
|
|
|
| - // The first time RunTasks is called above, the update timeout timer is not
|
| - // handled. This call of RunTasks will handle the update.
|
| + // The update response is successful, and has a reset command.
|
| + url_fetcher->set_status(net::URLRequestStatus());
|
| + url_fetcher->set_response_code(200);
|
| + url_fetcher->SetResponseString(
|
| + "i:goog-phish-shavar\n"
|
| + "u:redirect-server.example.com/path\n");
|
| + url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
|
| +
|
| + // We should have another request.
|
| + net::TestURLFetcher* chunk_url_fetcher =
|
| + url_fetcher_factory.GetFetcherByID(1);
|
| + ASSERT_TRUE(chunk_url_fetcher != NULL);
|
| + chunk_url_fetcher->set_status(net::URLRequestStatus());
|
| + chunk_url_fetcher->set_response_code(200);
|
| + chunk_url_fetcher->SetResponseString("THIS IS AN INVALID RESPONSE");
|
| + chunk_url_fetcher->delegate()->OnURLFetchComplete(chunk_url_fetcher);
|
| +
|
| + EXPECT_TRUE(pm->IsUpdateScheduled());
|
| +}
|
| +
|
| +// Tests a single valid update response, followed by a single redirect response
|
| +// containing chunks.
|
| +TEST_F(SafeBrowsingProtocolManagerTest, SingleRedirectResponseWithChunks) {
|
| + scoped_refptr<ImmediateSingleThreadTaskRunner> runner(
|
| + new ImmediateSingleThreadTaskRunner());
|
| + base::ThreadTaskRunnerHandle runner_handler(runner);
|
| + net::TestURLFetcherFactory url_fetcher_factory;
|
| +
|
| + testing::StrictMock<MockProtocolDelegate> test_delegate;
|
| + EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
|
| + EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
|
| + Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
|
| + std::vector<SBListChunkRanges>(),
|
| + false)));
|
| + EXPECT_CALL(test_delegate, AddChunks("goog-phish-shavar", _, _)).WillOnce(
|
| + testing::WithArgs<2>(
|
| + Invoke(DeferAddChunksCallback)));
|
| + EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
|
| +
|
| + scoped_ptr<SafeBrowsingProtocolManager> pm(
|
| + CreateProtocolManager(&test_delegate));
|
| +
|
| + // Kick off initialization. This returns chunks from the DB synchronously.
|
| + pm->ForceScheduleNextUpdate(base::TimeDelta());
|
| + runner->RunTasks();
|
| +
|
| + // We should have an URLFetcher at this point in time.
|
| + net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
|
| + ValidateUpdateFetcherRequest(url_fetcher);
|
| +
|
| + // The update response is successful, and has a reset command.
|
| + url_fetcher->set_status(net::URLRequestStatus());
|
| + url_fetcher->set_response_code(200);
|
| + url_fetcher->SetResponseString(
|
| + "i:goog-phish-shavar\n"
|
| + "u:redirect-server.example.com/path\n");
|
| + url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
|
| +
|
| + // We should have another request.
|
| + net::TestURLFetcher* chunk_url_fetcher =
|
| + url_fetcher_factory.GetFetcherByID(1);
|
| + ASSERT_TRUE(chunk_url_fetcher != NULL);
|
| + chunk_url_fetcher->set_status(net::URLRequestStatus());
|
| + chunk_url_fetcher->set_response_code(200);
|
| + chunk_url_fetcher->SetResponseString(
|
| + "a:4:4:9\n"
|
| + "host\1fdaf");
|
| + chunk_url_fetcher->delegate()->OnURLFetchComplete(chunk_url_fetcher);
|
| +
|
| + // The AddChunksCallback needs to be invoked
|
| runner->RunTasks();
|
| +
|
| + EXPECT_TRUE(pm->IsUpdateScheduled());
|
| }
|
|
|
| -// Tests what happens when there is a reset command in the response.
|
| -TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseReset) {
|
| +// Tests a single valid update response, followed by multiple redirect responses
|
| +// containing chunks.
|
| +TEST_F(SafeBrowsingProtocolManagerTest, MultipleRedirectResponsesWithChunks) {
|
| scoped_refptr<ImmediateSingleThreadTaskRunner> runner(
|
| new ImmediateSingleThreadTaskRunner());
|
| base::ThreadTaskRunnerHandle runner_handler(runner);
|
| @@ -583,7 +776,9 @@ TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseReset) {
|
| Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
|
| std::vector<SBListChunkRanges>(),
|
| false)));
|
| - EXPECT_CALL(test_delegate, ResetDatabase()).Times(1);
|
| + EXPECT_CALL(test_delegate, AddChunks("goog-phish-shavar", _, _)).
|
| + WillRepeatedly(testing::WithArgs<2>(
|
| + Invoke(DeferAddChunksCallback)));
|
| EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
|
|
|
| scoped_ptr<SafeBrowsingProtocolManager> pm(
|
| @@ -600,6 +795,41 @@ TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseReset) {
|
| // The update response is successful, and has a reset command.
|
| url_fetcher->set_status(net::URLRequestStatus());
|
| url_fetcher->set_response_code(200);
|
| - url_fetcher->SetResponseString("r:pleasereset\n");
|
| + url_fetcher->SetResponseString(
|
| + "i:goog-phish-shavar\n"
|
| + "u:redirect-server.example.com/one\n"
|
| + "u:redirect-server.example.com/two\n");
|
| url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
|
| +
|
| + // First redirect request.
|
| + net::TestURLFetcher* first_chunk_url_fetcher =
|
| + url_fetcher_factory.GetFetcherByID(1);
|
| + ASSERT_TRUE(first_chunk_url_fetcher != NULL);
|
| + first_chunk_url_fetcher->set_status(net::URLRequestStatus());
|
| + first_chunk_url_fetcher->set_response_code(200);
|
| + first_chunk_url_fetcher->SetResponseString(
|
| + "a:4:4:9\n"
|
| + "host\1aaaa");
|
| + first_chunk_url_fetcher->delegate()->OnURLFetchComplete(
|
| + first_chunk_url_fetcher);
|
| +
|
| + // Invoke the AddChunksCallback
|
| + runner->RunTasks();
|
| +
|
| + // Second redirect request.
|
| + net::TestURLFetcher* second_chunk_url_fetcher =
|
| + url_fetcher_factory.GetFetcherByID(2);
|
| + ASSERT_TRUE(second_chunk_url_fetcher != NULL);
|
| + second_chunk_url_fetcher->set_status(net::URLRequestStatus());
|
| + second_chunk_url_fetcher->set_response_code(200);
|
| + second_chunk_url_fetcher->SetResponseString(
|
| + "a:5:4:9\n"
|
| + "host\1bbbb");
|
| + second_chunk_url_fetcher->delegate()->OnURLFetchComplete(
|
| + second_chunk_url_fetcher);
|
| +
|
| + // The AddChunksCallback needs to be invoked
|
| + runner->RunTasks();
|
| +
|
| + EXPECT_TRUE(pm->IsUpdateScheduled());
|
| }
|
|
|