// 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/dynamic_application_loader.h"

#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/format_macros.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "mojo/common/common_type_converters.h"
#include "mojo/common/data_pipe_utils.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "mojo/services/network/public/interfaces/url_loader.mojom.h"
#include "shell/context.h"
#include "shell/data_pipe_peek.h"
#include "shell/filename_util.h"
#include "shell/switches.h"
#include "url/url_util.h"

namespace mojo {
namespace shell {

namespace {

static const char kMojoMagic[] = "#!mojo:";
static const size_t kMaxShebangLength = 2048;

void IgnoreResult(bool result) {
}

}  // namespace

// Encapsulates loading and running one individual application.
//
// Loaders are owned by DynamicApplicationLoader. DynamicApplicationLoader must
// ensure that all the parameters passed to Loader subclasses stay valid through
// Loader's lifetime.
//
// Async operations are done with WeakPtr to protect against
// DynamicApplicationLoader going away (and taking all the Loaders with it)
// while the async operation is outstanding.
class DynamicApplicationLoader::Loader {
 public:
  Loader(MimeTypeToURLMap* mime_type_to_url,
         Context* context,
         DynamicServiceRunnerFactory* runner_factory,
         ScopedMessagePipeHandle shell_handle,
         ApplicationLoader::LoadCallback load_callback,
         const LoaderCompleteCallback& loader_complete_callback)
      : shell_handle_(shell_handle.Pass()),
        load_callback_(load_callback),
        loader_complete_callback_(loader_complete_callback),
        context_(context),
        mime_type_to_url_(mime_type_to_url),
        runner_factory_(runner_factory),
        weak_ptr_factory_(this) {}

  virtual ~Loader() {}

 protected:
  virtual URLResponsePtr AsURLResponse(base::TaskRunner* task_runner,
                                       uint32_t skip) = 0;

  virtual void AsPath(
      base::TaskRunner* task_runner,
      base::Callback<void(const base::FilePath&, bool)> callback) = 0;

  virtual std::string MimeType() = 0;

  virtual bool HasMojoMagic() = 0;

  virtual bool PeekFirstLine(std::string* line) = 0;

  void Load() {
    // If the response begins with a #!mojo:<content-handler-url>, use it.
    GURL url;
    std::string shebang;
    if (PeekContentHandler(&shebang, &url)) {
      load_callback_.Run(
          url, shell_handle_.Pass(),
          AsURLResponse(context_->task_runners()->blocking_pool(),
                        static_cast<int>(shebang.size())));
      return;
    }

    MimeTypeToURLMap::iterator iter = mime_type_to_url_->find(MimeType());
    if (iter != mime_type_to_url_->end()) {
      load_callback_.Run(
          iter->second, shell_handle_.Pass(),
          AsURLResponse(context_->task_runners()->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.

    AsPath(context_->task_runners()->blocking_pool(),
           base::Bind(&Loader::RunLibrary, weak_ptr_factory_.GetWeakPtr()));
  }

  void ReportComplete() { loader_complete_callback_.Run(this); }

 private:
  bool PeekContentHandler(std::string* mojo_shebang,
                          GURL* mojo_content_handler_url) {
    std::string shebang;
    if (HasMojoMagic() && PeekFirstLine(&shebang)) {
      GURL url(shebang.substr(2, std::string::npos));
      if (url.is_valid()) {
        *mojo_shebang = shebang;
        *mojo_content_handler_url = url;
        return true;
      }
    }
    return false;
  }

  void RunLibrary(const base::FilePath& path, bool path_exists) {
    DCHECK(shell_handle_.is_valid());

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

    runner_ = runner_factory_->Create(context_);
    runner_->Start(
        path, shell_handle_.Pass(),
        base::Bind(&Loader::ReportComplete, weak_ptr_factory_.GetWeakPtr()));
  }

  ScopedMessagePipeHandle shell_handle_;
  ApplicationLoader::LoadCallback load_callback_;
  LoaderCompleteCallback loader_complete_callback_;
  Context* context_;
  MimeTypeToURLMap* mime_type_to_url_;
  DynamicServiceRunnerFactory* runner_factory_;
  scoped_ptr<DynamicServiceRunner> runner_;
  base::WeakPtrFactory<Loader> weak_ptr_factory_;
};

// A loader for local files.
class DynamicApplicationLoader::LocalLoader : public Loader {
 public:
  LocalLoader(const GURL& url,
              MimeTypeToURLMap* mime_type_to_url,
              Context* context,
              DynamicServiceRunnerFactory* runner_factory,
              ScopedMessagePipeHandle shell_handle,
              ApplicationLoader::LoadCallback load_callback,
              const LoaderCompleteCallback& loader_complete_callback)
      : Loader(mime_type_to_url,
               context,
               runner_factory,
               shell_handle.Pass(),
               load_callback,
               loader_complete_callback),
        url_(url),
        path_(UrlToFile(url)) {
    Load();
  }

 private:
  static base::FilePath UrlToFile(const GURL& url) {
    DCHECK(url.SchemeIsFile());
    url::RawCanonOutputW<1024> output;
    url::DecodeURLEscapeSequences(
        url.path().data(), static_cast<int>(url.path().length()), &output);
    base::string16 decoded_path =
        base::string16(output.data(), output.length());
#if defined(OS_WIN)
    base::TrimString(decoded_path, L"/", &decoded_path);
    base::FilePath path(decoded_path);
#else
    base::FilePath path(base::UTF16ToUTF8(decoded_path));
#endif
    return path;
  }

  URLResponsePtr AsURLResponse(base::TaskRunner* task_runner,
                               uint32_t skip) override {
    URLResponsePtr response(URLResponse::New());
    response->url = String::From(url_);
    DataPipe data_pipe;
    response->body = data_pipe.consumer_handle.Pass();
    int64 file_size;
    if (base::GetFileSize(path_, &file_size)) {
      response->headers = Array<String>(1);
      response->headers[0] =
          base::StringPrintf("Content-Length: %" PRId64, file_size);
    }
    common::CopyFromFile(path_, data_pipe.producer_handle.Pass(), skip,
                         task_runner, base::Bind(&IgnoreResult));
    return response.Pass();
  }

  void AsPath(
      base::TaskRunner* task_runner,
      base::Callback<void(const base::FilePath&, bool)> callback) override {
    // Async for consistency with network case.
    base::MessageLoop::current()->PostTask(
        FROM_HERE, base::Bind(callback, path_, base::PathExists(path_)));
  }

  std::string MimeType() override { return ""; }

  bool HasMojoMagic() override {
    std::string magic;
    ReadFileToString(path_, &magic, strlen(kMojoMagic));
    return magic == kMojoMagic;
  }

  bool PeekFirstLine(std::string* line) override {
    std::string start_of_file;
    ReadFileToString(path_, &start_of_file, kMaxShebangLength);
    size_t return_position = start_of_file.find('\n');
    if (return_position == std::string::npos)
      return false;
    *line = start_of_file.substr(0, return_position + 1);
    return true;
  }

  GURL url_;
  base::FilePath path_;

  DISALLOW_COPY_AND_ASSIGN(LocalLoader);
};

// A loader for network files.
class DynamicApplicationLoader::NetworkLoader : public Loader {
 public:
  NetworkLoader(const GURL& url,
                NetworkService* network_service,
                MimeTypeToURLMap* mime_type_to_url,
                Context* context,
                DynamicServiceRunnerFactory* runner_factory,
                ScopedMessagePipeHandle shell_handle,
                ApplicationLoader::LoadCallback load_callback,
                const LoaderCompleteCallback& loader_complete_callback)
      : Loader(mime_type_to_url,
               context,
               runner_factory,
               shell_handle.Pass(),
               load_callback,
               loader_complete_callback),
        weak_ptr_factory_(this) {
    StartNetworkRequest(url, network_service);
  }

  ~NetworkLoader() override {
    if (!path_.empty())
      base::DeleteFile(path_, false);
  }

 private:
  // TODO(hansmuller): Revisit this when a real peek operation is available.
  static const MojoDeadline kPeekTimeout = MOJO_DEADLINE_INDEFINITE;

  URLResponsePtr AsURLResponse(base::TaskRunner* task_runner,
                               uint32_t skip) override {
    if (skip != 0) {
      MojoResult result = ReadDataRaw(
          response_->body.get(), nullptr, &skip,
          MOJO_READ_DATA_FLAG_ALL_OR_NONE | MOJO_READ_DATA_FLAG_DISCARD);
      DCHECK_EQ(result, MOJO_RESULT_OK);
    }
    return response_.Pass();
  }

  void AsPath(
      base::TaskRunner* task_runner,
      base::Callback<void(const base::FilePath&, bool)> callback) override {
    if (!path_.empty() || !response_) {
      base::MessageLoop::current()->PostTask(
          FROM_HERE, base::Bind(callback, path_, base::PathExists(path_)));
      return;
    }
    base::CreateTemporaryFile(&path_);
    common::CopyToFile(response_->body.Pass(), path_, task_runner,
                       base::Bind(callback, path_));
  }

  std::string MimeType() override {
    DCHECK(response_);
    return response_->mime_type;
  }

  bool HasMojoMagic() override {
    std::string magic;
    return BlockingPeekNBytes(response_->body.get(), &magic, strlen(kMojoMagic),
                              kPeekTimeout) &&
           magic == kMojoMagic;
  }

  bool PeekFirstLine(std::string* line) override {
    return BlockingPeekLine(response_->body.get(), line, kMaxShebangLength,
                            kPeekTimeout);
  }

  void StartNetworkRequest(const GURL& url, NetworkService* network_service) {
    URLRequestPtr request(URLRequest::New());
    request->url = String::From(url);
    request->auto_follow_redirects = true;

    if (base::CommandLine::ForCurrentProcess()->HasSwitch(
            switches::kDisableCache)) {
      request->bypass_cache = true;
    }

    network_service->CreateURLLoader(GetProxy(&url_loader_));
    url_loader_->Start(request.Pass(),
                       base::Bind(&NetworkLoader::OnLoadComplete,
                                  weak_ptr_factory_.GetWeakPtr()));
  }

  void OnLoadComplete(URLResponsePtr response) {
    if (response->error) {
      LOG(ERROR) << "Error (" << response->error->code << ": "
                 << response->error->description << ") while fetching "
                 << response->url;
      ReportComplete();
      return;
    }
    response_ = response.Pass();
    Load();
  }

  URLLoaderPtr url_loader_;
  URLResponsePtr response_;
  base::FilePath path_;
  base::WeakPtrFactory<NetworkLoader> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(NetworkLoader);
};

DynamicApplicationLoader::DynamicApplicationLoader(
    Context* context,
    scoped_ptr<DynamicServiceRunnerFactory> runner_factory)
    : context_(context),
      runner_factory_(runner_factory.Pass()),

      // Unretained() is correct here because DynamicApplicationLoader owns the
      // loaders that we pass this callback to.
      loader_complete_callback_(
          base::Bind(&DynamicApplicationLoader::LoaderComplete,
                     base::Unretained(this))) {
}

DynamicApplicationLoader::~DynamicApplicationLoader() {
}

void DynamicApplicationLoader::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 DynamicApplicationLoader::Load(ApplicationManager* manager,
                                    const GURL& url,
                                    ScopedMessagePipeHandle shell_handle,
                                    LoadCallback load_callback) {
  if (url.SchemeIsFile()) {
    loaders_.push_back(new LocalLoader(
        url, &mime_type_to_url_, context_, runner_factory_.get(),
        shell_handle.Pass(), load_callback, loader_complete_callback_));
    return;
  }

  if (!network_service_) {
    context_->application_manager()->ConnectToService(
        GURL("mojo:network_service"), &network_service_);
  }

  loaders_.push_back(
      new NetworkLoader(url, network_service_.get(), &mime_type_to_url_,
                        context_, runner_factory_.get(), shell_handle.Pass(),
                        load_callback, loader_complete_callback_));
}

void DynamicApplicationLoader::OnApplicationError(ApplicationManager* manager,
                                                  const GURL& url) {
  // TODO(darin): What should we do about service errors? This implies that
  // the app closed its handle to the service manager. Maybe we don't care?
}

void DynamicApplicationLoader::LoaderComplete(Loader* loader) {
  loaders_.erase(std::find(loaders_.begin(), loaders_.end(), loader));
}

}  // namespace shell
}  // namespace mojo
