OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "third_party/mojo/src/mojo/edk/js/waiting_callback.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/message_loop/message_loop.h" | |
9 #include "gin/per_context_data.h" | |
10 #include "mojo/public/cpp/environment/environment.h" | |
11 | |
12 namespace mojo { | |
13 namespace js { | |
14 | |
15 namespace { | |
16 | |
17 v8::Handle<v8::Private> GetHiddenPropertyName(v8::Isolate* isolate) { | |
18 return v8::Private::ForApi( | |
19 isolate, gin::StringToV8(isolate, "::mojo::js::WaitingCallback")); | |
20 } | |
21 | |
22 } // namespace | |
23 | |
24 gin::WrapperInfo WaitingCallback::kWrapperInfo = { gin::kEmbedderNativeGin }; | |
25 | |
26 // static | |
27 gin::Handle<WaitingCallback> WaitingCallback::Create( | |
28 v8::Isolate* isolate, | |
29 v8::Handle<v8::Function> callback, | |
30 gin::Handle<HandleWrapper> handle_wrapper, | |
31 MojoHandleSignals signals) { | |
32 gin::Handle<WaitingCallback> waiting_callback = gin::CreateHandle( | |
33 isolate, new WaitingCallback(isolate, callback, handle_wrapper)); | |
34 waiting_callback->wait_id_ = Environment::GetDefaultAsyncWaiter()->AsyncWait( | |
35 handle_wrapper->get().value(), | |
36 signals, | |
37 MOJO_DEADLINE_INDEFINITE, | |
38 &WaitingCallback::CallOnHandleReady, | |
39 waiting_callback.get()); | |
40 return waiting_callback; | |
41 } | |
42 | |
43 void WaitingCallback::Cancel() { | |
44 if (!wait_id_) | |
45 return; | |
46 | |
47 handle_wrapper_->RemoveCloseObserver(this); | |
48 handle_wrapper_ = NULL; | |
49 Environment::GetDefaultAsyncWaiter()->CancelWait(wait_id_); | |
50 wait_id_ = 0; | |
51 } | |
52 | |
53 WaitingCallback::WaitingCallback(v8::Isolate* isolate, | |
54 v8::Handle<v8::Function> callback, | |
55 gin::Handle<HandleWrapper> handle_wrapper) | |
56 : wait_id_(0), handle_wrapper_(handle_wrapper.get()), weak_factory_(this) { | |
57 handle_wrapper_->AddCloseObserver(this); | |
58 v8::Handle<v8::Context> context = isolate->GetCurrentContext(); | |
59 runner_ = gin::PerContextData::From(context)->runner()->GetWeakPtr(); | |
60 GetWrapper(isolate) | |
61 ->SetPrivate(context, GetHiddenPropertyName(isolate), callback) | |
62 .FromJust(); | |
63 } | |
64 | |
65 WaitingCallback::~WaitingCallback() { | |
66 Cancel(); | |
67 } | |
68 | |
69 // static | |
70 void WaitingCallback::CallOnHandleReady(void* closure, MojoResult result) { | |
71 static_cast<WaitingCallback*>(closure)->OnHandleReady(result); | |
72 } | |
73 | |
74 void WaitingCallback::ClearWaitId() { | |
75 wait_id_ = 0; | |
76 handle_wrapper_->RemoveCloseObserver(this); | |
77 handle_wrapper_ = nullptr; | |
78 } | |
79 | |
80 void WaitingCallback::OnHandleReady(MojoResult result) { | |
81 ClearWaitId(); | |
82 CallCallback(result); | |
83 } | |
84 | |
85 void WaitingCallback::CallCallback(MojoResult result) { | |
86 // ClearWaitId must already have been called. | |
87 DCHECK(!wait_id_); | |
88 DCHECK(!handle_wrapper_); | |
89 | |
90 if (!runner_) | |
91 return; | |
92 | |
93 gin::Runner::Scope scope(runner_.get()); | |
94 v8::Isolate* isolate = runner_->GetContextHolder()->isolate(); | |
95 | |
96 v8::Handle<v8::Value> hidden_value = | |
97 GetWrapper(isolate) | |
98 ->GetPrivate(runner_->GetContextHolder()->context(), | |
99 GetHiddenPropertyName(isolate)) | |
100 .ToLocalChecked(); | |
101 v8::Handle<v8::Function> callback; | |
102 CHECK(gin::ConvertFromV8(isolate, hidden_value, &callback)); | |
103 | |
104 v8::Handle<v8::Value> args[] = { gin::ConvertToV8(isolate, result) }; | |
105 runner_->Call(callback, runner_->global(), 1, args); | |
106 } | |
107 | |
108 void WaitingCallback::OnWillCloseHandle() { | |
109 Environment::GetDefaultAsyncWaiter()->CancelWait(wait_id_); | |
110 | |
111 // This may be called from GC, so we can't execute Javascript now, call | |
112 // ClearWaitId explicitly, and CallCallback asynchronously. | |
113 ClearWaitId(); | |
114 base::MessageLoop::current()->PostTask( | |
115 FROM_HERE, | |
116 base::Bind(&WaitingCallback::CallCallback, weak_factory_.GetWeakPtr(), | |
117 MOJO_RESULT_INVALID_ARGUMENT)); | |
118 } | |
119 | |
120 } // namespace js | |
121 } // namespace mojo | |
OLD | NEW |