js_app.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved. 21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Use of this source code is governed by a BSD-style license that can be 31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// found in the LICENSE file. 41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "mojo/apps/js/js_app.h" 61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/bind.h" 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "gin/array_buffer.h" 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "gin/converter.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "mojo/apps/js/application_delegate_impl.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "mojo/apps/js/mojo_module.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "mojo/common/data_pipe_utils.h" 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace mojo { 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace apps { 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciJSApp::JSApp(ApplicationDelegateImpl* content_handler_app, 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& url, 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci URLResponsePtr content) 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : content_handler_app_(content_handler_app), 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url_(url), 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content_(content.Pass()), 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci thread_("Mojo JS " + url), 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content_handler_task_runner_( 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::MessageLoop::current()->task_runner()) { 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(on_content_handler_thread()); 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci runner_delegate_.AddBuiltinModule(Mojo::kModuleName, 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(Mojo::GetModule, this)); 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciJSApp::~JSApp() { 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool JSApp::Start() { 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(!js_app_task_runner_.get() && on_content_handler_thread()); 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0); 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci thread_.StartWithOptions(thread_options); 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(hansmuller): check thread_.StartWithOptions() return value. 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(hansmuller): need to funnel Run() failures back to the caller. 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci thread_.message_loop()->PostTask( 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FROM_HERE, base::Bind(&JSApp::Run, base::Unretained(this))); 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return true; 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid JSApp::Quit() { 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(on_js_app_thread()); 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The terminate operation is posted to the message_loop so that 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the shell_runner isn't destroyed before this JS function returns. 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci thread_.message_loop()->PostTask( 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FROM_HERE, base::Bind(&JSApp::Terminate, base::Unretained(this))); 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciHandle JSApp::ConnectToService(const std::string& application_url, 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& interface_name) { 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(on_js_app_thread()); 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MessagePipe pipe; 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content_handler_task_runner_->PostTask( 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FROM_HERE, 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&ApplicationDelegateImpl::ConnectToService, 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(content_handler_app_), 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Passed(pipe.handle1.Pass()), 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci application_url, 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci interface_name)); 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return pipe.handle0.release(); 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid JSApp::Run() { 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(!js_app_task_runner_.get() && !on_content_handler_thread()); 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci js_app_task_runner_ = base::MessageLoop::current()->task_runner(); 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(hansmuller): check the return value and fail gracefully. 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::string module; 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci common::BlockingCopyToString(content_->body.Pass(), &module); 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gin::IsolateHolder::Initialize(gin::IsolateHolder::kStrictMode, 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gin::ArrayBufferAllocator::SharedInstance()); 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci isolate_holder_.reset(new gin::IsolateHolder()); 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci isolate_holder_->AddRunMicrotasksObserver(); 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci shell_runner_.reset( 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new gin::ShellRunner(&runner_delegate_, isolate_holder_->isolate())); 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(hansmuller): exiting this scope here is OK? 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gin::Runner::Scope scope(shell_runner_.get()); 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci shell_runner_->Run(module.c_str(), url_.c_str()); 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid JSApp::Terminate() { 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci isolate_holder_->RemoveRunMicrotasksObserver(); 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci shell_runner_.reset(NULL); 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // This JSApp's thread must be stopped on the thread that started it. Ask the 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // content_handler_app_ to erase its AppVector entry for this app, which 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // implicitly destroys this JSApp and stops its thread. 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content_handler_task_runner_->PostTask( 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FROM_HERE, 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&ApplicationDelegateImpl::QuitJSApp, 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(content_handler_app_), 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(this))); 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool JSApp::on_content_handler_thread() const { 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return content_handler_task_runner_.get() && 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content_handler_task_runner_.get() == 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::MessageLoop::current()->task_runner().get(); 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool JSApp::on_js_app_thread() const { 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return js_app_task_runner_.get() && 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci js_app_task_runner_.get() == 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::MessageLoop::current()->task_runner().get(); 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace apps 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace mojo 121