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