// Copyright 2018 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 "services/network/net_log_exporter.h"

#include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "base/values.h"
#include "net/log/file_net_log_observer.h"
#include "net/log/net_log_util.h"
#include "net/url_request/url_request_context.h"
#include "services/network/network_context.h"
#include "services/network/network_service.h"
#include "services/network/public/cpp/network_switches.h"

namespace network {

NetLogExporter::NetLogExporter(NetworkContext* network_context)
    : network_context_(network_context), state_(STATE_IDLE) {}

NetLogExporter::~NetLogExporter() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  // In case scratch directory creation didn't finish by the time |this| is
  // destroyed, |destination_| is still owned here (rather than handed over to
  // FileNetLogObserver); ask the scheduler to close it someplace suitable.
  if (destination_.IsValid())
    CloseFileOffThread(std::move(destination_));

  // ~FileNetLogObserver will take care of unregistering from NetLog even
  // if StopObserving isn't invoked.
}

void NetLogExporter::Start(base::File destination,
                           base::Value extra_constants,
                           net::NetLogCaptureMode capture_mode,
                           uint64_t max_file_size,
                           StartCallback callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(destination.IsValid());

  if (state_ != STATE_IDLE) {
    CloseFileOffThread(std::move(destination));
    std::move(callback).Run(net::ERR_UNEXPECTED);
    return;
  }

  // Store the file explicitly since destroying it involves disk I/O, so must
  // be carefully controlled.
  destination_ = std::move(destination);

  state_ = STATE_WAITING_DIR;
  static_assert(kUnlimitedFileSize == net::FileNetLogObserver::kNoLimit,
                "Inconsistent unbounded size constants");
  if (max_file_size != kUnlimitedFileSize) {
    base::PostTaskWithTraitsAndReplyWithResult(
        FROM_HERE,
        {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
        base::BindOnce(&NetLogExporter::CreateScratchDir,
                       scratch_dir_create_handler_for_tests_),

        // Note: this a static method which takes a weak pointer as an argument,
        // so it will run if |this| is deleted.
        base::BindOnce(&NetLogExporter::StartWithScratchDirOrCleanup,
                       AsWeakPtr(), std::move(extra_constants), capture_mode,
                       max_file_size, std::move(callback)));
  } else {
    StartWithScratchDir(std::move(extra_constants), capture_mode, max_file_size,
                        std::move(callback), base::FilePath());
  }
}

void NetLogExporter::Stop(base::Value polled_data_value,
                          StopCallback callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  base::DictionaryValue* polled_data = nullptr;
  bool ok = polled_data_value.GetAsDictionary(&polled_data);
  DCHECK(ok);  // mojo is supposed to enforce that.

  if (state_ != STATE_RUNNING) {
    std::move(callback).Run(net::ERR_UNEXPECTED);
    return;
  }

  std::unique_ptr<base::DictionaryValue> net_info = net::GetNetInfo(
      network_context_->url_request_context(), net::NET_INFO_ALL_SOURCES);
  if (polled_data)
    net_info->MergeDictionary(polled_data);

  file_net_observer_->StopObserving(
      std::move(net_info),
      base::BindOnce([](StopCallback sc) { std::move(sc).Run(net::OK); },
                     std::move(callback)));
  file_net_observer_ = nullptr;
  state_ = STATE_IDLE;
}

void NetLogExporter::SetCreateScratchDirHandlerForTesting(
    const base::RepeatingCallback<base::FilePath()>& handler) {
  scratch_dir_create_handler_for_tests_ = handler;
}

void NetLogExporter::CloseFileOffThread(base::File file) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  if (file.IsValid()) {
    base::PostTaskWithTraits(
        FROM_HERE,
        {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
        base::BindOnce([](base::File f) { f.Close(); }, std::move(file)));
  }
}

base::FilePath NetLogExporter::CreateScratchDir(
    base::RepeatingCallback<base::FilePath()>
        scratch_dir_create_handler_for_tests) {
  if (scratch_dir_create_handler_for_tests)
    return scratch_dir_create_handler_for_tests.Run();

  base::ScopedTempDir scratch_dir;
  if (scratch_dir.CreateUniqueTempDir())
    return scratch_dir.Take();
  else
    return base::FilePath();
}

void NetLogExporter::StartWithScratchDirOrCleanup(
    base::WeakPtr<NetLogExporter> object,
    base::Value extra_constants,
    net::NetLogCaptureMode capture_mode,
    uint64_t max_file_size,
    StartCallback callback,
    const base::FilePath& scratch_dir_path) {
  NetLogExporter* instance = object.get();
  if (instance) {
    instance->StartWithScratchDir(std::move(extra_constants), capture_mode,
                                  max_file_size, std::move(callback),
                                  scratch_dir_path);
  } else if (!scratch_dir_path.empty()) {
    // An NetLogExporter got destroyed while it was trying to create a scratch
    // dir.
    base::PostTaskWithTraits(
        FROM_HERE,
        {base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
        base::BindOnce(
            [](const base::FilePath& dir) {
              // The delete is non-recursive (2nd argument false) since the
              // only time this is invoked the directory is expected to be
              // empty.
              base::DeleteFile(dir, false);
            },
            scratch_dir_path));
  }
}

void NetLogExporter::StartWithScratchDir(
    base::Value extra_constants_value,
    net::NetLogCaptureMode capture_mode,
    uint64_t max_file_size,
    StartCallback callback,
    const base::FilePath& scratch_dir_path) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  base::DictionaryValue* extra_constants = nullptr;
  bool ok = extra_constants_value.GetAsDictionary(&extra_constants);
  DCHECK(ok);  // mojo is supposed to enforce that before Start() is invoked.

  if (scratch_dir_path.empty() && max_file_size != kUnlimitedFileSize) {
    state_ = STATE_IDLE;
    CloseFileOffThread(std::move(destination_));
    std::move(callback).Run(net::ERR_INSUFFICIENT_RESOURCES);
    return;
  }

  state_ = STATE_RUNNING;

  std::unique_ptr<base::DictionaryValue> constants = net::GetNetConstants();

  if (extra_constants)
    constants->MergeDictionary(extra_constants);

  if (max_file_size != kUnlimitedFileSize) {
    file_net_observer_ = net::FileNetLogObserver::CreateBoundedPreExisting(
        scratch_dir_path, std::move(destination_), max_file_size,
        std::move(constants));
  } else {
    DCHECK(scratch_dir_path.empty());
    file_net_observer_ = net::FileNetLogObserver::CreateUnboundedPreExisting(
        std::move(destination_), std::move(constants));
  }

  // There might not be a NetworkService object e.g. on iOS; in that case
  // assume this present NetworkContext is all there is.
  if (network_context_->network_service()) {
    network_context_->network_service()->CreateNetLogEntriesForActiveObjects(
        file_net_observer_.get());
  } else {
    std::set<net::URLRequestContext*> contexts;
    contexts.insert(network_context_->url_request_context());
    net::CreateNetLogEntriesForActiveObjects(contexts,
                                             file_net_observer_.get());
  }

  file_net_observer_->StartObserving(
      network_context_->url_request_context()->net_log(), capture_mode);
  std::move(callback).Run(net::OK);
}

}  // namespace network
