// Copyright 2013 The Flutter 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 "component.h"

#include <dlfcn.h>
#include <fuchsia/mem/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/namespace.h>
#include <lib/ui/scenic/cpp/view_ref_pair.h>
#include <lib/ui/scenic/cpp/view_token_pair.h>
#include <lib/vfs/cpp/composed_service_dir.h>
#include <lib/vfs/cpp/remote_dir.h>
#include <lib/vfs/cpp/service.h>
#include <sys/stat.h>
#include <zircon/dlfcn.h>
#include <zircon/status.h>
#include <zircon/types.h>
#include <memory>
#include <regex>
#include <sstream>

#include "flutter/fml/mapping.h"
#include "flutter/fml/synchronization/waitable_event.h"
#include "flutter/fml/unique_fd.h"
#include "flutter/runtime/dart_vm_lifecycle.h"
#include "flutter/shell/common/switches.h"
#include "lib/fdio/io.h"
#include "runtime/dart/utils/files.h"
#include "runtime/dart/utils/handle_exception.h"
#include "runtime/dart/utils/mapped_resource.h"
#include "runtime/dart/utils/tempfs.h"
#include "runtime/dart/utils/vmo.h"

#include "flutter_runner_product_configuration.h"
#include "task_observers.h"
#include "task_runner_adapter.h"
#include "thread.h"

// TODO(kaushikiska): Use these constants from ::llcpp::fuchsia::io
// Can read from target object.
constexpr uint32_t OPEN_RIGHT_READABLE = 1u;

// Connection can map target object executable.
constexpr uint32_t OPEN_RIGHT_EXECUTABLE = 8u;

namespace flutter_runner {

constexpr char kDataKey[] = "data";
constexpr char kTmpPath[] = "/tmp";
constexpr char kServiceRootPath[] = "/svc";

ActiveApplication Application::Create(
    TerminationCallback termination_callback,
    fuchsia::sys::Package package,
    fuchsia::sys::StartupInfo startup_info,
    std::shared_ptr<sys::ServiceDirectory> runner_incoming_services,
    fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller) {
  std::unique_ptr<Thread> thread = std::make_unique<Thread>();
  std::unique_ptr<Application> application;

  fml::AutoResetWaitableEvent latch;
  async::PostTask(thread->dispatcher(), [&]() mutable {
    application.reset(
        new Application(std::move(termination_callback), std::move(package),
                        std::move(startup_info), runner_incoming_services,
                        std::move(controller)));
    latch.Signal();
  });

  latch.Wait();
  return {.thread = std::move(thread), .application = std::move(application)};
}

static std::string DebugLabelForURL(const std::string& url) {
  auto found = url.rfind("/");
  if (found == std::string::npos) {
    return url;
  } else {
    return {url, found + 1};
  }
}

static std::unique_ptr<fml::FileMapping> MakeFileMapping(const char* path,
                                                         bool executable) {
  uint32_t flags = OPEN_RIGHT_READABLE;
  if (executable) {
    flags |= OPEN_RIGHT_EXECUTABLE;
  }

  int fd = 0;
  // The returned file descriptor is compatible with standard posix operations
  // such as close, mmap, etc. We only need to treat open/open_at specially.
  zx_status_t status = fdio_open_fd(path, flags, &fd);

  if (status != ZX_OK) {
    return nullptr;
  }

  using Protection = fml::FileMapping::Protection;

  std::initializer_list<Protection> protection_execute = {Protection::kRead,
                                                          Protection::kExecute};
  std::initializer_list<Protection> protection_read = {Protection::kRead};
  auto mapping = std::make_unique<fml::FileMapping>(
      fml::UniqueFD{fd}, executable ? protection_execute : protection_read);

  if (!mapping->IsValid()) {
    return nullptr;
  }

  return mapping;
}

// Defaults to readonly. If executable is `true`, we treat it as `read + exec`.
static flutter::MappingCallback MakeDataFileMapping(const char* absolute_path,
                                                    bool executable = false) {
  return [absolute_path, executable = executable](void) {
    return MakeFileMapping(absolute_path, executable);
  };
}

Application::Application(
    TerminationCallback termination_callback,
    fuchsia::sys::Package package,
    fuchsia::sys::StartupInfo startup_info,
    std::shared_ptr<sys::ServiceDirectory> runner_incoming_services,
    fidl::InterfaceRequest<fuchsia::sys::ComponentController>
        application_controller_request)
    : termination_callback_(std::move(termination_callback)),
      debug_label_(DebugLabelForURL(startup_info.launch_info.url)),
      application_controller_(this),
      outgoing_dir_(new vfs::PseudoDir()),
      runner_incoming_services_(runner_incoming_services),
      weak_factory_(this) {
  application_controller_.set_error_handler(
      [this](zx_status_t status) { Kill(); });

  FML_DCHECK(fdio_ns_.is_valid());
  // LaunchInfo::url non-optional.
  auto& launch_info = startup_info.launch_info;

  // LaunchInfo::arguments optional.
  if (auto& arguments = launch_info.arguments) {
    settings_.dart_entrypoint_args = arguments.value();
  }

  // Determine /pkg/data directory from StartupInfo.
  std::string data_path;
  for (size_t i = 0; i < startup_info.program_metadata->size(); ++i) {
    auto pg = startup_info.program_metadata->at(i);
    if (pg.key.compare(kDataKey) == 0) {
      data_path = "pkg/" + pg.value;
    }
  }
  if (data_path.empty()) {
    FML_DLOG(ERROR) << "Could not find a /pkg/data directory for "
                    << package.resolved_url;
    return;
  }

  // Setup /tmp to be mapped to the process-local memfs.
  dart_utils::RunnerTemp::SetupComponent(fdio_ns_.get());

  // LaunchInfo::flat_namespace optional.
  for (size_t i = 0; i < startup_info.flat_namespace.paths.size(); ++i) {
    const auto& path = startup_info.flat_namespace.paths.at(i);
    if (path == kTmpPath) {
      continue;
    }

    zx::channel dir;
    if (path == kServiceRootPath) {
      svc_ = std::make_unique<sys::ServiceDirectory>(
          std::move(startup_info.flat_namespace.directories.at(i)));
      dir = svc_->CloneChannel().TakeChannel();
    } else {
      dir = std::move(startup_info.flat_namespace.directories.at(i));
    }

    zx_handle_t dir_handle = dir.release();
    if (fdio_ns_bind(fdio_ns_.get(), path.data(), dir_handle) != ZX_OK) {
      FML_DLOG(ERROR) << "Could not bind path to namespace: " << path;
      zx_handle_close(dir_handle);
    }
  }

  application_directory_.reset(fdio_ns_opendir(fdio_ns_.get()));
  FML_DCHECK(application_directory_.is_valid());

  application_assets_directory_.reset(openat(
      application_directory_.get(), data_path.c_str(), O_RDONLY | O_DIRECTORY));

  // TODO: LaunchInfo::out.

  // TODO: LaunchInfo::err.

  // LaunchInfo::service_request optional.
  if (launch_info.directory_request) {
    outgoing_dir_->Serve(fuchsia::io::OPEN_RIGHT_READABLE |
                             fuchsia::io::OPEN_RIGHT_WRITABLE |
                             fuchsia::io::OPEN_FLAG_DIRECTORY,
                         std::move(launch_info.directory_request));
  }

  directory_request_ = directory_ptr_.NewRequest();

  fidl::InterfaceHandle<fuchsia::io::Directory> flutter_public_dir;
  // TODO(anmittal): when fixing enumeration using new c++ vfs, make sure that
  // flutter_public_dir is only accessed once we receive OnOpen Event.
  // That will prevent FL-175 for public directory
  auto request = flutter_public_dir.NewRequest().TakeChannel();
  fdio_service_connect_at(directory_ptr_.channel().get(), "svc",
                          request.release());

  auto composed_service_dir = std::make_unique<vfs::ComposedServiceDir>();
  composed_service_dir->set_fallback(std::move(flutter_public_dir));

  // Clone and check if client is servicing the directory.
  directory_ptr_->Clone(fuchsia::io::OPEN_FLAG_DESCRIBE |
                            fuchsia::io::OPEN_RIGHT_READABLE |
                            fuchsia::io::OPEN_RIGHT_WRITABLE,
                        cloned_directory_ptr_.NewRequest());

  cloned_directory_ptr_.events().OnOpen =
      [this](zx_status_t status, std::unique_ptr<fuchsia::io::NodeInfo> info) {
        cloned_directory_ptr_.Unbind();
        if (status != ZX_OK) {
          FML_LOG(ERROR) << "could not bind out directory for flutter app("
                         << debug_label_
                         << "): " << zx_status_get_string(status);
          return;
        }
        const char* other_dirs[] = {"debug", "ctrl", "diagnostics"};
        // add other directories as RemoteDirs.
        for (auto& dir_str : other_dirs) {
          fidl::InterfaceHandle<fuchsia::io::Directory> dir;
          auto request = dir.NewRequest().TakeChannel();
          auto status = fdio_service_connect_at(directory_ptr_.channel().get(),
                                                dir_str, request.release());
          if (status == ZX_OK) {
            outgoing_dir_->AddEntry(
                dir_str, std::make_unique<vfs::RemoteDir>(dir.TakeChannel()));
          } else {
            FML_LOG(ERROR) << "could not add out directory entry(" << dir_str
                           << ") for flutter app(" << debug_label_
                           << "): " << zx_status_get_string(status);
          }
        }
      };

  cloned_directory_ptr_.set_error_handler(
      [this](zx_status_t status) { cloned_directory_ptr_.Unbind(); });

  // TODO: LaunchInfo::additional_services optional.

  // All launch arguments have been read. Perform service binding and
  // final settings configuration. The next call will be to create a view
  // for this application.
  composed_service_dir->AddService(
      fuchsia::ui::app::ViewProvider::Name_,
      std::make_unique<vfs::Service>(
          [this](zx::channel channel, async_dispatcher_t* dispatcher) {
            shells_bindings_.AddBinding(
                this, fidl::InterfaceRequest<fuchsia::ui::app::ViewProvider>(
                          std::move(channel)));
          }));

  outgoing_dir_->AddEntry("svc", std::move(composed_service_dir));

  // Setup the application controller binding.
  if (application_controller_request) {
    application_controller_.Bind(std::move(application_controller_request));
  }

  // Compare flutter_jit_runner in BUILD.gn.
  settings_.vm_snapshot_data =
      MakeDataFileMapping("/pkg/data/vm_snapshot_data.bin");
  settings_.vm_snapshot_instr =
      MakeDataFileMapping("/pkg/data/vm_snapshot_instructions.bin", true);

  settings_.isolate_snapshot_data =
      MakeDataFileMapping("/pkg/data/isolate_core_snapshot_data.bin");
  settings_.isolate_snapshot_instr = MakeDataFileMapping(
      "/pkg/data/isolate_core_snapshot_instructions.bin", true);

  {
    // Check if we can use the snapshot with the framework already loaded.
    std::string runner_framework;
    std::string app_framework;
    if (dart_utils::ReadFileToString("pkg/data/runner.frameworkversion",
                                     &runner_framework) &&
        dart_utils::ReadFileToStringAt(application_assets_directory_.get(),
                                       "app.frameworkversion",
                                       &app_framework) &&
        (runner_framework.compare(app_framework) == 0)) {
      settings_.vm_snapshot_data =
          MakeDataFileMapping("/pkg/data/framework_vm_snapshot_data.bin");
      settings_.vm_snapshot_instr =
          MakeDataFileMapping("/pkg/data/vm_snapshot_instructions.bin", true);

      settings_.isolate_snapshot_data = MakeDataFileMapping(
          "/pkg/data/framework_isolate_core_snapshot_data.bin");
      settings_.isolate_snapshot_instr = MakeDataFileMapping(
          "/pkg/data/isolate_core_snapshot_instructions.bin", true);

      FML_LOG(INFO) << "Using snapshot with framework for "
                    << package.resolved_url;
    } else {
      FML_LOG(INFO) << "Using snapshot without framework for "
                    << package.resolved_url;
    }
  }

  // Load and use product-specific configuration, if it exists.
  std::string json_string;
  if (dart_utils::ReadFileToString(
          "/config/data/frame_scheduling_performance_values", &json_string)) {
    product_config_ = FlutterRunnerProductConfiguration(json_string);
  }

#if defined(DART_PRODUCT)
  settings_.enable_observatory = false;
#else
  settings_.enable_observatory = true;

  // TODO(cbracken): pass this in as a param to allow 0.0.0.0, ::1, etc.
  settings_.observatory_host = "127.0.0.1";
#endif

  // Controls whether category "skia" trace events are enabled.
  settings_.trace_skia = true;

  settings_.icu_data_path = "";

  settings_.assets_dir = application_assets_directory_.get();

  // Compare flutter_jit_app in flutter_app.gni.
  settings_.application_kernel_list_asset = "app.dilplist";

  settings_.log_tag = debug_label_ + std::string{"(flutter)"};

  // No asserts in debug or release product.
  // No asserts in release with flutter_profile=true (non-product)
  // Yes asserts in non-product debug.
#if !defined(DART_PRODUCT) && (!defined(FLUTTER_PROFILE) || !defined(NDEBUG))
  // Debug mode
  settings_.disable_dart_asserts = false;
#else
  // Release mode
  settings_.disable_dart_asserts = true;
#endif

  settings_.task_observer_add =
      std::bind(&CurrentMessageLoopAddAfterTaskObserver, std::placeholders::_1,
                std::placeholders::_2);

  settings_.task_observer_remove = std::bind(
      &CurrentMessageLoopRemoveAfterTaskObserver, std::placeholders::_1);

  // TODO(FL-117): Re-enable causal async stack traces when this issue is
  // addressed.
  settings_.dart_flags = {"--no_causal_async_stacks"};

  // Disable code collection as it interferes with JIT code warmup
  // by decreasing usage counters and flushing code which is still useful.
  settings_.dart_flags.push_back("--no-collect_code");

  if (!flutter::DartVM::IsRunningPrecompiledCode()) {
    // The interpreter is enabled unconditionally in JIT mode. If an app is
    // built for debugging (that is, with no bytecode), the VM will fall back on
    // ASTs.
    settings_.dart_flags.push_back("--enable_interpreter");
  }

  // Don't collect CPU samples from Dart VM C++ code.
  settings_.dart_flags.push_back("--no_profile_vm");

  // Scale back CPU profiler sampling period on ARM64 to avoid overloading
  // the tracing engine.
#if defined(__aarch64__)
  settings_.dart_flags.push_back("--profile_period=10000");
#endif  // defined(__aarch64__)

  auto weak_application = weak_factory_.GetWeakPtr();
  auto platform_task_runner =
      CreateFMLTaskRunner(async_get_default_dispatcher());
  const std::string component_url = package.resolved_url;
  settings_.unhandled_exception_callback = [weak_application,
                                            platform_task_runner,
                                            runner_incoming_services,
                                            component_url](
                                               const std::string& error,
                                               const std::string& stack_trace) {
    if (weak_application) {
      // TODO(cbracken): unsafe. The above check and the PostTask below are
      // happening on the UI thread. If the Application dtor and thread
      // termination happen (on the platform thread) between the previous
      // line and the next line, a crash will occur since we'll be posting
      // to a dead thread. See Runner::OnApplicationTerminate() in
      // runner.cc.
      platform_task_runner->PostTask([weak_application,
                                      runner_incoming_services, component_url,
                                      error, stack_trace]() {
        if (weak_application) {
          dart_utils::HandleException(runner_incoming_services, component_url,
                                      error, stack_trace);
        } else {
          FML_LOG(WARNING)
              << "Exception was thrown which was not caught in Flutter app: "
              << error;
        }
      });
    } else {
      FML_LOG(WARNING)
          << "Exception was thrown which was not caught in Flutter app: "
          << error;
    }
    // Ideally we would return whether HandleException returned ZX_OK, but
    // short of knowing if the exception was correctly handled, we return
    // false to have the error and stack trace printed in the logs.
    return false;
  };

  AttemptVMLaunchWithCurrentSettings(settings_);
}

Application::~Application() = default;

const std::string& Application::GetDebugLabel() const {
  return debug_label_;
}

class FileInNamespaceBuffer final : public fml::Mapping {
 public:
  FileInNamespaceBuffer(int namespace_fd, const char* path, bool executable)
      : address_(nullptr), size_(0) {
    fuchsia::mem::Buffer buffer;
    if (!dart_utils::VmoFromFilenameAt(namespace_fd, path, executable,
                                       &buffer)) {
      return;
    }
    if (buffer.size == 0) {
      return;
    }

    uint32_t flags = ZX_VM_PERM_READ;
    if (executable) {
      flags |= ZX_VM_PERM_EXECUTE;
    }
    uintptr_t addr;
    zx_status_t status =
        zx::vmar::root_self()->map(0, buffer.vmo, 0, buffer.size, flags, &addr);
    if (status != ZX_OK) {
      FML_LOG(FATAL) << "Failed to map " << path << ": "
                     << zx_status_get_string(status);
    }

    address_ = reinterpret_cast<void*>(addr);
    size_ = buffer.size;
  }

  ~FileInNamespaceBuffer() {
    if (address_ != nullptr) {
      zx::vmar::root_self()->unmap(reinterpret_cast<uintptr_t>(address_),
                                   size_);
      address_ = nullptr;
      size_ = 0;
    }
  }

  // |fml::Mapping|
  const uint8_t* GetMapping() const override {
    return reinterpret_cast<const uint8_t*>(address_);
  }

  // |fml::Mapping|
  size_t GetSize() const override { return size_; }

 private:
  void* address_;
  size_t size_;

  FML_DISALLOW_COPY_AND_ASSIGN(FileInNamespaceBuffer);
};

std::unique_ptr<fml::Mapping> CreateWithContentsOfFile(int namespace_fd,
                                                       const char* file_path,
                                                       bool executable) {
  FML_TRACE_EVENT("flutter", "LoadFile", "path", file_path);
  auto source = std::make_unique<FileInNamespaceBuffer>(namespace_fd, file_path,
                                                        executable);
  return source->GetMapping() == nullptr ? nullptr : std::move(source);
}

void Application::AttemptVMLaunchWithCurrentSettings(
    const flutter::Settings& settings) {
  if (!flutter::DartVM::IsRunningPrecompiledCode()) {
    // We will be initializing the VM lazily in this case.
    return;
  }

  // Compare with flutter_aot_app in flutter_app.gni.
  fml::RefPtr<flutter::DartSnapshot> vm_snapshot;

  std::shared_ptr<dart_utils::ElfSnapshot> snapshot =
      std::make_shared<dart_utils::ElfSnapshot>();
  if (snapshot->Load(application_assets_directory_.get(),
                     "app_aot_snapshot.so")) {
    const uint8_t* isolate_data = snapshot->IsolateData();
    const uint8_t* isolate_instructions = snapshot->IsolateInstrs();
    const uint8_t* vm_data = snapshot->VmData();
    const uint8_t* vm_instructions = snapshot->VmInstrs();
    if (isolate_data == nullptr || isolate_instructions == nullptr ||
        vm_data == nullptr || vm_instructions == nullptr) {
      FML_LOG(FATAL) << "ELF snapshot missing AOT symbols.";
      return;
    }
    auto hold_snapshot = [snapshot](const uint8_t* _, size_t __) {};
    vm_snapshot = fml::MakeRefCounted<flutter::DartSnapshot>(
        std::make_shared<fml::NonOwnedMapping>(vm_data, 0, hold_snapshot),
        std::make_shared<fml::NonOwnedMapping>(vm_instructions, 0,
                                               hold_snapshot));
    isolate_snapshot_ = fml::MakeRefCounted<flutter::DartSnapshot>(
        std::make_shared<fml::NonOwnedMapping>(isolate_data, 0, hold_snapshot),
        std::make_shared<fml::NonOwnedMapping>(isolate_instructions, 0,
                                               hold_snapshot));
  } else {
    vm_snapshot = fml::MakeRefCounted<flutter::DartSnapshot>(
        CreateWithContentsOfFile(
            application_assets_directory_.get() /* /pkg/data */,
            "vm_snapshot_data.bin", false),
        CreateWithContentsOfFile(
            application_assets_directory_.get() /* /pkg/data */,
            "vm_snapshot_instructions.bin", true));

    isolate_snapshot_ = fml::MakeRefCounted<flutter::DartSnapshot>(
        CreateWithContentsOfFile(
            application_assets_directory_.get() /* /pkg/data */,
            "isolate_snapshot_data.bin", false),
        CreateWithContentsOfFile(
            application_assets_directory_.get() /* /pkg/data */,
            "isolate_snapshot_instructions.bin", true));
  }

  auto vm = flutter::DartVMRef::Create(settings_,               //
                                       std::move(vm_snapshot),  //
                                       isolate_snapshot_        //
  );
  FML_CHECK(vm) << "Mut be able to initialize the VM.";
}

void Application::Kill() {
  application_controller_.events().OnTerminated(
      last_return_code_.second, fuchsia::sys::TerminationReason::EXITED);

  termination_callback_(this);
  // WARNING: Don't do anything past this point as this instance may have been
  // collected.
}

void Application::Detach() {
  application_controller_.set_error_handler(nullptr);
}

void Application::OnEngineTerminate(const Engine* shell_holder) {
  auto found = std::find_if(shell_holders_.begin(), shell_holders_.end(),
                            [shell_holder](const auto& holder) {
                              return holder.get() == shell_holder;
                            });

  if (found == shell_holders_.end()) {
    return;
  }

  // We may launch multiple shell in this application. However, we will
  // terminate when the last shell goes away. The error code return to the
  // application controller will be the last isolate that had an error.
  auto return_code = shell_holder->GetEngineReturnCode();
  if (return_code.first) {
    last_return_code_ = return_code;
  }

  shell_holders_.erase(found);

  if (shell_holders_.size() == 0) {
    Kill();
    // WARNING: Don't do anything past this point because the delegate may have
    // collected this instance via the termination callback.
  }
}

void Application::CreateView(
    zx::eventpair token,
    fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> /*incoming_services*/,
    fidl::InterfaceHandle<
        fuchsia::sys::ServiceProvider> /*outgoing_services*/) {
  auto view_ref_pair = scenic::ViewRefPair::New();
  CreateViewWithViewRef(std::move(token), std::move(view_ref_pair.control_ref),
                        std::move(view_ref_pair.view_ref));
}

void Application::CreateViewWithViewRef(
    zx::eventpair view_token,
    fuchsia::ui::views::ViewRefControl control_ref,
    fuchsia::ui::views::ViewRef view_ref) {
  if (!svc_) {
    FML_DLOG(ERROR)
        << "Component incoming services was invalid when attempting to "
           "create a shell for a view provider request.";
    return;
  }

  shell_holders_.emplace(std::make_unique<Engine>(
      *this,                         // delegate
      debug_label_,                  // thread label
      svc_,                          // Component incoming services
      runner_incoming_services_,     // Runner incoming services
      settings_,                     // settings
      std::move(isolate_snapshot_),  // isolate snapshot
      scenic::ToViewToken(std::move(view_token)),  // view token
      scenic::ViewRefPair{
          .control_ref = std::move(control_ref),
          .view_ref = std::move(view_ref),
      },
      std::move(fdio_ns_),            // FDIO namespace
      std::move(directory_request_),  // outgoing request
      product_config_                 // product configuration
      ));
}

#if !defined(DART_PRODUCT)
void Application::WriteProfileToTrace() const {
  for (const auto& engine : shell_holders_) {
    engine->WriteProfileToTrace();
  }
}
#endif  // !defined(DART_PRODUCT)

}  // namespace flutter_runner
