Index: chrome/browser/sync/engine/syncer_proto_util.cc |
diff --git a/chrome/browser/sync/engine/syncer_proto_util.cc b/chrome/browser/sync/engine/syncer_proto_util.cc |
index 61f64fad5a9f6272793c20f521563d604aee6d78..7e87ef76d9729179e42927476cb27ca659430497 100644 |
--- a/chrome/browser/sync/engine/syncer_proto_util.cc |
+++ b/chrome/browser/sync/engine/syncer_proto_util.cc |
@@ -100,6 +100,9 @@ bool SyncerProtoUtil::VerifyResponseBirthday(syncable::Directory* dir, |
std::string local_birthday = dir->store_birthday(); |
+ // TODO(lipalani) : Remove this check here. When the new implementation |
+ // becomes the default this check should go away. This is handled by the |
+ // switch case in the new implementation. |
if (response->error_code() == ClientToServerResponse::CLEAR_PENDING || |
response->error_code() == ClientToServerResponse::NOT_MY_BIRTHDAY) { |
// Birthday verification failures result in stopping sync and deleting |
@@ -211,8 +214,90 @@ bool IsVeryFirstGetUpdates(const ClientToServerMessage& message) { |
return true; |
} |
+sync_api::SyncErrorType ConvertSyncErrorTypePBToLocalType( |
+ const sync_pb::ClientToServerResponse::ErrorType& error_type) { |
+ switch (error_type) { |
+ case ClientToServerResponse::SUCCESS: |
+ return sync_api::SUCCESS; |
+ case ClientToServerResponse::NOT_MY_BIRTHDAY: |
+ return sync_api::NOT_MY_BIRTHDAY; |
+ case ClientToServerResponse::THROTTLED: |
+ return sync_api::THROTTLED; |
+ case ClientToServerResponse::CLEAR_PENDING: |
+ return sync_api::CLEAR_PENDING; |
+ case ClientToServerResponse::TRANSIENT_ERROR: |
+ return sync_api::TRANSIENT_ERROR; |
+ case ClientToServerResponse::MIGRATION_DONE: |
+ return sync_api::MIGRATION_DONE; |
+ case ClientToServerResponse::UNKNOWN: |
+ return sync_api::UNKNOWN_ERROR; |
+ case ClientToServerResponse::USER_NOT_ACTIVATED: |
+ case ClientToServerResponse::AUTH_INVALID: |
+ case ClientToServerResponse::ACCESS_DENIED: |
+ return sync_api::INVALID_CREDENTIAL; |
+ default: |
+ NOTREACHED(); |
+ return sync_api::UNKNOWN_ERROR; |
+ } |
+} |
+ |
+sync_api::ClientAction ConvertClientActionPBToLocalClientAction( |
+ const sync_pb::ClientToServerResponse::Error::Action& action) { |
+ switch (action) { |
+ case ClientToServerResponse::Error::UPGRADE_CLIENT: |
+ return sync_api::UPGRADE_CLIENT; |
+ case ClientToServerResponse::Error::CLEAR_USER_DATA_AND_RESYNC: |
+ return sync_api::CLEAR_USER_DATA_AND_RESYNC; |
+ case ClientToServerResponse::Error::ENABLE_SYNC_ON_ACCOUNT: |
+ return sync_api::ENABLE_SYNC_ON_ACCOUNT; |
+ case ClientToServerResponse::Error::STOP_AND_RESTART_SYNC: |
+ return sync_api::STOP_AND_RESTART_SYNC; |
+ case ClientToServerResponse::Error::DISABLE_SYNC_ON_CLIENT: |
+ return sync_api::DISABLE_SYNC_ON_CLIENT; |
+ case ClientToServerResponse::Error::UNKNOWN_ACTION: |
+ return sync_api::UNKNOWN_ACTION; |
+ default: |
+ NOTREACHED(); |
+ return sync_api::UNKNOWN_ACTION; |
+ } |
+} |
+ |
+sync_api::SyncError ConvertErrorPBToLocalType( |
+ const sync_pb::ClientToServerResponse::Error& error) { |
+ sync_api::SyncError sync_error; |
+ sync_error.error_type = ConvertSyncErrorTypePBToLocalType(error.error_type()); |
+ sync_error.error_description = error.error_description(); |
+ sync_error.url = error.url(); |
+ sync_error.action = ConvertClientActionPBToLocalClientAction(error.action()); |
+ |
+ return sync_error; |
+} |
+ |
} // namespace |
+bool ShouldRequestEarlyExit(const sync_api::SyncError& error) { |
tim (not reviewing)
2011/08/22 15:14:57
Having this method here is a layering violation in
lipalani1
2011/08/22 21:43:53
hmm... This is how it is currently implemented and
tim (not reviewing)
2011/08/23 14:17:07
That's because we used an existing error ("birthda
|
+ switch (error.error_type) { |
+ case sync_api::SUCCESS: |
+ case sync_api::MIGRATION_DONE: |
+ return false; |
+ case sync_api::NOT_MY_BIRTHDAY: |
+ case sync_api::THROTTLED: |
tim (not reviewing)
2011/08/22 15:14:57
We shouldn't be requesting early exit on throttled
lipalani1
2011/08/22 21:43:53
Done.
|
+ case sync_api::CLEAR_PENDING: |
+ case sync_api::TRANSIENT_ERROR: |
tim (not reviewing)
2011/08/22 15:14:57
We definitely should not be requesting early exit
lipalani1
2011/08/22 21:43:53
Agree. it has already caused grievance for me :) W
|
+ case sync_api::INVALID_CREDENTIAL: |
tim (not reviewing)
2011/08/22 15:14:57
I think (as we discussed in review meetings) inval
lipalani1
2011/08/22 21:43:53
It is a seperate case. The event for 401 error is
tim (not reviewing)
2011/08/23 14:17:07
I agree with what you say here, but I still don't
|
+ return true; |
+ // Make the default a NOTREACHED. So if a new error is introduced we |
+ // think about its expected functionality. |
+ default: |
+ NOTREACHED(); |
+ return false; |
+ } |
+} |
+ |
+bool IsActionableError(const sync_api::SyncError& error) { |
+ return (error.action != sync_api::UNKNOWN_ACTION); |
+} |
+ |
// static |
bool SyncerProtoUtil::PostClientToServerMessage( |
const ClientToServerMessage& msg, |
@@ -234,6 +319,60 @@ bool SyncerProtoUtil::PostClientToServerMessage( |
msg, response)) |
return false; |
+ if (response->has_error()) { |
+ // We are talking to a server that is capable of sending the |error| tag. |
+ sync_api::SyncError sync_error = ConvertErrorPBToLocalType( |
+ response->error()); |
+ sessions::StatusController* status = session->status_controller(); |
+ status->set_sync_error(sync_error); |
+ |
+ // Birthday mismatch overrides any error that is sent by the server. |
+ if (!VerifyResponseBirthday(dir, response)) { |
+ sync_error.error_type = sync_api::NOT_MY_BIRTHDAY; |
+ sync_error.action = sync_api::DISABLE_SYNC_ON_CLIENT; |
+ } |
+ |
+ // Inform the syncer if we need to exit early. |
+ if (ShouldRequestEarlyExit(sync_error)) { |
+ session->status_controller()->set_syncer_stuck(true); |
+ session->delegate()->OnRequestEarlyExit(); |
+ } |
+ |
+ // Inform the syncer if there is an actionable error. |
+ if (IsActionableError(sync_error)) { |
+ session->delegate()->OnActionableError(session); |
+ } |
+ |
+ // Now do any special handling for the error type and decide on the return |
+ // value. |
+ switch (sync_error.error_type) { |
+ case sync_api::UNKNOWN_ERROR: |
+ LOG(WARNING) << "Sync protocol out-of-date. The server is using a more " |
+ << "recent version."; |
+ return false; |
+ case sync_api::SUCCESS: |
+ LogResponseProfilingData(*response); |
+ return true; |
+ case sync_api::THROTTLED: |
+ LOG(WARNING) << "Client silenced by server."; |
+ session->delegate()->OnSilencedUntil(base::TimeTicks::Now() + |
+ GetThrottleDelay(*response)); |
+ return false; |
+ case sync_api::TRANSIENT_ERROR: |
+ return false; |
+ case sync_api::MIGRATION_DONE: |
+ HandleMigrationDoneResponse(response, session); |
+ return false; |
+ default: |
+ NOTREACHED(); |
+ return false; |
+ } |
+ } |
+ |
+ // TODO(lipalani): Plug this legacy implementation to the new error framework. |
+ // New implementation code would have returned before by now. This is waiting |
+ // on the frontend code being implemented. Otherwise ripping this would break |
+ // sync. |
if (!VerifyResponseBirthday(dir, response)) { |
session->status_controller()->set_syncer_stuck(true); |
session->delegate()->OnShouldStopSyncingPermanently(); |