// 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 "base/bind.h"
#include "base/callback.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/rand_util.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/sys_info.h"
#include "dart/runtime/include/dart_api.h"
#include "dart/runtime/include/dart_native_api.h"
#include "mojo/dart/embedder/builtin.h"
#include "mojo/dart/embedder/dart_controller.h"
#include "mojo/dart/embedder/mojo_dart_state.h"
#include "mojo/dart/embedder/vmservice.h"
#include "mojo/message_pump/message_pump_mojo.h"
#include "mojo/public/c/system/core.h"
#include "tonic/dart_converter.h"
#include "tonic/dart_debugger.h"
#include "tonic/dart_dependency_catcher.h"
#include "tonic/dart_error.h"
#include "tonic/dart_library_loader.h"
#include "tonic/dart_library_provider.h"
#include "tonic/dart_library_provider_files.h"
#include "tonic/dart_library_provider_network.h"
#include "tonic/dart_script_loader_sync.h"

namespace mojo {
namespace dart {

extern const uint8_t* vm_isolate_snapshot_buffer;
extern const uint8_t* isolate_snapshot_buffer;

static const char* kAsyncLibURL = "dart:async";
static const char* kInternalLibURL = "dart:_internal";
static const char* kIsolateLibURL = "dart:isolate";
static const char* kCoreLibURL = "dart:core";

static uint8_t snapshot_magic_number[] = { 0xf5, 0xf5, 0xdc, 0xdc };

static Dart_Handle SetWorkingDirectory(Dart_Handle builtin_lib) {
  base::FilePath current_dir;
  PathService::Get(base::DIR_CURRENT, &current_dir);

  const int kNumArgs = 1;
  Dart_Handle dart_args[kNumArgs];
  std::string current_dir_string = current_dir.AsUTF8Unsafe();
  dart_args[0] = Dart_NewStringFromUTF8(
      reinterpret_cast<const uint8_t*>(current_dir_string.data()),
      current_dir_string.length());
  return Dart_Invoke(builtin_lib,
                     Dart_NewStringFromCString("_setWorkingDirectory"),
                     kNumArgs,
                     dart_args);
}

static Dart_Handle ResolveScriptUri(Dart_Handle builtin_lib, Dart_Handle uri) {
  const int kNumArgs = 1;
  Dart_Handle dart_args[kNumArgs];
  dart_args[0] = uri;
  return Dart_Invoke(builtin_lib,
                     Dart_NewStringFromCString("_resolveScriptUri"),
                     kNumArgs,
                     dart_args);
}

static Dart_Handle PrepareBuiltinLibraries(const std::string& package_root,
                                           const std::string& script_uri) {
  // First ensure all required libraries are available.
  Dart_Handle builtin_lib = Builtin::PrepareLibrary(Builtin::kBuiltinLibrary);
  Builtin::PrepareLibrary(Builtin::kMojoInternalLibrary);
  Builtin::PrepareLibrary(Builtin::kDartMojoIoLibrary);
  Dart_Handle url = Dart_NewStringFromCString(kInternalLibURL);
  DART_CHECK_VALID(url);
  Dart_Handle internal_lib = Dart_LookupLibrary(url);
  DART_CHECK_VALID(internal_lib);
  url = Dart_NewStringFromCString(kCoreLibURL);
  DART_CHECK_VALID(url);
  Dart_Handle core_lib = Dart_LookupLibrary(url);
  DART_CHECK_VALID(internal_lib);
  url = Dart_NewStringFromCString(kAsyncLibURL);
  DART_CHECK_VALID(url);
  Dart_Handle async_lib = Dart_LookupLibrary(url);
  DART_CHECK_VALID(async_lib);
  url = Dart_NewStringFromCString(kIsolateLibURL);
  DART_CHECK_VALID(url);
  Dart_Handle isolate_lib = Dart_LookupLibrary(url);
  DART_CHECK_VALID(isolate_lib);
  Dart_Handle mojo_internal_lib =
      Builtin::GetLibrary(Builtin::kMojoInternalLibrary);
  DART_CHECK_VALID(mojo_internal_lib);

  // We need to ensure that all the scripts loaded so far are finalized
  // as we are about to invoke some Dart code below to setup closures.
  Dart_Handle result = Dart_FinalizeLoading(false);
  DART_CHECK_VALID(result);

  // Import dart:_internal into dart:mojo.builtin for setting up hooks.
  result = Dart_LibraryImportLibrary(builtin_lib, internal_lib, Dart_Null());
  DART_CHECK_VALID(result);

  // Setup the internal library's 'internalPrint' function.
  Dart_Handle print = Dart_Invoke(builtin_lib,
                                  Dart_NewStringFromCString("_getPrintClosure"),
                                  0,
                                  nullptr);
  DART_CHECK_VALID(print);
  result = Dart_SetField(internal_lib,
                         Dart_NewStringFromCString("_printClosure"),
                         print);
  DART_CHECK_VALID(result);

  DART_CHECK_VALID(Dart_Invoke(
      builtin_lib, Dart_NewStringFromCString("_setupHooks"), 0, nullptr));
  DART_CHECK_VALID(Dart_Invoke(
      isolate_lib, Dart_NewStringFromCString("_setupHooks"), 0, nullptr));

  // Setup the 'scheduleImmediate' closure.
  Dart_Handle schedule_immediate_closure = Dart_Invoke(
      isolate_lib,
      Dart_NewStringFromCString("_getIsolateScheduleImmediateClosure"),
      0,
      nullptr);
  Dart_Handle schedule_args[1];
  schedule_args[0] = schedule_immediate_closure;
  result = Dart_Invoke(
      async_lib,
      Dart_NewStringFromCString("_setScheduleImmediateClosure"),
      1,
      schedule_args);
  DART_CHECK_VALID(result);

  // Set current working directory.
  result = SetWorkingDirectory(builtin_lib);
  if (Dart_IsError(result)) {
    return result;
  }

  // Set script entry uri.
  Dart_Handle uri = Dart_NewStringFromUTF8(
      reinterpret_cast<const uint8_t*>(script_uri.c_str()),
      script_uri.length());
  DART_CHECK_VALID(uri);
  result = ResolveScriptUri(builtin_lib, uri);

  // Set up package root.
  result = Dart_NewStringFromUTF8(
      reinterpret_cast<const uint8_t*>(package_root.c_str()),
      package_root.length());
  DART_CHECK_VALID(result);

  const int kNumArgs = 1;
  Dart_Handle dart_args[kNumArgs];
  dart_args[0] = result;
  result = Dart_Invoke(builtin_lib,
                     Dart_NewStringFromCString("_setPackageRoot"),
                     kNumArgs,
                     dart_args);
  DART_CHECK_VALID(result);

  // Setup the uriBase with the base uri of the mojo app.
  Dart_Handle uri_base = Dart_Invoke(
      builtin_lib,
      Dart_NewStringFromCString("_getUriBaseClosure"),
      0,
      nullptr);
  DART_CHECK_VALID(uri_base);
  result = Dart_SetField(core_lib,
                         Dart_NewStringFromCString("_uriBaseClosure"),
                         uri_base);
  DART_CHECK_VALID(result);
  return result;
}

static const intptr_t kStartIsolateArgumentsLength = 2;

static void SetupStartIsolateArguments(
    const DartControllerConfig& config,
    Dart_Handle main_closure,
    Dart_Handle* start_isolate_args) {
  // start_isolate_args:
  // [0] -> main closure
  // [1] -> args list.
  // args list:
  // [0] -> mojo handle.
  // [1] -> script uri
  // [2] -> list of script arguments in config.
  start_isolate_args[0] = main_closure;     // entryPoint
  DART_CHECK_VALID(start_isolate_args[0]);
  start_isolate_args[1] = Dart_NewList(3);  // args
  DART_CHECK_VALID(start_isolate_args[1]);
  Dart_Handle script_uri = Dart_NewStringFromUTF8(
      reinterpret_cast<const uint8_t*>(config.script_uri.data()),
      config.script_uri.length());
  Dart_ListSetAt(start_isolate_args[1], 0, Dart_NewInteger(config.handle));
  Dart_ListSetAt(start_isolate_args[1], 1, script_uri);
  Dart_Handle script_args = Dart_NewList(config.script_flags_count);
  DART_CHECK_VALID(script_args);
  Dart_ListSetAt(start_isolate_args[1], 2, script_args);
  for (intptr_t i = 0; i < config.script_flags_count; i++) {
    Dart_ListSetAt(script_args, i,
                   Dart_NewStringFromCString(config.script_flags[i]));
  }
}

static void RunIsolate(Dart_Isolate isolate,
                       const DartControllerConfig& config) {
  tonic::DartIsolateScope isolate_scope(isolate);
  tonic::DartApiScope api_scope;

  Dart_Handle result;

  // Load the root library into the builtin library so that main can be found.
  Dart_Handle builtin_lib =
      Builtin::GetLibrary(Builtin::kBuiltinLibrary);
  DART_CHECK_VALID(builtin_lib);
  Dart_Handle root_lib = Dart_RootLibrary();
  DART_CHECK_VALID(root_lib);
  result = Dart_LibraryImportLibrary(builtin_lib, root_lib, Dart_Null());
  DART_CHECK_VALID(result);

  if (config.compile_all) {
    result = Dart_CompileAll();
    DART_CHECK_VALID(result);
  }

  Dart_Handle main_closure = Dart_Invoke(
      builtin_lib,
      Dart_NewStringFromCString("_getMainClosure"),
      0,
      nullptr);
  DART_CHECK_VALID(main_closure);

  Dart_Handle start_isolate_args[kStartIsolateArgumentsLength];
  SetupStartIsolateArguments(config, main_closure, &start_isolate_args[0]);
  Dart_Handle isolate_lib =
      Dart_LookupLibrary(Dart_NewStringFromCString(kIsolateLibURL));
  DART_CHECK_VALID(isolate_lib);

  result = Dart_Invoke(isolate_lib,
                       Dart_NewStringFromCString("_startMainIsolate"),
                       kStartIsolateArgumentsLength,
                       start_isolate_args);
  DART_CHECK_VALID(result);

  result = Dart_RunLoop();
  tonic::LogIfError(result);
  DART_CHECK_VALID(result);
}

Dart_Handle DartController::LibraryTagHandler(Dart_LibraryTag tag,
                                              Dart_Handle library,
                                              Dart_Handle url) {
  if (tag == Dart_kCanonicalizeUrl) {
    std::string string = tonic::StdStringFromDart(url);
    if (StartsWithASCII(string, "dart:", true))
      return url;
  }
  return tonic::DartLibraryLoader::HandleLibraryTag(tag, library, url);
}

Dart_Isolate DartController::CreateIsolateHelper(
    void* dart_app,
    bool strict_compilation,
    IsolateCallbacks callbacks,
    const std::string& script_uri,
    const std::string& package_root,
    char** error,
    bool use_network_loader) {
  auto isolate_data = new MojoDartState(dart_app,
                                        strict_compilation,
                                        callbacks,
                                        script_uri,
                                        package_root);
  CHECK(isolate_snapshot_buffer != nullptr);
  Dart_Isolate isolate =
      Dart_CreateIsolate(script_uri.c_str(), "main", isolate_snapshot_buffer,
                         nullptr, isolate_data, error);
  if (isolate == nullptr) {
    delete isolate_data;
    return nullptr;
  }
  Dart_ExitIsolate();

  isolate_data->SetIsolate(isolate);
  if (service_connector_ != nullptr) {
    // This is not supported in the unit test harness.
    isolate_data->BindNetworkService(
        service_connector_->ConnectToService(
            DartControllerServiceConnector::kNetworkServiceId));
  }

  // Setup isolate and load script.
  {
    tonic::DartIsolateScope isolate_scope(isolate);
    tonic::DartApiScope api_scope;
    // Setup loader.
    const char* package_root_str = nullptr;
    if (package_root.empty()) {
      package_root_str = "/";
    } else {
      package_root_str = package_root.c_str();
    }
    isolate_data->library_loader().set_magic_number(
        snapshot_magic_number, sizeof(snapshot_magic_number));
    if (use_network_loader) {
      mojo::NetworkService* network_service = isolate_data->network_service();
      isolate_data->set_library_provider(
          new tonic::DartLibraryProviderNetwork(network_service));
    } else {
      isolate_data->set_library_provider(
          new tonic::DartLibraryProviderFiles(
              base::FilePath(package_root_str)));
    }
    Dart_Handle result = Dart_SetLibraryTagHandler(LibraryTagHandler);
    DART_CHECK_VALID(result);
    // Toggle checked mode.
    Dart_IsolateSetStrictCompilation(strict_compilation);
    // Prepare builtin and its dependent libraries.
    result = PrepareBuiltinLibraries(package_root, script_uri);
    DART_CHECK_VALID(result);

    // The VM is creating the service isolate.
    if (Dart_IsServiceIsolate(isolate)) {
      const intptr_t port = SupportDartMojoIo() ? 0 : -1;
      InitializeDartMojoIo();
      StartHandleWatcherIsolate();
      if (!VmService::Setup("127.0.0.1", port)) {
        *error = strdup(VmService::GetErrorMessage());
        return nullptr;
      }
      return isolate;
    }

    if ((script_uri == "vm-service") || (script_uri == "stop-handle-watcher")) {
      // Special case for starting and stopping the the handle watcher isolate.
      LoadEmptyScript(script_uri);
    } else {
      tonic::DartScriptLoaderSync::LoadScript(
          script_uri,
          isolate_data->library_provider());
    }

    InitializeDartMojoIo();
  }

  if (isolate_data->library_loader().error_during_loading()) {
    *error = strdup("Library loader reported error during loading. See log.");
    Dart_EnterIsolate(isolate);
    Dart_ShutdownIsolate();
    return nullptr;
  }

  // Make the isolate runnable so that it is ready to handle messages.
  bool retval = Dart_IsolateMakeRunnable(isolate);
  if (!retval) {
    *error = strdup("Invalid isolate state - Unable to make it runnable");
    Dart_EnterIsolate(isolate);
    Dart_ShutdownIsolate();
    return nullptr;
  }

  DCHECK(Dart_CurrentIsolate() == nullptr);

  return isolate;
}

Dart_Isolate DartController::IsolateCreateCallback(const char* script_uri,
                                                   const char* main,
                                                   const char* package_root,
                                                   Dart_IsolateFlags* flags,
                                                   void* callback_data,
                                                   char** error) {
  auto parent_isolate_data = MojoDartState::Cast(callback_data);
  std::string script_uri_string;
  std::string package_root_string;

  if (script_uri == nullptr) {
    if (callback_data == nullptr) {
      *error = strdup("Invalid 'callback_data' - Unable to spawn new isolate");
      return nullptr;
    }
    script_uri_string = parent_isolate_data->script_uri();
  } else {
    script_uri_string = std::string(script_uri);
  }
  if (package_root == nullptr) {
    if (parent_isolate_data != nullptr) {
      package_root_string = parent_isolate_data->package_root();
    }
  } else {
    package_root_string = std::string(package_root);
  }
  // Inherit parameters from parent isolate (if any).
  void* dart_app = nullptr;
  bool strict_compilation = true;
  // TODO(johnmccutchan): Use parent's setting?
  bool use_network_loader = false;
  IsolateCallbacks callbacks;
  if (parent_isolate_data != nullptr) {
    dart_app = parent_isolate_data->application_data();
    strict_compilation = parent_isolate_data->strict_compilation();
    callbacks = parent_isolate_data->callbacks();
  }
  return CreateIsolateHelper(dart_app,
                             strict_compilation,
                             callbacks,
                             script_uri_string,
                             package_root_string,
                             error,
                             use_network_loader);
}

void DartController::IsolateShutdownCallback(void* callback_data) {
  {
    tonic::DartApiScope api_scope;
    ShutdownDartMojoIo();
  }

  auto isolate_data = MojoDartState::Cast(callback_data);
  delete isolate_data;
}

void DartController::UnhandledExceptionCallback(Dart_Handle error) {
  auto isolate_data = MojoDartState::Current();
  if (!isolate_data->callbacks().exception.is_null()) {
    // TODO(zra): Instead of passing an error handle, it may make life easier
    // for clients if we pass any error string here instead.
    isolate_data->callbacks().exception.Run(error);
  }

  // Close handles generated by the isolate.
  std::set<MojoHandle>& handles = isolate_data->unclosed_handles();
  for (auto it = handles.begin(); it != handles.end(); ++it) {
    MojoClose((*it));
  }
  handles.clear();
}


bool DartController::initialized_ = false;
bool DartController::service_isolate_running_ = false;
bool DartController::strict_compilation_ = false;
DartControllerServiceConnector* DartController::service_connector_ = nullptr;
base::Lock DartController::lock_;

bool DartController::SupportDartMojoIo() {
  return service_connector_ != nullptr;
}

void DartController::InitializeDartMojoIo() {
  Dart_Isolate current_isolate = Dart_CurrentIsolate();
  CHECK(current_isolate != nullptr);
  if (!SupportDartMojoIo()) {
    return;
  }
  CHECK(service_connector_ != nullptr);
  MojoHandle network_service_mojo_handle = MOJO_HANDLE_INVALID;
  network_service_mojo_handle =
        service_connector_->ConnectToService(
            DartControllerServiceConnector::kNetworkServiceId);
  if (network_service_mojo_handle == MOJO_HANDLE_INVALID) {
    // Not supported.
    return;
  }
  // Pass handle into 'dart:io' library.
  Dart_Handle mojo_io_library =
      Builtin::GetLibrary(Builtin::kDartMojoIoLibrary);
  CHECK(!Dart_IsError(mojo_io_library));
  Dart_Handle method_name = Dart_NewStringFromCString("_initialize");
  CHECK(!Dart_IsError(method_name));
  Dart_Handle network_service_handle =
      Dart_NewInteger(network_service_mojo_handle);
  CHECK(!Dart_IsError(network_service_handle));
  Dart_Handle result = Dart_Invoke(mojo_io_library,
                                   method_name,
                                   1,
                                   &network_service_handle);
  CHECK(!Dart_IsError(result));
}

void DartController::ShutdownDartMojoIo() {
  Dart_Isolate current_isolate = Dart_CurrentIsolate();
  CHECK(current_isolate != nullptr);
  if (!SupportDartMojoIo()) {
    return;
  }
  Dart_Handle mojo_io_library =
      Builtin::GetLibrary(Builtin::kDartMojoIoLibrary);
  CHECK(!Dart_IsError(mojo_io_library));
  Dart_Handle method_name = Dart_NewStringFromCString("_shutdown");
  CHECK(!Dart_IsError(method_name));
  Dart_Handle result = Dart_Invoke(mojo_io_library,
                                   method_name,
                                   0,
                                   nullptr);
  if (Dart_IsError(result)) {
    Dart_PropagateError(result);
  }
}

void DartController::StartHandleWatcherIsolate() {
  Dart_Handle result;

  // Start the Mojo handle watcher isolate.
  Dart_Handle mojo_core_lib =
      Builtin::GetLibrary(Builtin::kMojoInternalLibrary);
  DART_CHECK_VALID(mojo_core_lib);
  Dart_Handle handle_watcher_type = Dart_GetType(
      mojo_core_lib,
      Dart_NewStringFromCString("MojoHandleWatcher"),
      0,
      nullptr);
  DART_CHECK_VALID(handle_watcher_type);
  result = Dart_Invoke(
      handle_watcher_type,
      Dart_NewStringFromCString("_start"),
      0,
      nullptr);
  DART_CHECK_VALID(result);
}

// TODO(johnmccutchan): Move handle watcher shutdown into the service isolate
// once the VM can shutdown cleanly.
void DartController::StopHandleWatcherIsolate() {
  // Spin up an isolate to initiate the handle watcher shutdown.
  IsolateCallbacks callbacks;
  char* error;
  Dart_Isolate shutdown_isolate = CreateIsolateHelper(
      nullptr, false, callbacks, "stop-handle-watcher", "", &error, false);
  CHECK(shutdown_isolate);

  Dart_EnterIsolate(shutdown_isolate);
  Dart_EnterScope();
  Dart_Handle result;

  // Stop the Mojo handle watcher isolate.
  Dart_Handle mojo_core_lib =
      Builtin::GetLibrary(Builtin::kMojoInternalLibrary);
  DART_CHECK_VALID(mojo_core_lib);
  Dart_Handle handle_watcher_type = Dart_GetType(
      mojo_core_lib,
      Dart_NewStringFromCString("MojoHandleWatcher"),
      0,
      nullptr);
  DART_CHECK_VALID(handle_watcher_type);
  result = Dart_Invoke(
      handle_watcher_type,
      Dart_NewStringFromCString("_stop"),
      0,
      nullptr);
  DART_CHECK_VALID(result);

  // Run until the handle watcher isolate has exited.
  result = Dart_RunLoop();
  tonic::LogIfError(result);
  DART_CHECK_VALID(result);

  Dart_ExitScope();
  Dart_ShutdownIsolate();
}

void DartController::InitVmIfNeeded(Dart_EntropySource entropy,
                                    const char** vm_flags,
                                    int vm_flags_count) {
  base::AutoLock al(lock_);
  if (initialized_) {
    return;
  }

  const int kNumFlags = vm_flags_count + 1;
  const char* flags[kNumFlags];

  // TODO(zra): Fix Dart VM Shutdown race.
  // There is a bug in Dart VM shutdown which causes its thread pool threads
  // to potentially fail to exit when the rest of the VM is going down. This
  // results in a segfault if they begin running again after the Dart
  // embedder has been unloaded. Setting this flag to 0 ensures that these
  // threads sleep forever instead of waking up and trying to run code
  // that isn't there anymore.
  flags[0] = "--worker-timeout-millis=0";

  for (int i = 0; i < vm_flags_count; ++i) {
    flags[i + 1] = vm_flags[i];
  }

  bool result = Dart_SetVMFlags(kNumFlags, flags);
  CHECK(result);

  // This should be called before calling Dart_Initialize.
  tonic::DartDebugger::InitDebugger();

  result = Dart_Initialize(vm_isolate_snapshot_buffer,
                           IsolateCreateCallback,
                           nullptr,  // Isolate interrupt callback.
                           UnhandledExceptionCallback,
                           IsolateShutdownCallback,
                           // File IO callbacks.
                           nullptr, nullptr, nullptr, nullptr,
                           entropy);
  CHECK(result);
  initialized_ = true;
}

void DartController::BlockForServiceIsolate() {
  base::AutoLock al(lock_);
  BlockForServiceIsolateLocked();
}

void DartController::BlockForServiceIsolateLocked() {
  if (service_isolate_running_) {
    return;
  }
  // By waiting for the load port, we ensure that the service isolate is fully
  // running before returning.
  Dart_ServiceWaitForLoadPort();
  service_isolate_running_ = true;
}

void DartController::LoadEmptyScript(const std::string& script_uri) {
  Dart_Handle uri = Dart_NewStringFromUTF8(
      reinterpret_cast<const uint8_t*>(script_uri.c_str()),
      script_uri.length());
  DART_CHECK_VALID(uri);
  Dart_Handle script_source = Dart_NewStringFromCString("");
  DART_CHECK_VALID(script_source);
  Dart_Handle result = Dart_LoadScript(uri, script_source, 0, 0);
  DART_CHECK_VALID(result);
  tonic::LogIfError(Dart_FinalizeLoading(true));
}

bool DartController::RunSingleDartScript(const DartControllerConfig& config) {
  InitVmIfNeeded(config.entropy,
                 config.vm_flags,
                 config.vm_flags_count);
  BlockForServiceIsolate();
  Dart_Isolate isolate = CreateIsolateHelper(config.application_data,
                                             config.strict_compilation,
                                             config.callbacks,
                                             config.script_uri,
                                             config.package_root,
                                             config.error,
                                             config.use_network_loader);
  if (isolate == nullptr) {
    return false;
  }

  RunIsolate(isolate, config);

  // Cleanup.
  Dart_EnterIsolate(isolate);
  Dart_ShutdownIsolate();
  Dart_Cleanup();
  return true;
}

static bool generateEntropy(uint8_t* buffer, intptr_t length) {
  base::RandBytes(reinterpret_cast<void*>(buffer), length);
  return true;
}

bool DartController::Initialize(
    DartControllerServiceConnector* service_connector,
    bool strict_compilation) {
  service_connector_ = service_connector;
  strict_compilation_ = strict_compilation;
  InitVmIfNeeded(generateEntropy, nullptr, 0);
  return true;
}

bool DartController::RunDartScript(const DartControllerConfig& config) {
  const bool strict = strict_compilation_ || config.strict_compilation;
  Dart_Isolate isolate = CreateIsolateHelper(config.application_data,
                                             strict,
                                             config.callbacks,
                                             config.script_uri,
                                             config.package_root,
                                             config.error,
                                             config.use_network_loader);
  if (isolate == nullptr) {
    return false;
  }

  RunIsolate(isolate, config);

  // Cleanup.
  Dart_EnterIsolate(isolate);
  Dart_ShutdownIsolate();

  return true;
}

void DartController::Shutdown() {
  base::AutoLock al(lock_);
  if (!initialized_) {
    return;
  }
  BlockForServiceIsolateLocked();
  StopHandleWatcherIsolate();
  Dart_Cleanup();
  service_isolate_running_ = false;
  initialized_ = false;
}

}  // namespace apps
}  // namespace mojo
