普通文本  |  180行  |  5.19 KB

// 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