| OLD | NEW |
| 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_runtime.h" | 5 #include "remoting/client/jni/chromoting_jni_runtime.h" |
| 6 | 6 |
| 7 #include "base/android/jni_android.h" | 7 #include "base/android/jni_android.h" |
| 8 #include "base/android/jni_array.h" | 8 #include "base/android/jni_array.h" |
| 9 #include "base/android/jni_string.h" | 9 #include "base/android/jni_string.h" |
| 10 #include "base/android/library_loader/library_loader_hooks.h" | 10 #include "base/android/library_loader/library_loader_hooks.h" |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 } | 206 } |
| 207 | 207 |
| 208 // ChromotingJniRuntime implementation. | 208 // ChromotingJniRuntime implementation. |
| 209 | 209 |
| 210 // static | 210 // static |
| 211 ChromotingJniRuntime* ChromotingJniRuntime::GetInstance() { | 211 ChromotingJniRuntime* ChromotingJniRuntime::GetInstance() { |
| 212 return base::Singleton<ChromotingJniRuntime>::get(); | 212 return base::Singleton<ChromotingJniRuntime>::get(); |
| 213 } | 213 } |
| 214 | 214 |
| 215 ChromotingJniRuntime::ChromotingJniRuntime() { | 215 ChromotingJniRuntime::ChromotingJniRuntime() { |
| 216 // On Android, the UI thread is managed by Java, so we need to attach and | 216 // Grab or create the threads. |
| 217 // start a special type of message loop to allow Chromium code to run tasks. | 217 // TODO(nicholss) We could runtime this as a constructor argument when jni |
| 218 ui_loop_.reset(new base::MessageLoopForUI()); | 218 // runtime is not no longer a singleton. |
| 219 ui_loop_->Start(); | 219 runtime_ = ChromotingClientRuntime::Create(); |
| 220 | |
| 221 // TODO(solb) Stop pretending to control the managed UI thread's lifetime. | |
| 222 ui_task_runner_ = new AutoThreadTaskRunner( | |
| 223 ui_loop_->task_runner(), base::MessageLoop::QuitWhenIdleClosure()); | |
| 224 network_task_runner_ = AutoThread::CreateWithType("native_net", | |
| 225 ui_task_runner_, | |
| 226 base::MessageLoop::TYPE_IO); | |
| 227 display_task_runner_ = AutoThread::Create("native_disp", | |
| 228 ui_task_runner_); | |
| 229 | |
| 230 url_requester_ = | |
| 231 new URLRequestContextGetter(network_task_runner_, network_task_runner_); | |
| 232 } | 220 } |
| 233 | 221 |
| 234 ChromotingJniRuntime::~ChromotingJniRuntime() { | 222 ChromotingJniRuntime::~ChromotingJniRuntime() { |
| 235 // The singleton should only ever be destroyed on the main thread. | 223 // The singleton should only ever be destroyed on the main thread. |
| 236 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 224 DCHECK(ui_task_runner()->BelongsToCurrentThread()); |
| 237 | 225 |
| 238 // The session must be shut down first, since it depends on our other | 226 // The session must be shut down first, since it depends on our other |
| 239 // components' still being alive. | 227 // components' still being alive. |
| 240 DisconnectFromHost(); | 228 DisconnectFromHost(); |
| 241 | 229 |
| 242 base::WaitableEvent done_event(false, false); | 230 base::WaitableEvent done_event(false, false); |
| 243 network_task_runner_->PostTask(FROM_HERE, base::Bind( | 231 network_task_runner()->PostTask( |
| 244 &ChromotingJniRuntime::DetachFromVmAndSignal, | 232 FROM_HERE, base::Bind(&ChromotingJniRuntime::DetachFromVmAndSignal, |
| 245 base::Unretained(this), | 233 base::Unretained(this), &done_event)); |
| 246 &done_event)); | |
| 247 done_event.Wait(); | 234 done_event.Wait(); |
| 248 display_task_runner_->PostTask(FROM_HERE, base::Bind( | 235 display_task_runner()->PostTask( |
| 249 &ChromotingJniRuntime::DetachFromVmAndSignal, | 236 FROM_HERE, base::Bind(&ChromotingJniRuntime::DetachFromVmAndSignal, |
| 250 base::Unretained(this), | 237 base::Unretained(this), &done_event)); |
| 251 &done_event)); | |
| 252 done_event.Wait(); | 238 done_event.Wait(); |
| 253 base::android::LibraryLoaderExitHook(); | 239 base::android::LibraryLoaderExitHook(); |
| 254 base::android::DetachFromVM(); | 240 base::android::DetachFromVM(); |
| 255 } | 241 } |
| 256 | 242 |
| 257 void ChromotingJniRuntime::ConnectToHost(const std::string& username, | 243 void ChromotingJniRuntime::ConnectToHost(const std::string& username, |
| 258 const std::string& auth_token, | 244 const std::string& auth_token, |
| 259 const std::string& host_jid, | 245 const std::string& host_jid, |
| 260 const std::string& host_id, | 246 const std::string& host_id, |
| 261 const std::string& host_pubkey, | 247 const std::string& host_pubkey, |
| 262 const std::string& pairing_id, | 248 const std::string& pairing_id, |
| 263 const std::string& pairing_secret, | 249 const std::string& pairing_secret, |
| 264 const std::string& capabilities, | 250 const std::string& capabilities, |
| 265 const std::string& flags) { | 251 const std::string& flags) { |
| 266 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 252 DCHECK(ui_task_runner()->BelongsToCurrentThread()); |
| 267 DCHECK(!session_.get()); | 253 DCHECK(!session_.get()); |
| 268 session_ = new ChromotingJniInstance(this, username, auth_token, host_jid, | 254 session_ = new ChromotingJniInstance(this, username, auth_token, host_jid, |
| 269 host_id, host_pubkey, pairing_id, | 255 host_id, host_pubkey, pairing_id, |
| 270 pairing_secret, capabilities, flags); | 256 pairing_secret, capabilities, flags); |
| 271 } | 257 } |
| 272 | 258 |
| 273 void ChromotingJniRuntime::DisconnectFromHost() { | 259 void ChromotingJniRuntime::DisconnectFromHost() { |
| 274 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 260 DCHECK(ui_task_runner()->BelongsToCurrentThread()); |
| 275 if (session_.get()) { | 261 if (session_.get()) { |
| 276 session_->Disconnect(); | 262 session_->Disconnect(); |
| 277 session_ = nullptr; | 263 session_ = nullptr; |
| 278 } | 264 } |
| 279 } | 265 } |
| 280 | 266 |
| 281 void ChromotingJniRuntime::OnConnectionState( | 267 void ChromotingJniRuntime::OnConnectionState( |
| 282 protocol::ConnectionToHost::State state, | 268 protocol::ConnectionToHost::State state, |
| 283 protocol::ErrorCode error) { | 269 protocol::ErrorCode error) { |
| 284 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 270 DCHECK(ui_task_runner()->BelongsToCurrentThread()); |
| 285 | 271 |
| 286 JNIEnv* env = base::android::AttachCurrentThread(); | 272 JNIEnv* env = base::android::AttachCurrentThread(); |
| 287 Java_JniInterface_onConnectionState(env, state, error); | 273 Java_JniInterface_onConnectionState(env, state, error); |
| 288 } | 274 } |
| 289 | 275 |
| 290 void ChromotingJniRuntime::DisplayAuthenticationPrompt(bool pairing_supported) { | 276 void ChromotingJniRuntime::DisplayAuthenticationPrompt(bool pairing_supported) { |
| 291 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 277 DCHECK(ui_task_runner()->BelongsToCurrentThread()); |
| 292 | 278 |
| 293 JNIEnv* env = base::android::AttachCurrentThread(); | 279 JNIEnv* env = base::android::AttachCurrentThread(); |
| 294 Java_JniInterface_displayAuthenticationPrompt(env, pairing_supported); | 280 Java_JniInterface_displayAuthenticationPrompt(env, pairing_supported); |
| 295 } | 281 } |
| 296 | 282 |
| 297 void ChromotingJniRuntime::CommitPairingCredentials(const std::string& host, | 283 void ChromotingJniRuntime::CommitPairingCredentials(const std::string& host, |
| 298 const std::string& id, | 284 const std::string& id, |
| 299 const std::string& secret) { | 285 const std::string& secret) { |
| 300 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 286 DCHECK(ui_task_runner()->BelongsToCurrentThread()); |
| 301 | 287 |
| 302 JNIEnv* env = base::android::AttachCurrentThread(); | 288 JNIEnv* env = base::android::AttachCurrentThread(); |
| 303 ScopedJavaLocalRef<jstring> j_host = ConvertUTF8ToJavaString(env, host); | 289 ScopedJavaLocalRef<jstring> j_host = ConvertUTF8ToJavaString(env, host); |
| 304 ScopedJavaLocalRef<jstring> j_id = ConvertUTF8ToJavaString(env, id); | 290 ScopedJavaLocalRef<jstring> j_id = ConvertUTF8ToJavaString(env, id); |
| 305 ScopedJavaLocalRef<jstring> j_secret = ConvertUTF8ToJavaString(env,secret); | 291 ScopedJavaLocalRef<jstring> j_secret = ConvertUTF8ToJavaString(env,secret); |
| 306 | 292 |
| 307 Java_JniInterface_commitPairingCredentials( | 293 Java_JniInterface_commitPairingCredentials( |
| 308 env, j_host.obj(), j_id.obj(), j_secret.obj()); | 294 env, j_host.obj(), j_id.obj(), j_secret.obj()); |
| 309 } | 295 } |
| 310 | 296 |
| 311 void ChromotingJniRuntime::FetchThirdPartyToken(const GURL& token_url, | 297 void ChromotingJniRuntime::FetchThirdPartyToken(const GURL& token_url, |
| 312 const std::string& client_id, | 298 const std::string& client_id, |
| 313 const std::string& scope) { | 299 const std::string& scope) { |
| 314 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 300 DCHECK(ui_task_runner()->BelongsToCurrentThread()); |
| 315 JNIEnv* env = base::android::AttachCurrentThread(); | 301 JNIEnv* env = base::android::AttachCurrentThread(); |
| 316 | 302 |
| 317 ScopedJavaLocalRef<jstring> j_url = | 303 ScopedJavaLocalRef<jstring> j_url = |
| 318 ConvertUTF8ToJavaString(env, token_url.spec()); | 304 ConvertUTF8ToJavaString(env, token_url.spec()); |
| 319 ScopedJavaLocalRef<jstring> j_client_id = | 305 ScopedJavaLocalRef<jstring> j_client_id = |
| 320 ConvertUTF8ToJavaString(env, client_id); | 306 ConvertUTF8ToJavaString(env, client_id); |
| 321 ScopedJavaLocalRef<jstring> j_scope = ConvertUTF8ToJavaString(env, scope); | 307 ScopedJavaLocalRef<jstring> j_scope = ConvertUTF8ToJavaString(env, scope); |
| 322 | 308 |
| 323 Java_JniInterface_fetchThirdPartyToken( | 309 Java_JniInterface_fetchThirdPartyToken( |
| 324 env, j_url.obj(), j_client_id.obj(), j_scope.obj()); | 310 env, j_url.obj(), j_client_id.obj(), j_scope.obj()); |
| 325 } | 311 } |
| 326 | 312 |
| 327 void ChromotingJniRuntime::SetCapabilities(const std::string& capabilities) { | 313 void ChromotingJniRuntime::SetCapabilities(const std::string& capabilities) { |
| 328 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 314 DCHECK(ui_task_runner()->BelongsToCurrentThread()); |
| 329 JNIEnv* env = base::android::AttachCurrentThread(); | 315 JNIEnv* env = base::android::AttachCurrentThread(); |
| 330 | 316 |
| 331 ScopedJavaLocalRef<jstring> j_cap = | 317 ScopedJavaLocalRef<jstring> j_cap = |
| 332 ConvertUTF8ToJavaString(env, capabilities); | 318 ConvertUTF8ToJavaString(env, capabilities); |
| 333 | 319 |
| 334 Java_JniInterface_setCapabilities(env, j_cap.obj()); | 320 Java_JniInterface_setCapabilities(env, j_cap.obj()); |
| 335 } | 321 } |
| 336 | 322 |
| 337 void ChromotingJniRuntime::HandleExtensionMessage(const std::string& type, | 323 void ChromotingJniRuntime::HandleExtensionMessage(const std::string& type, |
| 338 const std::string& message) { | 324 const std::string& message) { |
| 339 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 325 DCHECK(ui_task_runner()->BelongsToCurrentThread()); |
| 340 JNIEnv* env = base::android::AttachCurrentThread(); | 326 JNIEnv* env = base::android::AttachCurrentThread(); |
| 341 | 327 |
| 342 ScopedJavaLocalRef<jstring> j_type = ConvertUTF8ToJavaString(env, type); | 328 ScopedJavaLocalRef<jstring> j_type = ConvertUTF8ToJavaString(env, type); |
| 343 ScopedJavaLocalRef<jstring> j_message = ConvertUTF8ToJavaString(env, message); | 329 ScopedJavaLocalRef<jstring> j_message = ConvertUTF8ToJavaString(env, message); |
| 344 | 330 |
| 345 Java_JniInterface_handleExtensionMessage(env, j_type.obj(), j_message.obj()); | 331 Java_JniInterface_handleExtensionMessage(env, j_type.obj(), j_message.obj()); |
| 346 } | 332 } |
| 347 | 333 |
| 348 base::android::ScopedJavaLocalRef<jobject> ChromotingJniRuntime::NewBitmap( | 334 base::android::ScopedJavaLocalRef<jobject> ChromotingJniRuntime::NewBitmap( |
| 349 int width, int height) { | 335 int width, int height) { |
| 350 JNIEnv* env = base::android::AttachCurrentThread(); | 336 JNIEnv* env = base::android::AttachCurrentThread(); |
| 351 return Java_JniInterface_newBitmap(env, width, height); | 337 return Java_JniInterface_newBitmap(env, width, height); |
| 352 } | 338 } |
| 353 | 339 |
| 354 void ChromotingJniRuntime::UpdateFrameBitmap(jobject bitmap) { | 340 void ChromotingJniRuntime::UpdateFrameBitmap(jobject bitmap) { |
| 355 DCHECK(display_task_runner_->BelongsToCurrentThread()); | 341 DCHECK(display_task_runner()->BelongsToCurrentThread()); |
| 356 | 342 |
| 357 JNIEnv* env = base::android::AttachCurrentThread(); | 343 JNIEnv* env = base::android::AttachCurrentThread(); |
| 358 Java_JniInterface_setVideoFrame(env, bitmap); | 344 Java_JniInterface_setVideoFrame(env, bitmap); |
| 359 } | 345 } |
| 360 | 346 |
| 361 void ChromotingJniRuntime::UpdateCursorShape( | 347 void ChromotingJniRuntime::UpdateCursorShape( |
| 362 const protocol::CursorShapeInfo& cursor_shape) { | 348 const protocol::CursorShapeInfo& cursor_shape) { |
| 363 DCHECK(display_task_runner_->BelongsToCurrentThread()); | 349 DCHECK(display_task_runner()->BelongsToCurrentThread()); |
| 364 | 350 |
| 365 // const_cast<> is safe as long as the Java updateCursorShape() method copies | 351 // const_cast<> is safe as long as the Java updateCursorShape() method copies |
| 366 // the data out of the buffer without mutating it, and doesn't keep any | 352 // the data out of the buffer without mutating it, and doesn't keep any |
| 367 // reference to the buffer afterwards. Unfortunately, there seems to be no way | 353 // reference to the buffer afterwards. Unfortunately, there seems to be no way |
| 368 // to create a read-only ByteBuffer from a pointer-to-const. | 354 // to create a read-only ByteBuffer from a pointer-to-const. |
| 369 char* data = string_as_array(const_cast<std::string*>(&cursor_shape.data())); | 355 char* data = string_as_array(const_cast<std::string*>(&cursor_shape.data())); |
| 370 int cursor_total_bytes = | 356 int cursor_total_bytes = |
| 371 cursor_shape.width() * cursor_shape.height() * kBytesPerPixel; | 357 cursor_shape.width() * cursor_shape.height() * kBytesPerPixel; |
| 372 | 358 |
| 373 JNIEnv* env = base::android::AttachCurrentThread(); | 359 JNIEnv* env = base::android::AttachCurrentThread(); |
| 374 base::android::ScopedJavaLocalRef<jobject> buffer(env, | 360 base::android::ScopedJavaLocalRef<jobject> buffer(env, |
| 375 env->NewDirectByteBuffer(data, cursor_total_bytes)); | 361 env->NewDirectByteBuffer(data, cursor_total_bytes)); |
| 376 Java_JniInterface_updateCursorShape(env, | 362 Java_JniInterface_updateCursorShape(env, |
| 377 cursor_shape.width(), | 363 cursor_shape.width(), |
| 378 cursor_shape.height(), | 364 cursor_shape.height(), |
| 379 cursor_shape.hotspot_x(), | 365 cursor_shape.hotspot_x(), |
| 380 cursor_shape.hotspot_y(), | 366 cursor_shape.hotspot_y(), |
| 381 buffer.obj()); | 367 buffer.obj()); |
| 382 } | 368 } |
| 383 | 369 |
| 384 void ChromotingJniRuntime::RedrawCanvas() { | 370 void ChromotingJniRuntime::RedrawCanvas() { |
| 385 DCHECK(display_task_runner_->BelongsToCurrentThread()); | 371 DCHECK(display_task_runner()->BelongsToCurrentThread()); |
| 386 | 372 |
| 387 JNIEnv* env = base::android::AttachCurrentThread(); | 373 JNIEnv* env = base::android::AttachCurrentThread(); |
| 388 Java_JniInterface_redrawGraphicsInternal(env); | 374 Java_JniInterface_redrawGraphicsInternal(env); |
| 389 } | 375 } |
| 390 | 376 |
| 391 void ChromotingJniRuntime::DetachFromVmAndSignal(base::WaitableEvent* waiter) { | 377 void ChromotingJniRuntime::DetachFromVmAndSignal(base::WaitableEvent* waiter) { |
| 392 base::android::DetachFromVM(); | 378 base::android::DetachFromVM(); |
| 393 waiter->Signal(); | 379 waiter->Signal(); |
| 394 } | 380 } |
| 395 } // namespace remoting | 381 } // namespace remoting |
| OLD | NEW |