blob: 8b04e3f52421dc0b42786a082f13c8420d9841d8 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/invalidation/invalidation.h"
#include <cstddef>
#include "base/bind.h"
#include "base/json/json_string_value_serializer.h"
#include "base/location.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
#include "components/invalidation/ack_handler.h"
#include "components/invalidation/invalidation_util.h"
namespace syncer {
namespace {
const char kObjectIdKey[] = "objectId";
const char kIsUnknownVersionKey[] = "isUnknownVersion";
const char kVersionKey[] = "version";
const char kPayloadKey[] = "payload";
const int64 kInvalidVersion = -1;
}
Invalidation Invalidation::Init(const invalidation::ObjectId& id,
int64 version,
const std::string& payload) {
return Invalidation(id, false, version, payload, AckHandle::CreateUnique());
}
Invalidation Invalidation::InitUnknownVersion(
const invalidation::ObjectId& id) {
return Invalidation(
id, true, kInvalidVersion, std::string(), AckHandle::CreateUnique());
}
Invalidation Invalidation::InitFromDroppedInvalidation(
const Invalidation& dropped) {
return Invalidation(
dropped.id_, true, kInvalidVersion, std::string(), dropped.ack_handle_);
}
scoped_ptr<Invalidation> Invalidation::InitFromValue(
const base::DictionaryValue& value) {
invalidation::ObjectId id;
const base::DictionaryValue* object_id_dict;
if (!value.GetDictionary(kObjectIdKey, &object_id_dict) ||
!ObjectIdFromValue(*object_id_dict, &id)) {
DLOG(WARNING) << "Failed to parse id";
return scoped_ptr<Invalidation>();
}
bool is_unknown_version;
if (!value.GetBoolean(kIsUnknownVersionKey, &is_unknown_version)) {
DLOG(WARNING) << "Failed to parse is_unknown_version flag";
return scoped_ptr<Invalidation>();
}
if (is_unknown_version) {
return scoped_ptr<Invalidation>(new Invalidation(
id,
true,
kInvalidVersion,
std::string(),
AckHandle::CreateUnique()));
}
int64 version = 0;
std::string version_as_string;
if (!value.GetString(kVersionKey, &version_as_string)
|| !base::StringToInt64(version_as_string, &version)) {
DLOG(WARNING) << "Failed to parse version";
return scoped_ptr<Invalidation>();
}
std::string payload;
if (!value.GetString(kPayloadKey, &payload)) {
DLOG(WARNING) << "Failed to parse payload";
return scoped_ptr<Invalidation>();
}
return scoped_ptr<Invalidation>(new Invalidation(
id,
false,
version,
payload,
AckHandle::CreateUnique()));
}
Invalidation::~Invalidation() {
}
invalidation::ObjectId Invalidation::object_id() const {
return id_;
}
bool Invalidation::is_unknown_version() const {
return is_unknown_version_;
}
int64 Invalidation::version() const {
DCHECK(!is_unknown_version_);
return version_;
}
const std::string& Invalidation::payload() const {
DCHECK(!is_unknown_version_);
return payload_;
}
const AckHandle& Invalidation::ack_handle() const {
return ack_handle_;
}
void Invalidation::SetAckHandler(
base::WeakPtr<AckHandler> handler,
scoped_refptr<base::SequencedTaskRunner> handler_task_runner) {
ack_handler_ = handler;
ack_handler_task_runner_ = handler_task_runner;
}
bool Invalidation::SupportsAcknowledgement() const {
return !!ack_handler_task_runner_.get();
}
void Invalidation::Acknowledge() const {
if (SupportsAcknowledgement()) {
ack_handler_task_runner_->PostTask(
FROM_HERE,
base::Bind(&AckHandler::Acknowledge, ack_handler_, id_, ack_handle_));
}
}
void Invalidation::Drop() {
if (SupportsAcknowledgement()) {
ack_handler_task_runner_->PostTask(
FROM_HERE,
base::Bind(&AckHandler::Drop, ack_handler_, id_, ack_handle_));
}
}
bool Invalidation::Equals(const Invalidation& other) const {
return id_ == other.id_ && is_unknown_version_ == other.is_unknown_version_ &&
version_ == other.version_ && payload_ == other.payload_;
}
scoped_ptr<base::DictionaryValue> Invalidation::ToValue() const {
scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
value->Set(kObjectIdKey, ObjectIdToValue(id_).release());
if (is_unknown_version_) {
value->SetBoolean(kIsUnknownVersionKey, true);
} else {
value->SetBoolean(kIsUnknownVersionKey, false);
value->SetString(kVersionKey, base::Int64ToString(version_));
value->SetString(kPayloadKey, payload_);
}
return value.Pass();
}
std::string Invalidation::ToString() const {
std::string output;
JSONStringValueSerializer serializer(&output);
serializer.set_pretty_print(true);
serializer.Serialize(*ToValue().get());
return output;
}
Invalidation::Invalidation(const invalidation::ObjectId& id,
bool is_unknown_version,
int64 version,
const std::string& payload,
AckHandle ack_handle)
: id_(id),
is_unknown_version_(is_unknown_version),
version_(version),
payload_(payload),
ack_handle_(ack_handle) {
}
} // namespace syncer