17dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
27dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
37dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// found in the LICENSE file.
47dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "remoting/client/jni/chromoting_jni_runtime.h"
67dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/android/jni_android.h"
81e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/android/jni_array.h"
91e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/android/jni_string.h"
10d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/android/scoped_java_ref.h"
111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/basictypes.h"
121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/command_line.h"
137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/memory/singleton.h"
14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/stl_util.h"
15ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/synchronization/waitable_event.h"
161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "google_apis/google_api_keys.h"
171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "jni/JniInterface_jni.h"
189ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "media/base/yuv_convert.h"
19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "remoting/base/url_request_context_getter.h"
204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using base::android::ConvertJavaStringToUTF8;
231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using base::android::ConvertUTF8ToJavaString;
241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using base::android::ToJavaByteArray;
25d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)namespace {
277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
28d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)const int kBytesPerPixel = 4;
29d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
30d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}  // namespace
31d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace remoting {
337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool RegisterJni(JNIEnv* env) {
351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return remoting::RegisterNativesImpl(env);
361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Implementation of stubs defined in JniInterface_jni.h. These are the entry
391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// points for JNI calls from Java into C++.
401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)static void LoadNative(JNIEnv* env, jclass clazz, jobject context) {
421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  base::android::ScopedJavaLocalRef<jobject> context_activity(env, context);
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::android::InitApplicationContext(env, context_activity);
441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // The google_apis functions check the command-line arguments to make sure no
461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // runtime API keys have been specified by the environment. Unfortunately, we
471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // neither launch Chromium nor have a command line, so we need to prevent
481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // them from DCHECKing out when they go looking.
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::CommandLine::Init(0, NULL);
501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Create the singleton now so that the Chromoting threads will be set up.
521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  remoting::ChromotingJniRuntime::GetInstance();
531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)static jstring GetApiKey(JNIEnv* env, jclass clazz) {
56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return ConvertUTF8ToJavaString(
57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      env, google_apis::GetAPIKey().c_str()).Release();
581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)static jstring GetClientId(JNIEnv* env, jclass clazz) {
61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return ConvertUTF8ToJavaString(
62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      env, google_apis::GetOAuth2ClientID(
63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          google_apis::CLIENT_REMOTING).c_str()).Release();
641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)static jstring GetClientSecret(JNIEnv* env, jclass clazz) {
67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return ConvertUTF8ToJavaString(
68010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      env, google_apis::GetOAuth2ClientSecret(
69010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          google_apis::CLIENT_REMOTING).c_str()).Release();
701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)static void Connect(JNIEnv* env,
731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    jclass clazz,
741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    jstring username,
751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    jstring authToken,
761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    jstring hostJid,
771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    jstring hostId,
781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    jstring hostPubkey,
791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    jstring pairId,
806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                    jstring pairSecret,
816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                    jstring capabilities) {
821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  remoting::ChromotingJniRuntime::GetInstance()->ConnectToHost(
831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      ConvertJavaStringToUTF8(env, username).c_str(),
841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      ConvertJavaStringToUTF8(env, authToken).c_str(),
851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      ConvertJavaStringToUTF8(env, hostJid).c_str(),
861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      ConvertJavaStringToUTF8(env, hostId).c_str(),
871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      ConvertJavaStringToUTF8(env, hostPubkey).c_str(),
881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      ConvertJavaStringToUTF8(env, pairId).c_str(),
896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      ConvertJavaStringToUTF8(env, pairSecret).c_str(),
906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      ConvertJavaStringToUTF8(env, capabilities).c_str());
911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)static void Disconnect(JNIEnv* env, jclass clazz) {
941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  remoting::ChromotingJniRuntime::GetInstance()->DisconnectFromHost();
951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)static void AuthenticationResponse(JNIEnv* env,
981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                   jclass clazz,
991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                   jstring pin,
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   jboolean createPair,
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   jstring deviceName) {
1021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  remoting::ChromotingJniRuntime::GetInstance()->session()->ProvideSecret(
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ConvertJavaStringToUTF8(env, pin).c_str(), createPair,
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ConvertJavaStringToUTF8(env, deviceName));
1051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)static void ScheduleRedraw(JNIEnv* env, jclass clazz) {
1081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  remoting::ChromotingJniRuntime::GetInstance()->session()->RedrawDesktop();
1091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
111effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstatic void SendMouseEvent(JNIEnv* env,
112effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                           jclass clazz,
113effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                           jint x,
114effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                           jint y,
115effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                           jint whichButton,
116effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                           jboolean buttonDown) {
1171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Button must be within the bounds of the MouseEvent_MouseButton enum.
1181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(whichButton >= 0 && whichButton < 5);
1191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
120effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  remoting::ChromotingJniRuntime::GetInstance()->session()->SendMouseEvent(
121effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      x, y,
1221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      static_cast<remoting::protocol::MouseEvent_MouseButton>(whichButton),
1231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      buttonDown);
1241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
126effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstatic void SendMouseWheelEvent(JNIEnv* env,
127effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                jclass clazz,
128effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                jint delta_x,
129effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                jint delta_y) {
130effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  remoting::ChromotingJniRuntime::GetInstance()->session()->SendMouseWheelEvent(
131effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      delta_x, delta_y);
132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)static jboolean SendKeyEvent(JNIEnv* env,
135effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                         jclass clazz,
136effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                         jint keyCode,
137effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                         jboolean keyDown) {
1386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  return remoting::ChromotingJniRuntime::GetInstance()->session()->SendKeyEvent(
139effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      keyCode, keyDown);
140effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
141effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
142effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstatic void SendTextEvent(JNIEnv* env,
143effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                          jclass clazz,
144effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                          jstring text) {
145effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  remoting::ChromotingJniRuntime::GetInstance()->session()->SendTextEvent(
146effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      ConvertJavaStringToUTF8(env, text));
1471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)static void OnThirdPartyTokenFetched(JNIEnv* env,
150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                     jclass clazz,
151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                     jstring token,
152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                     jstring shared_secret) {
153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ChromotingJniRuntime* runtime = remoting::ChromotingJniRuntime::GetInstance();
154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  runtime->network_task_runner()->PostTask(FROM_HERE, base::Bind(
155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      &ChromotingJniInstance::HandleOnThirdPartyTokenFetched,
156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      runtime->session(),
157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      ConvertJavaStringToUTF8(env, token),
158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      ConvertJavaStringToUTF8(env, shared_secret)));
159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)static void SendExtensionMessage(JNIEnv* env,
1626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                 jclass clazz,
1636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                 jstring type,
1646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                 jstring data) {
1656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  remoting::ChromotingJniRuntime::GetInstance()->session()->SendClientMessage(
1666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      ConvertJavaStringToUTF8(env, type),
1676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      ConvertJavaStringToUTF8(env, data));
1686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// ChromotingJniRuntime implementation.
1711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// static
173bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben MurdochChromotingJniRuntime* ChromotingJniRuntime::GetInstance() {
174bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  return Singleton<ChromotingJniRuntime>::get();
1757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
177bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben MurdochChromotingJniRuntime::ChromotingJniRuntime() {
1787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  at_exit_manager_.reset(new base::AtExitManager());
1797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // On Android, the UI thread is managed by Java, so we need to attach and
1817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // start a special type of message loop to allow Chromium code to run tasks.
1827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ui_loop_.reset(new base::MessageLoopForUI());
1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ui_loop_->Start();
1847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // TODO(solb) Stop pretending to control the managed UI thread's lifetime.
1867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ui_task_runner_ = new AutoThreadTaskRunner(ui_loop_->message_loop_proxy(),
1877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                             base::MessageLoop::QuitClosure());
1887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  network_task_runner_ = AutoThread::CreateWithType("native_net",
1897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                                    ui_task_runner_,
1907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                                    base::MessageLoop::TYPE_IO);
1917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  display_task_runner_ = AutoThread::Create("native_disp",
1927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                            ui_task_runner_);
1937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  url_requester_ =
1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new URLRequestContextGetter(network_task_runner_, network_task_runner_);
1967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1979ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  // Allows later decoding of video frames.
1989ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  media::InitializeCPUSpecificYUVConversions();
1997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
201bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben MurdochChromotingJniRuntime::~ChromotingJniRuntime() {
2027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // The singleton should only ever be destroyed on the main thread.
2037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(ui_task_runner_->BelongsToCurrentThread());
2047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // The session must be shut down first, since it depends on our other
2067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // components' still being alive.
2077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DisconnectFromHost();
2087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
209ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  base::WaitableEvent done_event(false, false);
210ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  network_task_runner_->PostTask(FROM_HERE, base::Bind(
211ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      &ChromotingJniRuntime::DetachFromVmAndSignal,
212ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Unretained(this),
213ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      &done_event));
214ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  done_event.Wait();
215ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  display_task_runner_->PostTask(FROM_HERE, base::Bind(
216ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      &ChromotingJniRuntime::DetachFromVmAndSignal,
217ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Unretained(this),
218ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      &done_event));
219ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  done_event.Wait();
220ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  base::android::DetachFromVM();
2217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
223bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochvoid ChromotingJniRuntime::ConnectToHost(const char* username,
2247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                  const char* auth_token,
2257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                  const char* host_jid,
2267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                  const char* host_id,
227bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                                  const char* host_pubkey,
228bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                                  const char* pairing_id,
2296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                  const char* pairing_secret,
2306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                  const char* capabilities) {
2317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(ui_task_runner_->BelongsToCurrentThread());
2327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(!session_);
233bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  session_ = new ChromotingJniInstance(this,
234bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                                       username,
2357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                       auth_token,
2367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                       host_jid,
2377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                       host_id,
238bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                                       host_pubkey,
239bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                                       pairing_id,
2406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                       pairing_secret,
2416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                       capabilities);
2427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
244bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochvoid ChromotingJniRuntime::DisconnectFromHost() {
2457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(ui_task_runner_->BelongsToCurrentThread());
2467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (session_) {
2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    session_->Disconnect();
2487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    session_ = NULL;
2497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ChromotingJniRuntime::OnConnectionState(
2537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    protocol::ConnectionToHost::State state,
2547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    protocol::ErrorCode error) {
2557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(ui_task_runner_->BelongsToCurrentThread());
2567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  JNIEnv* env = base::android::AttachCurrentThread();
2586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  Java_JniInterface_onConnectionState(env, state, error);
2597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ChromotingJniRuntime::DisplayAuthenticationPrompt(bool pairing_supported) {
2627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(ui_task_runner_->BelongsToCurrentThread());
2637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  JNIEnv* env = base::android::AttachCurrentThread();
2651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Java_JniInterface_displayAuthenticationPrompt(env, pairing_supported);
2667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
268bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochvoid ChromotingJniRuntime::CommitPairingCredentials(const std::string& host,
269bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                                                    const std::string& id,
270bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                                                    const std::string& secret) {
271bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  DCHECK(ui_task_runner_->BelongsToCurrentThread());
272bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
273bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  JNIEnv* env = base::android::AttachCurrentThread();
2741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  ScopedJavaLocalRef<jstring> j_host = ConvertUTF8ToJavaString(env, host);
275116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ScopedJavaLocalRef<jstring> j_id = ConvertUTF8ToJavaString(env, id);
276116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ScopedJavaLocalRef<jstring> j_secret = ConvertUTF8ToJavaString(env,secret);
2771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Java_JniInterface_commitPairingCredentials(
2791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      env, j_host.obj(), j_id.obj(), j_secret.obj());
280bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
281bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ChromotingJniRuntime::FetchThirdPartyToken(const GURL& token_url,
283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                const std::string& client_id,
284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                const std::string& scope) {
285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(ui_task_runner_->BelongsToCurrentThread());
286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  JNIEnv* env = base::android::AttachCurrentThread();
287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ScopedJavaLocalRef<jstring> j_url =
289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      ConvertUTF8ToJavaString(env, token_url.spec());
290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ScopedJavaLocalRef<jstring> j_client_id =
291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      ConvertUTF8ToJavaString(env, client_id);
292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ScopedJavaLocalRef<jstring> j_scope = ConvertUTF8ToJavaString(env, scope);
293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Java_JniInterface_fetchThirdPartyToken(
295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      env, j_url.obj(), j_client_id.obj(), j_scope.obj());
296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ChromotingJniRuntime::SetCapabilities(const std::string& capabilities) {
2996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(ui_task_runner_->BelongsToCurrentThread());
3006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  JNIEnv* env = base::android::AttachCurrentThread();
3016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ScopedJavaLocalRef<jstring> j_cap =
3036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      ConvertUTF8ToJavaString(env, capabilities);
3046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  Java_JniInterface_setCapabilities(env, j_cap.obj());
3066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
3076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ChromotingJniRuntime::HandleExtensionMessage(const std::string& type,
3096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                                  const std::string& message) {
3106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(ui_task_runner_->BelongsToCurrentThread());
3116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  JNIEnv* env = base::android::AttachCurrentThread();
3126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ScopedJavaLocalRef<jstring> j_type = ConvertUTF8ToJavaString(env, type);
3146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ScopedJavaLocalRef<jstring> j_message = ConvertUTF8ToJavaString(env, message);
3156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  Java_JniInterface_handleExtensionMessage(env, j_type.obj(), j_message.obj());
3176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
3186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)base::android::ScopedJavaLocalRef<jobject> ChromotingJniRuntime::NewBitmap(
3204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    webrtc::DesktopSize size) {
3214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  JNIEnv* env = base::android::AttachCurrentThread();
3221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return Java_JniInterface_newBitmap(env, size.width(), size.height());
3234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ChromotingJniRuntime::UpdateFrameBitmap(jobject bitmap) {
3269ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  DCHECK(display_task_runner_->BelongsToCurrentThread());
3279ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch
3289ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  JNIEnv* env = base::android::AttachCurrentThread();
3291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Java_JniInterface_setVideoFrame(env, bitmap);
3309ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch}
3319ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch
332d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ChromotingJniRuntime::UpdateCursorShape(
333d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const protocol::CursorShapeInfo& cursor_shape) {
334d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(display_task_runner_->BelongsToCurrentThread());
335d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
336d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // const_cast<> is safe as long as the Java updateCursorShape() method copies
337d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // the data out of the buffer without mutating it, and doesn't keep any
338d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // reference to the buffer afterwards. Unfortunately, there seems to be no way
339d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // to create a read-only ByteBuffer from a pointer-to-const.
340d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  char* data = string_as_array(const_cast<std::string*>(&cursor_shape.data()));
341d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  int cursor_total_bytes =
342d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      cursor_shape.width() * cursor_shape.height() * kBytesPerPixel;
343d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
344d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  JNIEnv* env = base::android::AttachCurrentThread();
345d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  base::android::ScopedJavaLocalRef<jobject> buffer(env,
346d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      env->NewDirectByteBuffer(data, cursor_total_bytes));
3471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Java_JniInterface_updateCursorShape(env,
3481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                      cursor_shape.width(),
3491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                      cursor_shape.height(),
3501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                      cursor_shape.hotspot_x(),
3511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                      cursor_shape.hotspot_y(),
3521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                      buffer.obj());
353d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
354d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
355bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochvoid ChromotingJniRuntime::RedrawCanvas() {
3569ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  DCHECK(display_task_runner_->BelongsToCurrentThread());
3579ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch
3589ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  JNIEnv* env = base::android::AttachCurrentThread();
3591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Java_JniInterface_redrawGraphicsInternal(env);
3609ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch}
3619ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch
362ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ChromotingJniRuntime::DetachFromVmAndSignal(base::WaitableEvent* waiter) {
363ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  base::android::DetachFromVM();
364ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  waiter->Signal();
365ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
3667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}  // namespace remoting
367