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