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 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
400 | 400 |
401 def __init__(self): | 401 def __init__(self): |
402 # Monotonically increasing version number. The next object change will | 402 # Monotonically increasing version number. The next object change will |
403 # take on this value + 1. | 403 # take on this value + 1. |
404 self._version = 0 | 404 self._version = 0 |
405 | 405 |
406 # The definitive copy of this client's items: a map from ID string to a | 406 # The definitive copy of this client's items: a map from ID string to a |
407 # SyncEntity protocol buffer. | 407 # SyncEntity protocol buffer. |
408 self._entries = {} | 408 self._entries = {} |
409 | 409 |
410 # TODO(nick): uuid.uuid1() is better, but python 2.5 only. | 410 self.ResetStoreBirthday() |
411 self.store_birthday = '%0.30f' % random.random() | |
412 | 411 |
413 self.migration_history = MigrationHistory() | 412 self.migration_history = MigrationHistory() |
414 | 413 |
415 def _SaveEntry(self, entry): | 414 def _SaveEntry(self, entry): |
416 """Insert or update an entry in the change log, and give it a new version. | 415 """Insert or update an entry in the change log, and give it a new version. |
417 | 416 |
418 The ID fields of this entry are assumed to be valid server IDs. This | 417 The ID fields of this entry are assumed to be valid server IDs. This |
419 entry will be updated with a new version number and sync_timestamp. | 418 entry will be updated with a new version number and sync_timestamp. |
420 | 419 |
421 Args: | 420 Args: |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
553 """Ensure creation of all permanent items for a given set of sync types. | 552 """Ensure creation of all permanent items for a given set of sync types. |
554 | 553 |
555 Args: | 554 Args: |
556 requested_types: A list of sync data types from ALL_TYPES. | 555 requested_types: A list of sync data types from ALL_TYPES. |
557 Permanent items of only these types will be created. | 556 Permanent items of only these types will be created. |
558 """ | 557 """ |
559 for spec in self._PERMANENT_ITEM_SPECS: | 558 for spec in self._PERMANENT_ITEM_SPECS: |
560 if spec.sync_type in requested_types: | 559 if spec.sync_type in requested_types: |
561 self._CreatePermanentItem(spec) | 560 self._CreatePermanentItem(spec) |
562 | 561 |
| 562 def ResetStoreBirthday(self): |
| 563 """Resets the store birthday to a random value.""" |
| 564 # TODO(nick): uuid.uuid1() is better, but python 2.5 only. |
| 565 self.store_birthday = '%0.30f' % random.random() |
| 566 |
| 567 def StoreBirthday(self): |
| 568 """Gets the store birthday.""" |
| 569 return self.store_birthday |
| 570 |
563 def GetChanges(self, sieve): | 571 def GetChanges(self, sieve): |
564 """Get entries which have changed, oldest first. | 572 """Get entries which have changed, oldest first. |
565 | 573 |
566 The returned entries are limited to being _BATCH_SIZE many. The entries | 574 The returned entries are limited to being _BATCH_SIZE many. The entries |
567 are returned in strict version order. | 575 are returned in strict version order. |
568 | 576 |
569 Args: | 577 Args: |
570 sieve: An update sieve to use to filter out updates the client | 578 sieve: An update sieve to use to filter out updates the client |
571 has already seen. | 579 has already seen. |
572 Returns: | 580 Returns: |
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
877 return '?' | 885 return '?' |
878 client_id = client_id[0] | 886 client_id = client_id[0] |
879 if client_id not in self.clients: | 887 if client_id not in self.clients: |
880 self.clients[client_id] = self.client_name_generator.next() | 888 self.clients[client_id] = self.client_name_generator.next() |
881 return self.clients[client_id] | 889 return self.clients[client_id] |
882 | 890 |
883 def CheckStoreBirthday(self, request): | 891 def CheckStoreBirthday(self, request): |
884 """Raises StoreBirthdayError if the request's birthday is a mismatch.""" | 892 """Raises StoreBirthdayError if the request's birthday is a mismatch.""" |
885 if not request.HasField('store_birthday'): | 893 if not request.HasField('store_birthday'): |
886 return | 894 return |
887 if self.account.store_birthday != request.store_birthday: | 895 if self.account.StoreBirthday() != request.store_birthday: |
888 raise StoreBirthdayError | 896 raise StoreBirthdayError |
889 | 897 |
890 def HandleMigrate(self, path): | 898 def HandleMigrate(self, path): |
891 query = urlparse.urlparse(path)[4] | 899 query = urlparse.urlparse(path)[4] |
892 code = 200 | 900 code = 200 |
893 self.account_lock.acquire() | 901 self.account_lock.acquire() |
894 try: | 902 try: |
895 datatypes = [DataTypeStringToSyncTypeLoose(x) | 903 datatypes = [DataTypeStringToSyncTypeLoose(x) |
896 for x in urlparse.parse_qs(query).get('type',[])] | 904 for x in urlparse.parse_qs(query).get('type',[])] |
897 if datatypes: | 905 if datatypes: |
898 self.account.TriggerMigration(datatypes) | 906 self.account.TriggerMigration(datatypes) |
899 response = 'Migrated datatypes %s' % ( | 907 response = 'Migrated datatypes %s' % ( |
900 ' and '.join(SyncTypeToString(x).upper() for x in datatypes)) | 908 ' and '.join(SyncTypeToString(x).upper() for x in datatypes)) |
901 else: | 909 else: |
902 response = 'Please specify one or more <i>type=name</i> parameters' | 910 response = 'Please specify one or more <i>type=name</i> parameters' |
903 code = 400 | 911 code = 400 |
904 except DataTypeIdNotRecognized, error: | 912 except DataTypeIdNotRecognized, error: |
905 response = 'Could not interpret datatype name' | 913 response = 'Could not interpret datatype name' |
906 code = 400 | 914 code = 400 |
907 finally: | 915 finally: |
908 self.account_lock.release() | 916 self.account_lock.release() |
909 return (code, '<html><title>Migration: %d</title><H1>%d %s</H1></html>' % | 917 return (code, '<html><title>Migration: %d</title><H1>%d %s</H1></html>' % |
910 (code, code, response)) | 918 (code, code, response)) |
911 | 919 |
| 920 def HandleCreateBirthdayError(self): |
| 921 self.account.ResetStoreBirthday() |
| 922 return ( |
| 923 200, |
| 924 '<html><title>Birthday error</title><H1>Birthday error</H1></html>') |
| 925 |
912 def HandleCommand(self, query, raw_request): | 926 def HandleCommand(self, query, raw_request): |
913 """Decode and handle a sync command from a raw input of bytes. | 927 """Decode and handle a sync command from a raw input of bytes. |
914 | 928 |
915 This is the main entry point for this class. It is safe to call this | 929 This is the main entry point for this class. It is safe to call this |
916 method from multiple threads. | 930 method from multiple threads. |
917 | 931 |
918 Args: | 932 Args: |
919 raw_request: An iterable byte sequence to be interpreted as a sync | 933 raw_request: An iterable byte sequence to be interpreted as a sync |
920 protocol command. | 934 protocol command. |
921 Returns: | 935 Returns: |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1041 | 1055 |
1042 update_sieve.CheckMigrationState() | 1056 update_sieve.CheckMigrationState() |
1043 | 1057 |
1044 new_timestamp, entries, remaining = self.account.GetChanges(update_sieve) | 1058 new_timestamp, entries, remaining = self.account.GetChanges(update_sieve) |
1045 | 1059 |
1046 update_response.changes_remaining = remaining | 1060 update_response.changes_remaining = remaining |
1047 for entry in entries: | 1061 for entry in entries: |
1048 reply = update_response.entries.add() | 1062 reply = update_response.entries.add() |
1049 reply.CopyFrom(entry) | 1063 reply.CopyFrom(entry) |
1050 update_sieve.SaveProgress(new_timestamp, update_response) | 1064 update_sieve.SaveProgress(new_timestamp, update_response) |
OLD | NEW |