1 // Copyright (c) 2012 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 "base/prefs/pref_member.h" 6 #include "base/prefs/pref_service.h" 7 #include "base/run_loop.h" 8 #include "chrome/browser/sync/profile_sync_service.h" 9 #include "chrome/browser/sync/test/integration/bookmarks_helper.h" 10 #include "chrome/browser/sync/test/integration/passwords_helper.h" 11 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h" 12 #include "chrome/browser/sync/test/integration/single_client_status_change_checker.h" 13 #include "chrome/browser/sync/test/integration/sync_integration_test_util.h" 14 #include "chrome/browser/sync/test/integration/sync_test.h" 15 #include "chrome/common/pref_names.h" 16 #include "google_apis/gaia/google_service_auth_error.h" 17 #include "sync/protocol/sync_protocol_error.h" 18 19 using bookmarks_helper::AddFolder; 20 using bookmarks_helper::SetTitle; 21 using sync_integration_test_util::AwaitCommitActivityCompletion; 22 23 namespace { 24 25 class SyncDisabledChecker : public SingleClientStatusChangeChecker { 26 public: 27 explicit SyncDisabledChecker(ProfileSyncService* service) 28 : SingleClientStatusChangeChecker(service) {} 29 30 virtual bool IsExitConditionSatisfied() OVERRIDE { 31 return !service()->setup_in_progress() && 32 !service()->HasSyncSetupCompleted(); 33 } 34 35 virtual std::string GetDebugMessage() const OVERRIDE { 36 return "Sync Disabled"; 37 } 38 }; 39 40 class TypeDisabledChecker : public SingleClientStatusChangeChecker { 41 public: 42 explicit TypeDisabledChecker(ProfileSyncService* service, 43 syncer::ModelType type) 44 : SingleClientStatusChangeChecker(service), type_(type) {} 45 46 virtual bool IsExitConditionSatisfied() OVERRIDE { 47 return !service()->GetActiveDataTypes().Has(type_); 48 } 49 50 virtual std::string GetDebugMessage() const OVERRIDE { 51 return "Type disabled"; 52 } 53 private: 54 syncer::ModelType type_; 55 }; 56 57 bool AwaitSyncDisabled(ProfileSyncService* service) { 58 SyncDisabledChecker checker(service); 59 checker.Wait(); 60 return !checker.TimedOut(); 61 } 62 63 bool AwaitTypeDisabled(ProfileSyncService* service, 64 syncer::ModelType type) { 65 TypeDisabledChecker checker(service, type); 66 checker.Wait(); 67 return !checker.TimedOut(); 68 } 69 70 class SyncErrorTest : public SyncTest { 71 public: 72 SyncErrorTest() : SyncTest(SINGLE_CLIENT) {} 73 virtual ~SyncErrorTest() {} 74 75 private: 76 DISALLOW_COPY_AND_ASSIGN(SyncErrorTest); 77 }; 78 79 // TODO(pvalenzuela): Remove this class when all tests here are converted to 80 // use FakeServer. 81 class LegacySyncErrorTest : public SyncTest { 82 public: 83 LegacySyncErrorTest() : SyncTest(SINGLE_CLIENT_LEGACY) {} 84 virtual ~LegacySyncErrorTest() {} 85 86 private: 87 DISALLOW_COPY_AND_ASSIGN(LegacySyncErrorTest); 88 }; 89 90 // Helper class that waits until the sync engine has hit an actionable error. 91 class ActionableErrorChecker : public SingleClientStatusChangeChecker { 92 public: 93 explicit ActionableErrorChecker(ProfileSyncService* service) 94 : SingleClientStatusChangeChecker(service) {} 95 96 virtual ~ActionableErrorChecker() {} 97 98 // Checks if an actionable error has been hit. Called repeatedly each time PSS 99 // notifies observers of a state change. 100 virtual bool IsExitConditionSatisfied() OVERRIDE { 101 ProfileSyncService::Status status; 102 service()->QueryDetailedSyncStatus(&status); 103 return (status.sync_protocol_error.action != syncer::UNKNOWN_ACTION && 104 service()->HasUnrecoverableError()); 105 } 106 107 virtual std::string GetDebugMessage() const OVERRIDE { 108 return "ActionableErrorChecker"; 109 } 110 111 private: 112 DISALLOW_COPY_AND_ASSIGN(ActionableErrorChecker); 113 }; 114 115 IN_PROC_BROWSER_TEST_F(SyncErrorTest, BirthdayErrorTest) { 116 ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; 117 118 // Add an item, wait for sync, and trigger a birthday error on the server. 119 const BookmarkNode* node1 = AddFolder(0, 0, "title1"); 120 SetTitle(0, node1, "new_title1"); 121 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0)))); 122 ASSERT_TRUE(GetFakeServer()->SetNewStoreBirthday("new store birthday")); 123 124 // Now make one more change so we will do another sync. 125 const BookmarkNode* node2 = AddFolder(0, 0, "title2"); 126 SetTitle(0, node2, "new_title2"); 127 ASSERT_TRUE(AwaitSyncDisabled(GetSyncService((0)))); 128 } 129 130 IN_PROC_BROWSER_TEST_F(LegacySyncErrorTest, ActionableErrorTest) { 131 ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; 132 133 const BookmarkNode* node1 = AddFolder(0, 0, "title1"); 134 SetTitle(0, node1, "new_title1"); 135 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0)))); 136 137 syncer::SyncProtocolError protocol_error; 138 protocol_error.error_type = syncer::TRANSIENT_ERROR; 139 protocol_error.action = syncer::UPGRADE_CLIENT; 140 protocol_error.error_description = "Not My Fault"; 141 protocol_error.url = "www.google.com"; 142 TriggerSyncError(protocol_error, SyncTest::ERROR_FREQUENCY_ALWAYS); 143 144 // Now make one more change so we will do another sync. 145 const BookmarkNode* node2 = AddFolder(0, 0, "title2"); 146 SetTitle(0, node2, "new_title2"); 147 148 // Wait until an actionable error is encountered. 149 ActionableErrorChecker actionable_error_checker(GetSyncService((0))); 150 actionable_error_checker.Wait(); 151 ASSERT_FALSE(actionable_error_checker.TimedOut()); 152 153 ProfileSyncService::Status status; 154 GetSyncService((0))->QueryDetailedSyncStatus(&status); 155 ASSERT_EQ(status.sync_protocol_error.error_type, protocol_error.error_type); 156 ASSERT_EQ(status.sync_protocol_error.action, protocol_error.action); 157 ASSERT_EQ(status.sync_protocol_error.url, protocol_error.url); 158 ASSERT_EQ(status.sync_protocol_error.error_description, 159 protocol_error.error_description); 160 } 161 162 // Disabled, http://crbug.com/351160 . 163 IN_PROC_BROWSER_TEST_F(LegacySyncErrorTest, DISABLED_ErrorWhileSettingUp) { 164 ASSERT_TRUE(SetupClients()); 165 166 syncer::SyncProtocolError protocol_error; 167 protocol_error.error_type = syncer::TRANSIENT_ERROR; 168 protocol_error.error_description = "Not My Fault"; 169 protocol_error.url = "www.google.com"; 170 171 if (GetSyncService(0)->auto_start_enabled()) { 172 // In auto start enabled platforms like chrome os we should be 173 // able to set up even if the first sync while setting up fails. 174 // Trigger error on every 2 out of 3 requests. 175 TriggerSyncError(protocol_error, SyncTest::ERROR_FREQUENCY_TWO_THIRDS); 176 // Now setup sync and it should succeed. 177 ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; 178 } else { 179 // In Non auto start enabled environments if the setup sync fails then 180 // the setup would fail. So setup sync normally. 181 ASSERT_TRUE(SetupSync()) << "Setup sync failed"; 182 ASSERT_TRUE(GetClient(0)->DisableSyncForDatatype(syncer::AUTOFILL)); 183 184 // Trigger error on every 2 out of 3 requests. 185 TriggerSyncError(protocol_error, SyncTest::ERROR_FREQUENCY_TWO_THIRDS); 186 187 // Now enable a datatype, whose first 2 syncs would fail, but we should 188 // recover and setup succesfully on the third attempt. 189 ASSERT_TRUE(GetClient(0)->EnableSyncForDatatype(syncer::AUTOFILL)); 190 } 191 } 192 193 IN_PROC_BROWSER_TEST_F(LegacySyncErrorTest, 194 DISABLED_BirthdayErrorUsingActionableErrorTest) { 195 ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; 196 197 const BookmarkNode* node1 = AddFolder(0, 0, "title1"); 198 SetTitle(0, node1, "new_title1"); 199 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0)))); 200 201 syncer::SyncProtocolError protocol_error; 202 protocol_error.error_type = syncer::NOT_MY_BIRTHDAY; 203 protocol_error.action = syncer::DISABLE_SYNC_ON_CLIENT; 204 protocol_error.error_description = "Not My Fault"; 205 protocol_error.url = "www.google.com"; 206 TriggerSyncError(protocol_error, SyncTest::ERROR_FREQUENCY_ALWAYS); 207 208 // Now make one more change so we will do another sync. 209 const BookmarkNode* node2 = AddFolder(0, 0, "title2"); 210 SetTitle(0, node2, "new_title2"); 211 ASSERT_TRUE(AwaitSyncDisabled(GetSyncService((0)))); 212 ProfileSyncService::Status status; 213 GetSyncService((0))->QueryDetailedSyncStatus(&status); 214 ASSERT_EQ(status.sync_protocol_error.error_type, protocol_error.error_type); 215 ASSERT_EQ(status.sync_protocol_error.action, protocol_error.action); 216 ASSERT_EQ(status.sync_protocol_error.url, protocol_error.url); 217 ASSERT_EQ(status.sync_protocol_error.error_description, 218 protocol_error.error_description); 219 } 220 221 IN_PROC_BROWSER_TEST_F(LegacySyncErrorTest, DisableDatatypeWhileRunning) { 222 ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; 223 syncer::ModelTypeSet synced_datatypes = 224 GetSyncService((0))->GetActiveDataTypes(); 225 ASSERT_TRUE(synced_datatypes.Has(syncer::TYPED_URLS)); 226 ASSERT_TRUE(synced_datatypes.Has(syncer::SESSIONS)); 227 GetProfile(0)->GetPrefs()->SetBoolean( 228 prefs::kSavingBrowserHistoryDisabled, true); 229 230 // Wait for reconfigurations. 231 ASSERT_TRUE(AwaitTypeDisabled(GetSyncService(0), syncer::TYPED_URLS)); 232 ASSERT_TRUE(AwaitTypeDisabled(GetSyncService(0), syncer::SESSIONS)); 233 234 const BookmarkNode* node1 = AddFolder(0, 0, "title1"); 235 SetTitle(0, node1, "new_title1"); 236 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0)))); 237 // TODO(lipalani)" Verify initial sync ended for typed url is false. 238 } 239 240 } // namespace 241