profile_sync_service_typed_url_unittest.cc revision 513209b27ff55e2841eac0e4120199c23acce758
1// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <vector> 6 7#include "testing/gtest/include/gtest/gtest.h" 8 9#include "base/ref_counted.h" 10#include "base/string16.h" 11#include "base/thread.h" 12#include "base/time.h" 13#include "chrome/browser/history/history_backend.h" 14#include "chrome/browser/history/history_notifications.h" 15#include "chrome/browser/history/history_types.h" 16#include "chrome/browser/sync/abstract_profile_sync_service_test.h" 17#include "chrome/browser/sync/engine/syncapi.h" 18#include "chrome/browser/sync/glue/sync_backend_host.h" 19#include "chrome/browser/sync/glue/sync_backend_host_mock.h" 20#include "chrome/browser/sync/glue/typed_url_change_processor.h" 21#include "chrome/browser/sync/glue/typed_url_data_type_controller.h" 22#include "chrome/browser/sync/glue/typed_url_model_associator.h" 23#include "chrome/browser/sync/profile_sync_factory.h" 24#include "chrome/browser/sync/profile_sync_factory_mock.h" 25#include "chrome/browser/sync/profile_sync_service.h" 26#include "chrome/browser/sync/profile_sync_test_util.h" 27#include "chrome/browser/sync/protocol/typed_url_specifics.pb.h" 28#include "chrome/browser/sync/syncable/directory_manager.h" 29#include "chrome/browser/sync/test_profile_sync_service.h" 30#include "chrome/common/net/gaia/gaia_constants.h" 31#include "chrome/common/notification_service.h" 32#include "chrome/test/profile_mock.h" 33#include "chrome/test/sync/engine/test_id_factory.h" 34#include "chrome/test/testing_profile.h" 35#include "googleurl/src/gurl.h" 36#include "testing/gmock/include/gmock/gmock.h" 37 38using base::Time; 39using base::Thread; 40using browser_sync::SyncBackendHost; 41using browser_sync::SyncBackendHostMock; 42using browser_sync::TestIdFactory; 43using browser_sync::TypedUrlChangeProcessor; 44using browser_sync::TypedUrlDataTypeController; 45using browser_sync::TypedUrlModelAssociator; 46using browser_sync::UnrecoverableErrorHandler; 47using history::HistoryBackend; 48using history::URLID; 49using history::URLRow; 50using sync_api::SyncManager; 51using sync_api::UserShare; 52using syncable::BASE_VERSION; 53using syncable::CREATE; 54using syncable::DirectoryManager; 55using syncable::IS_DEL; 56using syncable::IS_DIR; 57using syncable::IS_UNAPPLIED_UPDATE; 58using syncable::IS_UNSYNCED; 59using syncable::MutableEntry; 60using syncable::SERVER_IS_DIR; 61using syncable::SERVER_VERSION; 62using syncable::SPECIFICS; 63using syncable::ScopedDirLookup; 64using syncable::UNIQUE_SERVER_TAG; 65using syncable::UNITTEST; 66using syncable::WriteTransaction; 67using testing::_; 68using testing::DoAll; 69using testing::DoDefault; 70using testing::Invoke; 71using testing::Return; 72using testing::SetArgumentPointee; 73using testing::WithArgs; 74 75class HistoryBackendMock : public HistoryBackend { 76 public: 77 HistoryBackendMock() : HistoryBackend(FilePath(), NULL, NULL) {} 78 MOCK_METHOD1(GetAllTypedURLs, bool(std::vector<history::URLRow>* entries)); 79 MOCK_METHOD2(GetVisitsForURL, bool(history::URLID id, 80 history::VisitVector* visits)); 81 MOCK_METHOD2(UpdateURL, bool(history::URLID id, const history::URLRow& url)); 82 MOCK_METHOD3(AddVisits, bool(const GURL& url, 83 const std::vector<base::Time>& visits, 84 history::VisitSource visit_source)); 85 MOCK_METHOD1(RemoveVisits, bool(const history::VisitVector& visits)); 86 MOCK_METHOD2(GetURL, bool(const GURL& url_id, history::URLRow* url_row)); 87 MOCK_METHOD2(SetPageTitle, void(const GURL& url, const std::wstring& title)); 88 MOCK_METHOD1(DeleteURL, void(const GURL& url)); 89}; 90 91class HistoryServiceMock : public HistoryService { 92 public: 93 HistoryServiceMock() {} 94 MOCK_METHOD2(ScheduleDBTask, Handle(HistoryDBTask*, 95 CancelableRequestConsumerBase*)); 96}; 97 98class RunOnDBThreadTask : public Task { 99 public: 100 RunOnDBThreadTask(HistoryBackend* backend, HistoryDBTask* task) 101 : backend_(backend), task_(task) {} 102 virtual void Run() { 103 task_->RunOnDBThread(backend_, NULL); 104 task_ = NULL; 105 } 106 private: 107 HistoryBackend* backend_; 108 scoped_refptr<HistoryDBTask> task_; 109}; 110 111ACTION_P2(RunTaskOnDBThread, thread, backend) { 112 thread->message_loop()->PostTask( 113 FROM_HERE, 114 new RunOnDBThreadTask(backend, arg0)); 115 return 0; 116} 117 118ACTION_P3(MakeTypedUrlSyncComponents, service, hb, dtc) { 119 TypedUrlModelAssociator* model_associator = 120 new TypedUrlModelAssociator(service, hb); 121 TypedUrlChangeProcessor* change_processor = 122 new TypedUrlChangeProcessor(model_associator, hb, service); 123 return ProfileSyncFactory::SyncComponents(model_associator, change_processor); 124} 125 126class ProfileSyncServiceTypedUrlTest : public AbstractProfileSyncServiceTest { 127 protected: 128 ProfileSyncServiceTypedUrlTest() 129 : history_thread_("history") { 130 } 131 132 virtual void SetUp() { 133 history_backend_ = new HistoryBackendMock(); 134 history_service_ = new HistoryServiceMock(); 135 EXPECT_CALL((*history_service_.get()), ScheduleDBTask(_, _)) 136 .WillRepeatedly(RunTaskOnDBThread(&history_thread_, 137 history_backend_.get())); 138 history_thread_.Start(); 139 140 notification_service_ = 141 new ThreadNotificationService(&history_thread_); 142 notification_service_->Init(); 143 } 144 145 virtual void TearDown() { 146 history_backend_ = NULL; 147 history_service_ = NULL; 148 service_.reset(); 149 notification_service_->TearDown(); 150 history_thread_.Stop(); 151 MessageLoop::current()->RunAllPending(); 152 } 153 154 void StartSyncService(Task* task) { 155 if (!service_.get()) { 156 service_.reset( 157 new TestProfileSyncService(&factory_, &profile_, "test", false, 158 task)); 159 TypedUrlDataTypeController* data_type_controller = 160 new TypedUrlDataTypeController(&factory_, 161 &profile_, 162 service_.get()); 163 164 EXPECT_CALL(factory_, CreateTypedUrlSyncComponents(_, _, _)). 165 WillOnce(MakeTypedUrlSyncComponents(service_.get(), 166 history_backend_.get(), 167 data_type_controller)); 168 EXPECT_CALL(factory_, CreateDataTypeManager(_, _)). 169 WillOnce(ReturnNewDataTypeManager()); 170 171 EXPECT_CALL(profile_, GetHistoryServiceWithoutCreating()). 172 WillRepeatedly(Return(history_service_.get())); 173 174 EXPECT_CALL(profile_, GetPasswordStore(_)). 175 WillOnce(Return(static_cast<PasswordStore*>(NULL))); 176 177 EXPECT_CALL(profile_, GetHistoryService(_)). 178 WillRepeatedly(Return(history_service_.get())); 179 180 token_service_.IssueAuthTokenForTest( 181 GaiaConstants::kSyncService, "token"); 182 183 EXPECT_CALL(profile_, GetTokenService()). 184 WillRepeatedly(Return(&token_service_)); 185 186 service_->RegisterDataTypeController(data_type_controller); 187 188 service_->Initialize(); 189 MessageLoop::current()->Run(); 190 } 191 } 192 193 void AddTypedUrlSyncNode(const history::URLRow& url, 194 const history::VisitVector& visits) { 195 sync_api::WriteTransaction trans( 196 service_->backend()->GetUserShareHandle()); 197 sync_api::ReadNode typed_url_root(&trans); 198 ASSERT_TRUE(typed_url_root.InitByTagLookup(browser_sync::kTypedUrlTag)); 199 200 sync_api::WriteNode node(&trans); 201 std::string tag = url.url().spec(); 202 ASSERT_TRUE(node.InitUniqueByCreation(syncable::TYPED_URLS, 203 typed_url_root, 204 tag)); 205 TypedUrlModelAssociator::WriteToSyncNode(url, visits, &node); 206 } 207 208 void GetTypedUrlsFromSyncDB(std::vector<history::URLRow>* urls) { 209 sync_api::ReadTransaction trans(service_->backend()->GetUserShareHandle()); 210 sync_api::ReadNode typed_url_root(&trans); 211 if (!typed_url_root.InitByTagLookup(browser_sync::kTypedUrlTag)) 212 return; 213 214 int64 child_id = typed_url_root.GetFirstChildId(); 215 while (child_id != sync_api::kInvalidId) { 216 sync_api::ReadNode child_node(&trans); 217 if (!child_node.InitByIdLookup(child_id)) 218 return; 219 220 const sync_pb::TypedUrlSpecifics& typed_url( 221 child_node.GetTypedUrlSpecifics()); 222 history::URLRow new_url(GURL(typed_url.url())); 223 224 new_url.set_title(UTF8ToUTF16(typed_url.title())); 225 new_url.set_typed_count(typed_url.typed_count()); 226 DCHECK(typed_url.visit_size()); 227 new_url.set_visit_count(typed_url.visit_size()); 228 new_url.set_last_visit(base::Time::FromInternalValue( 229 typed_url.visit(typed_url.visit_size() - 1))); 230 new_url.set_hidden(typed_url.hidden()); 231 232 urls->push_back(new_url); 233 child_id = child_node.GetSuccessorId(); 234 } 235 } 236 237 void SetIdleChangeProcessorExpectations() { 238 EXPECT_CALL((*history_backend_.get()), SetPageTitle(_, _)).Times(0); 239 EXPECT_CALL((*history_backend_.get()), UpdateURL(_, _)).Times(0); 240 EXPECT_CALL((*history_backend_.get()), GetURL(_, _)).Times(0); 241 EXPECT_CALL((*history_backend_.get()), DeleteURL(_)).Times(0); 242 } 243 244 static bool URLsEqual(history::URLRow& lhs, history::URLRow& rhs) { 245 return (lhs.url().spec().compare(rhs.url().spec()) == 0) && 246 (lhs.title().compare(rhs.title()) == 0) && 247 (lhs.visit_count() == rhs.visit_count()) && 248 (lhs.typed_count() == rhs.typed_count()) && 249 (lhs.last_visit() == rhs.last_visit()) && 250 (lhs.hidden() == rhs.hidden()); 251 } 252 253 static history::URLRow MakeTypedUrlEntry(const char* url, 254 const char* title, 255 int typed_count, 256 int64 last_visit, 257 bool hidden, 258 history::VisitVector* visits) { 259 GURL gurl(url); 260 URLRow history_url(gurl); 261 history_url.set_title(UTF8ToUTF16(title)); 262 history_url.set_typed_count(typed_count); 263 history_url.set_last_visit( 264 base::Time::FromInternalValue(last_visit)); 265 history_url.set_hidden(hidden); 266 visits->push_back(history::VisitRow( 267 history_url.id(), history_url.last_visit(), 0, 0, 0)); 268 history_url.set_visit_count(visits->size()); 269 return history_url; 270 } 271 272 friend class AddTypedUrlEntriesTask; 273 friend class CreateTypedUrlRootTask; 274 275 Thread history_thread_; 276 scoped_refptr<ThreadNotificationService> notification_service_; 277 278 ProfileMock profile_; 279 ProfileSyncFactoryMock factory_; 280 scoped_refptr<HistoryBackendMock> history_backend_; 281 scoped_refptr<HistoryServiceMock> history_service_; 282 283 TestIdFactory ids_; 284}; 285 286class AddTypedUrlEntriesTask : public Task { 287 public: 288 AddTypedUrlEntriesTask(ProfileSyncServiceTypedUrlTest* test, 289 const std::vector<history::URLRow>& entries) 290 : test_(test), entries_(entries) { 291 } 292 293 virtual void Run() { 294 test_->CreateRoot(syncable::TYPED_URLS); 295 for (size_t i = 0; i < entries_.size(); ++i) { 296 history::VisitVector visits; 297 visits.push_back(history::VisitRow( 298 entries_[i].id(), entries_[i].last_visit(), 0, 0, 0)); 299 test_->AddTypedUrlSyncNode(entries_[i], visits); 300 } 301 } 302 303 private: 304 ProfileSyncServiceTypedUrlTest* test_; 305 const std::vector<history::URLRow>& entries_; 306}; 307 308TEST_F(ProfileSyncServiceTypedUrlTest, EmptyNativeEmptySync) { 309 EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)). 310 WillOnce(Return(true)); 311 SetIdleChangeProcessorExpectations(); 312 CreateRootTask task(this, syncable::TYPED_URLS); 313 StartSyncService(&task); 314 std::vector<history::URLRow> sync_entries; 315 GetTypedUrlsFromSyncDB(&sync_entries); 316 EXPECT_EQ(0U, sync_entries.size()); 317} 318 319TEST_F(ProfileSyncServiceTypedUrlTest, HasNativeEmptySync) { 320 std::vector<history::URLRow> entries; 321 history::VisitVector visits; 322 entries.push_back(MakeTypedUrlEntry("http://foo.com", "bar", 323 2, 15, false, &visits)); 324 325 EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)). 326 WillOnce(DoAll(SetArgumentPointee<0>(entries), Return(true))); 327 EXPECT_CALL((*history_backend_.get()), GetVisitsForURL(_, _)). 328 WillRepeatedly(DoAll(SetArgumentPointee<1>(visits), Return(true))); 329 SetIdleChangeProcessorExpectations(); 330 CreateRootTask task(this, syncable::TYPED_URLS); 331 StartSyncService(&task); 332 std::vector<history::URLRow> sync_entries; 333 GetTypedUrlsFromSyncDB(&sync_entries); 334 ASSERT_EQ(1U, sync_entries.size()); 335 EXPECT_TRUE(URLsEqual(entries[0], sync_entries[0])); 336} 337 338TEST_F(ProfileSyncServiceTypedUrlTest, HasNativeHasSyncNoMerge) { 339 history::VisitVector native_visits; 340 history::VisitVector sync_visits; 341 history::URLRow native_entry(MakeTypedUrlEntry("http://native.com", "entry", 342 2, 15, false, &native_visits)); 343 history::URLRow sync_entry(MakeTypedUrlEntry("http://sync.com", "entry", 344 3, 16, false, &sync_visits)); 345 346 std::vector<history::URLRow> native_entries; 347 native_entries.push_back(native_entry); 348 EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)). 349 WillOnce(DoAll(SetArgumentPointee<0>(native_entries), Return(true))); 350 EXPECT_CALL((*history_backend_.get()), GetVisitsForURL(_, _)). 351 WillRepeatedly(DoAll(SetArgumentPointee<1>(native_visits), Return(true))); 352 EXPECT_CALL((*history_backend_.get()), 353 AddVisits(_, _, history::SOURCE_SYNCED)).WillRepeatedly(Return(true)); 354 355 std::vector<history::URLRow> sync_entries; 356 sync_entries.push_back(sync_entry); 357 AddTypedUrlEntriesTask task(this, sync_entries); 358 359 EXPECT_CALL((*history_backend_.get()), UpdateURL(_, _)). 360 WillRepeatedly(Return(true)); 361 StartSyncService(&task); 362 363 std::map<std::string, history::URLRow> expected; 364 expected[native_entry.url().spec()] = native_entry; 365 expected[sync_entry.url().spec()] = sync_entry; 366 367 std::vector<history::URLRow> new_sync_entries; 368 GetTypedUrlsFromSyncDB(&new_sync_entries); 369 370 EXPECT_TRUE(new_sync_entries.size() == expected.size()); 371 for (std::vector<history::URLRow>::iterator entry = new_sync_entries.begin(); 372 entry != new_sync_entries.end(); ++entry) { 373 EXPECT_TRUE(URLsEqual(expected[entry->url().spec()], *entry)); 374 } 375} 376 377TEST_F(ProfileSyncServiceTypedUrlTest, HasNativeHasSyncMerge) { 378 history::VisitVector native_visits; 379 history::URLRow native_entry(MakeTypedUrlEntry("http://native.com", "entry", 380 2, 15, false, &native_visits)); 381 history::VisitVector sync_visits; 382 history::URLRow sync_entry(MakeTypedUrlEntry("http://native.com", "name", 383 1, 17, false, &sync_visits)); 384 history::VisitVector merged_visits; 385 merged_visits.push_back(history::VisitRow( 386 sync_entry.id(), base::Time::FromInternalValue(15), 0, 0, 0)); 387 388 history::URLRow merged_entry(MakeTypedUrlEntry("http://native.com", "name", 389 2, 17, false, &merged_visits)); 390 391 std::vector<history::URLRow> native_entries; 392 native_entries.push_back(native_entry); 393 EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)). 394 WillOnce(DoAll(SetArgumentPointee<0>(native_entries), Return(true))); 395 EXPECT_CALL((*history_backend_.get()), GetVisitsForURL(_, _)). 396 WillRepeatedly(DoAll(SetArgumentPointee<1>(native_visits), Return(true))); 397 EXPECT_CALL((*history_backend_.get()), 398 AddVisits(_, _, history::SOURCE_SYNCED)). WillRepeatedly(Return(true)); 399 400 std::vector<history::URLRow> sync_entries; 401 sync_entries.push_back(sync_entry); 402 AddTypedUrlEntriesTask task(this, sync_entries); 403 404 EXPECT_CALL((*history_backend_.get()), UpdateURL(_, _)). 405 WillRepeatedly(Return(true)); 406 EXPECT_CALL((*history_backend_.get()), SetPageTitle(_, _)). 407 WillRepeatedly(Return()); 408 StartSyncService(&task); 409 410 std::vector<history::URLRow> new_sync_entries; 411 GetTypedUrlsFromSyncDB(&new_sync_entries); 412 ASSERT_EQ(1U, new_sync_entries.size()); 413 EXPECT_TRUE(URLsEqual(merged_entry, new_sync_entries[0])); 414} 415 416TEST_F(ProfileSyncServiceTypedUrlTest, ProcessUserChangeAdd) { 417 history::VisitVector added_visits; 418 history::URLRow added_entry(MakeTypedUrlEntry("http://added.com", "entry", 419 2, 15, false, &added_visits)); 420 421 EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)). 422 WillOnce(Return(true)); 423 EXPECT_CALL((*history_backend_.get()), GetVisitsForURL(_, _)). 424 WillOnce(DoAll(SetArgumentPointee<1>(added_visits), Return(true))); 425 426 SetIdleChangeProcessorExpectations(); 427 CreateRootTask task(this, syncable::TYPED_URLS); 428 StartSyncService(&task); 429 430 history::URLsModifiedDetails details; 431 details.changed_urls.push_back(added_entry); 432 scoped_refptr<ThreadNotifier> notifier(new ThreadNotifier(&history_thread_)); 433 notifier->Notify(NotificationType::HISTORY_TYPED_URLS_MODIFIED, 434 Details<history::URLsModifiedDetails>(&details)); 435 436 std::vector<history::URLRow> new_sync_entries; 437 GetTypedUrlsFromSyncDB(&new_sync_entries); 438 ASSERT_EQ(1U, new_sync_entries.size()); 439 EXPECT_TRUE(URLsEqual(added_entry, new_sync_entries[0])); 440} 441 442TEST_F(ProfileSyncServiceTypedUrlTest, ProcessUserChangeUpdate) { 443 history::VisitVector original_visits; 444 history::URLRow original_entry(MakeTypedUrlEntry("http://mine.com", "entry", 445 2, 15, false, 446 &original_visits)); 447 std::vector<history::URLRow> original_entries; 448 original_entries.push_back(original_entry); 449 450 EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)). 451 WillOnce(DoAll(SetArgumentPointee<0>(original_entries), Return(true))); 452 EXPECT_CALL((*history_backend_.get()), GetVisitsForURL(_, _)). 453 WillRepeatedly(DoAll(SetArgumentPointee<1>(original_visits), 454 Return(true))); 455 CreateRootTask task(this, syncable::TYPED_URLS); 456 StartSyncService(&task); 457 458 history::VisitVector updated_visits; 459 history::URLRow updated_entry(MakeTypedUrlEntry("http://mine.com", "entry", 460 7, 15, false, 461 &updated_visits)); 462 463 history::URLsModifiedDetails details; 464 details.changed_urls.push_back(updated_entry); 465 scoped_refptr<ThreadNotifier> notifier(new ThreadNotifier(&history_thread_)); 466 notifier->Notify(NotificationType::HISTORY_TYPED_URLS_MODIFIED, 467 Details<history::URLsModifiedDetails>(&details)); 468 469 std::vector<history::URLRow> new_sync_entries; 470 GetTypedUrlsFromSyncDB(&new_sync_entries); 471 ASSERT_EQ(1U, new_sync_entries.size()); 472 EXPECT_TRUE(URLsEqual(updated_entry, new_sync_entries[0])); 473} 474 475TEST_F(ProfileSyncServiceTypedUrlTest, ProcessUserChangeRemove) { 476 history::VisitVector original_visits1; 477 history::URLRow original_entry1(MakeTypedUrlEntry("http://mine.com", "entry", 478 2, 15, false, 479 &original_visits1)); 480 history::VisitVector original_visits2; 481 history::URLRow original_entry2(MakeTypedUrlEntry("http://mine2.com", 482 "entry2", 483 3, 15, false, 484 &original_visits2)); 485 std::vector<history::URLRow> original_entries; 486 original_entries.push_back(original_entry1); 487 original_entries.push_back(original_entry2); 488 489 EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)). 490 WillOnce(DoAll(SetArgumentPointee<0>(original_entries), Return(true))); 491 EXPECT_CALL((*history_backend_.get()), GetVisitsForURL(_, _)). 492 WillRepeatedly(DoAll(SetArgumentPointee<1>(original_visits1), 493 Return(true))); 494 CreateRootTask task(this, syncable::TYPED_URLS); 495 StartSyncService(&task); 496 497 history::URLsDeletedDetails changes; 498 changes.all_history = false; 499 changes.urls.insert(GURL("http://mine.com")); 500 scoped_refptr<ThreadNotifier> notifier(new ThreadNotifier(&history_thread_)); 501 notifier->Notify(NotificationType::HISTORY_URLS_DELETED, 502 Details<history::URLsDeletedDetails>(&changes)); 503 504 std::vector<history::URLRow> new_sync_entries; 505 GetTypedUrlsFromSyncDB(&new_sync_entries); 506 ASSERT_EQ(1U, new_sync_entries.size()); 507 EXPECT_TRUE(URLsEqual(original_entry2, new_sync_entries[0])); 508} 509 510TEST_F(ProfileSyncServiceTypedUrlTest, ProcessUserChangeRemoveAll) { 511 history::VisitVector original_visits1; 512 history::URLRow original_entry1(MakeTypedUrlEntry("http://mine.com", "entry", 513 2, 15, false, 514 &original_visits1)); 515 history::VisitVector original_visits2; 516 history::URLRow original_entry2(MakeTypedUrlEntry("http://mine2.com", 517 "entry2", 518 3, 15, false, 519 &original_visits2)); 520 std::vector<history::URLRow> original_entries; 521 original_entries.push_back(original_entry1); 522 original_entries.push_back(original_entry2); 523 524 EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)). 525 WillOnce(DoAll(SetArgumentPointee<0>(original_entries), Return(true))); 526 EXPECT_CALL((*history_backend_.get()), GetVisitsForURL(_, _)). 527 WillRepeatedly(DoAll(SetArgumentPointee<1>(original_visits1), 528 Return(true))); 529 CreateRootTask task(this, syncable::TYPED_URLS); 530 StartSyncService(&task); 531 532 history::URLsDeletedDetails changes; 533 changes.all_history = true; 534 scoped_refptr<ThreadNotifier> notifier(new ThreadNotifier(&history_thread_)); 535 notifier->Notify(NotificationType::HISTORY_URLS_DELETED, 536 Details<history::URLsDeletedDetails>(&changes)); 537 538 std::vector<history::URLRow> new_sync_entries; 539 GetTypedUrlsFromSyncDB(&new_sync_entries); 540 ASSERT_EQ(0U, new_sync_entries.size()); 541} 542