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 #include "chrome/browser/sync/invalidations/invalidator_storage.h" | 5 #include "chrome/browser/sync/invalidations/invalidator_storage.h" |
6 | 6 |
7 #include "base/base64.h" | 7 #include "base/base64.h" |
8 #include "base/bind.h" | |
9 #include "base/callback.h" | |
10 #include "base/location.h" | |
8 #include "base/logging.h" | 11 #include "base/logging.h" |
9 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
10 #include "base/string_number_conversions.h" | 13 #include "base/string_number_conversions.h" |
14 #include "base/task_runner.h" | |
11 #include "base/values.h" | 15 #include "base/values.h" |
12 #include "chrome/browser/prefs/pref_service.h" | 16 #include "chrome/browser/prefs/pref_service.h" |
13 #include "chrome/common/pref_names.h" | 17 #include "chrome/common/pref_names.h" |
14 #include "sync/internal_api/public/base/model_type.h" | 18 #include "sync/internal_api/public/base/model_type.h" |
19 #include "sync/notifier/invalidation_util.h" | |
15 | 20 |
16 using syncer::InvalidationStateMap; | 21 using syncer::InvalidationStateMap; |
17 | 22 |
18 namespace browser_sync { | 23 namespace browser_sync { |
19 | 24 |
20 namespace { | 25 namespace { |
21 | 26 |
22 const char kSourceKey[] = "source"; | 27 const char kSourceKey[] = "source"; |
23 const char kNameKey[] = "name"; | 28 const char kNameKey[] = "name"; |
24 const char kMaxVersionKey[] = "max-version"; | 29 const char kMaxVersionKey[] = "max-version"; |
30 const char kPayloadKey[] = "payload"; | |
31 const char kCurrentAckHandleKey[] = "current-ack"; | |
32 const char kExpectedAckHandleKey[] = "expected-ack"; | |
25 | 33 |
26 bool ValueToObjectIdAndState(const DictionaryValue& value, | 34 bool ValueToObjectIdAndState(const DictionaryValue& value, |
27 invalidation::ObjectId* id, | 35 invalidation::ObjectId* id, |
28 syncer::InvalidationState* state) { | 36 syncer::InvalidationState* state) { |
29 std::string source_str; | 37 std::string source_str; |
30 int source = 0; | |
31 std::string name; | |
32 std::string max_version_str; | |
33 if (!value.GetString(kSourceKey, &source_str)) { | 38 if (!value.GetString(kSourceKey, &source_str)) { |
34 DLOG(WARNING) << "Unable to deserialize source"; | 39 DLOG(WARNING) << "Unable to deserialize source"; |
35 return false; | 40 return false; |
36 } | 41 } |
42 int source = 0; | |
43 if (!base::StringToInt(source_str, &source)) { | |
44 DLOG(WARNING) << "Invalid source: " << source_str; | |
45 return false; | |
46 } | |
47 std::string name; | |
37 if (!value.GetString(kNameKey, &name)) { | 48 if (!value.GetString(kNameKey, &name)) { |
38 DLOG(WARNING) << "Unable to deserialize name"; | 49 DLOG(WARNING) << "Unable to deserialize name"; |
39 return false; | 50 return false; |
40 } | 51 } |
41 if (!value.GetString(kMaxVersionKey, &max_version_str)) { | 52 // Fields that may not be set if we've only received an invalidation for an |
42 DLOG(WARNING) << "Unable to deserialize max version"; | 53 // unknown version or for all types. |
43 return false; | 54 std::string max_version_str; |
55 if (value.GetString(kMaxVersionKey, &max_version_str)) { | |
akalin
2012/11/28 00:11:42
isn't kMaxVersionkey always present? looks like i
dcheng
2012/11/30 01:42:54
Hm. Yeah, you're right. I was thinking from the wr
| |
56 if (!base::StringToInt64(max_version_str, &state->version)) { | |
57 DLOG(WARNING) << "Invalid max invalidation version: " << max_version_str; | |
58 return false; | |
59 } | |
44 } | 60 } |
45 if (!base::StringToInt(source_str, &source)) { | 61 value.GetString(kPayloadKey, &state->payload); |
46 DLOG(WARNING) << "Invalid source: " << source_str; | 62 *id = invalidation::ObjectId(source, name); |
akalin
2012/11/28 00:11:42
move this closer to where source and name are set?
dcheng
2012/11/30 01:42:54
I did this intentionally to avoid a state where th
| |
47 return false; | 63 // The ack handle fields won't be set if upgrading from previous versions of |
akalin
2012/11/28 00:11:42
clear state first?
dcheng
2012/11/30 01:42:54
While this could be less error prone, it's also re
akalin
2012/11/30 02:45:15
i guess it's okay since this is a private function
| |
64 // Chrome. | |
65 const base::DictionaryValue* current_ack_handle_value = NULL; | |
66 if (value.GetDictionary(kCurrentAckHandleKey, ¤t_ack_handle_value)) { | |
67 state->current.ResetFromValue(*current_ack_handle_value); | |
48 } | 68 } |
49 if (!base::StringToInt64(max_version_str, &state->version)) { | 69 // TODO(dcheng): Consider regenerating the latest ack handle value on Chrome |
akalin
2012/11/28 00:11:42
hmm i don't understand this comment. what do you
dcheng
2012/11/30 01:42:54
One of my original ideas was to ignore the persist
| |
50 DLOG(WARNING) << "Invalid max invalidation version: " << max_version_str; | 70 // startup to allow for format changes? |
51 return false; | 71 const base::DictionaryValue* expected_ack_handle_value = NULL; |
72 if (value.GetDictionary(kExpectedAckHandleKey, &expected_ack_handle_value)) { | |
73 state->expected.ResetFromValue(*expected_ack_handle_value); | |
74 } else { | |
75 // In this case, we should never have a valid current value set. | |
76 DCHECK(!state->current.IsValid()); | |
77 state->current = syncer::AckHandle::InvalidAckHandle(); | |
52 } | 78 } |
53 *id = invalidation::ObjectId(source, name); | |
54 return true; | 79 return true; |
55 } | 80 } |
56 | 81 |
57 // The caller owns the returned value. | 82 // The caller owns the returned value. |
58 DictionaryValue* ObjectIdAndStateToValue( | 83 DictionaryValue* ObjectIdAndStateToValue( |
59 const invalidation::ObjectId& id, const syncer::InvalidationState& state) { | 84 const invalidation::ObjectId& id, const syncer::InvalidationState& state) { |
60 DictionaryValue* value = new DictionaryValue; | 85 DictionaryValue* value = new DictionaryValue; |
61 value->SetString(kSourceKey, base::IntToString(id.source())); | 86 value->SetString(kSourceKey, base::IntToString(id.source())); |
62 value->SetString(kNameKey, id.name()); | 87 value->SetString(kNameKey, id.name()); |
63 value->SetString(kMaxVersionKey, base::Int64ToString(state.version)); | 88 value->SetString(kMaxVersionKey, base::Int64ToString(state.version)); |
89 value->SetString(kPayloadKey, state.payload); | |
90 if (state.current.IsValid()) | |
91 value->Set(kCurrentAckHandleKey, state.current.ToValue().release()); | |
92 if (state.expected.IsValid()) | |
93 value->Set(kExpectedAckHandleKey, state.expected.ToValue().release()); | |
64 return value; | 94 return value; |
65 } | 95 } |
66 | 96 |
67 } // namespace | 97 } // namespace |
68 | 98 |
69 InvalidatorStorage::InvalidatorStorage(PrefService* pref_service) | 99 InvalidatorStorage::InvalidatorStorage(PrefService* pref_service) |
70 : pref_service_(pref_service) { | 100 : pref_service_(pref_service) { |
71 // TODO(tim): Create a Mock instead of maintaining the if(!pref_service_) case | 101 // TODO(tim): Create a Mock instead of maintaining the if(!pref_service_) case |
72 // throughout this file. This is a problem now due to lack of injection at | 102 // throughout this file. This is a problem now due to lack of injection at |
73 // ProfileSyncService. Bug 130176. | 103 // ProfileSyncService. Bug 130176. |
(...skipping 17 matching lines...) Expand all Loading... | |
91 if (!pref_service_) { | 121 if (!pref_service_) { |
92 return state_map; | 122 return state_map; |
93 } | 123 } |
94 const base::ListValue* state_map_list = | 124 const base::ListValue* state_map_list = |
95 pref_service_->GetList(prefs::kInvalidatorMaxInvalidationVersions); | 125 pref_service_->GetList(prefs::kInvalidatorMaxInvalidationVersions); |
96 CHECK(state_map_list); | 126 CHECK(state_map_list); |
97 DeserializeFromList(*state_map_list, &state_map); | 127 DeserializeFromList(*state_map_list, &state_map); |
98 return state_map; | 128 return state_map; |
99 } | 129 } |
100 | 130 |
101 void InvalidatorStorage::SetMaxVersion(const invalidation::ObjectId& id, | 131 void InvalidatorStorage::SetMaxVersionAndPayload( |
102 int64 max_version) { | 132 const invalidation::ObjectId& id, |
133 int64 max_version, | |
134 const std::string& payload) { | |
103 DCHECK(thread_checker_.CalledOnValidThread()); | 135 DCHECK(thread_checker_.CalledOnValidThread()); |
104 CHECK(pref_service_); | 136 CHECK(pref_service_); |
105 InvalidationStateMap state_map = GetAllInvalidationStates(); | 137 InvalidationStateMap state_map = GetAllInvalidationStates(); |
106 InvalidationStateMap::iterator it = state_map.find(id); | 138 InvalidationStateMap::iterator it = state_map.find(id); |
107 if ((it != state_map.end()) && (max_version <= it->second.version)) { | 139 if ((it != state_map.end()) && (max_version <= it->second.version)) { |
108 NOTREACHED(); | 140 NOTREACHED(); |
109 return; | 141 return; |
110 } | 142 } |
111 state_map[id].version = max_version; | 143 state_map[id].version = max_version; |
144 state_map[id].payload = payload; | |
112 | 145 |
113 base::ListValue state_map_list; | 146 base::ListValue state_map_list; |
114 SerializeToList(state_map, &state_map_list); | 147 SerializeToList(state_map, &state_map_list); |
115 pref_service_->Set(prefs::kInvalidatorMaxInvalidationVersions, | 148 pref_service_->Set(prefs::kInvalidatorMaxInvalidationVersions, |
116 state_map_list); | 149 state_map_list); |
117 } | 150 } |
118 | 151 |
119 void InvalidatorStorage::Forget(const syncer::ObjectIdSet& ids) { | 152 void InvalidatorStorage::Forget(const syncer::ObjectIdSet& ids) { |
120 DCHECK(thread_checker_.CalledOnValidThread()); | 153 DCHECK(thread_checker_.CalledOnValidThread()); |
121 CHECK(pref_service_); | 154 CHECK(pref_service_); |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
241 base::Base64Decode(base64_data, &data); | 274 base::Base64Decode(base64_data, &data); |
242 return data; | 275 return data; |
243 } | 276 } |
244 | 277 |
245 void InvalidatorStorage::Clear() { | 278 void InvalidatorStorage::Clear() { |
246 DCHECK(thread_checker_.CalledOnValidThread()); | 279 DCHECK(thread_checker_.CalledOnValidThread()); |
247 pref_service_->ClearPref(prefs::kInvalidatorMaxInvalidationVersions); | 280 pref_service_->ClearPref(prefs::kInvalidatorMaxInvalidationVersions); |
248 pref_service_->ClearPref(prefs::kInvalidatorInvalidationState); | 281 pref_service_->ClearPref(prefs::kInvalidatorInvalidationState); |
249 } | 282 } |
250 | 283 |
284 void InvalidatorStorage::GenerateAckHandles( | |
285 const syncer::ObjectIdSet& ids, | |
286 const scoped_refptr<base::TaskRunner>& task_runner, | |
287 const base::Callback<void(const syncer::AckHandleMap&)> callback) { | |
288 DCHECK(thread_checker_.CalledOnValidThread()); | |
289 CHECK(pref_service_); | |
290 InvalidationStateMap state_map = GetAllInvalidationStates(); | |
291 | |
292 syncer::AckHandleMap ack_handles; | |
293 for (syncer::ObjectIdSet::const_iterator it = ids.begin(); it != ids.end(); | |
294 ++it) { | |
295 state_map[*it].expected = syncer::AckHandle::CreateUnique(); | |
296 ack_handles.insert(std::make_pair(*it, state_map[*it].expected)); | |
297 } | |
298 | |
299 base::ListValue state_map_list; | |
300 SerializeToList(state_map, &state_map_list); | |
301 pref_service_->Set(prefs::kInvalidatorMaxInvalidationVersions, | |
302 state_map_list); | |
303 | |
304 task_runner->PostTask(FROM_HERE, base::Bind(callback, ack_handles)); | |
akalin
2012/11/28 00:11:42
do something with return value? maybe just ignore
dcheng
2012/11/30 01:42:54
Done.
| |
305 } | |
306 | |
307 void InvalidatorStorage::Acknowledge(const invalidation::ObjectId& id, | |
308 const syncer::AckHandle& ack_handle) { | |
309 DCHECK(thread_checker_.CalledOnValidThread()); | |
310 CHECK(pref_service_); | |
311 InvalidationStateMap state_map = GetAllInvalidationStates(); | |
312 | |
313 InvalidationStateMap::iterator it = state_map.find(id); | |
314 // This could happen if the acknowledgement is delayed and Forget() has | |
315 // already been called. | |
316 if (it == state_map.end()) | |
317 return; | |
318 it->second.current = ack_handle; | |
319 | |
320 base::ListValue state_map_list; | |
321 SerializeToList(state_map, &state_map_list); | |
322 pref_service_->Set(prefs::kInvalidatorMaxInvalidationVersions, | |
323 state_map_list); | |
324 } | |
325 | |
251 } // namespace browser_sync | 326 } // namespace browser_sync |
OLD | NEW |