Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/python2.4 | 1 #!/usr/bin/python2.4 |
| 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """An implementation of the server side of the Chromium sync protocol. | 6 """An implementation of the server side of the Chromium sync protocol. |
| 7 | 7 |
| 8 The details of the protocol are described mostly by comments in the protocol | 8 The details of the protocol are described mostly by comments in the protocol |
| 9 buffer definition at chrome/browser/sync/protocol/sync.proto. | 9 buffer definition at chrome/browser/sync/protocol/sync.proto. |
| 10 """ | 10 """ |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 96 def __init__(self, datatypes): | 96 def __init__(self, datatypes): |
| 97 self.datatypes = datatypes | 97 self.datatypes = datatypes |
| 98 | 98 |
| 99 | 99 |
| 100 class StoreBirthdayError(Error): | 100 class StoreBirthdayError(Error): |
| 101 """The client sent a birthday that doesn't correspond to this server.""" | 101 """The client sent a birthday that doesn't correspond to this server.""" |
| 102 | 102 |
| 103 | 103 |
| 104 class TransientError(Error): | 104 class TransientError(Error): |
| 105 """The client would be sent a transient error.""" | 105 """The client would be sent a transient error.""" |
| 106 | 106 |
|
ncarter (slow)
2011/09/21 22:48:08
Two blank lines here.
lipalani1
2011/09/22 20:14:35
Done.
| |
| 107 class SyncError(Error): | |
| 108 """The client would be sent an error.""" | |
| 109 | |
| 107 | 110 |
| 108 def GetEntryType(entry): | 111 def GetEntryType(entry): |
| 109 """Extract the sync type from a SyncEntry. | 112 """Extract the sync type from a SyncEntry. |
| 110 | 113 |
| 111 Args: | 114 Args: |
| 112 entry: A SyncEntity protobuf object whose type to determine. | 115 entry: A SyncEntity protobuf object whose type to determine. |
| 113 Returns: | 116 Returns: |
| 114 An enum value from ALL_TYPES if the entry's type can be determined, or None | 117 An enum value from ALL_TYPES if the entry's type can be determined, or None |
| 115 if the type cannot be determined. | 118 if the type cannot be determined. |
| 116 Raises: | 119 Raises: |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 408 self._version = 0 | 411 self._version = 0 |
| 409 | 412 |
| 410 # The definitive copy of this client's items: a map from ID string to a | 413 # The definitive copy of this client's items: a map from ID string to a |
| 411 # SyncEntity protocol buffer. | 414 # SyncEntity protocol buffer. |
| 412 self._entries = {} | 415 self._entries = {} |
| 413 | 416 |
| 414 self.ResetStoreBirthday() | 417 self.ResetStoreBirthday() |
| 415 | 418 |
| 416 self.migration_history = MigrationHistory() | 419 self.migration_history = MigrationHistory() |
| 417 | 420 |
| 421 self.error = sync_pb2.ClientToServerResponse.Error() | |
| 422 | |
| 423 self.send_error = False | |
| 424 | |
| 418 def _SaveEntry(self, entry): | 425 def _SaveEntry(self, entry): |
| 419 """Insert or update an entry in the change log, and give it a new version. | 426 """Insert or update an entry in the change log, and give it a new version. |
| 420 | 427 |
| 421 The ID fields of this entry are assumed to be valid server IDs. This | 428 The ID fields of this entry are assumed to be valid server IDs. This |
| 422 entry will be updated with a new version number and sync_timestamp. | 429 entry will be updated with a new version number and sync_timestamp. |
| 423 | 430 |
| 424 Args: | 431 Args: |
| 425 entry: The entry to be added or updated. | 432 entry: The entry to be added or updated. |
| 426 """ | 433 """ |
| 427 self._version += 1 | 434 self._version += 1 |
| (...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 915 if not request.HasField('store_birthday'): | 922 if not request.HasField('store_birthday'): |
| 916 return | 923 return |
| 917 if self.account.StoreBirthday() != request.store_birthday: | 924 if self.account.StoreBirthday() != request.store_birthday: |
| 918 raise StoreBirthdayError | 925 raise StoreBirthdayError |
| 919 | 926 |
| 920 def CheckTransientError(self): | 927 def CheckTransientError(self): |
| 921 """Raises TransientError if transient_error variable is set.""" | 928 """Raises TransientError if transient_error variable is set.""" |
| 922 if self.transient_error: | 929 if self.transient_error: |
| 923 raise TransientError | 930 raise TransientError |
| 924 | 931 |
| 932 def CheckSendError(self): | |
| 933 """Raises SyncError if the variable is set.""" | |
| 934 if self.account.send_error: | |
| 935 raise SyncError | |
| 936 | |
| 925 def HandleMigrate(self, path): | 937 def HandleMigrate(self, path): |
| 926 query = urlparse.urlparse(path)[4] | 938 query = urlparse.urlparse(path)[4] |
| 927 code = 200 | 939 code = 200 |
| 928 self.account_lock.acquire() | 940 self.account_lock.acquire() |
| 929 try: | 941 try: |
| 930 datatypes = [DataTypeStringToSyncTypeLoose(x) | 942 datatypes = [DataTypeStringToSyncTypeLoose(x) |
| 931 for x in urlparse.parse_qs(query).get('type',[])] | 943 for x in urlparse.parse_qs(query).get('type',[])] |
| 932 if datatypes: | 944 if datatypes: |
| 933 self.account.TriggerMigration(datatypes) | 945 self.account.TriggerMigration(datatypes) |
| 934 response = 'Migrated datatypes %s' % ( | 946 response = 'Migrated datatypes %s' % ( |
| 935 ' and '.join(SyncTypeToString(x).upper() for x in datatypes)) | 947 ' and '.join(SyncTypeToString(x).upper() for x in datatypes)) |
| 936 else: | 948 else: |
| 937 response = 'Please specify one or more <i>type=name</i> parameters' | 949 response = 'Please specify one or more <i>type=name</i> parameters' |
| 938 code = 400 | 950 code = 400 |
| 939 except DataTypeIdNotRecognized, error: | 951 except DataTypeIdNotRecognized, error: |
| 940 response = 'Could not interpret datatype name' | 952 response = 'Could not interpret datatype name' |
| 941 code = 400 | 953 code = 400 |
| 942 finally: | 954 finally: |
| 943 self.account_lock.release() | 955 self.account_lock.release() |
| 944 return (code, '<html><title>Migration: %d</title><H1>%d %s</H1></html>' % | 956 return (code, '<html><title>Migration: %d</title><H1>%d %s</H1></html>' % |
| 945 (code, code, response)) | 957 (code, code, response)) |
| 946 | 958 |
| 959 def HandleSetError(self, path): | |
| 960 query = urlparse.urlparse(path)[4] | |
| 961 self.account_lock.acquire() | |
| 962 code = 200; | |
| 963 response = 'Success' | |
| 964 try: | |
| 965 error_type = urlparse.parse_qs(query)['error'] | |
| 966 action = urlparse.parse_qs(query)['action'] | |
| 967 self.account.error.error_type = int(error_type[0]) | |
| 968 self.account.error.action = int(action[0]) | |
| 969 self.account.send_error = True | |
| 970 try: | |
| 971 self.account.error.url = (urlparse.parse_qs(query)['url'])[0] | |
| 972 except KeyError: | |
| 973 self.account.error.url = '' | |
| 974 try: | |
| 975 self.account.error.error_description = \ | |
| 976 (urlparse.parse_qs(query)['error_description'])[0] | |
| 977 except KeyError: | |
| 978 self.account.error.error_description = '' | |
| 979 response = ('Error = %d, action = %d, url = %s, description = %s' % | |
| 980 (self.account.error.error_type, self.account.error.action, | |
| 981 self.account.error.url, | |
| 982 self.account.error.error_description)) | |
| 983 except error: | |
| 984 response = 'Could not parse url' | |
| 985 code = 400 | |
| 986 finally: | |
| 987 self.account_lock.release() | |
| 988 return (code, '<html><title>Migration: %d</title><H1>%d %s</H1></html>' % | |
| 989 (code, code, response)) | |
| 990 | |
| 947 def HandleCreateBirthdayError(self): | 991 def HandleCreateBirthdayError(self): |
| 948 self.account.ResetStoreBirthday() | 992 self.account.ResetStoreBirthday() |
| 949 return ( | 993 return ( |
| 950 200, | 994 200, |
| 951 '<html><title>Birthday error</title><H1>Birthday error</H1></html>') | 995 '<html><title>Birthday error</title><H1>Birthday error</H1></html>') |
| 952 | 996 |
| 953 def HandleSetTransientError(self): | 997 def HandleSetTransientError(self): |
| 954 self.transient_error = True | 998 self.transient_error = True |
| 955 return ( | 999 return ( |
| 956 200, | 1000 200, |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 985 try: | 1029 try: |
| 986 request = sync_pb2.ClientToServerMessage() | 1030 request = sync_pb2.ClientToServerMessage() |
| 987 request.MergeFromString(raw_request) | 1031 request.MergeFromString(raw_request) |
| 988 contents = request.message_contents | 1032 contents = request.message_contents |
| 989 | 1033 |
| 990 response = sync_pb2.ClientToServerResponse() | 1034 response = sync_pb2.ClientToServerResponse() |
| 991 response.error_code = sync_pb2.ClientToServerResponse.SUCCESS | 1035 response.error_code = sync_pb2.ClientToServerResponse.SUCCESS |
| 992 self.CheckStoreBirthday(request) | 1036 self.CheckStoreBirthday(request) |
| 993 response.store_birthday = self.account.store_birthday | 1037 response.store_birthday = self.account.store_birthday |
| 994 self.CheckTransientError(); | 1038 self.CheckTransientError(); |
| 1039 self.CheckSendError(); | |
| 995 | 1040 |
| 996 print_context('->') | 1041 print_context('->') |
| 997 | 1042 |
| 998 if contents == sync_pb2.ClientToServerMessage.AUTHENTICATE: | 1043 if contents == sync_pb2.ClientToServerMessage.AUTHENTICATE: |
| 999 print 'Authenticate' | 1044 print 'Authenticate' |
| 1000 # We accept any authentication token, and support only one account. | 1045 # We accept any authentication token, and support only one account. |
| 1001 # TODO(nick): Mock out the GAIA authentication as well; hook up here. | 1046 # TODO(nick): Mock out the GAIA authentication as well; hook up here. |
| 1002 response.authenticate.user.email = 'syncjuser@chromium' | 1047 response.authenticate.user.email = 'syncjuser@chromium' |
| 1003 response.authenticate.user.display_name = 'Sync J User' | 1048 response.authenticate.user.display_name = 'Sync J User' |
| 1004 elif contents == sync_pb2.ClientToServerMessage.COMMIT: | 1049 elif contents == sync_pb2.ClientToServerMessage.COMMIT: |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1023 SyncTypeToProtocolDataTypeId(x) for x in error.datatypes] | 1068 SyncTypeToProtocolDataTypeId(x) for x in error.datatypes] |
| 1024 return (200, response.SerializeToString()) | 1069 return (200, response.SerializeToString()) |
| 1025 except StoreBirthdayError, error: | 1070 except StoreBirthdayError, error: |
| 1026 print_context('<-') | 1071 print_context('<-') |
| 1027 print 'NOT_MY_BIRTHDAY' | 1072 print 'NOT_MY_BIRTHDAY' |
| 1028 response = sync_pb2.ClientToServerResponse() | 1073 response = sync_pb2.ClientToServerResponse() |
| 1029 response.store_birthday = self.account.store_birthday | 1074 response.store_birthday = self.account.store_birthday |
| 1030 response.error_code = sync_pb2.ClientToServerResponse.NOT_MY_BIRTHDAY | 1075 response.error_code = sync_pb2.ClientToServerResponse.NOT_MY_BIRTHDAY |
| 1031 return (200, response.SerializeToString()) | 1076 return (200, response.SerializeToString()) |
| 1032 except TransientError as error: | 1077 except TransientError as error: |
| 1078 ### This is deprecated now. Would be remvoved once test cases are removed. | |
| 1033 print_context('<-') | 1079 print_context('<-') |
| 1034 print 'TRANSIENT_ERROR' | 1080 print 'TRANSIENT_ERROR' |
| 1035 response.store_birthday = self.account.store_birthday | 1081 response.store_birthday = self.account.store_birthday |
| 1036 response.error_code = sync_pb2.ClientToServerResponse.TRANSIENT_ERROR | 1082 response.error_code = sync_pb2.ClientToServerResponse.TRANSIENT_ERROR |
| 1037 return (200, response.SerializeToString()) | 1083 return (200, response.SerializeToString()) |
| 1084 except SyncError as error: | |
| 1085 print_context('<-') | |
| 1086 print 'ERROR' | |
| 1087 response.store_birthday = self.account.store_birthday | |
| 1088 response.error.error_type = self.account.error.error_type | |
| 1089 response.error.url = self.account.url | |
| 1090 response.error.error_description = self.account.error_description | |
| 1091 response.error.action = self.account.error.action | |
| 1092 return (200, response.SerializeToString()) | |
| 1038 finally: | 1093 finally: |
| 1039 self.account_lock.release() | 1094 self.account_lock.release() |
| 1040 | 1095 |
| 1041 def HandleCommit(self, commit_message, commit_response): | 1096 def HandleCommit(self, commit_message, commit_response): |
| 1042 """Respond to a Commit request by updating the user's account state. | 1097 """Respond to a Commit request by updating the user's account state. |
| 1043 | 1098 |
| 1044 Commit attempts stop after the first error, returning a CONFLICT result | 1099 Commit attempts stop after the first error, returning a CONFLICT result |
| 1045 for any unattempted entries. | 1100 for any unattempted entries. |
| 1046 | 1101 |
| 1047 Args: | 1102 Args: |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1102 | 1157 |
| 1103 update_sieve.CheckMigrationState() | 1158 update_sieve.CheckMigrationState() |
| 1104 | 1159 |
| 1105 new_timestamp, entries, remaining = self.account.GetChanges(update_sieve) | 1160 new_timestamp, entries, remaining = self.account.GetChanges(update_sieve) |
| 1106 | 1161 |
| 1107 update_response.changes_remaining = remaining | 1162 update_response.changes_remaining = remaining |
| 1108 for entry in entries: | 1163 for entry in entries: |
| 1109 reply = update_response.entries.add() | 1164 reply = update_response.entries.add() |
| 1110 reply.CopyFrom(entry) | 1165 reply.CopyFrom(entry) |
| 1111 update_sieve.SaveProgress(new_timestamp, update_response) | 1166 update_sieve.SaveProgress(new_timestamp, update_response) |
| OLD | NEW |