Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(208)

Side by Side Diff: remoting/client/jni/chromoting_jni_instance.cc

Issue 18612018: Restructure chromoting_jni_instance handling of Java strings (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Ensure connect and disconnect are called on the same thread Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "remoting/client/jni/chromoting_jni_instance.h" 5 #include "remoting/client/jni/chromoting_jni_instance.h"
6 6
7 #include "base/android/base_jni_registrar.h" 7 #include "base/android/base_jni_registrar.h"
8 #include "base/android/jni_android.h" 8 #include "base/android/jni_android.h"
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/memory/singleton.h" 12 #include "base/memory/singleton.h"
13 #include "net/android/net_jni_registrar.h" 13 #include "net/android/net_jni_registrar.h"
14 #include "remoting/base/url_request_context.h" 14 #include "remoting/base/url_request_context.h"
15 #include "remoting/client/audio_player.h" 15 #include "remoting/client/audio_player.h"
16 #include "remoting/protocol/libjingle_transport_factory.h" 16 #include "remoting/protocol/libjingle_transport_factory.h"
17 17
18 namespace remoting { 18 namespace remoting {
19 19
20 // static 20 // static
21 ChromotingJNIInstance* ChromotingJNIInstance::GetInstance() { 21 ChromotingJNIInstance* ChromotingJNIInstance::GetInstance() {
22 return Singleton<ChromotingJNIInstance>::get(); 22 return Singleton<ChromotingJNIInstance>::get();
23 } 23 }
24 24
25 ChromotingJNIInstance::ChromotingJNIInstance() 25 ChromotingJNIInstance::ChromotingJNIInstance()
26 : username_cstr_(NULL), 26 : connected_(false) {
27 auth_token_cstr_(NULL),
28 host_jid_cstr_(NULL),
29 host_id_cstr_(NULL),
30 host_pubkey_cstr_(NULL),
31 pin_cstr_(NULL) {
32 JNIEnv* env = base::android::AttachCurrentThread(); 27 JNIEnv* env = base::android::AttachCurrentThread();
33 28
29 // The base and networks stacks must be registered with JNI in order to work
30 // on Android. An AtExitManager cleans this up at world's end.
34 collector_.reset(new base::AtExitManager()); 31 collector_.reset(new base::AtExitManager());
35 base::android::RegisterJni(env); 32 base::android::RegisterJni(env);
36 net::android::RegisterJni(env); 33 net::android::RegisterJni(env);
37 34
38 LOG(INFO) << "starting main message loop"; 35 // On Android, the UI thread is managed by Java, so we need to attach and
36 // start a special type of message loop to allow Chromium code to run tasks.
37 LOG(INFO) << "Starting main message loop";
39 ui_loop_.reset(new base::MessageLoopForUI()); 38 ui_loop_.reset(new base::MessageLoopForUI());
40 ui_loop_->Start(); 39 ui_loop_->Start();
41 40
42 LOG(INFO) << "spawning additional threads"; 41 LOG(INFO) << "Spawning additional threads";
43 ui_runner_ = new AutoThreadTaskRunner(ui_loop_->message_loop_proxy(), 42 ui_task_runner_ = new AutoThreadTaskRunner(ui_loop_->message_loop_proxy(),
44 base::MessageLoop::QuitClosure()); 43 base::MessageLoop::QuitClosure());
45 net_runner_ = AutoThread::CreateWithType("native_net", 44 network_task_runner_ = AutoThread::CreateWithType("native_net",
46 ui_runner_, 45 ui_task_runner_,
47 base::MessageLoop::TYPE_IO); 46 base::MessageLoop::TYPE_IO);
48 disp_runner_ = AutoThread::CreateWithType("native_disp", 47 display_task_runner_ = AutoThread::CreateWithType("native_disp",
49 ui_runner_, 48 ui_task_runner_,
50 base::MessageLoop::TYPE_DEFAULT); 49 base::MessageLoop::TYPE_DEFAULT);
51 50
52 url_requester_ = new URLRequestContextGetter(ui_runner_, net_runner_); 51 url_requester_ = new URLRequestContextGetter(ui_task_runner_,
52 network_task_runner_);
53 53
54 class_ = static_cast<jclass>(env->NewGlobalRef(env->FindClass(JAVA_CLASS))); 54 class_ = static_cast<jclass>(env->NewGlobalRef(env->FindClass(JAVA_CLASS)));
55 } 55 }
56 56
57 ChromotingJNIInstance::~ChromotingJNIInstance() { 57 ChromotingJNIInstance::~ChromotingJNIInstance() {
58 DCHECK(!connected_);
59
58 JNIEnv* env = base::android::AttachCurrentThread(); 60 JNIEnv* env = base::android::AttachCurrentThread();
59 env->DeleteGlobalRef(class_); 61 env->DeleteGlobalRef(class_);
60 // TODO(solb) detach all threads from JVM 62 // TODO(solb): crbug.com/259594 Detach all threads from JVM here.
61 } 63 }
62 64
63 void ChromotingJNIInstance::ConnectToHost(jstring username, 65 void ChromotingJNIInstance::ConnectToHost(const char* username,
64 jstring auth_token, 66 const char* auth_token,
65 jstring host_jid, 67 const char* host_jid,
66 jstring host_id, 68 const char* host_id,
67 jstring host_pubkey) { 69 const char* host_pubkey) {
68 JNIEnv* env = base::android::AttachCurrentThread(); 70 DCHECK(ui_task_runner_->BelongsToCurrentThread() && !connected_);
Wez 2013/07/12 01:25:44 DCHECK() preconditions separately, so you can see
solb 2013/07/12 02:31:49 Done.
71 connected_ = true;
69 72
70 username_jstr_ = static_cast<jstring>(env->NewGlobalRef(username)); 73 username_ = username;
71 auth_token_jstr_ = static_cast<jstring>(env->NewGlobalRef(auth_token)); 74 auth_token_ = auth_token;
72 host_jid_jstr_ = static_cast<jstring>(env->NewGlobalRef(host_jid)); 75 host_jid_ = host_jid;
73 host_id_jstr_ = static_cast<jstring>(env->NewGlobalRef(host_id)); 76 host_id_ = host_id;
74 host_pubkey_jstr_ = static_cast<jstring>(env->NewGlobalRef(host_pubkey)); 77 host_pubkey_ = host_pubkey;
75 78
76 username_cstr_ = env->GetStringUTFChars(username_jstr_, NULL); 79 display_task_runner_->PostTask(FROM_HERE, base::Bind(
77 auth_token_cstr_ = env->GetStringUTFChars(auth_token_jstr_, NULL);
78 host_jid_cstr_ = env->GetStringUTFChars(host_jid_jstr_, NULL);
79 host_id_cstr_ = env->GetStringUTFChars(host_id_jstr_, NULL);
80 host_pubkey_cstr_ = env->GetStringUTFChars(host_pubkey_jstr_, NULL);
81
82 // We're a singleton, so Unretained is safe here.
83 disp_runner_->PostTask(FROM_HERE, base::Bind(
84 &ChromotingJNIInstance::ConnectToHostOnDisplayThread, 80 &ChromotingJNIInstance::ConnectToHostOnDisplayThread,
85 base::Unretained(this))); 81 base::Unretained(this)));
86 } 82 }
87 83
88 void ChromotingJNIInstance::DisconnectFromHost() { 84 void ChromotingJNIInstance::DisconnectFromHost() {
89 JNIEnv* env = base::android::AttachCurrentThread(); 85 DCHECK(ui_task_runner_->BelongsToCurrentThread() && connected_);
86 connected_ = false;
90 87
91 env->ReleaseStringUTFChars(username_jstr_, username_cstr_); 88 username_ = "";
92 env->ReleaseStringUTFChars(auth_token_jstr_, auth_token_cstr_); 89 auth_token_ = "";
93 env->ReleaseStringUTFChars(host_jid_jstr_, host_jid_cstr_); 90 host_jid_ = "";
94 env->ReleaseStringUTFChars(host_id_jstr_, host_id_cstr_); 91 host_id_ = "";
95 env->ReleaseStringUTFChars(host_pubkey_jstr_, host_pubkey_cstr_); 92 host_pubkey_ = "";
93 pin_ = "";
96 94
97 username_cstr_ = NULL; 95 network_task_runner_->PostTask(FROM_HERE, base::Bind(
98 auth_token_cstr_ = NULL;
99 host_jid_cstr_ = NULL;
100 host_id_cstr_ = NULL;
101 host_pubkey_cstr_ = NULL;
102
103 env->DeleteGlobalRef(username_jstr_);
104 env->DeleteGlobalRef(auth_token_jstr_);
105 env->DeleteGlobalRef(host_jid_jstr_);
106 env->DeleteGlobalRef(host_id_jstr_);
107 env->DeleteGlobalRef(host_pubkey_jstr_);
108
109 if (pin_cstr_) {
110 // AuthenticatedWithPin() has been called.
111 env->ReleaseStringUTFChars(pin_jstr_, pin_cstr_);
112 pin_cstr_ = NULL;
113 env->DeleteGlobalRef(pin_jstr_);
114 }
115
116 // We're a singleton, so Unretained is safe here.
117 net_runner_->PostTask(FROM_HERE, base::Bind(
118 &ChromotingJNIInstance::DisconnectFromHostOnNetworkThread, 96 &ChromotingJNIInstance::DisconnectFromHostOnNetworkThread,
119 base::Unretained(this))); 97 base::Unretained(this)));
120 } 98 }
121 99
122 void ChromotingJNIInstance::AuthenticateWithPin(jstring pin) { 100 void ChromotingJNIInstance::AuthenticateWithPin(const char* pin) {
123 JNIEnv* env = base::android::AttachCurrentThread(); 101 pin_ = pin;
124 102 network_task_runner_->PostTask(FROM_HERE, base::Bind(pin_callback_, pin_));
125 pin_jstr_ = static_cast<jstring>(env->NewGlobalRef(pin));
126 pin_cstr_ = env->GetStringUTFChars(pin_jstr_, NULL);
127
128 net_runner_->PostTask(FROM_HERE, base::Bind(announce_secret_, pin_cstr_));
129 } 103 }
130 104
131 void ChromotingJNIInstance::FetchSecret( 105 void ChromotingJNIInstance::FetchSecret(
132 bool pairable, 106 bool pairable,
133 const protocol::SecretFetchedCallback& callback_encore) { 107 const protocol::SecretFetchedCallback& callback) {
134 // All our work must be done on the UI thread. 108 if (!ui_task_runner_->BelongsToCurrentThread()) {
135 if (!ui_runner_->BelongsToCurrentThread()) { 109 ui_task_runner_->PostTask(FROM_HERE, base::Bind(
136 // We're a singleton, so Unretained is safe here.
137 ui_runner_->PostTask(FROM_HERE, base::Bind(
138 &ChromotingJNIInstance::FetchSecret, 110 &ChromotingJNIInstance::FetchSecret,
139 base::Unretained(this), 111 base::Unretained(this),
140 pairable, 112 pairable,
141 callback_encore)); 113 callback));
142 return; 114 return;
143 } 115 }
144 116
145 announce_secret_ = callback_encore; 117 pin_callback_ = callback;
146 JNIEnv* env = base::android::AttachCurrentThread(); 118 JNIEnv* env = base::android::AttachCurrentThread();
147 env->CallStaticVoidMethod( 119 env->CallStaticVoidMethod(
148 class_, 120 class_,
149 env->GetStaticMethodID(class_, "displayAuthenticationPrompt", "()V")); 121 env->GetStaticMethodID(class_, "displayAuthenticationPrompt", "()V"));
150 } 122 }
151 123
152 void ChromotingJNIInstance::OnConnectionState( 124 void ChromotingJNIInstance::OnConnectionState(
153 protocol::ConnectionToHost::State state, 125 protocol::ConnectionToHost::State state,
154 protocol::ErrorCode error) { 126 protocol::ErrorCode error) {
155 // All our work must be done on the UI thread. 127 if (!ui_task_runner_->BelongsToCurrentThread()) {
156 if (!ui_runner_->BelongsToCurrentThread()) { 128 ui_task_runner_->PostTask(FROM_HERE, base::Bind(
157 // We're a singleton, so Unretained is safe here.
158 ui_runner_->PostTask(FROM_HERE, base::Bind(
159 &ChromotingJNIInstance::OnConnectionState, 129 &ChromotingJNIInstance::OnConnectionState,
160 base::Unretained(this), 130 base::Unretained(this),
161 state, 131 state,
162 error)); 132 error));
163 return; 133 return;
164 } 134 }
165 135
166 JNIEnv* env = base::android::AttachCurrentThread(); 136 JNIEnv* env = base::android::AttachCurrentThread();
167 env->CallStaticVoidMethod( 137 env->CallStaticVoidMethod(
168 class_, 138 class_,
169 env->GetStaticMethodID(class_, "reportConnectionStatus", "(II)V"), 139 env->GetStaticMethodID(class_, "reportConnectionStatus", "(II)V"),
170 state, 140 state,
171 error); 141 error);
172 } 142 }
173 143
174 void ChromotingJNIInstance::OnConnectionReady(bool ready) { 144 void ChromotingJNIInstance::OnConnectionReady(bool ready) {
145 // We ignore this message, since OnConnectionState() tells us the same thing.
175 } 146 }
176 147
177 void ChromotingJNIInstance::SetCapabilities(const std::string& capabilities) {} 148 void ChromotingJNIInstance::SetCapabilities(const std::string& capabilities) {}
178 149
179 void ChromotingJNIInstance::SetPairingResponse( 150 void ChromotingJNIInstance::SetPairingResponse(
180 const protocol::PairingResponse& response) {} 151 const protocol::PairingResponse& response) {
152 // Pairing is unsupported.
Wez 2013/07/12 01:25:44 nit: No need for the comment given the NOTIMPLEMEN
solb 2013/07/12 02:31:49 Done.
153 NOTIMPLEMENTED();
154 }
181 155
182 protocol::ClipboardStub* ChromotingJNIInstance::GetClipboardStub() { 156 protocol::ClipboardStub* ChromotingJNIInstance::GetClipboardStub() {
183 NOTIMPLEMENTED(); 157 NOTIMPLEMENTED();
184 return NULL; 158 return NULL;
185 } 159 }
186 160
187 protocol::CursorShapeStub* ChromotingJNIInstance::GetCursorShapeStub() { 161 protocol::CursorShapeStub* ChromotingJNIInstance::GetCursorShapeStub() {
188 NOTIMPLEMENTED(); 162 NOTIMPLEMENTED();
189 return NULL; 163 return NULL;
190 } 164 }
191 165
192 // We don't use NOTIMPLEMENTED() here because NegotiatingClientAuthenticator
193 // calls this even if it doesn't use the configuration method, and we don't
194 // want to print an error on every run.
195 scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher> 166 scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher>
196 ChromotingJNIInstance::GetTokenFetcher(const std::string& host_public_key) { 167 ChromotingJNIInstance::GetTokenFetcher(const std::string& host_public_key) {
197 LOG(INFO) << "ChromotingJNIInstance::GetTokenFetcher(...) [unimplemented]"; 168 // Return null to indicate that third-party authentication is unsupported.
198 return scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher>(); 169 return scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher>();
199 } 170 }
200 171
201 void ChromotingJNIInstance::ConnectToHostOnDisplayThread() { 172 void ChromotingJNIInstance::ConnectToHostOnDisplayThread() {
202 DCHECK(disp_runner_->BelongsToCurrentThread()); 173 DCHECK(display_task_runner_->BelongsToCurrentThread());
203 174
204 if (!frames_.get()) { 175 if (!frame_consumer_.get()) {
205 frames_ = new FrameConsumerProxy(disp_runner_); 176 frame_consumer_ = new FrameConsumerProxy(display_task_runner_);
206 // TODO(solb) Instantiate some FrameConsumer implementation and attach it. 177 // TODO(solb) Instantiate some FrameConsumer implementation and attach it.
207 } 178 }
208 179
209 // We're a singleton, so Unretained is safe here. 180 network_task_runner_->PostTask(FROM_HERE, base::Bind(
210 net_runner_->PostTask(FROM_HERE, base::Bind(
211 &ChromotingJNIInstance::ConnectToHostOnNetworkThread, 181 &ChromotingJNIInstance::ConnectToHostOnNetworkThread,
212 base::Unretained(this))); 182 base::Unretained(this)));
213 } 183 }
214 184
215 void ChromotingJNIInstance::ConnectToHostOnNetworkThread() { 185 void ChromotingJNIInstance::ConnectToHostOnNetworkThread() {
216 DCHECK(net_runner_->BelongsToCurrentThread()); 186 DCHECK(network_task_runner_->BelongsToCurrentThread());
217 187
218 client_config_.reset(new ClientConfig()); 188 client_config_.reset(new ClientConfig());
219 client_config_->host_jid = host_jid_cstr_; 189 client_config_->host_jid = host_jid_;
220 client_config_->host_public_key = host_pubkey_cstr_; 190 client_config_->host_public_key = host_pubkey_;
221 // We're a singleton, so Unretained is safe here. 191
222 client_config_->fetch_secret_callback = base::Bind( 192 client_config_->fetch_secret_callback = base::Bind(
223 &ChromotingJNIInstance::FetchSecret, 193 &ChromotingJNIInstance::FetchSecret,
224 base::Unretained(this)); 194 base::Unretained(this));
225 client_config_->authentication_tag = host_id_cstr_; 195 client_config_->authentication_tag = host_id_;
226 196
227 // TODO(solb) Move these hardcoded values elsewhere: 197 // TODO(solb) Move these hardcoded values elsewhere:
228 client_config_->authentication_methods.push_back( 198 client_config_->authentication_methods.push_back(
229 protocol::AuthenticationMethod::FromString("spake2_pair"));
230 client_config_->authentication_methods.push_back(
231 protocol::AuthenticationMethod::FromString("spake2_hmac")); 199 protocol::AuthenticationMethod::FromString("spake2_hmac"));
232 client_config_->authentication_methods.push_back( 200 client_config_->authentication_methods.push_back(
233 protocol::AuthenticationMethod::FromString("spake2_plain")); 201 protocol::AuthenticationMethod::FromString("spake2_plain"));
234 202
235 client_context_.reset(new ClientContext(net_runner_.get())); 203 client_context_.reset(new ClientContext(network_task_runner_.get()));
236 client_context_->Start(); 204 client_context_->Start();
237 205
238 connection_.reset(new protocol::ConnectionToHost(true)); 206 connection_.reset(new protocol::ConnectionToHost(true));
239 207
240 client_.reset(new ChromotingClient(*client_config_, 208 client_.reset(new ChromotingClient(*client_config_,
241 client_context_.get(), 209 client_context_.get(),
242 connection_.get(), 210 connection_.get(),
243 this, 211 this,
244 frames_, 212 frame_consumer_,
245 scoped_ptr<AudioPlayer>())); 213 scoped_ptr<AudioPlayer>()));
246 214
247 chat_config_.reset(new XmppSignalStrategy::XmppServerConfig()); 215 signaling_config_.reset(new XmppSignalStrategy::XmppServerConfig());
248 chat_config_->host = CHAT_SERVER; 216 signaling_config_->host = CHAT_SERVER;
249 chat_config_->port = CHAT_PORT; 217 signaling_config_->port = CHAT_PORT;
250 chat_config_->use_tls = CHAT_USE_TLS; 218 signaling_config_->use_tls = CHAT_USE_TLS;
251 219
252 chat_.reset(new XmppSignalStrategy(url_requester_, 220 signaling_.reset(new XmppSignalStrategy(url_requester_,
253 username_cstr_, 221 username_,
254 auth_token_cstr_, 222 auth_token_,
255 CHAT_AUTH_METHOD, 223 CHAT_AUTH_METHOD,
256 *chat_config_)); 224 *signaling_config_));
257 225
258 netset_.reset(new NetworkSettings(NetworkSettings::NAT_TRAVERSAL_OUTGOING)); 226 network_settings_.reset(new NetworkSettings(
227 NetworkSettings::NAT_TRAVERSAL_OUTGOING));
259 scoped_ptr<protocol::TransportFactory> fact( 228 scoped_ptr<protocol::TransportFactory> fact(
260 protocol::LibjingleTransportFactory::Create(*netset_, url_requester_)); 229 protocol::LibjingleTransportFactory::Create(*network_settings_,
230 url_requester_));
261 231
262 client_->Start(chat_.get(), fact.Pass()); 232 client_->Start(signaling_.get(), fact.Pass());
263 } 233 }
264 234
265 void ChromotingJNIInstance::DisconnectFromHostOnNetworkThread() { 235 void ChromotingJNIInstance::DisconnectFromHostOnNetworkThread() {
266 DCHECK(net_runner_->BelongsToCurrentThread()); 236 DCHECK(network_task_runner_->BelongsToCurrentThread());
267 237
238 // |client_| must be torn down before |signaling_|.
268 client_.reset(); 239 client_.reset();
269 connection_.reset(); 240 connection_.reset();
270 client_context_.reset(); 241 client_context_.reset();
271 client_config_.reset(); 242 client_config_.reset();
272 chat_.reset(); // This object must outlive client_. 243 signaling_.reset();
273 chat_config_.reset(); // TODO(solb) Restructure to reuse between sessions. 244 signaling_config_.reset();
274 netset_.reset(); 245 network_settings_.reset();
275 } 246 }
276 247
277 } // namespace remoting 248 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698