Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/suggestions/suggestions_service_impl.h" | 5 #include "components/suggestions/suggestions_service_impl.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 41 using testing::DoAll; | 41 using testing::DoAll; |
| 42 using testing::Eq; | 42 using testing::Eq; |
| 43 using testing::NiceMock; | 43 using testing::NiceMock; |
| 44 using testing::Return; | 44 using testing::Return; |
| 45 using testing::SetArgPointee; | 45 using testing::SetArgPointee; |
| 46 using testing::StrictMock; | 46 using testing::StrictMock; |
| 47 | 47 |
| 48 namespace { | 48 namespace { |
| 49 | 49 |
| 50 const char kAccountId[] = "account"; | 50 const char kAccountId[] = "account"; |
| 51 const char kSuggestionsUrlPath[] = "/chromesuggestions"; | |
| 52 const char kBlacklistUrlPath[] = "/chromesuggestions/blacklist"; | |
| 53 const char kBlacklistClearUrlPath[] = "/chromesuggestions/blacklist/clear"; | |
| 51 const char kTestTitle[] = "a title"; | 54 const char kTestTitle[] = "a title"; |
| 52 const char kTestUrl[] = "http://go.com"; | 55 const char kTestUrl[] = "http://go.com"; |
| 53 const char kTestFaviconUrl[] = | 56 const char kTestFaviconUrl[] = |
| 54 "https://s2.googleusercontent.com/s2/favicons?domain_url=" | 57 "https://s2.googleusercontent.com/s2/favicons?domain_url=" |
| 55 "http://go.com&alt=s&sz=32"; | 58 "http://go.com&alt=s&sz=32"; |
| 56 const char kBlacklistedUrl[] = "http://blacklist.com"; | 59 const char kBlacklistedUrl[] = "http://blacklist.com"; |
| 57 const char kBlacklistedUrlAlt[] = "http://blacklist-atl.com"; | 60 const int64_t kTestSetExpiry = 12121212; // This timestamp lies in the past. |
| 58 const int64_t kTestDefaultExpiry = 1402200000000000; | |
| 59 const int64_t kTestSetExpiry = 1404792000000000; | |
| 60 | |
| 61 std::unique_ptr<net::FakeURLFetcher> CreateURLFetcher( | |
| 62 const GURL& url, | |
| 63 net::URLFetcherDelegate* delegate, | |
| 64 const std::string& response_data, | |
| 65 net::HttpStatusCode response_code, | |
| 66 net::URLRequestStatus::Status status) { | |
| 67 std::unique_ptr<net::FakeURLFetcher> fetcher(new net::FakeURLFetcher( | |
| 68 url, delegate, response_data, response_code, status)); | |
| 69 | |
| 70 if (response_code == net::HTTP_OK) { | |
| 71 scoped_refptr<net::HttpResponseHeaders> download_headers( | |
| 72 new net::HttpResponseHeaders("")); | |
| 73 download_headers->AddHeader("Content-Type: text/html"); | |
| 74 fetcher->set_response_headers(download_headers); | |
| 75 } | |
| 76 return fetcher; | |
| 77 } | |
| 78 | 61 |
| 79 // GMock matcher for protobuf equality. | 62 // GMock matcher for protobuf equality. |
| 80 MATCHER_P(EqualsProto, message, "") { | 63 MATCHER_P(EqualsProto, message, "") { |
| 81 // This implementation assumes protobuf serialization is deterministic, which | 64 // This implementation assumes protobuf serialization is deterministic, which |
| 82 // is true in practice but technically not something that code is supposed | 65 // is true in practice but technically not something that code is supposed |
| 83 // to rely on. However, it vastly simplifies the implementation. | 66 // to rely on. However, it vastly simplifies the implementation. |
| 84 std::string expected_serialized, actual_serialized; | 67 std::string expected_serialized, actual_serialized; |
| 85 message.SerializeToString(&expected_serialized); | 68 message.SerializeToString(&expected_serialized); |
| 86 arg.SerializeToString(&actual_serialized); | 69 arg.SerializeToString(&actual_serialized); |
| 87 return expected_serialized == actual_serialized; | 70 return expected_serialized == actual_serialized; |
| 88 } | 71 } |
| 89 | 72 |
| 90 } // namespace | 73 } // namespace |
| 91 | 74 |
| 92 namespace suggestions { | 75 namespace suggestions { |
| 93 | 76 |
| 94 SuggestionsProfile CreateSuggestionsProfile() { | 77 SuggestionsProfile CreateSuggestionsProfile() { |
| 95 SuggestionsProfile profile; | 78 SuggestionsProfile profile; |
| 96 profile.set_timestamp(123); | 79 profile.set_timestamp(123); |
| 97 ChromeSuggestion* suggestion = profile.add_suggestions(); | 80 ChromeSuggestion* suggestion = profile.add_suggestions(); |
| 98 suggestion->set_title(kTestTitle); | 81 suggestion->set_title(kTestTitle); |
| 99 suggestion->set_url(kTestUrl); | 82 suggestion->set_url(kTestUrl); |
| 100 suggestion->set_expiry_ts(kTestSetExpiry); | |
| 101 return profile; | 83 return profile; |
| 102 } | 84 } |
| 103 | 85 |
| 104 // Creates one suggestion with expiry timestamp and one without. | |
| 105 SuggestionsProfile CreateSuggestionsProfileWithExpiryTimestamps() { | |
| 106 SuggestionsProfile profile; | |
| 107 profile.set_timestamp(123); | |
| 108 ChromeSuggestion* suggestion = profile.add_suggestions(); | |
| 109 suggestion->set_title(kTestTitle); | |
| 110 suggestion->set_url(kTestUrl); | |
| 111 suggestion->set_expiry_ts(kTestSetExpiry); | |
| 112 | |
| 113 suggestion = profile.add_suggestions(); | |
| 114 suggestion->set_title(kTestTitle); | |
| 115 suggestion->set_url(kTestUrl); | |
| 116 | |
| 117 return profile; | |
| 118 } | |
| 119 | |
| 120 class MockSyncService : public syncer::FakeSyncService { | 86 class MockSyncService : public syncer::FakeSyncService { |
| 121 public: | 87 public: |
| 122 MockSyncService() {} | 88 MockSyncService() {} |
| 123 virtual ~MockSyncService() {} | 89 virtual ~MockSyncService() {} |
| 124 MOCK_CONST_METHOD0(CanSyncStart, bool()); | 90 MOCK_CONST_METHOD0(CanSyncStart, bool()); |
| 125 MOCK_CONST_METHOD0(IsSyncActive, bool()); | 91 MOCK_CONST_METHOD0(IsSyncActive, bool()); |
| 126 MOCK_CONST_METHOD0(ConfigurationDone, bool()); | 92 MOCK_CONST_METHOD0(ConfigurationDone, bool()); |
| 127 MOCK_CONST_METHOD0(GetActiveDataTypes, syncer::ModelTypeSet()); | 93 MOCK_CONST_METHOD0(GetActiveDataTypes, syncer::ModelTypeSet()); |
| 128 }; | 94 }; |
| 129 | 95 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 164 MOCK_METHOD2(GetTimeUntilURLReadyForUpload, | 130 MOCK_METHOD2(GetTimeUntilURLReadyForUpload, |
| 165 bool(const GURL&, base::TimeDelta*)); | 131 bool(const GURL&, base::TimeDelta*)); |
| 166 MOCK_METHOD1(GetCandidateForUpload, bool(GURL*)); | 132 MOCK_METHOD1(GetCandidateForUpload, bool(GURL*)); |
| 167 MOCK_METHOD1(RemoveUrl, bool(const GURL&)); | 133 MOCK_METHOD1(RemoveUrl, bool(const GURL&)); |
| 168 MOCK_METHOD1(FilterSuggestions, void(SuggestionsProfile*)); | 134 MOCK_METHOD1(FilterSuggestions, void(SuggestionsProfile*)); |
| 169 }; | 135 }; |
| 170 | 136 |
| 171 class SuggestionsServiceTest : public testing::Test { | 137 class SuggestionsServiceTest : public testing::Test { |
| 172 public: | 138 public: |
| 173 void CheckCallback(const SuggestionsProfile& suggestions_profile) { | 139 void CheckCallback(const SuggestionsProfile& suggestions_profile) { |
| 174 ++suggestions_data_callback_count_; | 140 ++data_callback_count_; |
| 175 if (suggestions_profile.suggestions_size() == 0) | 141 if (suggestions_profile.suggestions_size() == 0) |
| 176 ++suggestions_empty_data_count_; | 142 ++empty_callback_count_; |
| 177 } | 143 } |
| 178 | 144 |
| 179 int suggestions_data_callback_count_; | |
| 180 int suggestions_empty_data_count_; | |
| 181 | |
| 182 protected: | 145 protected: |
| 183 SuggestionsServiceTest() | 146 SuggestionsServiceTest() |
| 184 : suggestions_data_callback_count_(0), | 147 : data_callback_count_(0), |
| 185 suggestions_empty_data_count_(0), | 148 empty_callback_count_(0), |
| 186 signin_client_(&pref_service_), | 149 signin_client_(&pref_service_), |
| 187 signin_manager_(&signin_client_, &account_tracker_), | 150 signin_manager_(&signin_client_, &account_tracker_), |
| 188 factory_(nullptr, base::Bind(&CreateURLFetcher)), | 151 factory_(), |
| 189 mock_sync_service_(nullptr), | 152 mock_sync_service_(base::MakeUnique<MockSyncService>()), |
| 190 mock_thumbnail_manager_(nullptr), | 153 mock_thumbnail_manager_(nullptr), |
| 191 mock_blacklist_store_(nullptr), | 154 mock_blacklist_store_(nullptr), |
| 192 test_suggestions_store_(nullptr) { | 155 test_suggestions_store_(nullptr), |
| 156 request_context_(new net::TestURLRequestContextGetter( | |
| 157 io_message_loop_.task_runner())) { | |
| 193 SigninManagerBase::RegisterProfilePrefs(pref_service_.registry()); | 158 SigninManagerBase::RegisterProfilePrefs(pref_service_.registry()); |
| 194 SigninManagerBase::RegisterPrefs(pref_service_.registry()); | 159 SigninManagerBase::RegisterPrefs(pref_service_.registry()); |
| 195 | 160 |
| 196 signin_manager_.SignIn(kAccountId); | 161 signin_manager_.SignIn(kAccountId); |
| 197 token_service_.UpdateCredentials(kAccountId, "refresh_token"); | 162 token_service_.UpdateCredentials(kAccountId, "refresh_token"); |
| 198 token_service_.set_auto_post_fetch_response_on_message_loop(true); | 163 token_service_.set_auto_post_fetch_response_on_message_loop(true); |
| 199 } | 164 } |
| 200 | 165 |
| 201 ~SuggestionsServiceTest() override {} | 166 ~SuggestionsServiceTest() override {} |
| 202 | 167 |
| 203 void SetUp() override { | 168 void SetUp() override { |
| 204 request_context_ = | 169 IgnoreRepeatedMockCalls(); |
| 205 new net::TestURLRequestContextGetter(io_message_loop_.task_runner()); | 170 suggestions_service_ = CreateSuggestionsServiceWithMocks(); |
| 171 subscriptions_ = suggestions_service_->AddCallback(base::Bind( | |
| 172 &SuggestionsServiceTest::CheckCallback, base::Unretained(this))); | |
| 206 } | 173 } |
| 207 | 174 |
| 208 std::unique_ptr<SuggestionsServiceImpl> CreateSuggestionsServiceWithMocks() { | 175 void TearDown() override { |
| 209 mock_sync_service_ = base::MakeUnique<MockSyncService>(); | 176 testing::Mock::VerifyAndClearExpectations(mock_thumbnail_manager_); |
| 210 EXPECT_CALL(*mock_sync_service_, CanSyncStart()) | 177 testing::Mock::VerifyAndClearExpectations(mock_blacklist_store_); |
| 178 testing::Mock::VerifyAndClearExpectations(mock_sync_service_.get()); | |
| 179 subscriptions_.reset(); | |
| 180 suggestions_service_.reset(); | |
| 181 } | |
| 182 | |
| 183 GURL CurrentlyQueriedUrl() { | |
| 184 net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0); | |
| 185 if (!fetcher) { | |
| 186 return GURL(); | |
| 187 } | |
| 188 return fetcher->GetOriginalURL(); | |
| 189 } | |
| 190 | |
| 191 void RespondToFetch(const std::string& response_body, | |
| 192 net::HttpStatusCode response_code, | |
| 193 net::URLRequestStatus status) { | |
| 194 net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0); | |
| 195 ASSERT_TRUE(fetcher) << "Tried to respond to fetch that is not ongoing!"; | |
| 196 fetcher->SetResponseString(response_body); | |
| 197 fetcher->set_response_code(response_code); | |
| 198 fetcher->set_status(status); | |
| 199 fetcher->delegate()->OnURLFetchComplete(fetcher); | |
| 200 } | |
| 201 | |
| 202 void RespondToFetchWithProfile(const SuggestionsProfile& profile) { | |
| 203 RespondToFetch( | |
| 204 profile.SerializeAsString(), net::HTTP_OK, | |
| 205 net::URLRequestStatus(net::URLRequestStatus::SUCCESS, net::OK)); | |
| 206 } | |
| 207 | |
| 208 void NotifySuggestionsService() { | |
| 209 // The implementation of |OnStateChanged| is private in the | |
| 210 // SuggestionsService, but public for every SyncServiceObserver. | |
| 211 syncer::SyncServiceObserver* observer = suggestions_service(); | |
| 212 observer->OnStateChanged(sync_service()); | |
| 213 } | |
| 214 | |
| 215 void IgnoreRepeatedMockCalls() { | |
| 216 EXPECT_CALL(*sync_service(), CanSyncStart()) | |
| 211 .Times(AnyNumber()) | 217 .Times(AnyNumber()) |
| 212 .WillRepeatedly(Return(true)); | 218 .WillRepeatedly(Return(true)); |
| 213 EXPECT_CALL(*mock_sync_service_, IsSyncActive()) | 219 EXPECT_CALL(*sync_service(), IsSyncActive()) |
| 214 .Times(AnyNumber()) | 220 .Times(AnyNumber()) |
| 215 .WillRepeatedly(Return(true)); | 221 .WillRepeatedly(Return(true)); |
| 216 EXPECT_CALL(*mock_sync_service_, ConfigurationDone()) | 222 EXPECT_CALL(*sync_service(), ConfigurationDone()) |
| 217 .Times(AnyNumber()) | 223 .Times(AnyNumber()) |
| 218 .WillRepeatedly(Return(true)); | 224 .WillRepeatedly(Return(true)); |
| 219 EXPECT_CALL(*mock_sync_service_, GetActiveDataTypes()) | 225 EXPECT_CALL(*sync_service(), GetActiveDataTypes()) |
| 220 .Times(AnyNumber()) | 226 .Times(AnyNumber()) |
| 221 .WillRepeatedly( | 227 .WillRepeatedly( |
| 222 Return(syncer::ModelTypeSet(syncer::HISTORY_DELETE_DIRECTIVES))); | 228 Return(syncer::ModelTypeSet(syncer::HISTORY_DELETE_DIRECTIVES))); |
| 229 } | |
| 223 | 230 |
| 231 MockBlacklistStore* blacklist_store() { return mock_blacklist_store_; } | |
| 232 | |
| 233 SuggestionsServiceImpl* suggestions_service() { | |
| 234 return suggestions_service_.get(); | |
| 235 } | |
| 236 | |
| 237 TestSuggestionsStore* suggestions_store() { return test_suggestions_store_; } | |
| 238 | |
| 239 MockSyncService* sync_service() { return mock_sync_service_.get(); } | |
| 240 | |
| 241 MockImageManager* thumbnail_manager() { return mock_thumbnail_manager_; } | |
| 242 | |
| 243 FakeProfileOAuth2TokenService* token_service() { return &token_service_; } | |
| 244 | |
| 245 int data_callback_count() { return data_callback_count_; } | |
| 246 int empty_callback_count() { return empty_callback_count_; } | |
| 247 | |
| 248 private: | |
| 249 std::unique_ptr<SuggestionsServiceImpl> CreateSuggestionsServiceWithMocks() { | |
| 224 // These objects are owned by the returned SuggestionsService, but we keep | 250 // These objects are owned by the returned SuggestionsService, but we keep |
| 225 // the pointer around for testing. | 251 // the pointer around for testing. |
| 226 // TODO(treib): This is broken - if the test destroys the SuggestionsService | 252 // TODO(treib): This is broken - if the test destroys the SuggestionsService |
| 227 // (which it can easily do, since it has an owning pointer), we'll be left | 253 // (which it can easily do, since it has an owning pointer), we'll be left |
| 228 // with dangling pointers here. | 254 // with dangling pointers here. |
| 229 test_suggestions_store_ = new TestSuggestionsStore(); | 255 test_suggestions_store_ = new TestSuggestionsStore(); |
| 230 mock_thumbnail_manager_ = new StrictMock<MockImageManager>(); | 256 mock_thumbnail_manager_ = new StrictMock<MockImageManager>(); |
| 231 mock_blacklist_store_ = new StrictMock<MockBlacklistStore>(); | 257 mock_blacklist_store_ = new StrictMock<MockBlacklistStore>(); |
| 232 return base::MakeUnique<SuggestionsServiceImpl>( | 258 return base::MakeUnique<SuggestionsServiceImpl>( |
| 233 &signin_manager_, &token_service_, mock_sync_service_.get(), | 259 &signin_manager_, &token_service_, mock_sync_service_.get(), |
| 234 request_context_.get(), base::WrapUnique(test_suggestions_store_), | 260 request_context_.get(), base::WrapUnique(test_suggestions_store_), |
| 235 base::WrapUnique(mock_thumbnail_manager_), | 261 base::WrapUnique(mock_thumbnail_manager_), |
| 236 base::WrapUnique(mock_blacklist_store_)); | 262 base::WrapUnique(mock_blacklist_store_)); |
| 237 } | 263 } |
| 238 | 264 |
| 239 // Helper for Undo failure tests. Depending on |is_uploaded|, tests either | 265 int data_callback_count_; |
| 240 // the case where the URL is no longer in the local blacklist or the case | 266 int empty_callback_count_; |
| 241 // in which it's not yet candidate for upload. | |
| 242 void UndoBlacklistURLFailsHelper(bool is_uploaded) { | |
| 243 std::unique_ptr<SuggestionsServiceImpl> suggestions_service( | |
| 244 CreateSuggestionsServiceWithMocks()); | |
| 245 // Ensure scheduling the request doesn't happen before undo. | |
| 246 base::TimeDelta delay = base::TimeDelta::FromHours(1); | |
| 247 suggestions_service->set_blacklist_delay(delay); | |
| 248 | 267 |
| 249 auto subscription = suggestions_service->AddCallback(base::Bind( | 268 std::unique_ptr<SuggestionsServiceImpl> suggestions_service_; |
| 250 &SuggestionsServiceTest::CheckCallback, base::Unretained(this))); | |
| 251 | |
| 252 SuggestionsProfile suggestions_profile = CreateSuggestionsProfile(); | |
| 253 GURL blacklisted_url(kBlacklistedUrl); | |
| 254 | |
| 255 // Blacklist expectations. | |
| 256 EXPECT_CALL(*mock_blacklist_store_, BlacklistUrl(Eq(blacklisted_url))) | |
| 257 .WillOnce(Return(true)); | |
| 258 EXPECT_CALL(*mock_thumbnail_manager_, | |
| 259 Initialize(EqualsProto(suggestions_profile))); | |
| 260 EXPECT_CALL(*mock_blacklist_store_, FilterSuggestions(_)); | |
| 261 EXPECT_CALL(*mock_blacklist_store_, GetTimeUntilReadyForUpload(_)) | |
| 262 .WillOnce(DoAll(SetArgPointee<0>(delay), Return(true))); | |
| 263 // Undo expectations. | |
| 264 if (is_uploaded) { | |
| 265 // URL is not in local blacklist. | |
| 266 EXPECT_CALL(*mock_blacklist_store_, | |
| 267 GetTimeUntilURLReadyForUpload(Eq(blacklisted_url), _)) | |
| 268 .WillOnce(Return(false)); | |
| 269 } else { | |
| 270 // URL is not yet candidate for upload. | |
| 271 base::TimeDelta negative_delay = base::TimeDelta::FromHours(-1); | |
| 272 EXPECT_CALL(*mock_blacklist_store_, | |
| 273 GetTimeUntilURLReadyForUpload(Eq(blacklisted_url), _)) | |
| 274 .WillOnce(DoAll(SetArgPointee<1>(negative_delay), Return(true))); | |
| 275 } | |
| 276 | |
| 277 EXPECT_TRUE(suggestions_service->BlacklistURL(blacklisted_url)); | |
| 278 EXPECT_FALSE(suggestions_service->UndoBlacklistURL(blacklisted_url)); | |
| 279 | |
| 280 EXPECT_EQ(1, suggestions_data_callback_count_); | |
| 281 } | |
| 282 | |
| 283 bool HasPendingSuggestionsRequest( | |
| 284 SuggestionsServiceImpl* suggestions_service) { | |
| 285 return !!suggestions_service->pending_request_.get(); | |
| 286 } | |
| 287 | |
| 288 protected: | |
| 289 base::MessageLoopForIO io_message_loop_; | 269 base::MessageLoopForIO io_message_loop_; |
| 290 TestingPrefServiceSyncable pref_service_; | 270 TestingPrefServiceSyncable pref_service_; |
| 291 AccountTrackerService account_tracker_; | 271 AccountTrackerService account_tracker_; |
| 292 TestSigninClient signin_client_; | 272 TestSigninClient signin_client_; |
| 293 FakeSigninManagerBase signin_manager_; | 273 FakeSigninManagerBase signin_manager_; |
| 294 net::FakeURLFetcherFactory factory_; | 274 net::TestURLFetcherFactory factory_; |
| 295 FakeProfileOAuth2TokenService token_service_; | 275 FakeProfileOAuth2TokenService token_service_; |
| 296 std::unique_ptr<MockSyncService> mock_sync_service_; | 276 std::unique_ptr<MockSyncService> mock_sync_service_; |
| 277 std::unique_ptr<SuggestionsService::ResponseCallbackList::Subscription> | |
| 278 subscriptions_; | |
| 279 | |
| 297 // Only used if the SuggestionsService is built with mocks. Not owned. | 280 // Only used if the SuggestionsService is built with mocks. Not owned. |
| 298 MockImageManager* mock_thumbnail_manager_; | 281 MockImageManager* mock_thumbnail_manager_; |
| 299 MockBlacklistStore* mock_blacklist_store_; | 282 MockBlacklistStore* mock_blacklist_store_; |
| 300 TestSuggestionsStore* test_suggestions_store_; | 283 TestSuggestionsStore* test_suggestions_store_; |
| 301 scoped_refptr<net::TestURLRequestContextGetter> request_context_; | 284 scoped_refptr<net::TestURLRequestContextGetter> request_context_; |
| 302 | 285 |
| 303 private: | |
| 304 DISALLOW_COPY_AND_ASSIGN(SuggestionsServiceTest); | 286 DISALLOW_COPY_AND_ASSIGN(SuggestionsServiceTest); |
| 305 }; | 287 }; |
| 306 | 288 |
| 307 TEST_F(SuggestionsServiceTest, FetchSuggestionsData) { | 289 TEST_F(SuggestionsServiceTest, FetchSuggestionsData) { |
| 308 std::unique_ptr<SuggestionsService> suggestions_service( | 290 EXPECT_CALL(*thumbnail_manager(), Initialize(_)); |
| 309 CreateSuggestionsServiceWithMocks()); | 291 EXPECT_CALL(*blacklist_store(), FilterSuggestions(_)); |
| 310 auto subscription = suggestions_service->AddCallback(base::Bind( | 292 EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_)) |
| 311 &SuggestionsServiceTest::CheckCallback, base::Unretained(this))); | |
| 312 | |
| 313 SuggestionsProfile suggestions_profile = CreateSuggestionsProfile(); | |
| 314 | |
| 315 // Set up net::FakeURLFetcherFactory. | |
| 316 factory_.SetFakeResponse(SuggestionsServiceImpl::BuildSuggestionsURL(), | |
| 317 suggestions_profile.SerializeAsString(), | |
| 318 net::HTTP_OK, net::URLRequestStatus::SUCCESS); | |
| 319 | |
| 320 // Expectations. | |
| 321 EXPECT_CALL(*mock_thumbnail_manager_, Initialize(_)); | |
| 322 EXPECT_CALL(*mock_blacklist_store_, FilterSuggestions(_)); | |
| 323 EXPECT_CALL(*mock_blacklist_store_, GetTimeUntilReadyForUpload(_)) | |
| 324 .WillOnce(Return(false)); | 293 .WillOnce(Return(false)); |
| 325 | 294 |
| 326 // Send the request. The data should be returned to the callback. | 295 // Send the request. The data should be returned to the callback. |
| 327 suggestions_service->FetchSuggestionsData(); | 296 suggestions_service()->FetchSuggestionsData(); |
| 328 | 297 |
| 329 // Let the network request run. | |
| 330 base::RunLoop().RunUntilIdle(); | 298 base::RunLoop().RunUntilIdle(); |
| 299 EXPECT_FALSE(CurrentlyQueriedUrl().is_empty()); | |
| 300 EXPECT_TRUE(CurrentlyQueriedUrl().is_valid()); | |
| 301 EXPECT_EQ(CurrentlyQueriedUrl().path(), kSuggestionsUrlPath); | |
| 302 RespondToFetchWithProfile(CreateSuggestionsProfile()); | |
| 331 | 303 |
| 332 // Ensure that CheckCallback() ran once. | 304 // Ensure that CheckCallback() ran once. |
| 333 EXPECT_EQ(1, suggestions_data_callback_count_); | 305 EXPECT_EQ(1, data_callback_count()); |
| 334 | 306 |
| 335 test_suggestions_store_->LoadSuggestions(&suggestions_profile); | 307 SuggestionsProfile suggestions_profile; |
| 308 suggestions_store()->LoadSuggestions(&suggestions_profile); | |
| 336 ASSERT_EQ(1, suggestions_profile.suggestions_size()); | 309 ASSERT_EQ(1, suggestions_profile.suggestions_size()); |
| 337 EXPECT_EQ(kTestTitle, suggestions_profile.suggestions(0).title()); | 310 EXPECT_EQ(kTestTitle, suggestions_profile.suggestions(0).title()); |
| 338 EXPECT_EQ(kTestUrl, suggestions_profile.suggestions(0).url()); | 311 EXPECT_EQ(kTestUrl, suggestions_profile.suggestions(0).url()); |
| 339 EXPECT_EQ(kTestFaviconUrl, suggestions_profile.suggestions(0).favicon_url()); | 312 EXPECT_EQ(kTestFaviconUrl, suggestions_profile.suggestions(0).favicon_url()); |
| 340 } | 313 } |
| 341 | 314 |
| 342 TEST_F(SuggestionsServiceTest, FetchSuggestionsDataSyncNotInitializedEnabled) { | 315 TEST_F(SuggestionsServiceTest, FetchSuggestionsDataSyncNotInitializedEnabled) { |
| 343 std::unique_ptr<SuggestionsService> suggestions_service( | 316 EXPECT_CALL(*sync_service(), IsSyncActive()).WillRepeatedly(Return(false)); |
| 344 CreateSuggestionsServiceWithMocks()); | |
| 345 EXPECT_CALL(*mock_sync_service_, IsSyncActive()) | |
| 346 .WillRepeatedly(Return(false)); | |
| 347 | |
| 348 auto subscription = suggestions_service->AddCallback(base::Bind( | |
| 349 &SuggestionsServiceTest::CheckCallback, base::Unretained(this))); | |
| 350 | 317 |
| 351 // Try to fetch suggestions. Since sync is not active, no network request | 318 // Try to fetch suggestions. Since sync is not active, no network request |
| 352 // should be sent. | 319 // should be sent. |
| 353 suggestions_service->FetchSuggestionsData(); | 320 suggestions_service()->FetchSuggestionsData(); |
| 354 | 321 |
| 355 // Let any network request run. | 322 // Let any network request run. |
| 356 base::RunLoop().RunUntilIdle(); | 323 base::RunLoop().RunUntilIdle(); |
| 357 | 324 |
| 358 // Ensure that CheckCallback() didn't run. | 325 // Ensure that CheckCallback() didn't run. |
| 359 EXPECT_EQ(0, suggestions_data_callback_count_); | 326 EXPECT_EQ(0, data_callback_count()); |
| 360 | 327 |
| 361 // |test_suggestions_store_| should still contain the default values. | 328 // |suggestions_store()| should still contain the default values. |
| 362 SuggestionsProfile suggestions; | 329 SuggestionsProfile suggestions; |
| 363 test_suggestions_store_->LoadSuggestions(&suggestions); | 330 suggestions_store()->LoadSuggestions(&suggestions); |
| 364 EXPECT_EQ(CreateSuggestionsProfile().SerializeAsString(), | 331 EXPECT_EQ(CreateSuggestionsProfile().SerializeAsString(), |
| 365 suggestions.SerializeAsString()); | 332 suggestions.SerializeAsString()); |
| 366 } | 333 } |
| 367 | 334 |
| 368 TEST_F(SuggestionsServiceTest, FetchSuggestionsDataSyncDisabled) { | 335 TEST_F(SuggestionsServiceTest, ClearSuggestionsDataIfSyncDisabled) { |
| 369 std::unique_ptr<SuggestionsServiceImpl> suggestions_service( | 336 EXPECT_CALL(*sync_service(), CanSyncStart()).WillRepeatedly(Return(false)); |
| 370 CreateSuggestionsServiceWithMocks()); | |
| 371 EXPECT_CALL(*mock_sync_service_, CanSyncStart()) | |
| 372 .WillRepeatedly(Return(false)); | |
| 373 | 337 |
| 374 auto subscription = suggestions_service->AddCallback(base::Bind( | 338 NotifySuggestionsService(); |
| 375 &SuggestionsServiceTest::CheckCallback, base::Unretained(this))); | |
| 376 | 339 |
| 377 // Tell SuggestionsService that the sync state changed. The cache should be | 340 EXPECT_EQ(1, data_callback_count()); |
| 378 // cleared and empty data returned to the callback. | 341 EXPECT_EQ(1, empty_callback_count()); |
| 379 suggestions_service->OnStateChanged(mock_sync_service_.get()); | |
| 380 | |
| 381 // Ensure that CheckCallback ran once with empty data. | |
| 382 EXPECT_EQ(1, suggestions_data_callback_count_); | |
| 383 EXPECT_EQ(1, suggestions_empty_data_count_); | |
| 384 | 342 |
| 385 // Try to fetch suggestions. Since sync is not active, no network request | 343 // Try to fetch suggestions. Since sync is not active, no network request |
| 386 // should be sent. | 344 // should be sent. |
| 387 suggestions_service->FetchSuggestionsData(); | 345 suggestions_service()->FetchSuggestionsData(); |
| 388 | 346 |
| 389 // Let any network request run. | 347 // Let any network request run. |
| 390 base::RunLoop().RunUntilIdle(); | 348 base::RunLoop().RunUntilIdle(); |
| 391 | 349 |
| 392 // Ensure that CheckCallback didn't run again. | 350 // Ensure that CheckCallback didn't run again. |
| 393 EXPECT_EQ(1, suggestions_data_callback_count_); | 351 EXPECT_EQ(1, data_callback_count()); |
| 352 EXPECT_EQ(1, empty_callback_count()); | |
| 394 } | 353 } |
| 395 | 354 |
| 396 TEST_F(SuggestionsServiceTest, FetchSuggestionsDataNoAccessToken) { | 355 TEST_F(SuggestionsServiceTest, FetchSuggestionsDataNoAccessToken) { |
| 397 token_service_.set_auto_post_fetch_response_on_message_loop(false); | 356 token_service()->set_auto_post_fetch_response_on_message_loop(false); |
| 398 | 357 |
| 399 std::unique_ptr<SuggestionsServiceImpl> suggestions_service( | 358 EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_)) |
| 400 CreateSuggestionsServiceWithMocks()); | |
| 401 | |
| 402 auto subscription = suggestions_service->AddCallback(base::Bind( | |
| 403 &SuggestionsServiceTest::CheckCallback, base::Unretained(this))); | |
| 404 | |
| 405 EXPECT_CALL(*mock_blacklist_store_, GetTimeUntilReadyForUpload(_)) | |
| 406 .WillOnce(Return(false)); | 359 .WillOnce(Return(false)); |
| 407 | 360 |
| 408 suggestions_service->FetchSuggestionsData(); | 361 suggestions_service()->FetchSuggestionsData(); |
| 409 | 362 |
| 410 token_service_.IssueErrorForAllPendingRequests(GoogleServiceAuthError( | 363 token_service()->IssueErrorForAllPendingRequests(GoogleServiceAuthError( |
| 411 GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS)); | 364 GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS)); |
| 412 | 365 |
| 413 // No network request should be sent. | |
| 414 base::RunLoop().RunUntilIdle(); | 366 base::RunLoop().RunUntilIdle(); |
| 415 EXPECT_FALSE(HasPendingSuggestionsRequest(suggestions_service.get())); | 367 EXPECT_FALSE(suggestions_service()->has_pending_request_for_testing()); |
| 416 EXPECT_EQ(0, suggestions_data_callback_count_); | 368 EXPECT_EQ(0, data_callback_count()); |
| 417 } | 369 } |
| 418 | 370 |
| 419 TEST_F(SuggestionsServiceTest, IssueRequestIfNoneOngoingError) { | 371 TEST_F(SuggestionsServiceTest, FetchingSuggestionsIgnoresRequestFailure) { |
| 420 std::unique_ptr<SuggestionsServiceImpl> suggestions_service( | 372 EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_)) |
| 421 CreateSuggestionsServiceWithMocks()); | 373 .WillOnce(Return(false)); |
| 422 | 374 |
| 423 // Fake a request error. | 375 suggestions_service()->FetchSuggestionsData(); |
| 424 factory_.SetFakeResponse(SuggestionsServiceImpl::BuildSuggestionsURL(), | |
| 425 "irrelevant", net::HTTP_OK, | |
| 426 net::URLRequestStatus::FAILED); | |
| 427 | 376 |
| 428 EXPECT_CALL(*mock_blacklist_store_, GetTimeUntilReadyForUpload(_)) | 377 base::RunLoop().RunUntilIdle(); |
| 378 RespondToFetch("irrelevant", net::HTTP_OK, | |
| 379 net::URLRequestStatus(net::URLRequestStatus::FAILED, | |
| 380 net::ERR_INVALID_RESPONSE)); | |
| 381 | |
| 382 EXPECT_EQ(0, data_callback_count()); | |
| 383 } | |
| 384 | |
| 385 TEST_F(SuggestionsServiceTest, FetchingSuggestionsClearsStoreIfResponseNotOK) { | |
| 386 suggestions_store()->StoreSuggestions(CreateSuggestionsProfile()); | |
| 387 | |
| 388 // Expect that an upload to the blacklist is scheduled. | |
| 389 EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_)) | |
| 429 .WillOnce(Return(false)); | 390 .WillOnce(Return(false)); |
| 430 | 391 |
| 431 // Send the request. Empty data will be returned to the callback. | 392 // Send the request. Empty data will be returned to the callback. |
| 432 suggestions_service->IssueRequestIfNoneOngoing( | 393 suggestions_service()->FetchSuggestionsData(); |
| 433 SuggestionsServiceImpl::BuildSuggestionsURL()); | |
| 434 | 394 |
| 435 // (Testing only) wait until suggestion fetch is complete. | |
| 436 base::RunLoop().RunUntilIdle(); | 395 base::RunLoop().RunUntilIdle(); |
| 437 } | 396 RespondToFetch( |
| 397 "irrelevant", net::HTTP_BAD_REQUEST, | |
| 398 net::URLRequestStatus(net::URLRequestStatus::SUCCESS, net::OK)); | |
| 438 | 399 |
| 439 TEST_F(SuggestionsServiceTest, IssueRequestIfNoneOngoingResponseNotOK) { | |
| 440 std::unique_ptr<SuggestionsServiceImpl> suggestions_service( | |
| 441 CreateSuggestionsServiceWithMocks()); | |
| 442 | |
| 443 // Fake a non-200 response code. | |
| 444 factory_.SetFakeResponse(SuggestionsServiceImpl::BuildSuggestionsURL(), | |
| 445 "irrelevant", net::HTTP_BAD_REQUEST, | |
| 446 net::URLRequestStatus::SUCCESS); | |
| 447 | |
| 448 // Expect that an upload to the blacklist is scheduled. | |
| 449 EXPECT_CALL(*mock_blacklist_store_, GetTimeUntilReadyForUpload(_)) | |
| 450 .WillOnce(Return(false)); | |
| 451 | |
| 452 // Send the request. Empty data will be returned to the callback. | |
| 453 suggestions_service->IssueRequestIfNoneOngoing( | |
| 454 SuggestionsServiceImpl::BuildSuggestionsURL()); | |
| 455 | |
| 456 // (Testing only) wait until suggestion fetch is complete. | |
| 457 base::RunLoop().RunUntilIdle(); | |
| 458 | |
| 459 // Expect no suggestions in the cache. | |
| 460 SuggestionsProfile empty_suggestions; | 400 SuggestionsProfile empty_suggestions; |
| 461 EXPECT_FALSE(test_suggestions_store_->LoadSuggestions(&empty_suggestions)); | 401 EXPECT_FALSE(suggestions_store()->LoadSuggestions(&empty_suggestions)); |
| 462 } | 402 } |
| 463 | 403 |
| 464 TEST_F(SuggestionsServiceTest, BlacklistURL) { | 404 TEST_F(SuggestionsServiceTest, BlacklistURL) { |
| 465 std::unique_ptr<SuggestionsServiceImpl> suggestions_service( | 405 // Calling RunUntilIdle on the MessageLoop only works when the task is not |
| 466 CreateSuggestionsServiceWithMocks()); | 406 // posted for the future. |
| 467 base::TimeDelta no_delay = base::TimeDelta::FromSeconds(0); | 407 base::TimeDelta no_delay = base::TimeDelta::FromSeconds(0); |
| 468 suggestions_service->set_blacklist_delay(no_delay); | 408 suggestions_service()->set_blacklist_delay_for_testing(no_delay); |
| 469 | 409 |
| 470 auto subscription = suggestions_service->AddCallback(base::Bind( | 410 EXPECT_CALL(*thumbnail_manager(), Initialize(_)).Times(2); |
| 471 &SuggestionsServiceTest::CheckCallback, base::Unretained(this))); | |
| 472 | 411 |
| 473 GURL blacklisted_url(kBlacklistedUrl); | 412 EXPECT_CALL(*blacklist_store(), BlacklistUrl(Eq(GURL(kBlacklistedUrl)))) |
| 474 GURL request_url( | |
| 475 SuggestionsServiceImpl::BuildSuggestionsBlacklistURL(blacklisted_url)); | |
| 476 SuggestionsProfile suggestions_profile = CreateSuggestionsProfile(); | |
| 477 factory_.SetFakeResponse(request_url, suggestions_profile.SerializeAsString(), | |
| 478 net::HTTP_OK, net::URLRequestStatus::SUCCESS); | |
| 479 EXPECT_CALL(*mock_thumbnail_manager_, Initialize(_)).Times(2); | |
| 480 | |
| 481 // Expected calls to the blacklist store. | |
| 482 EXPECT_CALL(*mock_blacklist_store_, BlacklistUrl(Eq(blacklisted_url))) | |
| 483 .WillOnce(Return(true)); | 413 .WillOnce(Return(true)); |
| 484 EXPECT_CALL(*mock_blacklist_store_, FilterSuggestions(_)).Times(2); | 414 EXPECT_CALL(*blacklist_store(), FilterSuggestions(_)).Times(2); |
| 485 EXPECT_CALL(*mock_blacklist_store_, GetTimeUntilReadyForUpload(_)) | 415 EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_)) |
| 486 .WillOnce(DoAll(SetArgPointee<0>(no_delay), Return(true))) | 416 .WillOnce(DoAll(SetArgPointee<0>(no_delay), Return(true))) |
| 487 .WillOnce(Return(false)); | 417 .WillOnce(Return(false)); |
| 488 EXPECT_CALL(*mock_blacklist_store_, GetCandidateForUpload(_)) | 418 EXPECT_CALL(*blacklist_store(), GetCandidateForUpload(_)) |
| 489 .WillOnce(DoAll(SetArgPointee<0>(blacklisted_url), Return(true))); | 419 .WillOnce(DoAll(SetArgPointee<0>(GURL(kBlacklistedUrl)), Return(true))); |
| 490 EXPECT_CALL(*mock_blacklist_store_, RemoveUrl(Eq(blacklisted_url))) | 420 EXPECT_CALL(*blacklist_store(), RemoveUrl(Eq(GURL(kBlacklistedUrl)))) |
| 491 .WillOnce(Return(true)); | 421 .WillOnce(Return(true)); |
| 492 | 422 |
| 493 EXPECT_TRUE(suggestions_service->BlacklistURL(blacklisted_url)); | 423 EXPECT_TRUE(suggestions_service()->BlacklistURL(GURL(kBlacklistedUrl))); |
| 494 EXPECT_EQ(1, suggestions_data_callback_count_); | 424 EXPECT_EQ(1, data_callback_count()); |
| 495 | 425 |
| 496 // Wait on the upload task, the blacklist request and the next blacklist | 426 // Wait on the upload task, the blacklist request and the next blacklist |
| 497 // scheduling task. This only works when the scheduling task is not for future | 427 // scheduling task. |
| 498 // execution (note how both the SuggestionsService's scheduling delay and the | |
| 499 // BlacklistStore's candidacy delay are zero). | |
| 500 base::RunLoop().RunUntilIdle(); | 428 base::RunLoop().RunUntilIdle(); |
| 501 | 429 |
| 502 EXPECT_EQ(2, suggestions_data_callback_count_); | 430 EXPECT_EQ(CurrentlyQueriedUrl().path(), kBlacklistUrlPath); |
| 431 RespondToFetchWithProfile(CreateSuggestionsProfile()); | |
| 503 | 432 |
| 504 test_suggestions_store_->LoadSuggestions(&suggestions_profile); | 433 EXPECT_EQ(2, data_callback_count()); |
| 434 | |
| 435 SuggestionsProfile suggestions_profile; | |
| 436 suggestions_store()->LoadSuggestions(&suggestions_profile); | |
| 505 ASSERT_EQ(1, suggestions_profile.suggestions_size()); | 437 ASSERT_EQ(1, suggestions_profile.suggestions_size()); |
| 506 EXPECT_EQ(kTestTitle, suggestions_profile.suggestions(0).title()); | 438 EXPECT_EQ(kTestTitle, suggestions_profile.suggestions(0).title()); |
| 507 EXPECT_EQ(kTestUrl, suggestions_profile.suggestions(0).url()); | 439 EXPECT_EQ(kTestUrl, suggestions_profile.suggestions(0).url()); |
| 508 EXPECT_EQ(kTestFaviconUrl, suggestions_profile.suggestions(0).favicon_url()); | 440 EXPECT_EQ(kTestFaviconUrl, suggestions_profile.suggestions(0).favicon_url()); |
| 509 } | 441 } |
| 510 | 442 |
| 511 TEST_F(SuggestionsServiceTest, BlacklistURLFails) { | 443 TEST_F(SuggestionsServiceTest, BlacklistURLFails) { |
| 512 std::unique_ptr<SuggestionsService> suggestions_service( | |
| 513 CreateSuggestionsServiceWithMocks()); | |
| 514 | |
| 515 auto subscription = suggestions_service->AddCallback(base::Bind( | |
| 516 &SuggestionsServiceTest::CheckCallback, base::Unretained(this))); | |
| 517 | |
| 518 GURL blacklisted_url(kBlacklistedUrl); | 444 GURL blacklisted_url(kBlacklistedUrl); |
| 519 EXPECT_CALL(*mock_blacklist_store_, BlacklistUrl(Eq(blacklisted_url))) | 445 EXPECT_CALL(*blacklist_store(), BlacklistUrl(Eq(blacklisted_url))) |
| 520 .WillOnce(Return(false)); | 446 .WillOnce(Return(false)); |
| 521 | 447 |
| 522 EXPECT_FALSE(suggestions_service->BlacklistURL(blacklisted_url)); | 448 EXPECT_FALSE(suggestions_service()->BlacklistURL(blacklisted_url)); |
| 523 | 449 |
| 524 EXPECT_EQ(0, suggestions_data_callback_count_); | 450 EXPECT_EQ(0, data_callback_count()); |
| 525 } | 451 } |
| 526 | 452 |
| 527 // Initial blacklist request fails, triggering a second which succeeds. | 453 TEST_F(SuggestionsServiceTest, RetryBlacklistURLRequestAfterFailure) { |
| 528 TEST_F(SuggestionsServiceTest, BlacklistURLRequestFails) { | 454 // Calling RunUntilIdle on the MessageLoop only works when the task is not |
| 529 std::unique_ptr<SuggestionsServiceImpl> suggestions_service( | 455 // posted for the future. |
| 530 CreateSuggestionsServiceWithMocks()); | |
| 531 base::TimeDelta no_delay = base::TimeDelta::FromSeconds(0); | 456 base::TimeDelta no_delay = base::TimeDelta::FromSeconds(0); |
| 532 suggestions_service->set_blacklist_delay(no_delay); | 457 suggestions_service()->set_blacklist_delay_for_testing(no_delay); |
| 533 | 458 |
| 534 auto subscription = suggestions_service->AddCallback(base::Bind( | 459 EXPECT_CALL(*thumbnail_manager(), Initialize(_)).Times(2); |
| 535 &SuggestionsServiceTest::CheckCallback, base::Unretained(this))); | 460 EXPECT_CALL(*blacklist_store(), BlacklistUrl(Eq(GURL(kBlacklistedUrl)))) |
| 536 | |
| 537 GURL blacklisted_url(kBlacklistedUrl); | |
| 538 GURL request_url( | |
| 539 SuggestionsServiceImpl::BuildSuggestionsBlacklistURL(blacklisted_url)); | |
| 540 GURL blacklisted_url_alt(kBlacklistedUrlAlt); | |
| 541 GURL request_url_alt(SuggestionsServiceImpl::BuildSuggestionsBlacklistURL( | |
| 542 blacklisted_url_alt)); | |
| 543 SuggestionsProfile suggestions_profile = CreateSuggestionsProfile(); | |
| 544 | |
| 545 // Note: we want to set the response for the blacklist URL to first | |
| 546 // succeed, then fail. This doesn't seem possible. For simplicity of testing, | |
| 547 // we'll pretend the URL changed in the BlacklistStore between the first and | |
| 548 // the second request, and adjust expectations accordingly. | |
| 549 factory_.SetFakeResponse(request_url, "irrelevant", net::HTTP_OK, | |
| 550 net::URLRequestStatus::FAILED); | |
| 551 factory_.SetFakeResponse(request_url_alt, | |
| 552 suggestions_profile.SerializeAsString(), | |
| 553 net::HTTP_OK, net::URLRequestStatus::SUCCESS); | |
| 554 | |
| 555 // Expectations. | |
| 556 EXPECT_CALL(*mock_thumbnail_manager_, Initialize(_)).Times(2); | |
| 557 EXPECT_CALL(*mock_blacklist_store_, BlacklistUrl(Eq(blacklisted_url))) | |
| 558 .WillOnce(Return(true)); | 461 .WillOnce(Return(true)); |
| 559 EXPECT_CALL(*mock_blacklist_store_, FilterSuggestions(_)).Times(2); | 462 EXPECT_CALL(*blacklist_store(), FilterSuggestions(_)).Times(2); |
| 560 EXPECT_CALL(*mock_blacklist_store_, GetTimeUntilReadyForUpload(_)) | 463 EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_)) |
| 561 .WillOnce(DoAll(SetArgPointee<0>(no_delay), Return(true))) | 464 .WillOnce(DoAll(SetArgPointee<0>(no_delay), Return(true))) |
| 562 .WillOnce(DoAll(SetArgPointee<0>(no_delay), Return(true))) | 465 .WillOnce(DoAll(SetArgPointee<0>(no_delay), Return(true))) |
| 563 .WillOnce(Return(false)); | 466 .WillOnce(Return(false)); |
| 564 EXPECT_CALL(*mock_blacklist_store_, GetCandidateForUpload(_)) | 467 EXPECT_CALL(*blacklist_store(), GetCandidateForUpload(_)) |
| 565 .WillOnce(DoAll(SetArgPointee<0>(blacklisted_url), Return(true))) | 468 .WillOnce(DoAll(SetArgPointee<0>(GURL(kBlacklistedUrl)), Return(true))) |
| 566 .WillOnce(DoAll(SetArgPointee<0>(blacklisted_url_alt), Return(true))); | 469 .WillOnce(DoAll(SetArgPointee<0>(GURL(kBlacklistedUrl)), Return(true))); |
| 567 EXPECT_CALL(*mock_blacklist_store_, RemoveUrl(Eq(blacklisted_url_alt))) | 470 EXPECT_CALL(*blacklist_store(), RemoveUrl(Eq(GURL(kBlacklistedUrl)))) |
| 568 .WillOnce(Return(true)); | 471 .WillOnce(Return(true)); |
| 569 | 472 |
| 570 // Blacklist call, first request attempt. | 473 // Blacklist call, first request attempt. |
| 571 EXPECT_TRUE(suggestions_service->BlacklistURL(blacklisted_url)); | 474 EXPECT_TRUE(suggestions_service()->BlacklistURL(GURL(kBlacklistedUrl))); |
| 572 EXPECT_EQ(1, suggestions_data_callback_count_); | 475 EXPECT_EQ(1, data_callback_count()); |
| 573 | 476 |
| 574 // Wait for the first scheduling, the first request, the second scheduling, | 477 // Wait for the first scheduling receiving a failing response. |
| 575 // second request and the third scheduling. Again, note that calling | |
| 576 // RunUntilIdle on the MessageLoop only works when the task is not posted for | |
| 577 // the future. | |
| 578 base::RunLoop().RunUntilIdle(); | 478 base::RunLoop().RunUntilIdle(); |
| 479 EXPECT_EQ(CurrentlyQueriedUrl().path(), kBlacklistUrlPath); | |
| 480 RespondToFetch("irrelevant", net::HTTP_OK, | |
| 481 net::URLRequestStatus(net::URLRequestStatus::FAILED, | |
| 482 net::ERR_INVALID_RESPONSE)); | |
| 579 | 483 |
| 580 test_suggestions_store_->LoadSuggestions(&suggestions_profile); | 484 // Wait for the second scheduling followed by a successful response. |
| 485 base::RunLoop().RunUntilIdle(); | |
| 486 ASSERT_TRUE(CurrentlyQueriedUrl().is_valid()); | |
| 487 EXPECT_EQ(CurrentlyQueriedUrl().path(), kBlacklistUrlPath); | |
| 488 RespondToFetchWithProfile(CreateSuggestionsProfile()); | |
| 489 | |
| 490 SuggestionsProfile suggestions_profile; | |
| 491 suggestions_store()->LoadSuggestions(&suggestions_profile); | |
| 581 ASSERT_EQ(1, suggestions_profile.suggestions_size()); | 492 ASSERT_EQ(1, suggestions_profile.suggestions_size()); |
| 582 EXPECT_EQ(kTestTitle, suggestions_profile.suggestions(0).title()); | 493 EXPECT_EQ(kTestTitle, suggestions_profile.suggestions(0).title()); |
| 583 EXPECT_EQ(kTestUrl, suggestions_profile.suggestions(0).url()); | 494 EXPECT_EQ(kTestUrl, suggestions_profile.suggestions(0).url()); |
| 584 EXPECT_EQ(kTestFaviconUrl, suggestions_profile.suggestions(0).favicon_url()); | 495 EXPECT_EQ(kTestFaviconUrl, suggestions_profile.suggestions(0).favicon_url()); |
| 585 } | 496 } |
| 586 | 497 |
| 587 TEST_F(SuggestionsServiceTest, UndoBlacklistURL) { | 498 TEST_F(SuggestionsServiceTest, UndoBlacklistURL) { |
| 588 std::unique_ptr<SuggestionsServiceImpl> suggestions_service( | |
| 589 CreateSuggestionsServiceWithMocks()); | |
| 590 // Ensure scheduling the request doesn't happen before undo. | 499 // Ensure scheduling the request doesn't happen before undo. |
| 591 base::TimeDelta delay = base::TimeDelta::FromHours(1); | 500 base::TimeDelta delay = base::TimeDelta::FromHours(1); |
| 592 suggestions_service->set_blacklist_delay(delay); | 501 suggestions_service()->set_blacklist_delay_for_testing(delay); |
| 593 | |
| 594 auto subscription = suggestions_service->AddCallback(base::Bind( | |
| 595 &SuggestionsServiceTest::CheckCallback, base::Unretained(this))); | |
| 596 | 502 |
| 597 SuggestionsProfile suggestions_profile = CreateSuggestionsProfile(); | 503 SuggestionsProfile suggestions_profile = CreateSuggestionsProfile(); |
| 598 GURL blacklisted_url(kBlacklistedUrl); | 504 GURL blacklisted_url(kBlacklistedUrl); |
| 599 | 505 |
| 600 // Blacklist expectations. | 506 // Blacklist expectations. |
| 601 EXPECT_CALL(*mock_blacklist_store_, BlacklistUrl(Eq(blacklisted_url))) | 507 EXPECT_CALL(*blacklist_store(), BlacklistUrl(Eq(blacklisted_url))) |
| 602 .WillOnce(Return(true)); | 508 .WillOnce(Return(true)); |
| 603 EXPECT_CALL(*mock_thumbnail_manager_, | 509 EXPECT_CALL(*thumbnail_manager(), |
| 604 Initialize(EqualsProto(suggestions_profile))) | 510 Initialize(EqualsProto(suggestions_profile))) |
| 605 .Times(AnyNumber()); | 511 .Times(AnyNumber()); |
| 606 EXPECT_CALL(*mock_blacklist_store_, FilterSuggestions(_)).Times(AnyNumber()); | 512 EXPECT_CALL(*blacklist_store(), FilterSuggestions(_)).Times(AnyNumber()); |
| 607 EXPECT_CALL(*mock_blacklist_store_, GetTimeUntilReadyForUpload(_)) | 513 EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_)) |
| 608 .WillOnce(DoAll(SetArgPointee<0>(delay), Return(true))); | 514 .WillOnce(DoAll(SetArgPointee<0>(delay), Return(true))); |
| 609 // Undo expectations. | 515 // Undo expectations. |
| 610 EXPECT_CALL(*mock_blacklist_store_, | 516 EXPECT_CALL(*blacklist_store(), |
| 611 GetTimeUntilURLReadyForUpload(Eq(blacklisted_url), _)) | 517 GetTimeUntilURLReadyForUpload(Eq(blacklisted_url), _)) |
| 612 .WillOnce(DoAll(SetArgPointee<1>(delay), Return(true))); | 518 .WillOnce(DoAll(SetArgPointee<1>(delay), Return(true))); |
| 613 EXPECT_CALL(*mock_blacklist_store_, RemoveUrl(Eq(blacklisted_url))) | 519 EXPECT_CALL(*blacklist_store(), RemoveUrl(Eq(blacklisted_url))) |
| 614 .WillOnce(Return(true)); | 520 .WillOnce(Return(true)); |
| 615 | 521 |
| 616 EXPECT_TRUE(suggestions_service->BlacklistURL(blacklisted_url)); | 522 EXPECT_TRUE(suggestions_service()->BlacklistURL(blacklisted_url)); |
| 617 EXPECT_TRUE(suggestions_service->UndoBlacklistURL(blacklisted_url)); | 523 EXPECT_TRUE(suggestions_service()->UndoBlacklistURL(blacklisted_url)); |
| 618 | 524 |
| 619 EXPECT_EQ(2, suggestions_data_callback_count_); | 525 EXPECT_EQ(2, data_callback_count()); |
| 620 } | 526 } |
| 621 | 527 |
| 622 TEST_F(SuggestionsServiceTest, ClearBlacklist) { | 528 TEST_F(SuggestionsServiceTest, ClearBlacklist) { |
| 623 std::unique_ptr<SuggestionsServiceImpl> suggestions_service( | |
| 624 CreateSuggestionsServiceWithMocks()); | |
| 625 // Ensure scheduling the request doesn't happen before undo. | 529 // Ensure scheduling the request doesn't happen before undo. |
| 626 base::TimeDelta delay = base::TimeDelta::FromHours(1); | 530 base::TimeDelta delay = base::TimeDelta::FromHours(1); |
| 627 suggestions_service->set_blacklist_delay(delay); | 531 suggestions_service()->set_blacklist_delay_for_testing(delay); |
| 628 | |
| 629 auto subscription = suggestions_service->AddCallback(base::Bind( | |
| 630 &SuggestionsServiceTest::CheckCallback, base::Unretained(this))); | |
| 631 | |
| 632 SuggestionsProfile suggestions_profile = CreateSuggestionsProfile(); | |
| 633 GURL blacklisted_url(kBlacklistedUrl); | |
| 634 | |
| 635 factory_.SetFakeResponse( | |
| 636 SuggestionsServiceImpl::BuildSuggestionsBlacklistClearURL(), | |
| 637 suggestions_profile.SerializeAsString(), net::HTTP_OK, | |
| 638 net::URLRequestStatus::SUCCESS); | |
| 639 | 532 |
| 640 // Blacklist expectations. | 533 // Blacklist expectations. |
| 641 EXPECT_CALL(*mock_blacklist_store_, BlacklistUrl(Eq(blacklisted_url))) | 534 EXPECT_CALL(*blacklist_store(), BlacklistUrl(Eq(GURL(kBlacklistedUrl)))) |
| 642 .WillOnce(Return(true)); | 535 .WillOnce(Return(true)); |
| 643 EXPECT_CALL(*mock_thumbnail_manager_, | 536 EXPECT_CALL(*thumbnail_manager(), |
| 644 Initialize(EqualsProto(suggestions_profile))) | 537 Initialize(EqualsProto(CreateSuggestionsProfile()))) |
| 645 .Times(AnyNumber()); | 538 .Times(AnyNumber()); |
| 646 EXPECT_CALL(*mock_blacklist_store_, FilterSuggestions(_)).Times(AnyNumber()); | 539 EXPECT_CALL(*blacklist_store(), FilterSuggestions(_)).Times(AnyNumber()); |
| 647 EXPECT_CALL(*mock_blacklist_store_, GetTimeUntilReadyForUpload(_)) | 540 EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_)) |
| 648 .WillOnce(DoAll(SetArgPointee<0>(delay), Return(true))); | 541 .WillOnce(DoAll(SetArgPointee<0>(delay), Return(true))); |
| 649 EXPECT_CALL(*mock_blacklist_store_, ClearBlacklist()); | 542 EXPECT_CALL(*blacklist_store(), ClearBlacklist()); |
| 650 | 543 |
| 651 EXPECT_TRUE(suggestions_service->BlacklistURL(blacklisted_url)); | 544 EXPECT_TRUE(suggestions_service()->BlacklistURL(GURL(kBlacklistedUrl))); |
| 652 suggestions_service->ClearBlacklist(); | 545 suggestions_service()->ClearBlacklist(); |
| 653 | 546 |
| 654 EXPECT_EQ(2, suggestions_data_callback_count_); | 547 base::RunLoop().RunUntilIdle(); |
| 548 EXPECT_EQ(CurrentlyQueriedUrl().path(), kBlacklistClearUrlPath); | |
| 549 | |
| 550 EXPECT_EQ(2, data_callback_count()); | |
| 655 } | 551 } |
| 656 | 552 |
| 657 TEST_F(SuggestionsServiceTest, UndoBlacklistURLFailsIfNotInBlacklist) { | 553 TEST_F(SuggestionsServiceTest, UndoBlacklistURLFailsIfNotInBlacklist) { |
| 658 UndoBlacklistURLFailsHelper(true); | 554 // Ensure scheduling the request doesn't happen before undo. |
| 555 base::TimeDelta delay = base::TimeDelta::FromHours(1); | |
| 556 suggestions_service()->set_blacklist_delay_for_testing(delay); | |
| 557 | |
| 558 // Blacklist expectations. | |
| 559 EXPECT_CALL(*blacklist_store(), BlacklistUrl(Eq(GURL(kBlacklistedUrl)))) | |
| 560 .WillOnce(Return(true)); | |
| 561 EXPECT_CALL(*thumbnail_manager(), | |
| 562 Initialize(EqualsProto(CreateSuggestionsProfile()))); | |
| 563 EXPECT_CALL(*blacklist_store(), FilterSuggestions(_)); | |
| 564 EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_)) | |
| 565 .WillOnce(DoAll(SetArgPointee<0>(delay), Return(true))); | |
| 566 // Undo expectations. | |
| 567 // URL is not in local blacklist. | |
| 568 EXPECT_CALL(*blacklist_store(), | |
| 569 GetTimeUntilURLReadyForUpload(Eq(GURL(kBlacklistedUrl)), _)) | |
| 570 .WillOnce(Return(false)); | |
| 571 | |
| 572 EXPECT_TRUE(suggestions_service()->BlacklistURL(GURL(kBlacklistedUrl))); | |
| 573 EXPECT_FALSE(suggestions_service()->UndoBlacklistURL(GURL(kBlacklistedUrl))); | |
| 574 | |
| 575 EXPECT_EQ(1, data_callback_count()); | |
| 659 } | 576 } |
| 660 | 577 |
| 661 TEST_F(SuggestionsServiceTest, UndoBlacklistURLFailsIfAlreadyCandidate) { | 578 TEST_F(SuggestionsServiceTest, UndoBlacklistURLFailsIfAlreadyCandidate) { |
| 662 UndoBlacklistURLFailsHelper(false); | 579 // Ensure scheduling the request doesn't happen before undo. |
| 580 base::TimeDelta delay = base::TimeDelta::FromHours(1); | |
| 581 suggestions_service()->set_blacklist_delay_for_testing(delay); | |
| 582 | |
| 583 SuggestionsProfile suggestions_profile = CreateSuggestionsProfile(); | |
| 584 | |
| 585 // Blacklist expectations. | |
| 586 EXPECT_CALL(*blacklist_store(), BlacklistUrl(Eq(GURL(kBlacklistedUrl)))) | |
| 587 .WillOnce(Return(true)); | |
| 588 EXPECT_CALL(*thumbnail_manager(), | |
| 589 Initialize(EqualsProto(suggestions_profile))); | |
| 590 EXPECT_CALL(*blacklist_store(), FilterSuggestions(_)); | |
| 591 EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_)) | |
| 592 .WillOnce(DoAll(SetArgPointee<0>(delay), Return(true))); | |
| 593 // Undo expectations. | |
| 594 base::TimeDelta negative_delay = base::TimeDelta::FromHours(-1); | |
| 595 EXPECT_CALL(*blacklist_store(), | |
| 596 GetTimeUntilURLReadyForUpload(Eq(GURL(kBlacklistedUrl)), _)) | |
| 597 .WillOnce(DoAll(SetArgPointee<1>(negative_delay), Return(true))); | |
| 598 | |
| 599 EXPECT_TRUE(suggestions_service()->BlacklistURL(GURL(kBlacklistedUrl))); | |
| 600 EXPECT_FALSE(suggestions_service()->UndoBlacklistURL(GURL(kBlacklistedUrl))); | |
| 601 | |
| 602 EXPECT_EQ(1, data_callback_count()); | |
| 663 } | 603 } |
| 664 | 604 |
| 665 TEST_F(SuggestionsServiceTest, GetBlacklistedUrlNotBlacklistRequest) { | 605 TEST_F(SuggestionsServiceTest, TemporaryIncreasesBlacklistDelayOnFailure) { |
| 666 // Not a blacklist request. | 606 EXPECT_CALL(*thumbnail_manager(), Initialize(_)).Times(AnyNumber()); |
| 667 std::unique_ptr<net::FakeURLFetcher> fetcher( | 607 EXPECT_CALL(*blacklist_store(), FilterSuggestions(_)).Times(AnyNumber()); |
| 668 CreateURLFetcher(GURL("http://not-blacklisting.com/a?b=c"), nullptr, "", | 608 EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_)) |
| 669 net::HTTP_OK, net::URLRequestStatus::SUCCESS)); | 609 .Times(AnyNumber()) |
| 670 GURL retrieved_url; | 610 .WillRepeatedly(Return(false)); |
| 671 EXPECT_FALSE( | 611 base::TimeDelta initial_delay = |
| 672 SuggestionsServiceImpl::GetBlacklistedUrl(*fetcher, &retrieved_url)); | 612 suggestions_service()->blacklist_delay_for_testing(); |
| 613 | |
| 614 // Delay unchanged on success. | |
| 615 suggestions_service()->FetchSuggestionsData(); | |
| 616 base::RunLoop().RunUntilIdle(); | |
| 617 RespondToFetchWithProfile(CreateSuggestionsProfile()); | |
| 618 EXPECT_EQ(initial_delay, | |
| 619 suggestions_service()->blacklist_delay_for_testing()); | |
| 620 | |
| 621 // Delay increases on failure. | |
| 622 suggestions_service()->FetchSuggestionsData(); | |
| 623 base::RunLoop().RunUntilIdle(); | |
| 624 RespondToFetch( | |
| 625 "irrelevant", net::HTTP_BAD_REQUEST, | |
| 626 net::URLRequestStatus(net::URLRequestStatus::SUCCESS, net::OK)); | |
| 627 EXPECT_GT(suggestions_service()->blacklist_delay_for_testing(), | |
| 628 initial_delay); | |
| 629 | |
| 630 // Delay resets on success. | |
| 631 suggestions_service()->FetchSuggestionsData(); | |
| 632 base::RunLoop().RunUntilIdle(); | |
| 633 RespondToFetchWithProfile(CreateSuggestionsProfile()); | |
| 634 EXPECT_EQ(initial_delay, | |
| 635 suggestions_service()->blacklist_delay_for_testing()); | |
| 673 } | 636 } |
| 674 | 637 |
| 675 TEST_F(SuggestionsServiceTest, GetBlacklistedUrlBlacklistRequest) { | 638 TEST_F(SuggestionsServiceTest, DoesNotOverrideDefaultExpiryTime) { |
| 676 // An actual blacklist request. | 639 EXPECT_CALL(*thumbnail_manager(), Initialize(_)); |
| 677 std::string blacklisted_url = "http://blacklisted.com/a?b=c&d=e"; | 640 EXPECT_CALL(*blacklist_store(), FilterSuggestions(_)); |
| 678 std::string encoded_blacklisted_url = | 641 EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_)) |
| 679 "http%3A%2F%2Fblacklisted.com%2Fa%3Fb%3Dc%26d%3De"; | 642 .WillOnce(Return(false)); |
| 680 std::string blacklist_request_prefix( | |
| 681 SuggestionsServiceImpl::BuildSuggestionsBlacklistURLPrefix()); | |
| 682 std::unique_ptr<net::FakeURLFetcher> fetcher(CreateURLFetcher( | |
| 683 GURL(blacklist_request_prefix + encoded_blacklisted_url), nullptr, "", | |
| 684 net::HTTP_OK, net::URLRequestStatus::SUCCESS)); | |
| 685 GURL retrieved_url; | |
| 686 EXPECT_TRUE( | |
| 687 SuggestionsServiceImpl::GetBlacklistedUrl(*fetcher, &retrieved_url)); | |
| 688 EXPECT_EQ(blacklisted_url, retrieved_url.spec()); | |
|
fhorschig
2017/05/10 08:41:07
This case is covered by other tests like RetryBlac
| |
| 689 } | |
| 690 | 643 |
| 691 TEST_F(SuggestionsServiceTest, UpdateBlacklistDelay) { | 644 suggestions_service()->FetchSuggestionsData(); |
| 692 std::unique_ptr<SuggestionsServiceImpl> suggestions_service( | |
| 693 CreateSuggestionsServiceWithMocks()); | |
| 694 base::TimeDelta initial_delay = suggestions_service->blacklist_delay(); | |
| 695 | 645 |
| 696 // Delay unchanged on success. | 646 base::RunLoop().RunUntilIdle(); |
| 697 suggestions_service->UpdateBlacklistDelay(true); | 647 // Creates one suggestion without timestamp and adds a second with timestamp. |
| 698 EXPECT_EQ(initial_delay, suggestions_service->blacklist_delay()); | 648 SuggestionsProfile profile = CreateSuggestionsProfile(); |
| 649 ChromeSuggestion* suggestion = profile.add_suggestions(); | |
| 650 suggestion->set_title(kTestTitle); | |
| 651 suggestion->set_url(kTestUrl); | |
| 652 suggestion->set_expiry_ts(kTestSetExpiry); | |
| 653 RespondToFetchWithProfile(profile); | |
| 699 | 654 |
| 700 // Delay increases on failure. | 655 SuggestionsProfile suggestions_profile; |
| 701 suggestions_service->UpdateBlacklistDelay(false); | 656 suggestions_store()->LoadSuggestions(&suggestions_profile); |
| 702 EXPECT_GT(suggestions_service->blacklist_delay(), initial_delay); | 657 ASSERT_EQ(2, suggestions_profile.suggestions_size()); |
| 703 | 658 // Suggestion[1] had a very old time stamp but should not be updated. |
| 704 // Delay resets on success. | 659 EXPECT_EQ(kTestSetExpiry, suggestions_profile.suggestions(1).expiry_ts()); |
| 705 suggestions_service->UpdateBlacklistDelay(true); | 660 // Suggestion[0] had no time stamp and should be ahead of the old suggestion. |
| 706 EXPECT_EQ(initial_delay, suggestions_service->blacklist_delay()); | 661 EXPECT_GT(kTestSetExpiry, suggestions_profile.suggestions(0).expiry_ts()); |
| 707 } | |
| 708 | |
| 709 TEST_F(SuggestionsServiceTest, CheckDefaultTimeStamps) { | |
| 710 std::unique_ptr<SuggestionsServiceImpl> suggestions_service( | |
| 711 CreateSuggestionsServiceWithMocks()); | |
| 712 SuggestionsProfile suggestions = | |
| 713 CreateSuggestionsProfileWithExpiryTimestamps(); | |
| 714 suggestions_service->SetDefaultExpiryTimestamp(&suggestions, | |
| 715 kTestDefaultExpiry); | |
| 716 EXPECT_EQ(kTestSetExpiry, suggestions.suggestions(0).expiry_ts()); | |
| 717 EXPECT_EQ(kTestDefaultExpiry, suggestions.suggestions(1).expiry_ts()); | |
| 718 } | 662 } |
| 719 | 663 |
| 720 TEST_F(SuggestionsServiceTest, GetPageThumbnail) { | 664 TEST_F(SuggestionsServiceTest, GetPageThumbnail) { |
| 721 std::unique_ptr<SuggestionsService> suggestions_service( | |
| 722 CreateSuggestionsServiceWithMocks()); | |
| 723 | |
| 724 GURL test_url(kTestUrl); | 665 GURL test_url(kTestUrl); |
| 725 GURL thumbnail_url("https://www.thumbnails.com/thumb.jpg"); | 666 GURL thumbnail_url("https://www.thumbnails.com/thumb.jpg"); |
| 726 base::Callback<void(const GURL&, const gfx::Image&)> dummy_callback; | 667 base::Callback<void(const GURL&, const gfx::Image&)> dummy_callback; |
| 727 | 668 |
| 728 EXPECT_CALL(*mock_thumbnail_manager_, GetImageForURL(test_url, _)); | 669 EXPECT_CALL(*thumbnail_manager(), GetImageForURL(test_url, _)); |
| 729 suggestions_service->GetPageThumbnail(test_url, dummy_callback); | 670 suggestions_service()->GetPageThumbnail(test_url, dummy_callback); |
| 730 | 671 |
| 731 EXPECT_CALL(*mock_thumbnail_manager_, AddImageURL(test_url, thumbnail_url)); | 672 EXPECT_CALL(*thumbnail_manager(), AddImageURL(test_url, thumbnail_url)); |
| 732 EXPECT_CALL(*mock_thumbnail_manager_, GetImageForURL(test_url, _)); | 673 EXPECT_CALL(*thumbnail_manager(), GetImageForURL(test_url, _)); |
| 733 suggestions_service->GetPageThumbnailWithURL(test_url, thumbnail_url, | 674 suggestions_service()->GetPageThumbnailWithURL(test_url, thumbnail_url, |
| 734 dummy_callback); | 675 dummy_callback); |
| 735 } | 676 } |
| 736 | 677 |
| 737 } // namespace suggestions | 678 } // namespace suggestions |
| OLD | NEW |