// Copyright 2015 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/network/network_module.h"

#include "base/bind.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "cobalt/network/network_system.h"
#include "cobalt/network/switches.h"
#include "net/url_request/static_http_user_agent_settings.h"

namespace cobalt {
namespace network {

namespace {
#if defined(ENABLE_NETWORK_LOGGING)
const char kCaptureModeIncludeCookiesAndCredentials[] =
    "IncludeCookiesAndCredentials";
const char kCaptureModeIncludeSocketBytes[] = "IncludeSocketBytes";
#endif
}  // namespace

NetworkModule::NetworkModule(const Options& options)
    : storage_manager_(NULL), options_(options) {
  Initialize("Null user agent string.", NULL);
}

NetworkModule::NetworkModule(const std::string& user_agent_string,
                             storage::StorageManager* storage_manager,
                             base::EventDispatcher* event_dispatcher,
                             const Options& options)
    : storage_manager_(storage_manager), options_(options) {
  Initialize(user_agent_string, event_dispatcher);
}

NetworkModule::~NetworkModule() {
  // Order of destruction is important here.
  // URLRequestContext and NetworkDelegate must be destroyed on the IO thread.
  // The ObjectWatchMultiplexer must be destroyed last.  (The sockets owned
  // by URLRequestContext will destroy their ObjectWatchers, which need the
  // multiplexer.)
  url_request_context_getter_ = NULL;
#if defined(DIAL_SERVER)
  dial_service_proxy_ = NULL;
  task_runner()->DeleteSoon(FROM_HERE, dial_service_.release());
#endif

  task_runner()->DeleteSoon(FROM_HERE, cookie_jar_.release());
  task_runner()->DeleteSoon(FROM_HERE, net_poster_.release());
  task_runner()->DeleteSoon(FROM_HERE, url_request_context_.release());
  task_runner()->DeleteSoon(FROM_HERE, network_delegate_.release());

  // This will run the above task, and then stop the thread.
  thread_.reset(NULL);
#if !defined(STARBOARD)
  object_watch_multiplexer_.reset(NULL);
#endif
  network_system_.reset(NULL);
}

std::string NetworkModule::GetUserAgent() const {
  DCHECK(http_user_agent_settings_);
  return http_user_agent_settings_->GetUserAgent();
}

network_bridge::PostSender NetworkModule::GetPostSender() const {
  return base::Bind(&network_bridge::NetPoster::Send,
                    base::Unretained(net_poster_.get()));
}

void NetworkModule::SetProxy(const std::string& custom_proxy_rules) {
  task_runner()->PostTask(
      FROM_HERE, base::Bind(&URLRequestContext::SetProxy,
                            base::Unretained(url_request_context_.get()),
                            custom_proxy_rules));
}

void NetworkModule::SetEnableQuic(bool enable_quic) {
  task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&URLRequestContext::SetEnableQuic,
                 base::Unretained(url_request_context_.get()), enable_quic));
}

void NetworkModule::Initialize(const std::string& user_agent_string,
                               base::EventDispatcher* event_dispatcher) {
  thread_.reset(new base::Thread("NetworkModule"));
#if !defined(STARBOARD)
  object_watch_multiplexer_.reset(new base::ObjectWatchMultiplexer());
#endif
  network_system_ = NetworkSystem::Create(event_dispatcher);
  http_user_agent_settings_.reset(new net::StaticHttpUserAgentSettings(
      options_.preferred_language, user_agent_string));

#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();

  if (command_line->HasSwitch(switches::kUserAgent)) {
    std::string custom_user_agent =
        command_line->GetSwitchValueASCII(switches::kUserAgent);
    http_user_agent_settings_.reset(new net::StaticHttpUserAgentSettings(
        options_.preferred_language, custom_user_agent));
  }

  if (command_line->HasSwitch(switches::kMaxNetworkDelay)) {
    base::StringToInt64(
        command_line->GetSwitchValueASCII(switches::kMaxNetworkDelay),
        &options_.max_network_delay);
  }

#if defined(ENABLE_NETWORK_LOGGING)
  if (command_line->HasSwitch(switches::kNetLog)) {
    // If this is not a valid path, net logs will be sent to VLOG(1).
    base::FilePath net_log_path =
        command_line->GetSwitchValuePath(switches::kNetLog);
    net::NetLogCaptureMode capture_mode;
    if (command_line->HasSwitch(switches::kNetLogCaptureMode)) {
      std::string capture_mode_string =
          command_line->GetSwitchValueASCII(switches::kNetLogCaptureMode);
      if (capture_mode_string == kCaptureModeIncludeCookiesAndCredentials) {
        capture_mode = net::NetLogCaptureMode::IncludeCookiesAndCredentials();
      } else if (capture_mode_string == kCaptureModeIncludeSocketBytes) {
        capture_mode = net::NetLogCaptureMode::IncludeSocketBytes();
      }
    }
    net_log_.reset(new CobaltNetLog(net_log_path, capture_mode));
  }
#endif

#endif  // ENABLE_DEBUG_COMMAND_LINE_SWITCHES

  // Launch the IO thread.
  base::Thread::Options thread_options;
  thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
  thread_options.stack_size = 256 * 1024;
  thread_options.priority = base::ThreadPriority::NORMAL;
  thread_->StartWithOptions(thread_options);

  base::WaitableEvent creation_event(
      base::WaitableEvent::ResetPolicy::MANUAL,
      base::WaitableEvent::InitialState::NOT_SIGNALED);
  // Run Network module startup on IO thread,
  // so the network delegate and URL request context are
  // constructed on that thread.
  task_runner()->PostTask(
      FROM_HERE, base::Bind(&NetworkModule::OnCreate, base::Unretained(this),
                            &creation_event));
  // Wait for OnCreate() to run, so we can be sure our members
  // have been constructed.
  creation_event.Wait();
  DCHECK(url_request_context_);
  url_request_context_getter_ = new network::URLRequestContextGetter(
      url_request_context_.get(), thread_.get());
}

void NetworkModule::OnCreate(base::WaitableEvent* creation_event) {
  DCHECK(task_runner()->BelongsToCurrentThread());

  net::NetLog* net_log = NULL;
#if defined(ENABLE_NETWORK_LOGGING)
  net_log = net_log_.get();
#endif
  url_request_context_.reset(
      new URLRequestContext(storage_manager_, options_.custom_proxy, net_log,
                            options_.ignore_certificate_errors, task_runner()));
  network_delegate_.reset(
      new NetworkDelegate(options_.cookie_policy, options_.https_requirement));
  url_request_context_->set_http_user_agent_settings(
      http_user_agent_settings_.get());
  url_request_context_->set_network_delegate(network_delegate_.get());
  cookie_jar_.reset(new CookieJarImpl(url_request_context_->cookie_store(),
                                      task_runner().get()));
#if defined(DIAL_SERVER)
  dial_service_.reset(new net::DialService());
  dial_service_proxy_ = new net::DialServiceProxy(dial_service_->AsWeakPtr());
#endif

  net_poster_.reset(new NetPoster(this));

  creation_event->Signal();
}

}  // namespace network
}  // namespace cobalt
