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

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: Rebase atop trunk 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 // TODO(solb) We shouldn't really control the managed UI thread's lifetime.
Wez 2013/07/12 20:13:41 nit: We _don't_ really control its lifetime, I thi
solb 2013/07/12 21:10:54 Done.
44 base::MessageLoop::QuitClosure()); 43 ui_task_runner_ = new AutoThreadTaskRunner(ui_loop_->message_loop_proxy(),
45 net_runner_ = AutoThread::CreateWithType("native_net", 44 base::MessageLoop::QuitClosure());
46 ui_runner_, 45 network_task_runner_ = AutoThread::CreateWithType("native_net",
47 base::MessageLoop::TYPE_IO); 46 ui_task_runner_,
48 disp_runner_ = AutoThread::CreateWithType("native_disp", 47 base::MessageLoop::TYPE_IO);
49 ui_runner_, 48 display_task_runner_ = AutoThread::Create("native_disp",
50 base::MessageLoop::TYPE_DEFAULT); 49 ui_task_runner_);
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() {
Wez 2013/07/12 20:13:41 nit: check which thread this is torn down on?
solb 2013/07/12 21:10:54 Done.
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());
71 DCHECK(!connected_);
72 connected_ = true;
69 73
70 username_jstr_ = static_cast<jstring>(env->NewGlobalRef(username)); 74 username_ = username;
71 auth_token_jstr_ = static_cast<jstring>(env->NewGlobalRef(auth_token)); 75 auth_token_ = auth_token;
72 host_jid_jstr_ = static_cast<jstring>(env->NewGlobalRef(host_jid)); 76 host_jid_ = host_jid;
73 host_id_jstr_ = static_cast<jstring>(env->NewGlobalRef(host_id)); 77 host_id_ = host_id;
74 host_pubkey_jstr_ = static_cast<jstring>(env->NewGlobalRef(host_pubkey)); 78 host_pubkey_ = host_pubkey;
75 79
76 username_cstr_ = env->GetStringUTFChars(username_jstr_, NULL); 80 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, 81 &ChromotingJNIInstance::ConnectToHostOnDisplayThread,
85 base::Unretained(this))); 82 base::Unretained(this)));
86 } 83 }
87 84
88 void ChromotingJNIInstance::DisconnectFromHost() { 85 void ChromotingJNIInstance::DisconnectFromHost() {
89 JNIEnv* env = base::android::AttachCurrentThread(); 86 DCHECK(ui_task_runner_->BelongsToCurrentThread() && connected_);
Wez 2013/07/12 20:13:41 Check thread & connected_ state separately, as abo
solb 2013/07/12 21:10:54 Sorry; I'm not sure how that slipped through.
87 connected_ = false;
90 88
91 env->ReleaseStringUTFChars(username_jstr_, username_cstr_); 89 network_task_runner_->PostTask(FROM_HERE, base::Bind(
92 env->ReleaseStringUTFChars(auth_token_jstr_, auth_token_cstr_);
93 env->ReleaseStringUTFChars(host_jid_jstr_, host_jid_cstr_);
94 env->ReleaseStringUTFChars(host_id_jstr_, host_id_cstr_);
95 env->ReleaseStringUTFChars(host_pubkey_jstr_, host_pubkey_cstr_);
96
97 username_cstr_ = NULL;
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, 90 &ChromotingJNIInstance::DisconnectFromHostOnNetworkThread,
119 base::Unretained(this))); 91 base::Unretained(this)));
120 } 92 }
121 93
122 void ChromotingJNIInstance::AuthenticateWithPin(jstring pin) { 94 void ChromotingJNIInstance::AuthenticateWithPin(const char* pin) {
Wez 2013/07/12 20:13:41 Do you need to check which thread this is called o
solb 2013/07/12 21:10:54 Done.
123 JNIEnv* env = base::android::AttachCurrentThread(); 95 pin_ = pin;
Wez 2013/07/12 20:13:41 Why do you store the PIN at all? You never seem to
solb 2013/07/12 21:10:54 Good point. I think this is a bit of a leftover, b
124 96 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 } 97 }
130 98
131 void ChromotingJNIInstance::FetchSecret( 99 void ChromotingJNIInstance::FetchSecret(
132 bool pairable, 100 bool pairable,
133 const protocol::SecretFetchedCallback& callback_encore) { 101 const protocol::SecretFetchedCallback& callback) {
134 // All our work must be done on the UI thread. 102 if (!ui_task_runner_->BelongsToCurrentThread()) {
135 if (!ui_runner_->BelongsToCurrentThread()) { 103 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, 104 &ChromotingJNIInstance::FetchSecret,
139 base::Unretained(this), 105 base::Unretained(this),
140 pairable, 106 pairable,
141 callback_encore)); 107 callback));
142 return; 108 return;
143 } 109 }
144 110
145 announce_secret_ = callback_encore; 111 pin_callback_ = callback;
146 JNIEnv* env = base::android::AttachCurrentThread(); 112 JNIEnv* env = base::android::AttachCurrentThread();
147 env->CallStaticVoidMethod( 113 env->CallStaticVoidMethod(
148 class_, 114 class_,
149 env->GetStaticMethodID(class_, "displayAuthenticationPrompt", "()V")); 115 env->GetStaticMethodID(class_, "displayAuthenticationPrompt", "()V"));
150 } 116 }
151 117
152 void ChromotingJNIInstance::OnConnectionState( 118 void ChromotingJNIInstance::OnConnectionState(
153 protocol::ConnectionToHost::State state, 119 protocol::ConnectionToHost::State state,
154 protocol::ErrorCode error) { 120 protocol::ErrorCode error) {
155 // All our work must be done on the UI thread. 121 if (!ui_task_runner_->BelongsToCurrentThread()) {
156 if (!ui_runner_->BelongsToCurrentThread()) { 122 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, 123 &ChromotingJNIInstance::OnConnectionState,
160 base::Unretained(this), 124 base::Unretained(this),
161 state, 125 state,
162 error)); 126 error));
163 return; 127 return;
164 } 128 }
165 129
166 JNIEnv* env = base::android::AttachCurrentThread(); 130 JNIEnv* env = base::android::AttachCurrentThread();
167 env->CallStaticVoidMethod( 131 env->CallStaticVoidMethod(
168 class_, 132 class_,
169 env->GetStaticMethodID(class_, "reportConnectionStatus", "(II)V"), 133 env->GetStaticMethodID(class_, "reportConnectionStatus", "(II)V"),
170 state, 134 state,
171 error); 135 error);
172 } 136 }
173 137
174 void ChromotingJNIInstance::OnConnectionReady(bool ready) { 138 void ChromotingJNIInstance::OnConnectionReady(bool ready) {
139 // We ignore this message, since OnConnectionState() tells us the same thing.
175 } 140 }
176 141
177 void ChromotingJNIInstance::SetCapabilities(const std::string& capabilities) {} 142 void ChromotingJNIInstance::SetCapabilities(const std::string& capabilities) {}
178 143
179 void ChromotingJNIInstance::SetPairingResponse( 144 void ChromotingJNIInstance::SetPairingResponse(
180 const protocol::PairingResponse& response) {} 145 const protocol::PairingResponse& response) {
146 NOTIMPLEMENTED();
147 }
181 148
182 protocol::ClipboardStub* ChromotingJNIInstance::GetClipboardStub() { 149 protocol::ClipboardStub* ChromotingJNIInstance::GetClipboardStub() {
183 NOTIMPLEMENTED(); 150 NOTIMPLEMENTED();
184 return NULL; 151 return NULL;
185 } 152 }
186 153
187 protocol::CursorShapeStub* ChromotingJNIInstance::GetCursorShapeStub() { 154 protocol::CursorShapeStub* ChromotingJNIInstance::GetCursorShapeStub() {
188 NOTIMPLEMENTED(); 155 NOTIMPLEMENTED();
189 return NULL; 156 return NULL;
190 } 157 }
191 158
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> 159 scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher>
196 ChromotingJNIInstance::GetTokenFetcher(const std::string& host_public_key) { 160 ChromotingJNIInstance::GetTokenFetcher(const std::string& host_public_key) {
197 LOG(INFO) << "ChromotingJNIInstance::GetTokenFetcher(...) [unimplemented]"; 161 // Return null to indicate that third-party authentication is unsupported.
198 return scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher>(); 162 return scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher>();
199 } 163 }
200 164
201 void ChromotingJNIInstance::ConnectToHostOnDisplayThread() { 165 void ChromotingJNIInstance::ConnectToHostOnDisplayThread() {
202 DCHECK(disp_runner_->BelongsToCurrentThread()); 166 DCHECK(display_task_runner_->BelongsToCurrentThread());
203 167
204 if (!frames_.get()) { 168 if (!frame_consumer_.get()) {
205 frames_ = new FrameConsumerProxy(disp_runner_); 169 frame_consumer_ = new FrameConsumerProxy(display_task_runner_);
206 // TODO(solb) Instantiate some FrameConsumer implementation and attach it. 170 // TODO(solb) Instantiate some FrameConsumer implementation and attach it.
207 } 171 }
208 172
209 // We're a singleton, so Unretained is safe here. 173 network_task_runner_->PostTask(FROM_HERE, base::Bind(
210 net_runner_->PostTask(FROM_HERE, base::Bind(
211 &ChromotingJNIInstance::ConnectToHostOnNetworkThread, 174 &ChromotingJNIInstance::ConnectToHostOnNetworkThread,
212 base::Unretained(this))); 175 base::Unretained(this)));
213 } 176 }
214 177
215 void ChromotingJNIInstance::ConnectToHostOnNetworkThread() { 178 void ChromotingJNIInstance::ConnectToHostOnNetworkThread() {
216 DCHECK(net_runner_->BelongsToCurrentThread()); 179 DCHECK(network_task_runner_->BelongsToCurrentThread());
217 180
218 client_config_.reset(new ClientConfig()); 181 client_config_.reset(new ClientConfig());
219 client_config_->host_jid = host_jid_cstr_; 182 client_config_->host_jid = host_jid_;
220 client_config_->host_public_key = host_pubkey_cstr_; 183 client_config_->host_public_key = host_pubkey_;
221 // We're a singleton, so Unretained is safe here. 184
222 client_config_->fetch_secret_callback = base::Bind( 185 client_config_->fetch_secret_callback = base::Bind(
223 &ChromotingJNIInstance::FetchSecret, 186 &ChromotingJNIInstance::FetchSecret,
224 base::Unretained(this)); 187 base::Unretained(this));
225 client_config_->authentication_tag = host_id_cstr_; 188 client_config_->authentication_tag = host_id_;
226 189
227 // TODO(solb) Move these hardcoded values elsewhere: 190 // TODO(solb) Move these hardcoded values elsewhere:
228 client_config_->authentication_methods.push_back( 191 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")); 192 protocol::AuthenticationMethod::FromString("spake2_hmac"));
232 client_config_->authentication_methods.push_back( 193 client_config_->authentication_methods.push_back(
233 protocol::AuthenticationMethod::FromString("spake2_plain")); 194 protocol::AuthenticationMethod::FromString("spake2_plain"));
234 195
235 client_context_.reset(new ClientContext(net_runner_.get())); 196 client_context_.reset(new ClientContext(network_task_runner_.get()));
236 client_context_->Start(); 197 client_context_->Start();
237 198
238 connection_.reset(new protocol::ConnectionToHost(true)); 199 connection_.reset(new protocol::ConnectionToHost(true));
239 200
240 client_.reset(new ChromotingClient(*client_config_, 201 client_.reset(new ChromotingClient(*client_config_,
241 client_context_.get(), 202 client_context_.get(),
242 connection_.get(), 203 connection_.get(),
243 this, 204 this,
244 frames_, 205 frame_consumer_,
245 scoped_ptr<AudioPlayer>())); 206 scoped_ptr<AudioPlayer>()));
246 207
247 chat_config_.reset(new XmppSignalStrategy::XmppServerConfig()); 208 signaling_config_.reset(new XmppSignalStrategy::XmppServerConfig());
248 chat_config_->host = CHAT_SERVER; 209 signaling_config_->host = CHAT_SERVER;
249 chat_config_->port = CHAT_PORT; 210 signaling_config_->port = CHAT_PORT;
250 chat_config_->use_tls = CHAT_USE_TLS; 211 signaling_config_->use_tls = CHAT_USE_TLS;
251 212
252 chat_.reset(new XmppSignalStrategy(url_requester_, 213 signaling_.reset(new XmppSignalStrategy(url_requester_,
253 username_cstr_, 214 username_,
254 auth_token_cstr_, 215 auth_token_,
255 CHAT_AUTH_METHOD, 216 CHAT_AUTH_METHOD,
256 *chat_config_)); 217 *signaling_config_));
257 218
258 netset_.reset(new NetworkSettings(NetworkSettings::NAT_TRAVERSAL_OUTGOING)); 219 network_settings_.reset(new NetworkSettings(
220 NetworkSettings::NAT_TRAVERSAL_OUTGOING));
259 scoped_ptr<protocol::TransportFactory> fact( 221 scoped_ptr<protocol::TransportFactory> fact(
260 protocol::LibjingleTransportFactory::Create(*netset_, url_requester_)); 222 protocol::LibjingleTransportFactory::Create(*network_settings_,
223 url_requester_));
261 224
262 client_->Start(chat_.get(), fact.Pass()); 225 client_->Start(signaling_.get(), fact.Pass());
263 } 226 }
264 227
265 void ChromotingJNIInstance::DisconnectFromHostOnNetworkThread() { 228 void ChromotingJNIInstance::DisconnectFromHostOnNetworkThread() {
266 DCHECK(net_runner_->BelongsToCurrentThread()); 229 DCHECK(network_task_runner_->BelongsToCurrentThread());
267 230
231 username_ = "";
232 auth_token_ = "";
233 host_jid_ = "";
234 host_id_ = "";
235 host_pubkey_ = "";
236 pin_ = "";
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