OLD | NEW |
---|---|
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """An implementation of the server side of the Chromium sync protocol. | 5 """An implementation of the server side of the Chromium sync protocol. |
6 | 6 |
7 The details of the protocol are described mostly by comments in the protocol | 7 The details of the protocol are described mostly by comments in the protocol |
8 buffer definition at chrome/browser/sync/protocol/sync.proto. | 8 buffer definition at chrome/browser/sync/protocol/sync.proto. |
9 """ | 9 """ |
10 | 10 |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
257 Attributes: | 257 Attributes: |
258 tag: A known-to-the-client value that uniquely identifies a server-created | 258 tag: A known-to-the-client value that uniquely identifies a server-created |
259 permanent item. | 259 permanent item. |
260 name: The human-readable display name for this item. | 260 name: The human-readable display name for this item. |
261 parent_tag: The tag of the permanent item's parent. If ROOT_ID, indicates | 261 parent_tag: The tag of the permanent item's parent. If ROOT_ID, indicates |
262 a top-level item. Otherwise, this must be the tag value of some other | 262 a top-level item. Otherwise, this must be the tag value of some other |
263 server-created permanent item. | 263 server-created permanent item. |
264 sync_type: A value from ALL_TYPES, giving the datatype of this permanent | 264 sync_type: A value from ALL_TYPES, giving the datatype of this permanent |
265 item. This controls which types of client GetUpdates requests will | 265 item. This controls which types of client GetUpdates requests will |
266 cause the permanent item to be created and returned. | 266 cause the permanent item to be created and returned. |
267 create_by_default: Whether the permanent item is created at startup or not. | |
268 This value is set to True in the default case. Non-default permanent items | |
269 are those that are created only when a client explicitly tells the server | |
270 to do so. | |
267 """ | 271 """ |
268 | 272 |
269 def __init__(self, tag, name, parent_tag, sync_type): | 273 def __init__(self, tag, name, parent_tag, sync_type, create_by_default=True): |
270 self.tag = tag | 274 self.tag = tag |
271 self.name = name | 275 self.name = name |
272 self.parent_tag = parent_tag | 276 self.parent_tag = parent_tag |
273 self.sync_type = sync_type | 277 self.sync_type = sync_type |
278 self.create_by_default = create_by_default | |
274 | 279 |
275 | 280 |
276 class MigrationHistory(object): | 281 class MigrationHistory(object): |
277 """A record of the migration events associated with an account. | 282 """A record of the migration events associated with an account. |
278 | 283 |
279 Each migration event invalidates one or more datatypes on all clients | 284 Each migration event invalidates one or more datatypes on all clients |
280 that had synced the datatype before the event. Such clients will continue | 285 that had synced the datatype before the event. Such clients will continue |
281 to receive MigrationDone errors until they throw away their progress and | 286 to receive MigrationDone errors until they throw away their progress and |
282 re-sync that datatype from the beginning. | 287 re-sync that datatype from the beginning. |
283 """ | 288 """ |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
402 # Specify all the permanent items that a model might need. | 407 # Specify all the permanent items that a model might need. |
403 _PERMANENT_ITEM_SPECS = [ | 408 _PERMANENT_ITEM_SPECS = [ |
404 PermanentItem('google_chrome', name='Google Chrome', | 409 PermanentItem('google_chrome', name='Google Chrome', |
405 parent_tag=ROOT_ID, sync_type=TOP_LEVEL), | 410 parent_tag=ROOT_ID, sync_type=TOP_LEVEL), |
406 PermanentItem('google_chrome_bookmarks', name='Bookmarks', | 411 PermanentItem('google_chrome_bookmarks', name='Bookmarks', |
407 parent_tag='google_chrome', sync_type=BOOKMARK), | 412 parent_tag='google_chrome', sync_type=BOOKMARK), |
408 PermanentItem('bookmark_bar', name='Bookmark Bar', | 413 PermanentItem('bookmark_bar', name='Bookmark Bar', |
409 parent_tag='google_chrome_bookmarks', sync_type=BOOKMARK), | 414 parent_tag='google_chrome_bookmarks', sync_type=BOOKMARK), |
410 PermanentItem('other_bookmarks', name='Other Bookmarks', | 415 PermanentItem('other_bookmarks', name='Other Bookmarks', |
411 parent_tag='google_chrome_bookmarks', sync_type=BOOKMARK), | 416 parent_tag='google_chrome_bookmarks', sync_type=BOOKMARK), |
417 PermanentItem('synced_bookmarks', name='Synced Bookmarks', | |
418 parent_tag='google_chrome_bookmarks', sync_type=BOOKMARK, | |
419 create_by_default=False), | |
412 PermanentItem('google_chrome_preferences', name='Preferences', | 420 PermanentItem('google_chrome_preferences', name='Preferences', |
413 parent_tag='google_chrome', sync_type=PREFERENCE), | 421 parent_tag='google_chrome', sync_type=PREFERENCE), |
414 PermanentItem('google_chrome_autofill', name='Autofill', | 422 PermanentItem('google_chrome_autofill', name='Autofill', |
415 parent_tag='google_chrome', sync_type=AUTOFILL), | 423 parent_tag='google_chrome', sync_type=AUTOFILL), |
416 PermanentItem('google_chrome_autofill_profiles', name='Autofill Profiles', | 424 PermanentItem('google_chrome_autofill_profiles', name='Autofill Profiles', |
417 parent_tag='google_chrome', sync_type=AUTOFILL_PROFILE), | 425 parent_tag='google_chrome', sync_type=AUTOFILL_PROFILE), |
418 PermanentItem('google_chrome_app_settings', | 426 PermanentItem('google_chrome_app_settings', |
419 name='App Settings', | 427 name='App Settings', |
420 parent_tag='google_chrome', sync_type=APP_SETTINGS), | 428 parent_tag='google_chrome', sync_type=APP_SETTINGS), |
421 PermanentItem('google_chrome_extension_settings', | 429 PermanentItem('google_chrome_extension_settings', |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
588 entry.id_string = id_string | 596 entry.id_string = id_string |
589 entry.non_unique_name = spec.name | 597 entry.non_unique_name = spec.name |
590 entry.name = spec.name | 598 entry.name = spec.name |
591 entry.server_defined_unique_tag = spec.tag | 599 entry.server_defined_unique_tag = spec.tag |
592 entry.folder = True | 600 entry.folder = True |
593 entry.deleted = False | 601 entry.deleted = False |
594 entry.specifics.CopyFrom(GetDefaultEntitySpecifics(spec.sync_type)) | 602 entry.specifics.CopyFrom(GetDefaultEntitySpecifics(spec.sync_type)) |
595 self._WritePosition(entry, self._ServerTagToId(spec.parent_tag)) | 603 self._WritePosition(entry, self._ServerTagToId(spec.parent_tag)) |
596 self._SaveEntry(entry) | 604 self._SaveEntry(entry) |
597 | 605 |
598 def _CreatePermanentItems(self, requested_types): | 606 def _CreateDefaultPermanentItems(self, requested_types): |
599 """Ensure creation of all permanent items for a given set of sync types. | 607 """Ensure creation of all default permanent items for a given set of types. |
600 | 608 |
601 Args: | 609 Args: |
602 requested_types: A list of sync data types from ALL_TYPES. | 610 requested_types: A list of sync data types from ALL_TYPES. |
603 Permanent items of only these types will be created. | 611 All default permanent items of only these types will be created. |
604 """ | 612 """ |
605 for spec in self._PERMANENT_ITEM_SPECS: | 613 for spec in self._PERMANENT_ITEM_SPECS: |
606 if spec.sync_type in requested_types: | 614 if spec.sync_type in requested_types and spec.create_by_default: |
607 self._CreatePermanentItem(spec) | 615 self._CreatePermanentItem(spec) |
608 | 616 |
609 def ResetStoreBirthday(self): | 617 def ResetStoreBirthday(self): |
610 """Resets the store birthday to a random value.""" | 618 """Resets the store birthday to a random value.""" |
611 # TODO(nick): uuid.uuid1() is better, but python 2.5 only. | 619 # TODO(nick): uuid.uuid1() is better, but python 2.5 only. |
612 self.store_birthday = '%0.30f' % random.random() | 620 self.store_birthday = '%0.30f' % random.random() |
613 | 621 |
614 def StoreBirthday(self): | 622 def StoreBirthday(self): |
615 """Gets the store birthday.""" | 623 """Gets the store birthday.""" |
616 return self.store_birthday | 624 return self.store_birthday |
(...skipping 10 matching lines...) Expand all Loading... | |
627 Returns: | 635 Returns: |
628 A tuple of (version, entries, changes_remaining). Version is a new | 636 A tuple of (version, entries, changes_remaining). Version is a new |
629 timestamp value, which should be used as the starting point for the | 637 timestamp value, which should be used as the starting point for the |
630 next query. Entries is the batch of entries meeting the current | 638 next query. Entries is the batch of entries meeting the current |
631 timestamp query. Changes_remaining indicates the number of changes | 639 timestamp query. Changes_remaining indicates the number of changes |
632 left on the server after this batch. | 640 left on the server after this batch. |
633 """ | 641 """ |
634 if not sieve.HasAnyTimestamp(): | 642 if not sieve.HasAnyTimestamp(): |
635 return (0, [], 0) | 643 return (0, [], 0) |
636 min_timestamp = sieve.GetMinTimestamp() | 644 min_timestamp = sieve.GetMinTimestamp() |
637 self._CreatePermanentItems(sieve.GetFirstTimeTypes()) | 645 self._CreateDefaultPermanentItems(sieve.GetFirstTimeTypes()) |
638 change_log = sorted(self._entries.values(), | 646 change_log = sorted(self._entries.values(), |
639 key=operator.attrgetter('version')) | 647 key=operator.attrgetter('version')) |
640 new_changes = [x for x in change_log if x.version > min_timestamp] | 648 new_changes = [x for x in change_log if x.version > min_timestamp] |
641 # Pick batch_size new changes, and then filter them. This matches | 649 # Pick batch_size new changes, and then filter them. This matches |
642 # the RPC behavior of the production sync server. | 650 # the RPC behavior of the production sync server. |
643 batch = new_changes[:self._BATCH_SIZE] | 651 batch = new_changes[:self._BATCH_SIZE] |
644 if not batch: | 652 if not batch: |
645 # Client is up to date. | 653 # Client is up to date. |
646 return (min_timestamp, [], 0) | 654 return (min_timestamp, [], 0) |
647 | 655 |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
918 """ | 926 """ |
919 | 927 |
920 nigori_tag = "google_chrome_nigori" | 928 nigori_tag = "google_chrome_nigori" |
921 nigori_original = self._entries.get(self._ServerTagToId(nigori_tag)) | 929 nigori_original = self._entries.get(self._ServerTagToId(nigori_tag)) |
922 if (nigori_original.specifics.nigori.sync_tabs): | 930 if (nigori_original.specifics.nigori.sync_tabs): |
923 return | 931 return |
924 nigori_new = copy.deepcopy(nigori_original) | 932 nigori_new = copy.deepcopy(nigori_original) |
925 nigori_new.specifics.nigori.sync_tabs = True | 933 nigori_new.specifics.nigori.sync_tabs = True |
926 self._SaveEntry(nigori_new) | 934 self._SaveEntry(nigori_new) |
927 | 935 |
936 def TriggerCreateSyncedBookmarks(self): | |
937 """Create the Synced Bookmarks folder under the Bookmarks permanent item. | |
938 | |
939 Clients will then receive the Synced Bookmarks folder on future | |
940 GetUpdates, and new bookmarks can be added within the Synced Bookmarks | |
941 folder. | |
942 """ | |
943 | |
944 synced_bookmarks_spec = (spec for spec in self._PERMANENT_ITEM_SPECS if | |
945 spec.tag == "synced_bookmarks").next() | |
ncarter (slow)
2012/03/15 22:44:52
This is a pretty unidiomatic use of a generator ex
| |
946 self._CreatePermanentItem(synced_bookmarks_spec) | |
947 | |
928 def SetInducedError(self, error, error_frequency, | 948 def SetInducedError(self, error, error_frequency, |
929 sync_count_before_errors): | 949 sync_count_before_errors): |
930 self.induced_error = error | 950 self.induced_error = error |
931 self.induced_error_frequency = error_frequency | 951 self.induced_error_frequency = error_frequency |
932 self.sync_count_before_errors = sync_count_before_errors | 952 self.sync_count_before_errors = sync_count_before_errors |
933 | 953 |
934 def GetInducedError(self): | 954 def GetInducedError(self): |
935 return self.induced_error | 955 return self.induced_error |
936 | 956 |
937 | 957 |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1067 200, | 1087 200, |
1068 '<html><title>Transient error</title><H1>Transient error</H1></html>') | 1088 '<html><title>Transient error</title><H1>Transient error</H1></html>') |
1069 | 1089 |
1070 def HandleSetSyncTabs(self): | 1090 def HandleSetSyncTabs(self): |
1071 """Set the 'sync_tab' field of the nigori node for this account.""" | 1091 """Set the 'sync_tab' field of the nigori node for this account.""" |
1072 self.account.TriggerSyncTabs() | 1092 self.account.TriggerSyncTabs() |
1073 return ( | 1093 return ( |
1074 200, | 1094 200, |
1075 '<html><title>Sync Tabs</title><H1>Sync Tabs</H1></html>') | 1095 '<html><title>Sync Tabs</title><H1>Sync Tabs</H1></html>') |
1076 | 1096 |
1097 def HandleCreateSyncedBookmarks(self): | |
1098 """Create the Synced Bookmarks folder under Bookmarks.""" | |
1099 self.account.TriggerCreateSyncedBookmarks() | |
1100 return ( | |
1101 200, | |
1102 '<html><title>Synced Bookmarks</title><H1>Synced Bookmarks</H1></html>') | |
1103 | |
1077 def HandleCommand(self, query, raw_request): | 1104 def HandleCommand(self, query, raw_request): |
1078 """Decode and handle a sync command from a raw input of bytes. | 1105 """Decode and handle a sync command from a raw input of bytes. |
1079 | 1106 |
1080 This is the main entry point for this class. It is safe to call this | 1107 This is the main entry point for this class. It is safe to call this |
1081 method from multiple threads. | 1108 method from multiple threads. |
1082 | 1109 |
1083 Args: | 1110 Args: |
1084 raw_request: An iterable byte sequence to be interpreted as a sync | 1111 raw_request: An iterable byte sequence to be interpreted as a sync |
1085 protocol command. | 1112 protocol command. |
1086 Returns: | 1113 Returns: |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1226 | 1253 |
1227 update_sieve.CheckMigrationState() | 1254 update_sieve.CheckMigrationState() |
1228 | 1255 |
1229 new_timestamp, entries, remaining = self.account.GetChanges(update_sieve) | 1256 new_timestamp, entries, remaining = self.account.GetChanges(update_sieve) |
1230 | 1257 |
1231 update_response.changes_remaining = remaining | 1258 update_response.changes_remaining = remaining |
1232 for entry in entries: | 1259 for entry in entries: |
1233 reply = update_response.entries.add() | 1260 reply = update_response.entries.add() |
1234 reply.CopyFrom(entry) | 1261 reply.CopyFrom(entry) |
1235 update_sieve.SaveProgress(new_timestamp, update_response) | 1262 update_sieve.SaveProgress(new_timestamp, update_response) |
OLD | NEW |