OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "services/js/js_app.h" | 5 #include "services/js/js_app.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "gin/array_buffer.h" | 8 #include "base/message_loop/message_loop.h" |
9 #include "gin/converter.h" | 9 #include "gin/converter.h" |
| 10 #include "gin/modules/module_registry.h" |
| 11 #include "gin/try_catch.h" |
10 #include "mojo/common/data_pipe_utils.h" | 12 #include "mojo/common/data_pipe_utils.h" |
| 13 #include "mojo/edk/js/core.h" |
| 14 #include "mojo/edk/js/handle.h" |
| 15 #include "mojo/edk/js/support.h" |
| 16 #include "mojo/public/cpp/bindings/interface_request.h" |
| 17 #include "services/js/js_app_shell.h" |
11 #include "services/js/mojo_bridge_module.h" | 18 #include "services/js/mojo_bridge_module.h" |
12 | 19 |
13 namespace mojo { | 20 namespace mojo { |
14 namespace js { | 21 namespace js { |
15 | 22 |
| 23 const char JSApp::kMainModuleName[] = "main"; |
| 24 |
16 JSApp::JSApp(ShellPtr shell, URLResponsePtr response) : shell_(shell.Pass()) { | 25 JSApp::JSApp(ShellPtr shell, URLResponsePtr response) : shell_(shell.Pass()) { |
17 // TODO(hansmuller): handle load failure here and below. | 26 isolate_holder_.AddRunMicrotasksObserver(); |
| 27 |
18 DCHECK(!response.is_null()); | 28 DCHECK(!response.is_null()); |
19 file_name_ = response->url; | 29 std::string url(response->url); |
20 bool result = common::BlockingCopyToString(response->body.Pass(), &source_); | 30 std::string source; |
21 DCHECK(result); | 31 CHECK(common::BlockingCopyToString(response->body.Pass(), &source)); |
22 | 32 |
23 runner_delegate.AddBuiltinModule(MojoInternals::kModuleName, | 33 v8::Isolate* isolate = isolate_holder_.isolate(); |
24 base::Bind(MojoInternals::GetModule, this)); | 34 shell_runner_.reset(new gin::ShellRunner(&runner_delegate_, isolate)); |
| 35 gin::Runner::Scope scope(shell_runner_.get()); |
| 36 shell_runner_->Run(source.c_str(), kMainModuleName); |
| 37 |
| 38 gin::ModuleRegistry* registry = |
| 39 gin::ModuleRegistry::From(shell_runner_->GetContextHolder()->context()); |
| 40 registry->LoadModule( |
| 41 isolate, |
| 42 kMainModuleName, |
| 43 base::Bind(&JSApp::OnAppLoaded, base::Unretained(this), url)); |
| 44 } |
| 45 |
| 46 JSApp::~JSApp() { |
| 47 app_instance_.Reset(); |
| 48 } |
| 49 |
| 50 |
| 51 void JSApp::OnAppLoaded(std::string url, v8::Handle<v8::Value> main_module) { |
| 52 gin::Runner::Scope scope(shell_runner_.get()); |
| 53 gin::TryCatch try_catch; |
| 54 v8::Isolate* isolate = isolate_holder_.isolate(); |
| 55 |
| 56 v8::Handle<v8::Value> argv[] = { |
| 57 gin::ConvertToV8(isolate, JSAppShell::Create(isolate, this)), |
| 58 gin::ConvertToV8(isolate, url) |
| 59 }; |
| 60 |
| 61 v8::Handle<v8::Function> app_class; |
| 62 CHECK(gin::ConvertFromV8(isolate, main_module, &app_class)); |
| 63 app_instance_.Reset(isolate, app_class->NewInstance(arraysize(argv), argv)); |
| 64 if (try_catch.HasCaught()) |
| 65 runner_delegate_.UnhandledException(shell_runner_.get(), try_catch); |
| 66 |
25 shell_.set_client(this); | 67 shell_.set_client(this); |
26 } | 68 } |
27 | 69 |
28 JSApp::~JSApp() { | 70 void JSApp::ConnectToApplication(const std::string& application_url, |
| 71 ScopedMessagePipeHandle service_provider) { |
| 72 shell_->ConnectToApplication( |
| 73 application_url, MakeRequest<ServiceProvider>(service_provider.Pass())); |
| 74 } |
| 75 |
| 76 void JSApp::CallAppInstanceMethod( |
| 77 const std::string& name, int argc, v8::Handle<v8::Value> argv[]) { |
| 78 v8::Isolate* isolate = isolate_holder_.isolate(); |
| 79 v8::Local<v8::Object> app = |
| 80 v8::Local<v8::Object>::New(isolate, app_instance_); |
| 81 v8::Handle<v8::Value> key = gin::StringToV8(isolate, name); |
| 82 v8::Handle<v8::Value> value = app->Get(key); |
| 83 if (!value->IsFunction()) |
| 84 return; |
| 85 v8::Handle<v8::Function> app_method; |
| 86 CHECK(gin::ConvertFromV8(isolate, value, &app_method)); |
| 87 shell_runner_->Call(app_method, app, argc, argv); |
| 88 } |
| 89 |
| 90 void JSApp::Initialize(Array<String> app_args) { |
| 91 gin::Runner::Scope scope(shell_runner_.get()); |
| 92 v8::Isolate* isolate = isolate_holder_.isolate(); |
| 93 v8::Handle<v8::Value> argv[] = { |
| 94 gin::ConvertToV8(isolate, app_args.To<std::vector<std::string>>()), |
| 95 }; |
| 96 CallAppInstanceMethod("initialize", 1, argv); |
| 97 } |
| 98 |
| 99 void JSApp::AcceptConnection(const String& requestor_url, |
| 100 ServiceProviderPtr provider) { |
| 101 gin::Runner::Scope scope(shell_runner_.get()); |
| 102 v8::Isolate* isolate = isolate_holder_.isolate(); |
| 103 v8::Handle<v8::Value> argv[] = { |
| 104 gin::ConvertToV8(isolate, requestor_url.To<std::string>()), |
| 105 gin::ConvertToV8(isolate, provider.PassMessagePipe().get()), |
| 106 }; |
| 107 CallAppInstanceMethod("acceptConnection", arraysize(argv), argv); |
29 } | 108 } |
30 | 109 |
31 void JSApp::Quit() { | 110 void JSApp::Quit() { |
32 isolate_holder_.RemoveRunMicrotasksObserver(); | 111 isolate_holder_.RemoveRunMicrotasksObserver(); |
33 base::MessageLoop::current()->PostTask( | 112 base::MessageLoop::current()->PostTask( |
34 FROM_HERE, base::Bind(&JSApp::QuitInternal, base::Unretained(this))); | 113 FROM_HERE, base::Bind(&JSApp::QuitInternal, base::Unretained(this))); |
35 } | 114 } |
36 | 115 |
37 MessagePipeHandle JSApp::ConnectToApplication( | |
38 const std::string& application_url) { | |
39 MessagePipe pipe; | |
40 InterfaceRequest<ServiceProvider> request = | |
41 MakeRequest<ServiceProvider>(pipe.handle1.Pass()); | |
42 shell_->ConnectToApplication(application_url, request.Pass()); | |
43 return pipe.handle0.Pass().release(); | |
44 } | |
45 | |
46 MessagePipeHandle JSApp::RequestorMessagePipeHandle() { | |
47 return requestor_handle_.get(); | |
48 } | |
49 | |
50 void JSApp::AcceptConnection(const String& requestor_url, | |
51 ServiceProviderPtr provider) { | |
52 requestor_handle_ = provider.PassMessagePipe(); | |
53 | |
54 isolate_holder_.AddRunMicrotasksObserver(); | |
55 shell_runner_.reset( | |
56 new gin::ShellRunner(&runner_delegate, isolate_holder_.isolate())); | |
57 gin::Runner::Scope scope(shell_runner_.get()); | |
58 shell_runner_->Run(source_.c_str(), file_name_.c_str()); | |
59 } | |
60 | |
61 void JSApp::Initialize(Array<String> args) { | |
62 } | |
63 | |
64 void JSApp::QuitInternal() { | 116 void JSApp::QuitInternal() { |
65 shell_runner_.reset(); | 117 shell_runner_.reset(); |
66 base::MessageLoop::current()->QuitWhenIdle(); | 118 base::MessageLoop::current()->QuitWhenIdle(); |
67 } | 119 } |
68 | 120 |
69 } // namespace js | 121 } // namespace js |
70 } // namespace mojo | 122 } // namespace mojo |
| 123 |
OLD | NEW |