1 // Copyright 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "sync/internal_api/public/base/invalidation.h" 6 7 #include <cstddef> 8 9 #include "base/json/json_string_value_serializer.h" 10 #include "base/rand_util.h" 11 #include "base/strings/string_number_conversions.h" 12 #include "base/values.h" 13 #include "sync/notifier/ack_handler.h" 14 #include "sync/notifier/dropped_invalidation_tracker.h" 15 #include "sync/notifier/invalidation_util.h" 16 17 namespace syncer { 18 19 namespace { 20 const char kObjectIdKey[] = "objectId"; 21 const char kIsUnknownVersionKey[] = "isUnknownVersion"; 22 const char kVersionKey[] = "version"; 23 const char kPayloadKey[] = "payload"; 24 const int64 kInvalidVersion = -1; 25 } 26 27 Invalidation Invalidation::Init( 28 const invalidation::ObjectId& id, 29 int64 version, 30 const std::string& payload) { 31 return Invalidation(id, false, version, payload, AckHandle::CreateUnique()); 32 } 33 34 Invalidation Invalidation::InitUnknownVersion( 35 const invalidation::ObjectId& id) { 36 return Invalidation(id, true, kInvalidVersion, 37 std::string(), AckHandle::CreateUnique()); 38 } 39 40 Invalidation Invalidation::InitFromDroppedInvalidation( 41 const Invalidation& dropped) { 42 return Invalidation(dropped.id_, true, kInvalidVersion, 43 std::string(), dropped.ack_handle_); 44 } 45 46 scoped_ptr<Invalidation> Invalidation::InitFromValue( 47 const base::DictionaryValue& value) { 48 invalidation::ObjectId id; 49 50 const base::DictionaryValue* object_id_dict; 51 if (!value.GetDictionary(kObjectIdKey, &object_id_dict) 52 || !ObjectIdFromValue(*object_id_dict, &id)) { 53 DLOG(WARNING) << "Failed to parse id"; 54 return scoped_ptr<Invalidation>(); 55 } 56 bool is_unknown_version; 57 if (!value.GetBoolean(kIsUnknownVersionKey, &is_unknown_version)) { 58 DLOG(WARNING) << "Failed to parse is_unknown_version flag"; 59 return scoped_ptr<Invalidation>(); 60 } 61 if (is_unknown_version) { 62 return scoped_ptr<Invalidation>(new Invalidation( 63 id, 64 true, 65 kInvalidVersion, 66 std::string(), 67 AckHandle::CreateUnique())); 68 } else { 69 int64 version; 70 std::string version_as_string; 71 if (!value.GetString(kVersionKey, &version_as_string) 72 || !base::StringToInt64(version_as_string, &version)) { 73 DLOG(WARNING) << "Failed to parse version"; 74 return scoped_ptr<Invalidation>(); 75 } 76 std::string payload; 77 if (!value.GetString(kPayloadKey, &payload)) { 78 DLOG(WARNING) << "Failed to parse payload"; 79 return scoped_ptr<Invalidation>(); 80 } 81 return scoped_ptr<Invalidation>(new Invalidation( 82 id, 83 false, 84 version, 85 payload, 86 AckHandle::CreateUnique())); 87 } 88 } 89 90 Invalidation::~Invalidation() {} 91 92 invalidation::ObjectId Invalidation::object_id() const { 93 return id_; 94 } 95 96 bool Invalidation::is_unknown_version() const { 97 return is_unknown_version_; 98 } 99 100 int64 Invalidation::version() const { 101 DCHECK(!is_unknown_version_); 102 return version_; 103 } 104 105 const std::string& Invalidation::payload() const { 106 DCHECK(!is_unknown_version_); 107 return payload_; 108 } 109 110 const AckHandle& Invalidation::ack_handle() const { 111 return ack_handle_; 112 } 113 114 void Invalidation::set_ack_handler(syncer::WeakHandle<AckHandler> handler) { 115 ack_handler_ = handler; 116 } 117 118 bool Invalidation::SupportsAcknowledgement() const { 119 return ack_handler_.IsInitialized(); 120 } 121 122 void Invalidation::Acknowledge() const { 123 if (SupportsAcknowledgement()) { 124 ack_handler_.Call(FROM_HERE, 125 &AckHandler::Acknowledge, 126 id_, 127 ack_handle_); 128 } 129 } 130 131 void Invalidation::Drop(DroppedInvalidationTracker* tracker) const { 132 DCHECK(tracker->object_id() == object_id()); 133 tracker->RecordDropEvent(ack_handler_, ack_handle_); 134 if (SupportsAcknowledgement()) { 135 ack_handler_.Call(FROM_HERE, 136 &AckHandler::Drop, 137 id_, 138 ack_handle_); 139 } 140 } 141 142 bool Invalidation::Equals(const Invalidation& other) const { 143 return id_ == other.id_ 144 && is_unknown_version_ == other.is_unknown_version_ 145 && version_ == other.version_ 146 && payload_ == other.payload_; 147 } 148 149 scoped_ptr<base::DictionaryValue> Invalidation::ToValue() const { 150 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue()); 151 value->Set(kObjectIdKey, ObjectIdToValue(id_).release()); 152 if (is_unknown_version_) { 153 value->SetBoolean(kIsUnknownVersionKey, true); 154 } else { 155 value->SetBoolean(kIsUnknownVersionKey, false); 156 value->SetString(kVersionKey, base::Int64ToString(version_)); 157 value->SetString(kPayloadKey, payload_); 158 } 159 return value.Pass(); 160 } 161 162 std::string Invalidation::ToString() const { 163 std::string output; 164 JSONStringValueSerializer serializer(&output); 165 serializer.set_pretty_print(true); 166 serializer.Serialize(*ToValue().get()); 167 return output; 168 } 169 170 Invalidation::Invalidation( 171 const invalidation::ObjectId& id, 172 bool is_unknown_version, 173 int64 version, 174 const std::string& payload, 175 AckHandle ack_handle) 176 : id_(id), 177 is_unknown_version_(is_unknown_version), 178 version_(version), 179 payload_(payload), 180 ack_handle_(ack_handle) {} 181 182 } // namespace syncer 183