| Index: mojo/apps/js/js_app.cc
|
| diff --git a/mojo/apps/js/js_app.cc b/mojo/apps/js/js_app.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..046bab8c5917763267d80d45f481358195f829e1
|
| --- /dev/null
|
| +++ b/mojo/apps/js/js_app.cc
|
| @@ -0,0 +1,123 @@
|
| +// 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 "mojo/apps/js/js_app.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "gin/converter.h"
|
| +#include "mojo/apps/js/content_handler.h"
|
| +#include "mojo/apps/js/mojo_module.h"
|
| +#include "mojo/common/data_pipe_utils.h"
|
| +
|
| +namespace mojo {
|
| +namespace apps {
|
| +
|
| +JSAppRunnerDelegate::JSAppRunnerDelegate(JSApp* js_app) {
|
| + AddBuiltinModule(Mojo::kModuleName, base::Bind(Mojo::GetModule, js_app));
|
| +}
|
| +
|
| +JSApp::JSApp(ApplicationDelegateImpl* content_handler_app,
|
| + const std::string& url,
|
| + URLResponsePtr content)
|
| + : content_handler_app_(content_handler_app),
|
| + url_(url),
|
| + content_(content.Pass()),
|
| + thread_("Mojo JS " + url),
|
| + content_handler_task_runner_(base::MessageLoop::current()->task_runner()),
|
| + runner_delegate_(this) {
|
| + CHECK(on_content_handler_thread());
|
| +}
|
| +
|
| +JSApp::~JSApp() {
|
| +}
|
| +
|
| +bool JSApp::Start() {
|
| + CHECK(!js_app_task_runner_.get() && on_content_handler_thread());
|
| + base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0);
|
| + thread_.StartWithOptions(thread_options);
|
| +
|
| + // TODO(hansmuller): check thread_.StartWithOptions() return value.
|
| + // TODO(hansmuller): need to funnel Run() failures back to the caller.
|
| +
|
| + // The lifetime of the this JSApp is managed by the content_handler_app_.
|
| + thread_.message_loop()->PostTask(
|
| + FROM_HERE, base::Bind(&JSApp::Run, base::Unretained(this)));
|
| + return true;
|
| +}
|
| +
|
| +void JSApp::Quit() {
|
| + CHECK(on_js_app_thread());
|
| +
|
| + // The the terminate operation is posted to the message_loop so that
|
| + // the shell_runner isn't destroyed before this JS function returns.
|
| + // The lifetime of the this JSApp is managed by the content_handler_app_.
|
| + thread_.message_loop()->PostTask(
|
| + FROM_HERE, base::Bind(&JSApp::Terminate, base::Unretained(this)));
|
| +}
|
| +
|
| +Handle JSApp::ConnectToService(const std::string& application_url,
|
| + const std::string& interface_name) {
|
| + CHECK(on_js_app_thread());
|
| + MessagePipe pipe;
|
| +
|
| + // The lifetime of content_handler_app_ is managed by the ApplicationRunner.
|
| + content_handler_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&ApplicationDelegateImpl::ConnectToService,
|
| + base::Unretained(content_handler_app_),
|
| + base::Passed(pipe.handle1.Pass()),
|
| + application_url,
|
| + interface_name));
|
| +
|
| + return pipe.handle0.release();
|
| +}
|
| +
|
| +void JSApp::Run() {
|
| + CHECK(!js_app_task_runner_.get() && !on_content_handler_thread());
|
| + js_app_task_runner_ = base::MessageLoop::current()->task_runner();
|
| +
|
| + // TODO(hansmuller): check the return value and fail gracefully.
|
| + std::string module;
|
| + common::BlockingCopyToString(content_->body.Pass(), &module);
|
| +
|
| + isolate_holder_.reset(
|
| + new gin::IsolateHolder(gin::IsolateHolder::kStrictMode));
|
| +
|
| + shell_runner_.reset(
|
| + new gin::ShellRunner(&runner_delegate_, isolate_holder_->isolate()));
|
| +
|
| + // TODO(hansmuller): exiting this scope here is OK?
|
| + gin::Runner::Scope scope(shell_runner_.get());
|
| + shell_runner_->Run(module.c_str(), url_.c_str());
|
| +}
|
| +
|
| +void JSApp::Terminate() {
|
| + shell_runner_.reset(NULL);
|
| +
|
| + // This JSApp's thread must be stopped on the thread that started it. Ask the
|
| + // content_handler_app_ to drop its reference to this app, which implicitly
|
| + // destroys this JSApp and stops its thread.
|
| + // The lifetime of content_handler_app_ is managed by the ApplicationRunner.
|
| + // The lifetime of the this JSApp is managed by the content_handler_app_.
|
| + content_handler_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&ApplicationDelegateImpl::QuitJSApp,
|
| + base::Unretained(content_handler_app_),
|
| + base::Unretained(this)));
|
| +}
|
| +
|
| +bool JSApp::on_content_handler_thread() const {
|
| + return content_handler_task_runner_.get() &&
|
| + content_handler_task_runner_.get() ==
|
| + base::MessageLoop::current()->task_runner().get();
|
| +}
|
| +
|
| +bool JSApp::on_js_app_thread() const {
|
| + return js_app_task_runner_.get() &&
|
| + js_app_task_runner_.get() ==
|
| + base::MessageLoop::current()->task_runner().get();
|
| +}
|
| +
|
| +} // namespace apps
|
| +} // namespace mojo
|
|
|