| 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 runtime_ = ChromotingClientRuntime::GetInstance(); |
| 218 ui_loop_.reset(new base::MessageLoopForUI()); | |
| 219 ui_loop_->Start(); | |
| 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 } | 218 } |
| 233 | 219 |
| 234 ChromotingJniRuntime::~ChromotingJniRuntime() { | 220 ChromotingJniRuntime::~ChromotingJniRuntime() { |
| 235 // The singleton should only ever be destroyed on the main thread. | 221 // The singleton should only ever be destroyed on the main thread. |
| 236 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 222 DCHECK(ui_task_runner()->BelongsToCurrentThread()); |
| 237 | 223 |
| 238 // The session must be shut down first, since it depends on our other | 224 // The session must be shut down first, since it depends on our other |
| 239 // components' still being alive. | 225 // components' still being alive. |
| 240 DisconnectFromHost(); | 226 DisconnectFromHost(); |
| 241 | 227 |
| 242 base::WaitableEvent done_event(false, false); | 228 base::WaitableEvent done_event(false, false); |
| 243 network_task_runner_->PostTask(FROM_HERE, base::Bind( | 229 network_task_runner()->PostTask( |
| 244 &ChromotingJniRuntime::DetachFromVmAndSignal, | 230 FROM_HERE, base::Bind(&ChromotingJniRuntime::DetachFromVmAndSignal, |
| 245 base::Unretained(this), | 231 base::Unretained(this), &done_event)); |
| 246 &done_event)); | |
| 247 done_event.Wait(); | 232 done_event.Wait(); |
| 248 display_task_runner_->PostTask(FROM_HERE, base::Bind( | 233 display_task_runner()->PostTask( |
| 249 &ChromotingJniRuntime::DetachFromVmAndSignal, | 234 FROM_HERE, base::Bind(&ChromotingJniRuntime::DetachFromVmAndSignal, |
| 250 base::Unretained(this), | 235 base::Unretained(this), &done_event)); |
| 251 &done_event)); | |
| 252 done_event.Wait(); | 236 done_event.Wait(); |
| 253 base::android::LibraryLoaderExitHook(); | 237 base::android::LibraryLoaderExitHook(); |
| 254 base::android::DetachFromVM(); | 238 base::android::DetachFromVM(); |
| 255 } | 239 } |
| 256 | 240 |
| 257 void ChromotingJniRuntime::ConnectToHost(const std::string& username, | 241 void ChromotingJniRuntime::ConnectToHost(const std::string& username, |
| 258 const std::string& auth_token, | 242 const std::string& auth_token, |
| 259 const std::string& host_jid, | 243 const std::string& host_jid, |
| 260 const std::string& host_id, | 244 const std::string& host_id, |
| 261 const std::string& host_pubkey, | 245 const std::string& host_pubkey, |
| 262 const std::string& pairing_id, | 246 const std::string& pairing_id, |
| 263 const std::string& pairing_secret, | 247 const std::string& pairing_secret, |
| 264 const std::string& capabilities, | 248 const std::string& capabilities, |
| 265 const std::string& flags) { | 249 const std::string& flags) { |
| 266 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 250 DCHECK(ui_task_runner()->BelongsToCurrentThread()); |
| 267 DCHECK(!session_.get()); | 251 DCHECK(!session_.get()); |
| 268 session_ = new ChromotingJniInstance(this, username, auth_token, host_jid, | 252 session_ = new ChromotingJniInstance(this, username, auth_token, host_jid, |
| 269 host_id, host_pubkey, pairing_id, | 253 host_id, host_pubkey, pairing_id, |
| 270 pairing_secret, capabilities, flags); | 254 pairing_secret, capabilities, flags); |
| 271 } | 255 } |
| 272 | 256 |
| 273 void ChromotingJniRuntime::DisconnectFromHost() { | 257 void ChromotingJniRuntime::DisconnectFromHost() { |
| 274 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 258 DCHECK(ui_task_runner()->BelongsToCurrentThread()); |
| 275 if (session_.get()) { | 259 if (session_.get()) { |
| 276 session_->Disconnect(); | 260 session_->Disconnect(); |
| 277 session_ = nullptr; | 261 session_ = nullptr; |
| 278 } | 262 } |
| 279 } | 263 } |
| 280 | 264 |
| 281 void ChromotingJniRuntime::OnConnectionState( | 265 void ChromotingJniRuntime::OnConnectionState( |
| 282 protocol::ConnectionToHost::State state, | 266 protocol::ConnectionToHost::State state, |
| 283 protocol::ErrorCode error) { | 267 protocol::ErrorCode error) { |
| 284 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 268 DCHECK(ui_task_runner()->BelongsToCurrentThread()); |
| 285 | 269 |
| 286 JNIEnv* env = base::android::AttachCurrentThread(); | 270 JNIEnv* env = base::android::AttachCurrentThread(); |
| 287 Java_JniInterface_onConnectionState(env, state, error); | 271 Java_JniInterface_onConnectionState(env, state, error); |
| 288 } | 272 } |
| 289 | 273 |
| 290 void ChromotingJniRuntime::DisplayAuthenticationPrompt(bool pairing_supported) { | 274 void ChromotingJniRuntime::DisplayAuthenticationPrompt(bool pairing_supported) { |
| 291 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 275 DCHECK(ui_task_runner()->BelongsToCurrentThread()); |
| 292 | 276 |
| 293 JNIEnv* env = base::android::AttachCurrentThread(); | 277 JNIEnv* env = base::android::AttachCurrentThread(); |
| 294 Java_JniInterface_displayAuthenticationPrompt(env, pairing_supported); | 278 Java_JniInterface_displayAuthenticationPrompt(env, pairing_supported); |
| 295 } | 279 } |
| 296 | 280 |
| 297 void ChromotingJniRuntime::CommitPairingCredentials(const std::string& host, | 281 void ChromotingJniRuntime::CommitPairingCredentials(const std::string& host, |
| 298 const std::string& id, | 282 const std::string& id, |
| 299 const std::string& secret) { | 283 const std::string& secret) { |
| 300 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 284 DCHECK(ui_task_runner()->BelongsToCurrentThread()); |
| 301 | 285 |
| 302 JNIEnv* env = base::android::AttachCurrentThread(); | 286 JNIEnv* env = base::android::AttachCurrentThread(); |
| 303 ScopedJavaLocalRef<jstring> j_host = ConvertUTF8ToJavaString(env, host); | 287 ScopedJavaLocalRef<jstring> j_host = ConvertUTF8ToJavaString(env, host); |
| 304 ScopedJavaLocalRef<jstring> j_id = ConvertUTF8ToJavaString(env, id); | 288 ScopedJavaLocalRef<jstring> j_id = ConvertUTF8ToJavaString(env, id); |
| 305 ScopedJavaLocalRef<jstring> j_secret = ConvertUTF8ToJavaString(env,secret); | 289 ScopedJavaLocalRef<jstring> j_secret = ConvertUTF8ToJavaString(env,secret); |
| 306 | 290 |
| 307 Java_JniInterface_commitPairingCredentials( | 291 Java_JniInterface_commitPairingCredentials( |
| 308 env, j_host.obj(), j_id.obj(), j_secret.obj()); | 292 env, j_host.obj(), j_id.obj(), j_secret.obj()); |
| 309 } | 293 } |
| 310 | 294 |
| 311 void ChromotingJniRuntime::FetchThirdPartyToken(const GURL& token_url, | 295 void ChromotingJniRuntime::FetchThirdPartyToken(const GURL& token_url, |
| 312 const std::string& client_id, | 296 const std::string& client_id, |
| 313 const std::string& scope) { | 297 const std::string& scope) { |
| 314 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 298 DCHECK(ui_task_runner()->BelongsToCurrentThread()); |
| 315 JNIEnv* env = base::android::AttachCurrentThread(); | 299 JNIEnv* env = base::android::AttachCurrentThread(); |
| 316 | 300 |
| 317 ScopedJavaLocalRef<jstring> j_url = | 301 ScopedJavaLocalRef<jstring> j_url = |
| 318 ConvertUTF8ToJavaString(env, token_url.spec()); | 302 ConvertUTF8ToJavaString(env, token_url.spec()); |
| 319 ScopedJavaLocalRef<jstring> j_client_id = | 303 ScopedJavaLocalRef<jstring> j_client_id = |
| 320 ConvertUTF8ToJavaString(env, client_id); | 304 ConvertUTF8ToJavaString(env, client_id); |
| 321 ScopedJavaLocalRef<jstring> j_scope = ConvertUTF8ToJavaString(env, scope); | 305 ScopedJavaLocalRef<jstring> j_scope = ConvertUTF8ToJavaString(env, scope); |
| 322 | 306 |
| 323 Java_JniInterface_fetchThirdPartyToken( | 307 Java_JniInterface_fetchThirdPartyToken( |
| 324 env, j_url.obj(), j_client_id.obj(), j_scope.obj()); | 308 env, j_url.obj(), j_client_id.obj(), j_scope.obj()); |
| 325 } | 309 } |
| 326 | 310 |
| 327 void ChromotingJniRuntime::SetCapabilities(const std::string& capabilities) { | 311 void ChromotingJniRuntime::SetCapabilities(const std::string& capabilities) { |
| 328 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 312 DCHECK(ui_task_runner()->BelongsToCurrentThread()); |
| 329 JNIEnv* env = base::android::AttachCurrentThread(); | 313 JNIEnv* env = base::android::AttachCurrentThread(); |
| 330 | 314 |
| 331 ScopedJavaLocalRef<jstring> j_cap = | 315 ScopedJavaLocalRef<jstring> j_cap = |
| 332 ConvertUTF8ToJavaString(env, capabilities); | 316 ConvertUTF8ToJavaString(env, capabilities); |
| 333 | 317 |
| 334 Java_JniInterface_setCapabilities(env, j_cap.obj()); | 318 Java_JniInterface_setCapabilities(env, j_cap.obj()); |
| 335 } | 319 } |
| 336 | 320 |
| 337 void ChromotingJniRuntime::HandleExtensionMessage(const std::string& type, | 321 void ChromotingJniRuntime::HandleExtensionMessage(const std::string& type, |
| 338 const std::string& message) { | 322 const std::string& message) { |
| 339 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 323 DCHECK(ui_task_runner()->BelongsToCurrentThread()); |
| 340 JNIEnv* env = base::android::AttachCurrentThread(); | 324 JNIEnv* env = base::android::AttachCurrentThread(); |
| 341 | 325 |
| 342 ScopedJavaLocalRef<jstring> j_type = ConvertUTF8ToJavaString(env, type); | 326 ScopedJavaLocalRef<jstring> j_type = ConvertUTF8ToJavaString(env, type); |
| 343 ScopedJavaLocalRef<jstring> j_message = ConvertUTF8ToJavaString(env, message); | 327 ScopedJavaLocalRef<jstring> j_message = ConvertUTF8ToJavaString(env, message); |
| 344 | 328 |
| 345 Java_JniInterface_handleExtensionMessage(env, j_type.obj(), j_message.obj()); | 329 Java_JniInterface_handleExtensionMessage(env, j_type.obj(), j_message.obj()); |
| 346 } | 330 } |
| 347 | 331 |
| 348 base::android::ScopedJavaLocalRef<jobject> ChromotingJniRuntime::NewBitmap( | 332 base::android::ScopedJavaLocalRef<jobject> ChromotingJniRuntime::NewBitmap( |
| 349 int width, int height) { | 333 int width, int height) { |
| 350 JNIEnv* env = base::android::AttachCurrentThread(); | 334 JNIEnv* env = base::android::AttachCurrentThread(); |
| 351 return Java_JniInterface_newBitmap(env, width, height); | 335 return Java_JniInterface_newBitmap(env, width, height); |
| 352 } | 336 } |
| 353 | 337 |
| 354 void ChromotingJniRuntime::UpdateFrameBitmap(jobject bitmap) { | 338 void ChromotingJniRuntime::UpdateFrameBitmap(jobject bitmap) { |
| 355 DCHECK(display_task_runner_->BelongsToCurrentThread()); | 339 DCHECK(display_task_runner()->BelongsToCurrentThread()); |
| 356 | 340 |
| 357 JNIEnv* env = base::android::AttachCurrentThread(); | 341 JNIEnv* env = base::android::AttachCurrentThread(); |
| 358 Java_JniInterface_setVideoFrame(env, bitmap); | 342 Java_JniInterface_setVideoFrame(env, bitmap); |
| 359 } | 343 } |
| 360 | 344 |
| 361 void ChromotingJniRuntime::UpdateCursorShape( | 345 void ChromotingJniRuntime::UpdateCursorShape( |
| 362 const protocol::CursorShapeInfo& cursor_shape) { | 346 const protocol::CursorShapeInfo& cursor_shape) { |
| 363 DCHECK(display_task_runner_->BelongsToCurrentThread()); | 347 DCHECK(display_task_runner()->BelongsToCurrentThread()); |
| 364 | 348 |
| 365 // const_cast<> is safe as long as the Java updateCursorShape() method copies | 349 // 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 | 350 // 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 | 351 // reference to the buffer afterwards. Unfortunately, there seems to be no way |
| 368 // to create a read-only ByteBuffer from a pointer-to-const. | 352 // to create a read-only ByteBuffer from a pointer-to-const. |
| 369 char* data = string_as_array(const_cast<std::string*>(&cursor_shape.data())); | 353 char* data = string_as_array(const_cast<std::string*>(&cursor_shape.data())); |
| 370 int cursor_total_bytes = | 354 int cursor_total_bytes = |
| 371 cursor_shape.width() * cursor_shape.height() * kBytesPerPixel; | 355 cursor_shape.width() * cursor_shape.height() * kBytesPerPixel; |
| 372 | 356 |
| 373 JNIEnv* env = base::android::AttachCurrentThread(); | 357 JNIEnv* env = base::android::AttachCurrentThread(); |
| 374 base::android::ScopedJavaLocalRef<jobject> buffer(env, | 358 base::android::ScopedJavaLocalRef<jobject> buffer(env, |
| 375 env->NewDirectByteBuffer(data, cursor_total_bytes)); | 359 env->NewDirectByteBuffer(data, cursor_total_bytes)); |
| 376 Java_JniInterface_updateCursorShape(env, | 360 Java_JniInterface_updateCursorShape(env, |
| 377 cursor_shape.width(), | 361 cursor_shape.width(), |
| 378 cursor_shape.height(), | 362 cursor_shape.height(), |
| 379 cursor_shape.hotspot_x(), | 363 cursor_shape.hotspot_x(), |
| 380 cursor_shape.hotspot_y(), | 364 cursor_shape.hotspot_y(), |
| 381 buffer.obj()); | 365 buffer.obj()); |
| 382 } | 366 } |
| 383 | 367 |
| 384 void ChromotingJniRuntime::RedrawCanvas() { | 368 void ChromotingJniRuntime::RedrawCanvas() { |
| 385 DCHECK(display_task_runner_->BelongsToCurrentThread()); | 369 DCHECK(display_task_runner()->BelongsToCurrentThread()); |
| 386 | 370 |
| 387 JNIEnv* env = base::android::AttachCurrentThread(); | 371 JNIEnv* env = base::android::AttachCurrentThread(); |
| 388 Java_JniInterface_redrawGraphicsInternal(env); | 372 Java_JniInterface_redrawGraphicsInternal(env); |
| 389 } | 373 } |
| 390 | 374 |
| 391 void ChromotingJniRuntime::DetachFromVmAndSignal(base::WaitableEvent* waiter) { | 375 void ChromotingJniRuntime::DetachFromVmAndSignal(base::WaitableEvent* waiter) { |
| 392 base::android::DetachFromVM(); | 376 base::android::DetachFromVM(); |
| 393 waiter->Signal(); | 377 waiter->Signal(); |
| 394 } | 378 } |
| 395 } // namespace remoting | 379 } // namespace remoting |
| OLD | NEW |