// Copyright 2014 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/application_manager/application_manager.h"

#include "base/bind.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/string_util.h"
#include "base/trace_event/trace_event.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/services/authenticating_url_loader_interceptor/public/interfaces/authenticating_url_loader_interceptor_meta_factory.mojom.h"
#include "mojo/services/authentication/public/interfaces/authentication.mojom.h"
#include "mojo/services/content_handler/public/interfaces/content_handler.mojom.h"
#include "shell/application_manager/fetcher.h"
#include "shell/application_manager/local_fetcher.h"
#include "shell/application_manager/network_fetcher.h"
#include "shell/application_manager/query_util.h"
#include "shell/application_manager/shell_impl.h"

using mojo::Application;
using mojo::ApplicationPtr;
using mojo::InterfaceRequest;
using mojo::ServiceProvider;
using mojo::ServiceProviderPtr;

namespace shell {

namespace {

// Used by TestAPI.
bool has_created_instance = false;

std::vector<std::string> Concatenate(const std::vector<std::string>& v1,
                                     const std::vector<std::string>& v2) {
  if (!v1.size())
    return v2;
  if (!v2.size())
    return v1;
  std::vector<std::string> result(v1);
  result.insert(result.end(), v1.begin(), v1.end());
  return result;
}

}  // namespace

class ApplicationManager::ContentHandlerConnection {
 public:
  ContentHandlerConnection(ApplicationManager* manager,
                           const GURL& content_handler_url)
      : manager_(manager), content_handler_url_(content_handler_url) {
    ServiceProviderPtr services;
    manager->ConnectToApplication(content_handler_url, GURL(),
                                  mojo::GetProxy(&services), nullptr,
                                  base::Closure());
    mojo::MessagePipe pipe;
    content_handler_.Bind(
        mojo::InterfacePtrInfo<mojo::ContentHandler>(pipe.handle0.Pass(), 0u));
    services->ConnectToService(mojo::ContentHandler::Name_,
                               pipe.handle1.Pass());
    content_handler_.set_connection_error_handler(
        [this]() { manager_->OnContentHandlerError(this); });
  }
  ~ContentHandlerConnection() {}

  mojo::ContentHandler* content_handler() { return content_handler_.get(); }

  GURL content_handler_url() { return content_handler_url_; }

 private:
  ApplicationManager* manager_;
  GURL content_handler_url_;
  mojo::ContentHandlerPtr content_handler_;

  DISALLOW_COPY_AND_ASSIGN(ContentHandlerConnection);
};

// static
ApplicationManager::TestAPI::TestAPI(ApplicationManager* manager)
    : manager_(manager) {
}

ApplicationManager::TestAPI::~TestAPI() {
}

bool ApplicationManager::TestAPI::HasCreatedInstance() {
  return has_created_instance;
}

bool ApplicationManager::TestAPI::HasFactoryForURL(const GURL& url) const {
  return manager_->identity_to_shell_impl_.find(Identity(url)) !=
         manager_->identity_to_shell_impl_.end();
}

ApplicationManager::ApplicationManager(const Options& options,
                                       Delegate* delegate)
    : options_(options),
      delegate_(delegate),
      blocking_pool_(nullptr),
      initialized_authentication_interceptor_(false),
      weak_ptr_factory_(this) {
}

ApplicationManager::~ApplicationManager() {
}

void ApplicationManager::TerminateShellConnections() {
  identity_to_shell_impl_.clear();
}

void ApplicationManager::ConnectToApplication(
    const GURL& requested_url,
    const GURL& requestor_url,
    InterfaceRequest<ServiceProvider> services,
    ServiceProviderPtr exposed_services,
    const base::Closure& on_application_end) {
  ConnectToApplicationWithParameters(
      requested_url, requestor_url, services.Pass(), exposed_services.Pass(),
      on_application_end, std::vector<std::string>());
}

void ApplicationManager::ConnectToApplicationWithParameters(
    const GURL& requested_url,
    const GURL& requestor_url,
    InterfaceRequest<ServiceProvider> services,
    ServiceProviderPtr exposed_services,
    const base::Closure& on_application_end,
    const std::vector<std::string>& pre_redirect_parameters) {
  TRACE_EVENT_INSTANT2(
      "mojo_shell", "ApplicationManager::ConnectToApplicationWithParameters",
      TRACE_EVENT_SCOPE_THREAD, "requested_url", requested_url.spec(),
      "requestor_url", requestor_url.spec());
  DCHECK(requested_url.is_valid());

  // We check both the mapped and resolved urls for existing shell_impls because
  // external applications can be registered for the unresolved mojo:foo urls.

  GURL mapped_url = delegate_->ResolveMappings(requested_url);
  if (ConnectToRunningApplication(mapped_url, requestor_url, &services,
                                  &exposed_services)) {
    return;
  }

  GURL resolved_url = delegate_->ResolveMojoURL(mapped_url);
  if (ConnectToRunningApplication(resolved_url, requestor_url, &services,
                                  &exposed_services)) {
    return;
  }

  // The application is not running, let's compute the parameters.
  std::vector<std::string> parameters =
      Concatenate(pre_redirect_parameters, GetArgsForURL(resolved_url));

  if (ConnectToApplicationWithLoader(mapped_url, requestor_url, &services,
                                     &exposed_services, on_application_end,
                                     parameters, GetLoaderForURL(mapped_url))) {
    return;
  }

  if (ConnectToApplicationWithLoader(
          resolved_url, requestor_url, &services, &exposed_services,
          on_application_end, parameters, GetLoaderForURL(resolved_url))) {
    return;
  }

  if (ConnectToApplicationWithLoader(resolved_url, requestor_url, &services,
                                     &exposed_services, on_application_end,
                                     parameters, default_loader_.get())) {
    return;
  }

  auto callback = base::Bind(
      &ApplicationManager::HandleFetchCallback, weak_ptr_factory_.GetWeakPtr(),
      requestor_url, base::Passed(services.Pass()),
      base::Passed(exposed_services.Pass()), on_application_end, parameters);

  if (resolved_url.SchemeIsFile()) {
    new LocalFetcher(resolved_url, GetBaseURLAndQuery(resolved_url, nullptr),
                     callback);
    return;
  }

  if (!url_response_disk_cache_) {
    ConnectToService(GURL("mojo:url_response_disk_cache"),
                     &url_response_disk_cache_);
    ConnectToService(GURL("mojo:network_service"), &network_service_);
    ConnectToService(GURL("mojo:network_service"),
                     &authenticating_network_service_);
  }

  mojo::NetworkService* network_service = authenticating_network_service_.get();

  // NOTE: Attempting to initialize the apps used authentication for while
  // connecting to those apps would result in a recursive loop, so it has to be
  // explicitly avoided here. What this means in practice is that these apps
  // cannot themselves require authentication to obtain.
  if (EndsWith(resolved_url.path(), "/authentication.mojo", true) ||
      EndsWith(resolved_url.path(),
               "/authenticating_url_loader_interceptor.mojo", true)) {
    network_service = network_service_.get();
  } else if (!initialized_authentication_interceptor_) {
    authentication::AuthenticationServicePtr authentication_service;
    ConnectToService(GURL("mojo:authentication"), &authentication_service);
    mojo::AuthenticatingURLLoaderInterceptorMetaFactoryPtr
        interceptor_meta_factory;
    ConnectToService(GURL("mojo:authenticating_url_loader_interceptor"),
                     &interceptor_meta_factory);
    mojo::URLLoaderInterceptorFactoryPtr interceptor_factory;
    interceptor_meta_factory->CreateURLLoaderInterceptorFactory(
        GetProxy(&interceptor_factory), authentication_service.Pass());
    authenticating_network_service_->RegisterURLLoaderInterceptor(
        interceptor_factory.Pass());
    initialized_authentication_interceptor_ = true;
  }

  new NetworkFetcher(options_.disable_cache, options_.force_offline_by_default,
                     resolved_url, url_response_disk_cache_.get(),
                     network_service, callback);
}

bool ApplicationManager::ConnectToRunningApplication(
    const GURL& resolved_url,
    const GURL& requestor_url,
    InterfaceRequest<ServiceProvider>* services,
    ServiceProviderPtr* exposed_services) {
  GURL application_url = GetBaseURLAndQuery(resolved_url, nullptr);
  ShellImpl* shell_impl = GetShellImpl(application_url);
  if (!shell_impl)
    return false;

  ConnectToClient(shell_impl, resolved_url, requestor_url, services->Pass(),
                  exposed_services->Pass());
  return true;
}

bool ApplicationManager::ConnectToApplicationWithLoader(
    const GURL& resolved_url,
    const GURL& requestor_url,
    InterfaceRequest<ServiceProvider>* services,
    ServiceProviderPtr* exposed_services,
    const base::Closure& on_application_end,
    const std::vector<std::string>& parameters,
    ApplicationLoader* loader) {
  if (!loader)
    return false;

  loader->Load(
      resolved_url,
      RegisterShell(resolved_url, requestor_url, services->Pass(),
                    exposed_services->Pass(), on_application_end, parameters));
  return true;
}

InterfaceRequest<Application> ApplicationManager::RegisterShell(
    const GURL& resolved_url,
    const GURL& requestor_url,
    InterfaceRequest<ServiceProvider> services,
    ServiceProviderPtr exposed_services,
    const base::Closure& on_application_end,
    const std::vector<std::string>& parameters) {
  Identity app_identity(resolved_url);

  mojo::ApplicationPtr application;
  InterfaceRequest<Application> application_request =
      mojo::GetProxy(&application);
  ShellImpl* shell =
      new ShellImpl(application.Pass(), this, app_identity, on_application_end);
  identity_to_shell_impl_[app_identity] = make_scoped_ptr(shell);
  shell->InitializeApplication(mojo::Array<mojo::String>::From(parameters));
  ConnectToClient(shell, resolved_url, requestor_url, services.Pass(),
                  exposed_services.Pass());
  return application_request.Pass();
}

ShellImpl* ApplicationManager::GetShellImpl(const GURL& url) {
  const auto& shell_it = identity_to_shell_impl_.find(Identity(url));
  if (shell_it != identity_to_shell_impl_.end())
    return shell_it->second.get();
  return nullptr;
}

void ApplicationManager::ConnectToClient(
    ShellImpl* shell_impl,
    const GURL& resolved_url,
    const GURL& requestor_url,
    InterfaceRequest<ServiceProvider> services,
    ServiceProviderPtr exposed_services) {
  shell_impl->ConnectToClient(resolved_url, requestor_url, services.Pass(),
                              exposed_services.Pass());
}

void ApplicationManager::HandleFetchCallback(
    const GURL& requestor_url,
    InterfaceRequest<ServiceProvider> services,
    ServiceProviderPtr exposed_services,
    const base::Closure& on_application_end,
    const std::vector<std::string>& parameters,
    scoped_ptr<Fetcher> fetcher) {
  if (!fetcher) {
    // Network error. Drop |application_request| to tell requestor.
    return;
  }

  GURL redirect_url = fetcher->GetRedirectURL();
  if (!redirect_url.is_empty()) {
    // And around we go again... Whee!
    ConnectToApplicationWithParameters(redirect_url, requestor_url,
                                       services.Pass(), exposed_services.Pass(),
                                       on_application_end, parameters);
    return;
  }

  // We already checked if the application was running before we fetched it, but
  // it might have started while the fetch was outstanding. We don't want to
  // have two copies of the app running, so check again.
  //
  // Also, it's possible the original URL was redirected to an app that is
  // already running.
  if (ConnectToRunningApplication(fetcher->GetURL(), requestor_url, &services,
                                  &exposed_services)) {
    return;
  }

  InterfaceRequest<Application> request(
      RegisterShell(fetcher->GetURL(), requestor_url, services.Pass(),
                    exposed_services.Pass(), on_application_end, parameters));

  // If the response begins with a #!mojo <content-handler-url>, use it.
  GURL content_handler_url;
  std::string shebang;
  if (fetcher->PeekContentHandler(&shebang, &content_handler_url)) {
    LoadWithContentHandler(
        content_handler_url, request.Pass(),
        fetcher->AsURLResponse(blocking_pool_,
                               static_cast<int>(shebang.size())));
    return;
  }

  auto it = mime_type_to_url_.find(fetcher->MimeType());
  if (it != mime_type_to_url_.end()) {
    LoadWithContentHandler(it->second, request.Pass(),
                           fetcher->AsURLResponse(blocking_pool_, 0));
    return;
  }

  // TODO(aa): Sanity check that the thing we got looks vaguely like a mojo
  // application. That could either mean looking for the platform-specific dll
  // header, or looking for some specific mojo signature prepended to the
  // library.
  // TODO(vtl): (Maybe this should be done by the factory/runner?)

  GURL base_resolved_url = GetBaseURLAndQuery(fetcher->GetURL(), nullptr);
  NativeRunnerFactory::Options options;
  if (url_to_native_options_.find(base_resolved_url) !=
      url_to_native_options_.end()) {
    DVLOG(2) << "Applying stored native options to resolved URL "
             << fetcher->GetURL();
    options = url_to_native_options_[base_resolved_url];
  }

  TRACE_EVENT_ASYNC_BEGIN1("mojo_shell", "ApplicationManager::RetrievePath",
                           fetcher.get(), "url", fetcher->GetURL().spec());
  fetcher->AsPath(
      blocking_pool_,
      base::Bind(&ApplicationManager::RunNativeApplication,
                 weak_ptr_factory_.GetWeakPtr(), base::Passed(request.Pass()),
                 options, base::Passed(fetcher.Pass())));
}

void ApplicationManager::RunNativeApplication(
    InterfaceRequest<Application> application_request,
    const NativeRunnerFactory::Options& options,
    scoped_ptr<Fetcher> fetcher,
    const base::FilePath& path,
    bool path_exists) {
  TRACE_EVENT_ASYNC_END0("mojo_shell", "ApplicationManager::RetrievePath",
                         fetcher.get());
  // We only passed fetcher to keep it alive. Done with it now.
  fetcher.reset();

  DCHECK(application_request.is_pending());

  if (!path_exists) {
    LOG(ERROR) << "Library not started because library path '" << path.value()
               << "' does not exist.";
    return;
  }

  TRACE_EVENT1("mojo_shell", "ApplicationManager::RunNativeApplication", "path",
               path.AsUTF8Unsafe());
  NativeRunner* runner = native_runner_factory_->Create(options).release();
  native_runners_.push_back(runner);
  runner->Start(path, application_request.Pass(),
                base::Bind(&ApplicationManager::CleanupRunner,
                           weak_ptr_factory_.GetWeakPtr(), runner));
}

void ApplicationManager::RegisterContentHandler(
    const std::string& mime_type,
    const GURL& content_handler_url) {
  DCHECK(content_handler_url.is_valid())
      << "Content handler URL is invalid for mime type " << mime_type;
  mime_type_to_url_[mime_type] = content_handler_url;
}

void ApplicationManager::LoadWithContentHandler(
    const GURL& content_handler_url,
    InterfaceRequest<Application> application_request,
    mojo::URLResponsePtr url_response) {
  ContentHandlerConnection* connection = nullptr;
  auto it = url_to_content_handler_.find(content_handler_url);
  if (it != url_to_content_handler_.end()) {
    connection = it->second.get();
  } else {
    connection = new ContentHandlerConnection(this, content_handler_url);
    url_to_content_handler_[content_handler_url] = make_scoped_ptr(connection);
  }

  connection->content_handler()->StartApplication(application_request.Pass(),
                                                  url_response.Pass());
}

void ApplicationManager::SetLoaderForURL(scoped_ptr<ApplicationLoader> loader,
                                         const GURL& url) {
  url_to_loader_[url] = loader.Pass();
}

void ApplicationManager::SetLoaderForScheme(
    scoped_ptr<ApplicationLoader> loader,
    const std::string& scheme) {
  scheme_to_loader_[scheme] = loader.Pass();
}

void ApplicationManager::SetArgsForURL(const std::vector<std::string>& args,
                                       const GURL& url) {
  url_to_args_[url].insert(url_to_args_[url].end(), args.begin(), args.end());
  GURL mapped_url = delegate_->ResolveMappings(url);
  if (mapped_url != url) {
    url_to_args_[mapped_url].insert(url_to_args_[mapped_url].end(),
                                    args.begin(), args.end());
  }
  GURL resolved_url = delegate_->ResolveMojoURL(mapped_url);
  if (resolved_url != mapped_url) {
    url_to_args_[resolved_url].insert(url_to_args_[resolved_url].end(),
                                      args.begin(), args.end());
  }
}

void ApplicationManager::SetNativeOptionsForURL(
    const NativeRunnerFactory::Options& options,
    const GURL& url) {
  DCHECK(!url.has_query());  // Precondition.
  // Apply mappings and resolution to get the resolved URL.
  GURL resolved_url =
      delegate_->ResolveMojoURL(delegate_->ResolveMappings(url));
  DCHECK(!resolved_url.has_query());  // Still shouldn't have query.
  // TODO(vtl): We should probably also remove/disregard the query string (and
  // maybe canonicalize in other ways).
  DVLOG(2) << "Storing native options for resolved URL " << resolved_url
           << " (original URL " << url << ")";
  url_to_native_options_[resolved_url] = options;
}

ApplicationLoader* ApplicationManager::GetLoaderForURL(const GURL& url) {
  auto url_it = url_to_loader_.find(GetBaseURLAndQuery(url, nullptr));
  if (url_it != url_to_loader_.end())
    return url_it->second.get();
  auto scheme_it = scheme_to_loader_.find(url.scheme());
  if (scheme_it != scheme_to_loader_.end())
    return scheme_it->second.get();
  return nullptr;
}

void ApplicationManager::OnShellImplError(ShellImpl* shell_impl) {
  // Called from ~ShellImpl, so we do not need to call Destroy here.
  const Identity identity = shell_impl->identity();
  base::Closure on_application_end = shell_impl->on_application_end();
  // Remove the shell.
  auto it = identity_to_shell_impl_.find(identity);
  DCHECK(it != identity_to_shell_impl_.end());
  identity_to_shell_impl_.erase(it);
  if (!on_application_end.is_null())
    on_application_end.Run();
}

void ApplicationManager::OnContentHandlerError(
    ContentHandlerConnection* content_handler) {
  // Remove the mapping to the content handler.
  auto it =
      url_to_content_handler_.find(content_handler->content_handler_url());
  DCHECK(it != url_to_content_handler_.end());
  url_to_content_handler_.erase(it);
}

mojo::ScopedMessagePipeHandle ApplicationManager::ConnectToServiceByName(
    const GURL& application_url,
    const std::string& interface_name) {
  ServiceProviderPtr services;
  ConnectToApplication(application_url, GURL(), mojo::GetProxy(&services),
                       nullptr, base::Closure());
  mojo::MessagePipe pipe;
  services->ConnectToService(interface_name, pipe.handle1.Pass());
  return pipe.handle0.Pass();
}

std::vector<std::string> ApplicationManager::GetArgsForURL(const GURL& url) {
  const auto& args_it = url_to_args_.find(url);
  if (args_it != url_to_args_.end())
    return args_it->second;
  return std::vector<std::string>();
}

void ApplicationManager::CleanupRunner(NativeRunner* runner) {
  native_runners_.erase(
      std::find(native_runners_.begin(), native_runners_.end(), runner));
}

}  // namespace shell
