// Copyright 2015 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 "flutter/runtime/dart_init.h"

#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "dart/runtime/bin/embedded_dart_io.h"
#include "dart/runtime/include/dart_mirrors_api.h"
#include "flutter/assets/unzipper_provider.h"
#include "flutter/assets/zip_asset_store.h"
#include "flutter/common/settings.h"
#include "flutter/glue/trace_event.h"
#include "flutter/lib/io/dart_io.h"
#include "flutter/lib/ui/dart_runtime_hooks.h"
#include "flutter/lib/ui/dart_ui.h"
#include "flutter/lib/ui/ui_dart_state.h"
#include "flutter/runtime/dart_service_isolate.h"
#include "flutter/runtime/start_up.h"
#include "lib/ftl/arraysize.h"
#include "lib/ftl/build_config.h"
#include "lib/ftl/logging.h"
#include "lib/ftl/time/time_delta.h"
#include "lib/tonic/converter/dart_converter.h"
#include "lib/tonic/dart_class_library.h"
#include "lib/tonic/dart_state.h"
#include "lib/tonic/dart_sticky_error.h"
#include "lib/tonic/dart_wrappable.h"
#include "lib/tonic/debugger/dart_debugger.h"
#include "lib/tonic/file_loader/file_loader.h"
#include "lib/tonic/logging/dart_error.h"
#include "lib/tonic/logging/dart_invoke.h"
#include "lib/tonic/scopes/dart_api_scope.h"
#include "lib/tonic/scopes/dart_isolate_scope.h"
#include "lib/tonic/typed_data/uint8_list.h"

using tonic::DartClassProvider;
using tonic::LogIfError;
using tonic::ToDart;

namespace dart {
namespace observatory {

#if FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_RELEASE

// These two symbols are defined in |observatory_archive.cc| which is generated
// by the |//dart/runtime/observatory:archive_observatory| rule. Both of these
// symbols will be part of the data segment and therefore are read only.
extern unsigned int observatory_assets_archive_len;
extern const uint8_t* observatory_assets_archive;

#endif  // FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_RELEASE

}  // namespace observatory
}  // namespace dart

namespace blink {

const char kKernelAssetKey[] = "kernel_blob.bin";
const char kSnapshotAssetKey[] = "snapshot_blob.bin";

namespace {

// Arguments passed to the Dart VM in all configurations.
static const char* kDartLanguageArgs[] = {
    "--enable_mirrors=false",
    "--background_compilation",
    "--await_is_keyword",
    "--assert_initializer",
};

static const char* kDartPrecompilationArgs[] = {
    "--precompilation",
};

static const char* kDartWriteProtectCodeArgs[] FTL_ALLOW_UNUSED_TYPE = {
    "--no_write_protect_code",
};

static const char* kDartCheckedModeArgs[] = {
    // clang-format off
    "--enable_asserts",
    "--enable_type_checks",
    "--error_on_bad_type",
    "--error_on_bad_override",
    // clang-format on
};

static const char* kDartStartPausedArgs[]{
    "--pause_isolates_on_start",
};

static const char* kDartTraceStartupArgs[]{
    "--timeline_streams=Compiler,Dart,Embedder,GC",
};

static const char* kDartEndlessTraceBufferArgs[]{
    "--timeline_recorder=endless",
};

constexpr char kFileUriPrefix[] = "file://";
constexpr size_t kFileUriPrefixLength = sizeof(kFileUriPrefix) - 1;

static const uint8_t* g_default_isolate_snapshot_data = nullptr;
static const uint8_t* g_default_isolate_snapshot_instructions = nullptr;
static bool g_service_isolate_initialized = false;
static ServiceIsolateHook g_service_isolate_hook = nullptr;
static RegisterNativeServiceProtocolExtensionHook
    g_register_native_service_protocol_extensions_hook = nullptr;

void IsolateShutdownCallback(void* callback_data) {
  if (tonic::DartStickyError::IsSet()) {
    tonic::DartApiScope api_scope;
    FTL_LOG(ERROR) << "Isolate " << tonic::StdStringFromDart(Dart_DebugName())
                   << " exited with an error";
    Dart_Handle sticky_error = Dart_GetStickyError();
    FTL_CHECK(LogIfError(sticky_error));
  }
  tonic::DartState* dart_state = static_cast<tonic::DartState*>(callback_data);
  delete dart_state;
}

bool DartFileModifiedCallback(const char* source_url, int64_t since_ms) {
  if (strncmp(source_url, kFileUriPrefix, kFileUriPrefixLength) != 0u) {
    // Assume modified.
    return true;
  }

  const char* path = source_url + kFileUriPrefixLength;
  struct stat info;
  if (stat(path, &info) < 0)
    return true;

  // If st_mtime is zero, it's more likely that the file system doesn't support
  // mtime than that the file was actually modified in the 1970s.
  if (!info.st_mtime)
    return true;

  // It's very unclear what time bases we're with here. The Dart API doesn't
  // document the time base for since_ms. Reading the code, the value varies by
  // platform, with a typical source being something like gettimeofday.
  //
  // We add one to st_mtime because st_mtime has less precision than since_ms
  // and we want to treat the file as modified if the since time is between
  // ticks of the mtime.
  ftl::TimeDelta mtime = ftl::TimeDelta::FromSeconds(info.st_mtime + 1);
  ftl::TimeDelta since = ftl::TimeDelta::FromMilliseconds(since_ms);

  return mtime > since;
}

void ThreadExitCallback() {}

bool IsServiceIsolateURL(const char* url_name) {
  return url_name != nullptr &&
         std::string(url_name) == DART_VM_SERVICE_ISOLATE_NAME;
}

static bool StringEndsWith(const std::string& string,
                           const std::string& ending) {
  if (ending.size() > string.size())
    return false;

  return string.compare(string.size() - ending.size(), ending.size(), ending) ==
         0;
}

Dart_Isolate ServiceIsolateCreateCallback(const char* script_uri,
                                          char** error) {
#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_RELEASE
  // No VM-service in release mode.
  return nullptr;
#else  // FLUTTER_RUNTIME_MODE
  tonic::DartState* dart_state = new tonic::DartState();
  Dart_Isolate isolate = Dart_CreateIsolate(
      script_uri, "main", g_default_isolate_snapshot_data,
      g_default_isolate_snapshot_instructions, nullptr, dart_state, error);
  FTL_CHECK(isolate) << error;
  dart_state->SetIsolate(isolate);
  FTL_CHECK(Dart_IsServiceIsolate(isolate));
  FTL_CHECK(!LogIfError(
      Dart_SetLibraryTagHandler(tonic::DartState::HandleLibraryTag)));
  {
    tonic::DartApiScope dart_api_scope;
    DartIO::InitForIsolate();
    DartUI::InitForIsolate();
    DartRuntimeHooks::Install(DartRuntimeHooks::SecondaryIsolate, script_uri);
    const Settings& settings = Settings::Get();
    if (settings.enable_observatory) {
      std::string ip = settings.ipv6 ? "::1" : "127.0.0.1";
      const intptr_t port = settings.observatory_port;
      const bool disable_websocket_origin_check = false;
      const bool service_isolate_booted = DartServiceIsolate::Startup(
          ip, port, tonic::DartState::HandleLibraryTag,
          IsRunningPrecompiledCode(), disable_websocket_origin_check, error);
      FTL_CHECK(service_isolate_booted) << error;
    }

    if (g_service_isolate_hook)
      g_service_isolate_hook(IsRunningPrecompiledCode());
  }
  Dart_ExitIsolate();

  g_service_isolate_initialized = true;
  // Register any native service protocol extensions.
  if (g_register_native_service_protocol_extensions_hook) {
    g_register_native_service_protocol_extensions_hook(
        IsRunningPrecompiledCode());
  }
  return isolate;
#endif  // FLUTTER_RUNTIME_MODE
}


Dart_Isolate IsolateCreateCallback(const char* script_uri,
                                   const char* main,
                                   const char* package_root,
                                   const char* package_config,
                                   Dart_IsolateFlags* flags,
                                   void* callback_data,
                                   char** error) {
  TRACE_EVENT0("flutter", __func__);

  if (IsServiceIsolateURL(script_uri)) {
    return ServiceIsolateCreateCallback(script_uri, error);
  }

  std::string entry_uri = script_uri;
  // Are we running from a Dart source file?
  const bool running_from_source = StringEndsWith(entry_uri, ".dart");

  std::vector<uint8_t> kernel_data;
  std::vector<uint8_t> snapshot_data;
  std::string entry_path;
  if (!IsRunningPrecompiledCode()) {
    // Check that the entry script URI starts with file://
    if (entry_uri.find(kFileUriPrefix) != 0u) {
      *error = strdup("Isolates must use file:// URIs");
      return nullptr;
    }
    // Entry script path (file:// is stripped).
    entry_path = std::string(script_uri + strlen(kFileUriPrefix));
    if (!running_from_source) {
      // Attempt to copy the snapshot from the asset bundle.
      const std::string& bundle_path = entry_path;
      ftl::RefPtr<ZipAssetStore> zip_asset_store =
          ftl::MakeRefCounted<ZipAssetStore>(
              GetUnzipperProviderForPath(std::move(bundle_path)));
      zip_asset_store->GetAsBuffer(kKernelAssetKey, &kernel_data);
      zip_asset_store->GetAsBuffer(kSnapshotAssetKey, &snapshot_data);
    }
  }

  UIDartState* parent_dart_state = static_cast<UIDartState*>(callback_data);
  UIDartState* dart_state = parent_dart_state->CreateForChildIsolate();

  Dart_Isolate isolate = Dart_CreateIsolate(
      script_uri, main, g_default_isolate_snapshot_data,
      g_default_isolate_snapshot_instructions, nullptr, dart_state, error);
  FTL_CHECK(isolate) << error;
  dart_state->SetIsolate(isolate);
  FTL_CHECK(!LogIfError(
      Dart_SetLibraryTagHandler(tonic::DartState::HandleLibraryTag)));

  {
    tonic::DartApiScope dart_api_scope;
    DartIO::InitForIsolate();
    DartUI::InitForIsolate();
    DartRuntimeHooks::Install(DartRuntimeHooks::SecondaryIsolate, script_uri);

    std::unique_ptr<DartClassProvider> ui_class_provider(
        new DartClassProvider(dart_state, "dart:ui"));
    dart_state->class_library().add_provider("ui",
                                             std::move(ui_class_provider));

    if (!kernel_data.empty()) {
      // We are running kernel code.
      FTL_CHECK(!LogIfError(Dart_LoadKernel(Dart_ReadKernelBinary(kernel_data.data(),
                                                                  kernel_data.size()))));
    } else if (!snapshot_data.empty()) {
      // We are running from a script snapshot.
      FTL_CHECK(!LogIfError(Dart_LoadScriptFromSnapshot(snapshot_data.data(),
                                                        snapshot_data.size())));
    } else if (running_from_source) {
      // We are running from source.
      // Forward the .packages configuration from the parent isolate to the
      // child isolate.
      tonic::FileLoader& parent_loader = parent_dart_state->file_loader();
      const std::string& packages = parent_loader.packages();
      tonic::FileLoader& loader = dart_state->file_loader();
      if (!packages.empty() && !loader.LoadPackagesMap(packages)) {
        FTL_LOG(WARNING) << "Failed to load package map: " << packages;
      }
      // Load the script.
      FTL_CHECK(!LogIfError(loader.LoadScript(entry_path)));
    }

    dart_state->isolate_client()->DidCreateSecondaryIsolate(isolate);
  }

  Dart_ExitIsolate();

  FTL_CHECK(Dart_IsolateMakeRunnable(isolate));
  return isolate;
}

Dart_Handle GetVMServiceAssetsArchiveCallback() {
#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_RELEASE
  return nullptr;
#else   // FLUTTER_RUNTIME_MODE
  return tonic::DartConverter<tonic::Uint8List>::ToDart(
      ::dart::observatory::observatory_assets_archive,
      ::dart::observatory::observatory_assets_archive_len);
#endif  // FLUTTER_RUNTIME_MODE
}

static const char kStdoutStreamId[] = "Stdout";
static const char kStderrStreamId[] = "Stderr";

static bool ServiceStreamListenCallback(const char* stream_id) {
  if (strcmp(stream_id, kStdoutStreamId) == 0) {
    dart::bin::SetCaptureStdout(true);
    return true;
  } else if (strcmp(stream_id, kStderrStreamId) == 0) {
    dart::bin::SetCaptureStderr(true);
    return true;
  }
  return false;
}

static void ServiceStreamCancelCallback(const char* stream_id) {
  if (strcmp(stream_id, kStdoutStreamId) == 0) {
    dart::bin::SetCaptureStdout(false);
  } else if (strcmp(stream_id, kStderrStreamId) == 0) {
    dart::bin::SetCaptureStderr(false);
  }
}

}  // namespace

bool IsRunningPrecompiledCode() {
  return Dart_IsPrecompiledRuntime();
}

EmbedderTracingCallbacks* g_tracing_callbacks = nullptr;

EmbedderTracingCallbacks::EmbedderTracingCallbacks(
    EmbedderTracingCallback start,
    EmbedderTracingCallback stop)
    : start_tracing_callback(start), stop_tracing_callback(stop) {}

void SetEmbedderTracingCallbacks(
    std::unique_ptr<EmbedderTracingCallbacks> callbacks) {
  g_tracing_callbacks = callbacks.release();
}

static void EmbedderTimelineStartRecording() {
  if (g_tracing_callbacks)
    g_tracing_callbacks->start_tracing_callback();
}

static void EmbedderTimelineStopRecording() {
  if (g_tracing_callbacks)
    g_tracing_callbacks->stop_tracing_callback();
}

static std::vector<const char*> ProfilingFlags(bool enable_profiling) {
// Disable Dart's built in profiler when building a debug build. This
// works around a race condition that would sometimes stop a crash's
// stack trace from being printed on Android.
#ifndef NDEBUG
  enable_profiling = false;
#endif

  // We want to disable profiling by default because it overwhelms LLDB. But
  // the VM enables the same by default. In either case, we have some profiling
  // flags.
  if (enable_profiling) {
    return {
        // Dart assumes ARM devices are insufficiently powerful and sets the
        // default profile period to 100Hz. This number is suitable for older
        // Raspberry Pi devices but quite low for current smartphones.
        "--profile_period=1000",
        // This is the default. But just be explicit.
        "--profiler",
        // This instructs the profiler to walk C++ frames, and to include
        // them in the profile.
        "--profile-vm"};
  } else {
    return {"--no-profiler"};
  }
}

void SetServiceIsolateHook(ServiceIsolateHook hook) {
  FTL_CHECK(!g_service_isolate_initialized);
  g_service_isolate_hook = hook;
}

void SetRegisterNativeServiceProtocolExtensionHook(
    RegisterNativeServiceProtocolExtensionHook hook) {
  FTL_CHECK(!g_service_isolate_initialized);
  g_register_native_service_protocol_extensions_hook = hook;
}

void PushBackAll(std::vector<const char*>* args,
                 const char** argv,
                 size_t argc) {
  for (size_t i = 0; i < argc; ++i) {
    args->push_back(argv[i]);
  }
}

void InitDartVM(const uint8_t* vm_snapshot_data,
                const uint8_t* vm_snapshot_instructions,
                const uint8_t* default_isolate_snapshot_data,
                const uint8_t* default_isolate_snapshot_instructions) {
  TRACE_EVENT0("flutter", __func__);

  g_default_isolate_snapshot_data = default_isolate_snapshot_data;
  g_default_isolate_snapshot_instructions =
      default_isolate_snapshot_instructions;

  const Settings& settings = Settings::Get();

  {
    TRACE_EVENT0("flutter", "dart::bin::BootstrapDartIo");
    dart::bin::BootstrapDartIo();

    if (!settings.temp_directory_path.empty()) {
      dart::bin::SetSystemTempDirectory(settings.temp_directory_path.c_str());
    }
  }

  std::vector<const char*> args;

  // Instruct the VM to ignore unrecognized flags.
  // There is a lot of diversity in a lot of combinations when it
  // comes to the arguments the VM supports. And, if the VM comes across a flag
  // it does not recognize, it exits immediately.
  args.push_back("--ignore-unrecognized-flags");

  for (const auto& profiler_flag :
       ProfilingFlags(settings.enable_dart_profiling)) {
    args.push_back(profiler_flag);
  }

  PushBackAll(&args, kDartLanguageArgs, arraysize(kDartLanguageArgs));

  if (IsRunningPrecompiledCode()) {
    PushBackAll(&args, kDartPrecompilationArgs,
                arraysize(kDartPrecompilationArgs));
  }

#if defined(OS_FUCHSIA) && defined(NDEBUG)
  // Do not enable checked mode for Fuchsia release builds
  // TODO(mikejurka): remove this once precompiled code is working on Fuchsia
  const bool use_checked_mode = false;
#else
  // Enable checked mode if we are not running precompiled code. We run non-
  // precompiled code only in the debug product mode.
  const bool use_checked_mode =
      !IsRunningPrecompiledCode() && !settings.dart_non_checked_mode;
#endif

#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
  // Debug mode uses the JIT, disable code page write protection to avoid
  // memory page protection changes before and after every compilation.
  PushBackAll(&args, kDartWriteProtectCodeArgs,
              arraysize(kDartWriteProtectCodeArgs));
#endif

  if (use_checked_mode)
    PushBackAll(&args, kDartCheckedModeArgs, arraysize(kDartCheckedModeArgs));

  if (settings.start_paused)
    PushBackAll(&args, kDartStartPausedArgs, arraysize(kDartStartPausedArgs));

  if (settings.endless_trace_buffer || settings.trace_startup) {
    // If we are tracing startup, make sure the trace buffer is endless so we
    // don't lose early traces.
    PushBackAll(&args, kDartEndlessTraceBufferArgs,
                arraysize(kDartEndlessTraceBufferArgs));
  }

  if (settings.trace_startup) {
    PushBackAll(&args, kDartTraceStartupArgs, arraysize(kDartTraceStartupArgs));
  }

  for (size_t i = 0; i < settings.dart_flags.size(); i++)
    args.push_back(settings.dart_flags[i].c_str());

  FTL_CHECK(Dart_SetVMFlags(args.size(), args.data()));

#if FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_RELEASE
  if (!IsRunningPrecompiledCode()) {
    TRACE_EVENT0("flutter", "DartDebugger::InitDebugger");
    // This should be called before calling Dart_Initialize.
    tonic::DartDebugger::InitDebugger();
  }
#endif

  DartUI::InitForGlobal();

  // Setup embedder tracing hooks. To avoid data races, it is recommended that
  // these hooks be installed before the DartInitialize, so do that setup now.
  Dart_SetEmbedderTimelineCallbacks(&EmbedderTimelineStartRecording,
                                    &EmbedderTimelineStopRecording);

  Dart_SetFileModifiedCallback(&DartFileModifiedCallback);

  {
    TRACE_EVENT0("flutter", "Dart_Initialize");
    Dart_InitializeParams params = {};
    params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
    params.vm_snapshot_data = vm_snapshot_data;
    params.vm_snapshot_instructions = vm_snapshot_instructions;
    params.create = IsolateCreateCallback;
    params.shutdown = IsolateShutdownCallback;
    params.thread_exit = ThreadExitCallback;
    params.get_service_assets = GetVMServiceAssetsArchiveCallback;
    char* init_error = Dart_Initialize(&params);
    if (init_error != nullptr)
      FTL_LOG(FATAL) << "Error while initializing the Dart VM: " << init_error;
    free(init_error);

    // Send the earliest available timestamp in the application lifecycle to
    // timeline. The difference between this timestamp and the time we render
    // the very first frame gives us a good idea about Flutter's startup time.
    // Use a duration event so about:tracing will consider this event when
    // deciding the earliest event to use as time 0.
    if (blink::engine_main_enter_ts != 0) {
      Dart_TimelineEvent("FlutterEngineMainEnter",     // label
                         blink::engine_main_enter_ts,  // timestamp0
                         blink::engine_main_enter_ts,  // timestamp1_or_async_id
                         Dart_Timeline_Event_Duration,  // event type
                         0,                             // argument_count
                         nullptr,                       // argument_names
                         nullptr                        // argument_values
                         );
    }
  }

  // Allow streaming of stdout and stderr by the Dart vm.
  Dart_SetServiceStreamCallbacks(&ServiceStreamListenCallback,
                                 &ServiceStreamCancelCallback);
}

}  // namespace blink
