// Copyright (c) 2012 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 "net/log/net_log.h"

#include "base/bind.h"
#include "base/debug/alias.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/values.h"
#include "net/base/net_errors.h"

namespace net {

namespace {

// Returns parameters for logging data transferred events. At a minum includes
// the number of bytes transferred. If the capture mode allows logging byte
// contents and |byte_count| > 0, then will include the actual bytes. The
// bytes are hex-encoded, since base::StringValue only supports UTF-8.
base::Value* BytesTransferredCallback(int byte_count,
                                      const char* bytes,
                                      NetLogCaptureMode capture_mode) {
  base::DictionaryValue* dict = new base::DictionaryValue();
  dict->SetInteger("byte_count", byte_count);
  if (capture_mode.include_socket_bytes() && byte_count > 0)
    dict->SetString("hex_encoded_bytes", base::HexEncode(bytes, byte_count));
  return dict;
}

base::Value* SourceEventParametersCallback(
    const NetLog::Source source,
    NetLogCaptureMode /* capture_mode */) {
  if (!source.IsValid())
    return NULL;
  base::DictionaryValue* event_params = new base::DictionaryValue();
  source.AddToEventParameters(event_params);
  return event_params;
}

base::Value* NetLogBoolCallback(const char* name,
                                bool value,
                                NetLogCaptureMode /* capture_mode */) {
  base::DictionaryValue* event_params = new base::DictionaryValue();
  event_params->SetBoolean(name, value);
  return event_params;
}

base::Value* NetLogIntegerCallback(const char* name,
                                   int value,
                                   NetLogCaptureMode /* capture_mode */) {
  base::DictionaryValue* event_params = new base::DictionaryValue();
  event_params->SetInteger(name, value);
  return event_params;
}

base::Value* NetLogInt64Callback(const char* name,
                                 int64 value,
                                 NetLogCaptureMode /* capture_mode */) {
  base::DictionaryValue* event_params = new base::DictionaryValue();
  event_params->SetString(name, base::Int64ToString(value));
  return event_params;
}

base::Value* NetLogStringCallback(const char* name,
                                  const std::string* value,
                                  NetLogCaptureMode /* capture_mode */) {
  base::DictionaryValue* event_params = new base::DictionaryValue();
  event_params->SetString(name, *value);
  return event_params;
}

base::Value* NetLogString16Callback(const char* name,
                                    const base::string16* value,
                                    NetLogCaptureMode /* capture_mode */) {
  base::DictionaryValue* event_params = new base::DictionaryValue();
  event_params->SetString(name, *value);
  return event_params;
}

}  // namespace

// LoadTimingInfo requires this be 0.
const uint32 NetLog::Source::kInvalidId = 0;

NetLog::Source::Source() : type(SOURCE_NONE), id(kInvalidId) {
}

NetLog::Source::Source(SourceType type, uint32 id) : type(type), id(id) {
}

bool NetLog::Source::IsValid() const {
  return id != kInvalidId;
}

void NetLog::Source::AddToEventParameters(
    base::DictionaryValue* event_params) const {
  base::DictionaryValue* dict = new base::DictionaryValue();
  dict->SetInteger("type", static_cast<int>(type));
  dict->SetInteger("id", static_cast<int>(id));
  event_params->Set("source_dependency", dict);
}

NetLog::ParametersCallback NetLog::Source::ToEventParametersCallback() const {
  return base::Bind(&SourceEventParametersCallback, *this);
}

// static
bool NetLog::Source::FromEventParameters(base::Value* event_params,
                                         Source* source) {
  base::DictionaryValue* dict = NULL;
  base::DictionaryValue* source_dict = NULL;
  int source_id = -1;
  int source_type = NetLog::SOURCE_COUNT;
  if (!event_params || !event_params->GetAsDictionary(&dict) ||
      !dict->GetDictionary("source_dependency", &source_dict) ||
      !source_dict->GetInteger("id", &source_id) ||
      !source_dict->GetInteger("type", &source_type)) {
    *source = Source();
    return false;
  }

  DCHECK_GE(source_id, 0);
  DCHECK_LT(source_type, NetLog::SOURCE_COUNT);
  *source = Source(static_cast<SourceType>(source_type), source_id);
  return true;
}

base::Value* NetLog::Entry::ToValue() const {
  base::DictionaryValue* entry_dict(new base::DictionaryValue());

  entry_dict->SetString("time", TickCountToString(data_->time));

  // Set the entry source.
  base::DictionaryValue* source_dict = new base::DictionaryValue();
  source_dict->SetInteger("id", data_->source.id);
  source_dict->SetInteger("type", static_cast<int>(data_->source.type));
  entry_dict->Set("source", source_dict);

  // Set the event info.
  entry_dict->SetInteger("type", static_cast<int>(data_->type));
  entry_dict->SetInteger("phase", static_cast<int>(data_->phase));

  // Set the event-specific parameters.
  if (data_->parameters_callback) {
    base::Value* value = data_->parameters_callback->Run(capture_mode_);
    if (value)
      entry_dict->Set("params", value);
  }

  return entry_dict;
}

base::Value* NetLog::Entry::ParametersToValue() const {
  if (data_->parameters_callback)
    return data_->parameters_callback->Run(capture_mode_);
  return NULL;
}

NetLog::EntryData::EntryData(EventType type,
                             Source source,
                             EventPhase phase,
                             base::TimeTicks time,
                             const ParametersCallback* parameters_callback)
    : type(type),
      source(source),
      phase(phase),
      time(time),
      parameters_callback(parameters_callback) {
}

NetLog::EntryData::~EntryData() {
}

NetLog::Entry::Entry(const EntryData* data, NetLogCaptureMode capture_mode)
    : data_(data), capture_mode_(capture_mode) {
}

NetLog::Entry::~Entry() {
}

NetLog::ThreadSafeObserver::ThreadSafeObserver() : net_log_(NULL) {
}

NetLog::ThreadSafeObserver::~ThreadSafeObserver() {
  // Make sure we aren't watching a NetLog on destruction.  Because the NetLog
  // may pass events to each observer on multiple threads, we cannot safely
  // stop watching a NetLog automatically from a parent class.
  DCHECK(!net_log_);
}

NetLogCaptureMode NetLog::ThreadSafeObserver::capture_mode() const {
  DCHECK(net_log_);
  return capture_mode_;
}

NetLog* NetLog::ThreadSafeObserver::net_log() const {
  return net_log_;
}

void NetLog::ThreadSafeObserver::OnAddEntryData(const EntryData& entry_data) {
  OnAddEntry(Entry(&entry_data, capture_mode()));
}

NetLog::NetLog()
    : last_id_(0),
      effective_capture_mode_int32_(
          NetLogCaptureMode::None().ToInternalValue()) {
}

NetLog::~NetLog() {
}

void NetLog::AddGlobalEntry(EventType type) {
  AddEntry(type, Source(NetLog::SOURCE_NONE, NextID()), NetLog::PHASE_NONE,
           NULL);
}

void NetLog::AddGlobalEntry(
    EventType type,
    const NetLog::ParametersCallback& parameters_callback) {
  AddEntry(type, Source(NetLog::SOURCE_NONE, NextID()), NetLog::PHASE_NONE,
           &parameters_callback);
}

uint32 NetLog::NextID() {
  return base::subtle::NoBarrier_AtomicIncrement(&last_id_, 1);
}

NetLogCaptureMode NetLog::GetCaptureMode() const {
  base::subtle::Atomic32 capture_mode =
      base::subtle::NoBarrier_Load(&effective_capture_mode_int32_);
  return NetLogCaptureMode::FromInternalValue(capture_mode);
}

void NetLog::DeprecatedAddObserver(NetLog::ThreadSafeObserver* observer,
                                   NetLogCaptureMode capture_mode) {
  DCHECK(capture_mode.enabled());

  base::AutoLock lock(lock_);

  DCHECK(!observer->net_log_);
  DCHECK(!observer->capture_mode_.enabled());
  observers_.AddObserver(observer);
  observer->net_log_ = this;
  observer->capture_mode_ = capture_mode;
  UpdateCaptureMode();
}

void NetLog::SetObserverCaptureMode(NetLog::ThreadSafeObserver* observer,
                                    NetLogCaptureMode capture_mode) {
  DCHECK(capture_mode.enabled());
  base::AutoLock lock(lock_);

  DCHECK(observers_.HasObserver(observer));
  DCHECK_EQ(this, observer->net_log_);
  DCHECK(observer->capture_mode_.enabled());
  observer->capture_mode_ = capture_mode;
  UpdateCaptureMode();
}

void NetLog::DeprecatedRemoveObserver(NetLog::ThreadSafeObserver* observer) {
  base::AutoLock lock(lock_);

  DCHECK(observers_.HasObserver(observer));
  DCHECK_EQ(this, observer->net_log_);
  DCHECK(observer->capture_mode_.enabled());
  observers_.RemoveObserver(observer);
  observer->net_log_ = NULL;
  observer->capture_mode_ = NetLogCaptureMode();
  UpdateCaptureMode();
}

void NetLog::UpdateCaptureMode() {
  lock_.AssertAcquired();

  // Accumulate the capture mode of all the observers to find the maximum level.
  NetLogCaptureMode new_capture_mode = NetLogCaptureMode::None();
  ObserverListBase<ThreadSafeObserver>::Iterator it(&observers_);
  ThreadSafeObserver* observer;
  while ((observer = it.GetNext()) != NULL) {
    new_capture_mode =
        NetLogCaptureMode::Max(new_capture_mode, observer->capture_mode());
  }
  base::subtle::NoBarrier_Store(&effective_capture_mode_int32_,
                                new_capture_mode.ToInternalValue());
}

// static
std::string NetLog::TickCountToString(const base::TimeTicks& time) {
  int64 delta_time = (time - base::TimeTicks()).InMilliseconds();
  return base::Int64ToString(delta_time);
}

// static
const char* NetLog::EventTypeToString(EventType event) {
  switch (event) {
#define EVENT_TYPE(label) \
  case TYPE_##label:      \
    return #label;
#include "net/log/net_log_event_type_list.h"
#undef EVENT_TYPE
    default:
      NOTREACHED();
      return NULL;
  }
}

// static
base::Value* NetLog::GetEventTypesAsValue() {
  base::DictionaryValue* dict = new base::DictionaryValue();
  for (int i = 0; i < EVENT_COUNT; ++i) {
    dict->SetInteger(EventTypeToString(static_cast<EventType>(i)), i);
  }
  return dict;
}

// static
const char* NetLog::SourceTypeToString(SourceType source) {
  switch (source) {
#define SOURCE_TYPE(label) \
  case SOURCE_##label:     \
    return #label;
#include "net/log/net_log_source_type_list.h"
#undef SOURCE_TYPE
    default:
      NOTREACHED();
      return NULL;
  }
}

// static
base::Value* NetLog::GetSourceTypesAsValue() {
  base::DictionaryValue* dict = new base::DictionaryValue();
  for (int i = 0; i < SOURCE_COUNT; ++i) {
    dict->SetInteger(SourceTypeToString(static_cast<SourceType>(i)), i);
  }
  return dict;
}

// static
const char* NetLog::EventPhaseToString(EventPhase phase) {
  switch (phase) {
    case PHASE_BEGIN:
      return "PHASE_BEGIN";
    case PHASE_END:
      return "PHASE_END";
    case PHASE_NONE:
      return "PHASE_NONE";
  }
  NOTREACHED();
  return NULL;
}

// static
NetLog::ParametersCallback NetLog::BoolCallback(const char* name, bool value) {
  return base::Bind(&NetLogBoolCallback, name, value);
}

// static
NetLog::ParametersCallback NetLog::IntegerCallback(const char* name,
                                                   int value) {
  return base::Bind(&NetLogIntegerCallback, name, value);
}

// static
NetLog::ParametersCallback NetLog::Int64Callback(const char* name,
                                                 int64 value) {
  return base::Bind(&NetLogInt64Callback, name, value);
}

// static
NetLog::ParametersCallback NetLog::StringCallback(const char* name,
                                                  const std::string* value) {
  DCHECK(value);
  return base::Bind(&NetLogStringCallback, name, value);
}

// static
NetLog::ParametersCallback NetLog::StringCallback(const char* name,
                                                  const base::string16* value) {
  DCHECK(value);
  return base::Bind(&NetLogString16Callback, name, value);
}

void NetLog::AddEntry(EventType type,
                      const Source& source,
                      EventPhase phase,
                      const NetLog::ParametersCallback* parameters_callback) {
  if (!GetCaptureMode().enabled())
    return;
  EntryData entry_data(type, source, phase, base::TimeTicks::Now(),
                       parameters_callback);

  // Notify all of the log observers.
  base::AutoLock lock(lock_);
  FOR_EACH_OBSERVER(ThreadSafeObserver, observers_, OnAddEntryData(entry_data));
}

BoundNetLog::~BoundNetLog() {
  liveness_ = DEAD;
}

void BoundNetLog::AddEntry(NetLog::EventType type,
                           NetLog::EventPhase phase) const {
  CrashIfInvalid();

  if (!net_log_)
    return;
  net_log_->AddEntry(type, source_, phase, NULL);
}

void BoundNetLog::AddEntry(
    NetLog::EventType type,
    NetLog::EventPhase phase,
    const NetLog::ParametersCallback& get_parameters) const {
  CrashIfInvalid();

  if (!net_log_)
    return;
  net_log_->AddEntry(type, source_, phase, &get_parameters);
}

void BoundNetLog::AddEvent(NetLog::EventType type) const {
  AddEntry(type, NetLog::PHASE_NONE);
}

void BoundNetLog::AddEvent(
    NetLog::EventType type,
    const NetLog::ParametersCallback& get_parameters) const {
  AddEntry(type, NetLog::PHASE_NONE, get_parameters);
}

void BoundNetLog::BeginEvent(NetLog::EventType type) const {
  AddEntry(type, NetLog::PHASE_BEGIN);
}

void BoundNetLog::BeginEvent(
    NetLog::EventType type,
    const NetLog::ParametersCallback& get_parameters) const {
  AddEntry(type, NetLog::PHASE_BEGIN, get_parameters);
}

void BoundNetLog::EndEvent(NetLog::EventType type) const {
  AddEntry(type, NetLog::PHASE_END);
}

void BoundNetLog::EndEvent(
    NetLog::EventType type,
    const NetLog::ParametersCallback& get_parameters) const {
  AddEntry(type, NetLog::PHASE_END, get_parameters);
}

void BoundNetLog::AddEventWithNetErrorCode(NetLog::EventType event_type,
                                           int net_error) const {
  DCHECK_NE(ERR_IO_PENDING, net_error);
  if (net_error >= 0) {
    AddEvent(event_type);
  } else {
    AddEvent(event_type, NetLog::IntegerCallback("net_error", net_error));
  }
}

void BoundNetLog::EndEventWithNetErrorCode(NetLog::EventType event_type,
                                           int net_error) const {
  DCHECK_NE(ERR_IO_PENDING, net_error);
  if (net_error >= 0) {
    EndEvent(event_type);
  } else {
    EndEvent(event_type, NetLog::IntegerCallback("net_error", net_error));
  }
}

void BoundNetLog::AddByteTransferEvent(NetLog::EventType event_type,
                                       int byte_count,
                                       const char* bytes) const {
  AddEvent(event_type, base::Bind(BytesTransferredCallback, byte_count, bytes));
}

NetLogCaptureMode BoundNetLog::GetCaptureMode() const {
  CrashIfInvalid();

  if (net_log_)
    return net_log_->GetCaptureMode();
  return NetLogCaptureMode();
}

// static
BoundNetLog BoundNetLog::Make(NetLog* net_log, NetLog::SourceType source_type) {
  if (!net_log)
    return BoundNetLog();

  NetLog::Source source(source_type, net_log->NextID());
  return BoundNetLog(source, net_log);
}

void BoundNetLog::CrashIfInvalid() const {
  Liveness liveness = liveness_;

  if (liveness == ALIVE)
    return;

  base::debug::Alias(&liveness);
  CHECK_EQ(ALIVE, liveness);
}

}  // namespace net
