// 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(OS_STARBOARD)
  object_watch_multiplexer_.reset(NULL);
#endif
  network_system_.reset(NULL);
}

std::string NetworkModule::GetUserAgent() const {
  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::DisableQuic() {
  task_runner()->PostTask(
      FROM_HERE, base::Bind(&URLRequestContext::DisableQuic,
                            base::Unretained(url_request_context_.get())));
}

void NetworkModule::Initialize(const std::string& user_agent_string,
                               base::EventDispatcher* event_dispatcher) {
  thread_.reset(new base::Thread("NetworkModule"));
#if !defined(OS_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 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 priority is set to LOW (background) due to the following
  // constraints:
  // (1) Setting to high could result in an increase in unresponsiveness
  //     and input latency on single-core devices.
  // (2) Setting to normal results in choppy video playback performance
  //     on lower-end devices.
  // It was found with some testing that BACKGROUND priority gives the
  // desired performance on low-end devices without impacting the more
  // capable devices.
  thread_options.priority = base::ThreadPriority::BACKGROUND;
  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
