// Copyright 2013 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 "shell/context.h"

#include <vector>

#include "base/base_switches.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "mojo/common/trace_provider_impl.h"
#include "mojo/common/tracing_impl.h"
#include "mojo/edk/embedder/embedder.h"
#include "mojo/edk/embedder/simple_platform_support.h"
#include "mojo/public/cpp/application/application_connection.h"
#include "mojo/public/cpp/application/application_delegate.h"
#include "mojo/public/cpp/application/application_impl.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/services/tracing/public/interfaces/tracing.mojom.h"
#include "shell/application_manager/application_loader.h"
#include "shell/application_manager/application_manager.h"
#include "shell/background_application_loader.h"
#include "shell/command_line_util.h"
#include "shell/filename_util.h"
#include "shell/in_process_native_runner.h"
#include "shell/out_of_process_native_runner.h"
#include "shell/switches.h"
#include "shell/tracer.h"
#include "shell/url_response_disk_cache_loader.h"
#include "url/gurl.h"

using mojo::ServiceProvider;
using mojo::ServiceProviderPtr;

namespace shell {
namespace {

// Used to ensure we only init once.
class Setup {
 public:
  Setup() {
    mojo::embedder::Init(
        make_scoped_ptr(new mojo::embedder::SimplePlatformSupport()));
  }

  ~Setup() {}

 private:
  DISALLOW_COPY_AND_ASSIGN(Setup);
};

ApplicationManager::Options MakeApplicationManagerOptions() {
  ApplicationManager::Options options;
  options.disable_cache = base::CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kDisableCache);
  return options;
}

bool ConfigureURLMappings(const base::CommandLine& command_line,
                          Context* context) {
  URLResolver* resolver = context->url_resolver();

  // Configure the resolution of unknown mojo: URLs.
  GURL base_url;
  if (command_line.HasSwitch(switches::kOrigin))
    base_url = GURL(command_line.GetSwitchValueASCII(switches::kOrigin));
  else
    // Use the shell's file root if the base was not specified.
    base_url = context->ResolveShellFileURL("");

  if (!base_url.is_valid())
    return false;

  resolver->SetMojoBaseURL(base_url);

  // The network service must be loaded from the filesystem.
  // This mapping is done before the command line URL mapping are processed, so
  // that it can be overridden.
  resolver->AddURLMapping(
      GURL("mojo:network_service"),
      context->ResolveShellFileURL("file:network_service.mojo"));

  // Command line URL mapping.
  std::vector<URLResolver::OriginMapping> origin_mappings =
      URLResolver::GetOriginMappings(command_line.argv());
  for (const auto& origin_mapping : origin_mappings)
    resolver->AddOriginMapping(GURL(origin_mapping.origin),
                               GURL(origin_mapping.base_url));

  if (command_line.HasSwitch(switches::kURLMappings)) {
    const std::string mappings =
        command_line.GetSwitchValueASCII(switches::kURLMappings);

    base::StringPairs pairs;
    if (!base::SplitStringIntoKeyValuePairs(mappings, '=', ',', &pairs))
      return false;
    using StringPair = std::pair<std::string, std::string>;
    for (const StringPair& pair : pairs) {
      const GURL from(pair.first);
      const GURL to = context->ResolveCommandLineURL(pair.second);
      if (!from.is_valid() || !to.is_valid())
        return false;
      resolver->AddURLMapping(from, to);
    }
  }
  return true;
}

void InitContentHandlers(ApplicationManager* manager,
                         const base::CommandLine& command_line) {
  // Default content handlers.
  manager->RegisterContentHandler("application/pdf", GURL("mojo:pdf_viewer"));
  manager->RegisterContentHandler("image/png", GURL("mojo:png_viewer"));
  manager->RegisterContentHandler("text/html", GURL("mojo:html_viewer"));

  // Command-line-specified content handlers.
  std::string handlers_spec =
      command_line.GetSwitchValueASCII(switches::kContentHandlers);
  if (handlers_spec.empty())
    return;

#if defined(OS_ANDROID)
  // TODO(eseidel): On Android we pass command line arguments is via the
  // 'parameters' key on the intent, which we specify during 'am shell start'
  // via --esa, however that expects comma-separated values and says:
  //   am shell --help:
  //     [--esa <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]]
  //     (to embed a comma into a string escape it using "\,")
  // Whatever takes 'parameters' and constructs a CommandLine is failing to
  // un-escape the commas, we need to move this fix to that file.
  ReplaceSubstringsAfterOffset(&handlers_spec, 0, "\\,", ",");
#endif

  std::vector<std::string> parts;
  base::SplitString(handlers_spec, ',', &parts);
  if (parts.size() % 2 != 0) {
    LOG(ERROR) << "Invalid value for switch " << switches::kContentHandlers
               << ": must be a comma-separated list of mimetype/url pairs."
               << handlers_spec;
    return;
  }

  for (size_t i = 0; i < parts.size(); i += 2) {
    GURL url(parts[i + 1]);
    if (!url.is_valid()) {
      LOG(ERROR) << "Invalid value for switch " << switches::kContentHandlers
                 << ": '" << parts[i + 1] << "' is not a valid URL.";
      return;
    }
    // TODO(eseidel): We should also validate that the mimetype is valid
    // net/base/mime_util.h could do this, but we don't want to depend on net.
    manager->RegisterContentHandler(parts[i], url);
  }
}

void InitNativeOptions(ApplicationManager* manager,
                       const base::CommandLine& command_line) {
  std::vector<std::string> force_in_process_url_list;
  base::SplitString(command_line.GetSwitchValueASCII(switches::kForceInProcess),
                    ',', &force_in_process_url_list);
  for (const auto& force_in_process_url : force_in_process_url_list) {
    GURL gurl(force_in_process_url);
    if (!gurl.is_valid()) {
      LOG(ERROR) << "Invalid value for switch " << switches::kForceInProcess
                 << ": '" << force_in_process_url << "'is not a valid URL.";
      return;
    }

    NativeRunnerFactory::Options options;
    options.force_in_process = true;
    manager->SetNativeOptionsForURL(options, gurl);
  }
}

class TracingServiceProvider : public ServiceProvider {
 public:
  TracingServiceProvider(Tracer* tracer,
                         mojo::InterfaceRequest<ServiceProvider> request)
      : tracer_(tracer), binding_(this, request.Pass()) {}
  ~TracingServiceProvider() override {}

  void ConnectToService(const mojo::String& service_name,
                        mojo::ScopedMessagePipeHandle client_handle) override {
    if (tracer_ && service_name == tracing::TraceProvider::Name_) {
      tracer_->ConnectToProvider(
          mojo::MakeRequest<tracing::TraceProvider>(client_handle.Pass()));
    }
  }

 private:
  Tracer* tracer_;
  mojo::StrongBinding<mojo::ServiceProvider> binding_;

  DISALLOW_COPY_AND_ASSIGN(TracingServiceProvider);
};

}  // namespace

Context::Context(Tracer* tracer)
    : tracer_(tracer),
      application_manager_(MakeApplicationManagerOptions(), this) {
  DCHECK(!base::MessageLoop::current());

  // By default assume that the local apps reside alongside the shell.
  // TODO(ncbray): really, this should be passed in rather than defaulting.
  // This default makes sense for desktop but not Android.
  base::FilePath shell_dir;
  PathService::Get(base::DIR_MODULE, &shell_dir);
  SetShellFileRoot(shell_dir);

  base::FilePath cwd;
  PathService::Get(base::DIR_CURRENT, &cwd);
  SetCommandLineCWD(cwd);
}

Context::~Context() {
  DCHECK(!base::MessageLoop::current());
}

// static
void Context::EnsureEmbedderIsInitialized() {
  static base::LazyInstance<Setup>::Leaky setup = LAZY_INSTANCE_INITIALIZER;
  setup.Get();
}

void Context::SetShellFileRoot(const base::FilePath& path) {
  shell_file_root_ = AddTrailingSlashIfNeeded(FilePathToFileURL(path));
}

GURL Context::ResolveShellFileURL(const std::string& path) {
  return shell_file_root_.Resolve(path);
}

void Context::SetCommandLineCWD(const base::FilePath& path) {
  command_line_cwd_ = AddTrailingSlashIfNeeded(FilePathToFileURL(path));
}

GURL Context::ResolveCommandLineURL(const std::string& path) {
  return command_line_cwd_.Resolve(path);
}

bool Context::Init() {
  base::FilePath shell_path = base::MakeAbsoluteFilePath(
      base::CommandLine::ForCurrentProcess()->GetProgram());
  base::FilePath shell_child_path =
      shell_path.DirName().AppendASCII("mojo_shell_child");
  return InitWithPaths(shell_child_path);
}

bool Context::InitWithPaths(const base::FilePath& shell_child_path) {
  TRACE_EVENT0("mojo_shell", "Context::InitWithPaths");
  const base::CommandLine& command_line =
      *base::CommandLine::ForCurrentProcess();

  if (command_line.HasSwitch(switches::kWaitForDebugger))
    base::debug::WaitForDebugger(60, true);

  mojo_shell_child_path_ = shell_child_path;

  task_runners_.reset(
      new TaskRunners(base::MessageLoop::current()->message_loop_proxy()));

  application_manager()->SetLoaderForURL(
      make_scoped_ptr(new BackgroundApplicationLoader(
          make_scoped_ptr(
              new URLResponseDiskCacheLoader(task_runners_->blocking_pool())),
          "url_response_disk_cache", base::MessageLoop::TYPE_DEFAULT)),
      GURL("mojo:url_response_disk_cache"));

  EnsureEmbedderIsInitialized();

  // TODO(vtl): Probably these failures should be checked before |Init()|, and
  // this function simply shouldn't fail.
  if (!shell_file_root_.is_valid())
    return false;
  if (!ConfigureURLMappings(command_line, this))
    return false;

  mojo::embedder::InitIPCSupport(
      mojo::embedder::ProcessType::MASTER, task_runners_->shell_runner(), this,
      task_runners_->io_runner(), mojo::embedder::ScopedPlatformHandle());

  scoped_ptr<NativeRunnerFactory> runner_factory;
  if (command_line.HasSwitch(switches::kEnableMultiprocess))
    runner_factory.reset(new OutOfProcessNativeRunnerFactory(this));
  else
    runner_factory.reset(new InProcessNativeRunnerFactory(this));
  application_manager_.set_blocking_pool(task_runners_->blocking_pool());
  application_manager_.set_native_runner_factory(runner_factory.Pass());

  InitContentHandlers(&application_manager_, command_line);
  InitNativeOptions(&application_manager_, command_line);

  // The mojo_shell --args-for command-line switch is handled specially because
  // it can appear more than once. The base::CommandLine class collapses
  // multiple occurrences of the same switch.
  base::CommandLine* current = base::CommandLine::ForCurrentProcess();
  for (size_t i = 1; i < current->argv().size(); ++i)
    ApplyApplicationArgs(this, current->argv()[i]);

  ServiceProviderPtr tracing_services;
  ServiceProviderPtr tracing_exposed_services;
  new TracingServiceProvider(tracer_, GetProxy(&tracing_exposed_services));
  application_manager_.ConnectToApplication(
      GURL("mojo:tracing"), GURL(""), GetProxy(&tracing_services),
      tracing_exposed_services.Pass(), base::Closure());

  if (command_line.HasSwitch(switches::kTraceStartup)) {
    DCHECK(tracer_);
    tracing::TraceCollectorPtr coordinator;
    auto coordinator_request = GetProxy(&coordinator);
    tracing_services->ConnectToService(tracing::TraceCollector::Name_,
                                       coordinator_request.PassMessagePipe());
    tracer_->StartCollectingFromTracingService(coordinator.Pass());
  }

  return true;
}

void Context::Shutdown() {
  TRACE_EVENT0("mojo_shell", "Context::Shutdown");
  DCHECK_EQ(base::MessageLoop::current()->task_runner(),
            task_runners_->shell_runner());
  mojo::embedder::ShutdownIPCSupport();
  // We'll quit when we get OnShutdownComplete().
  base::MessageLoop::current()->Run();
}

GURL Context::ResolveMappings(const GURL& url) {
  return url_resolver_.ApplyMappings(url);
}

GURL Context::ResolveMojoURL(const GURL& url) {
  return url_resolver_.ResolveMojoURL(url);
}

void Context::OnShutdownComplete() {
  DCHECK_EQ(base::MessageLoop::current()->task_runner(),
            task_runners_->shell_runner());
  base::MessageLoop::current()->Quit();
}

void Context::OnSlaveDisconnect(mojo::embedder::SlaveInfo slave_info) {
  // TODO(vtl): Do something, once we actually have |slave_info|.
}

void Context::Run(const GURL& url) {
  ServiceProviderPtr services;
  ServiceProviderPtr exposed_services;

  app_urls_.insert(url);
  application_manager_.ConnectToApplication(
      url, GURL(), mojo::GetProxy(&services), exposed_services.Pass(),
      base::Bind(&Context::OnApplicationEnd, base::Unretained(this), url));
}

void Context::OnApplicationEnd(const GURL& url) {
  if (app_urls_.find(url) != app_urls_.end()) {
    app_urls_.erase(url);
    if (app_urls_.empty() && base::MessageLoop::current()->is_running()) {
      DCHECK_EQ(base::MessageLoop::current()->task_runner(),
                task_runners_->shell_runner());
      base::MessageLoop::current()->Quit();
    }
  }
}

}  // namespace shell
