blob: 0a31b55df61c9111011802da7653a5c7f43bedb7 [file] [log] [blame]
// 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 "services/dart/dart_app.h"
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/trace_event/trace_event.h"
#include "mojo/dart/embedder/dart_controller.h"
#include "mojo/dart/embedder/mojo_dart_state.h"
#include "mojo/data_pipe_utils/data_pipe_utils.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "third_party/zlib/google/zip_reader.h"
#include "url/gurl.h"
using mojo::Application;
namespace dart {
DartApp::DartApp(mojo::InterfaceRequest<Application> application_request,
const std::string& base_uri,
const base::FilePath& application_dir,
bool strict,
bool run_on_message_loop,
bool override_pause_isolates_flags,
bool pause_isolates_on_start,
bool pause_isolates_on_exit)
: application_request_(application_request.Pass()),
application_dir_(application_dir),
main_isolate_(nullptr) {
base::FilePath snapshot_path = application_dir_.Append("snapshot_blob.bin");
config_.base_uri = base_uri;
config_.use_dart_run_loop = !run_on_message_loop;
// Look for snapshot_blob.bin. If exists, then load from snapshot.
if (base::PathExists(snapshot_path)) {
config_.script_uri = snapshot_path.AsUTF8Unsafe();
config_.package_root = "";
} else {
LOG(ERROR) << "Dart entry point could not be found under: "
<< application_dir_.AsUTF8Unsafe();
base::MessageLoop::current()->QuitWhenIdle();
}
config_.application_data = reinterpret_cast<void*>(this);
config_.strict_compilation = strict;
config_.SetVmFlags(nullptr, 0);
if (override_pause_isolates_flags) {
config_.OverridePauseIsolateFlags(pause_isolates_on_start,
pause_isolates_on_exit);
}
base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(&DartApp::OnAppLoaded, base::Unretained(this)));
}
// Assume that |url| ends in a file name in lib/, and as a peer to lib/
// is the packages directory.
// 1) Strip the filename.
// 2) Strip lib/
// 3) Append with packages/.
// 4) Reconstruct full url.
static std::string SimplePackageRootFromUrl(std::string url) {
GURL gurl = GURL(url);
base::FilePath path = base::FilePath(gurl.path());
path = path.DirName();
path = path.DirName();
path = path.Append("packages");
path = path.AsEndingWithSeparator();
const std::string& path_string = path.value();
GURL::Replacements path_replacement;
path_replacement.SetPath(path_string.data(),
url::Component(0, path_string.size()));
gurl = gurl.ReplaceComponents(path_replacement);
return gurl.spec();
}
// Returns the path component from |url|.
static std::string ExtractPath(std::string url) {
GURL gurl = GURL(url);
return gurl.path();
}
static bool IsFileScheme(std::string url) {
GURL gurl = GURL(url);
return gurl.SchemeIsFile();
}
DartApp::DartApp(mojo::InterfaceRequest<Application> application_request,
const std::string& url,
bool strict,
bool run_on_message_loop,
bool override_pause_isolates_flags,
bool pause_isolates_on_start,
bool pause_isolates_on_exit)
: application_request_(application_request.Pass()),
main_isolate_(nullptr) {
config_.application_data = reinterpret_cast<void*>(this);
config_.strict_compilation = strict;
config_.base_uri = url;
config_.use_dart_run_loop = !run_on_message_loop;
if (IsFileScheme(url)) {
// Strip file:// and use the path directly.
config_.script_uri = ExtractPath(url);
config_.package_root = ExtractPath(SimplePackageRootFromUrl(url));
config_.use_network_loader = false;
} else {
// Use the full url.
config_.script_uri = url;
config_.package_root = SimplePackageRootFromUrl(url);
config_.use_network_loader = true;
}
config_.SetVmFlags(nullptr, 0);
if (override_pause_isolates_flags) {
config_.OverridePauseIsolateFlags(pause_isolates_on_start,
pause_isolates_on_exit);
}
base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(&DartApp::OnAppLoaded, base::Unretained(this)));
}
DartApp::~DartApp() {
if (main_isolate_ != nullptr) {
mojo::dart::DartController::ShutdownIsolate(main_isolate_);
main_isolate_ = nullptr;
}
}
void DartApp::OnAppLoaded() {
char* error = nullptr;
config_.handle = application_request_.PassMessagePipe().release().value();
config_.error = &error;
main_isolate_ = mojo::dart::DartController::StartupIsolate(config_);
if (!main_isolate_) {
LOG(ERROR) << error;
free(error);
}
if (config_.use_dart_run_loop) {
// let TraceLog know about that RunToCompletion blocks the message loop.
auto trace_log = base::trace_event::TraceLog::GetInstance();
trace_log->SetCurrentThreadBlocksMessageLoop();
mojo::dart::DartController::RunToCompletion(main_isolate_);
base::MessageLoop::current()->QuitWhenIdle();
}
}
} // namespace dart