PageRenderTime 52ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/remoting/client/jni/chromoting_jni_runtime.cc

https://gitlab.com/jonnialva90/iridium-browser
C++ | 376 lines | 291 code | 62 blank | 23 comment | 2 complexity | cb972cec9baa3a3db81b55e70d651911 MD5 | raw file
  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
  3. // found in the LICENSE file.
  4. #include "remoting/client/jni/chromoting_jni_runtime.h"
  5. #include "base/android/jni_android.h"
  6. #include "base/android/jni_array.h"
  7. #include "base/android/jni_string.h"
  8. #include "base/android/library_loader/library_loader_hooks.h"
  9. #include "base/android/scoped_java_ref.h"
  10. #include "base/basictypes.h"
  11. #include "base/command_line.h"
  12. #include "base/memory/singleton.h"
  13. #include "base/stl_util.h"
  14. #include "base/synchronization/waitable_event.h"
  15. #include "google_apis/google_api_keys.h"
  16. #include "jni/JniInterface_jni.h"
  17. #include "remoting/base/url_request_context_getter.h"
  18. using base::android::ConvertJavaStringToUTF8;
  19. using base::android::ConvertUTF8ToJavaString;
  20. using base::android::ToJavaByteArray;
  21. namespace {
  22. const int kBytesPerPixel = 4;
  23. } // namespace
  24. namespace remoting {
  25. bool RegisterChromotingJniRuntime(JNIEnv* env) {
  26. return remoting::RegisterNativesImpl(env);
  27. }
  28. // Implementation of stubs defined in JniInterface_jni.h. These are the entry
  29. // points for JNI calls from Java into C++.
  30. static void LoadNative(JNIEnv* env,
  31. const JavaParamRef<jclass>& clazz,
  32. const JavaParamRef<jobject>& context) {
  33. base::android::InitApplicationContext(env, context);
  34. // The google_apis functions check the command-line arguments to make sure no
  35. // runtime API keys have been specified by the environment. Unfortunately, we
  36. // neither launch Chromium nor have a command line, so we need to prevent
  37. // them from DCHECKing out when they go looking.
  38. base::CommandLine::Init(0, nullptr);
  39. // Create the singleton now so that the Chromoting threads will be set up.
  40. remoting::ChromotingJniRuntime::GetInstance();
  41. }
  42. static ScopedJavaLocalRef<jstring> GetApiKey(
  43. JNIEnv* env,
  44. const JavaParamRef<jclass>& clazz) {
  45. return ConvertUTF8ToJavaString(env, google_apis::GetAPIKey().c_str());
  46. }
  47. static ScopedJavaLocalRef<jstring> GetClientId(
  48. JNIEnv* env,
  49. const JavaParamRef<jclass>& clazz) {
  50. return ConvertUTF8ToJavaString(
  51. env,
  52. google_apis::GetOAuth2ClientID(google_apis::CLIENT_REMOTING).c_str());
  53. }
  54. static ScopedJavaLocalRef<jstring> GetClientSecret(
  55. JNIEnv* env,
  56. const JavaParamRef<jclass>& clazz) {
  57. return ConvertUTF8ToJavaString(
  58. env,
  59. google_apis::GetOAuth2ClientSecret(google_apis::CLIENT_REMOTING).c_str());
  60. }
  61. static void Connect(JNIEnv* env,
  62. const JavaParamRef<jclass>& clazz,
  63. const JavaParamRef<jstring>& username,
  64. const JavaParamRef<jstring>& authToken,
  65. const JavaParamRef<jstring>& hostJid,
  66. const JavaParamRef<jstring>& hostId,
  67. const JavaParamRef<jstring>& hostPubkey,
  68. const JavaParamRef<jstring>& pairId,
  69. const JavaParamRef<jstring>& pairSecret,
  70. const JavaParamRef<jstring>& capabilities) {
  71. remoting::ChromotingJniRuntime::GetInstance()->ConnectToHost(
  72. ConvertJavaStringToUTF8(env, username).c_str(),
  73. ConvertJavaStringToUTF8(env, authToken).c_str(),
  74. ConvertJavaStringToUTF8(env, hostJid).c_str(),
  75. ConvertJavaStringToUTF8(env, hostId).c_str(),
  76. ConvertJavaStringToUTF8(env, hostPubkey).c_str(),
  77. ConvertJavaStringToUTF8(env, pairId).c_str(),
  78. ConvertJavaStringToUTF8(env, pairSecret).c_str(),
  79. ConvertJavaStringToUTF8(env, capabilities).c_str());
  80. }
  81. static void Disconnect(JNIEnv* env, const JavaParamRef<jclass>& clazz) {
  82. remoting::ChromotingJniRuntime::GetInstance()->DisconnectFromHost();
  83. }
  84. static void AuthenticationResponse(JNIEnv* env,
  85. const JavaParamRef<jclass>& clazz,
  86. const JavaParamRef<jstring>& pin,
  87. jboolean createPair,
  88. const JavaParamRef<jstring>& deviceName) {
  89. remoting::ChromotingJniRuntime::GetInstance()->session()->ProvideSecret(
  90. ConvertJavaStringToUTF8(env, pin).c_str(), createPair,
  91. ConvertJavaStringToUTF8(env, deviceName));
  92. }
  93. static void ScheduleRedraw(JNIEnv* env, const JavaParamRef<jclass>& clazz) {
  94. remoting::ChromotingJniRuntime::GetInstance()->session()->RedrawDesktop();
  95. }
  96. static void SendMouseEvent(JNIEnv* env,
  97. const JavaParamRef<jclass>& clazz,
  98. jint x,
  99. jint y,
  100. jint whichButton,
  101. jboolean buttonDown) {
  102. // Button must be within the bounds of the MouseEvent_MouseButton enum.
  103. DCHECK(whichButton >= 0 && whichButton < 5);
  104. remoting::ChromotingJniRuntime::GetInstance()->session()->SendMouseEvent(
  105. x, y,
  106. static_cast<remoting::protocol::MouseEvent_MouseButton>(whichButton),
  107. buttonDown);
  108. }
  109. static void SendMouseWheelEvent(JNIEnv* env,
  110. const JavaParamRef<jclass>& clazz,
  111. jint delta_x,
  112. jint delta_y) {
  113. remoting::ChromotingJniRuntime::GetInstance()->session()->SendMouseWheelEvent(
  114. delta_x, delta_y);
  115. }
  116. static jboolean SendKeyEvent(JNIEnv* env,
  117. const JavaParamRef<jclass>& clazz,
  118. jint scanCode,
  119. jint keyCode,
  120. jboolean keyDown) {
  121. return remoting::ChromotingJniRuntime::GetInstance()->session()->SendKeyEvent(
  122. scanCode, keyCode, keyDown);
  123. }
  124. static void SendTextEvent(JNIEnv* env,
  125. const JavaParamRef<jclass>& clazz,
  126. const JavaParamRef<jstring>& text) {
  127. remoting::ChromotingJniRuntime::GetInstance()->session()->SendTextEvent(
  128. ConvertJavaStringToUTF8(env, text));
  129. }
  130. static void EnableVideoChannel(JNIEnv* env,
  131. const JavaParamRef<jclass>& clazz,
  132. jboolean enable) {
  133. remoting::ChromotingJniRuntime::GetInstance()->session()->EnableVideoChannel(
  134. enable);
  135. }
  136. static void OnThirdPartyTokenFetched(
  137. JNIEnv* env,
  138. const JavaParamRef<jclass>& clazz,
  139. const JavaParamRef<jstring>& token,
  140. const JavaParamRef<jstring>& shared_secret) {
  141. ChromotingJniRuntime* runtime = remoting::ChromotingJniRuntime::GetInstance();
  142. runtime->network_task_runner()->PostTask(FROM_HERE, base::Bind(
  143. &ChromotingJniInstance::HandleOnThirdPartyTokenFetched,
  144. runtime->session(),
  145. ConvertJavaStringToUTF8(env, token),
  146. ConvertJavaStringToUTF8(env, shared_secret)));
  147. }
  148. static void SendExtensionMessage(JNIEnv* env,
  149. const JavaParamRef<jclass>& clazz,
  150. const JavaParamRef<jstring>& type,
  151. const JavaParamRef<jstring>& data) {
  152. remoting::ChromotingJniRuntime::GetInstance()->session()->SendClientMessage(
  153. ConvertJavaStringToUTF8(env, type),
  154. ConvertJavaStringToUTF8(env, data));
  155. }
  156. // ChromotingJniRuntime implementation.
  157. // static
  158. ChromotingJniRuntime* ChromotingJniRuntime::GetInstance() {
  159. return base::Singleton<ChromotingJniRuntime>::get();
  160. }
  161. ChromotingJniRuntime::ChromotingJniRuntime() {
  162. // On Android, the UI thread is managed by Java, so we need to attach and
  163. // start a special type of message loop to allow Chromium code to run tasks.
  164. ui_loop_.reset(new base::MessageLoopForUI());
  165. ui_loop_->Start();
  166. // TODO(solb) Stop pretending to control the managed UI thread's lifetime.
  167. ui_task_runner_ = new AutoThreadTaskRunner(ui_loop_->task_runner(),
  168. base::MessageLoop::QuitClosure());
  169. network_task_runner_ = AutoThread::CreateWithType("native_net",
  170. ui_task_runner_,
  171. base::MessageLoop::TYPE_IO);
  172. display_task_runner_ = AutoThread::Create("native_disp",
  173. ui_task_runner_);
  174. url_requester_ =
  175. new URLRequestContextGetter(network_task_runner_, network_task_runner_);
  176. }
  177. ChromotingJniRuntime::~ChromotingJniRuntime() {
  178. // The singleton should only ever be destroyed on the main thread.
  179. DCHECK(ui_task_runner_->BelongsToCurrentThread());
  180. // The session must be shut down first, since it depends on our other
  181. // components' still being alive.
  182. DisconnectFromHost();
  183. base::WaitableEvent done_event(false, false);
  184. network_task_runner_->PostTask(FROM_HERE, base::Bind(
  185. &ChromotingJniRuntime::DetachFromVmAndSignal,
  186. base::Unretained(this),
  187. &done_event));
  188. done_event.Wait();
  189. display_task_runner_->PostTask(FROM_HERE, base::Bind(
  190. &ChromotingJniRuntime::DetachFromVmAndSignal,
  191. base::Unretained(this),
  192. &done_event));
  193. done_event.Wait();
  194. base::android::LibraryLoaderExitHook();
  195. base::android::DetachFromVM();
  196. }
  197. void ChromotingJniRuntime::ConnectToHost(const char* username,
  198. const char* auth_token,
  199. const char* host_jid,
  200. const char* host_id,
  201. const char* host_pubkey,
  202. const char* pairing_id,
  203. const char* pairing_secret,
  204. const char* capabilities) {
  205. DCHECK(ui_task_runner_->BelongsToCurrentThread());
  206. DCHECK(!session_.get());
  207. session_ = new ChromotingJniInstance(this,
  208. username,
  209. auth_token,
  210. host_jid,
  211. host_id,
  212. host_pubkey,
  213. pairing_id,
  214. pairing_secret,
  215. capabilities);
  216. }
  217. void ChromotingJniRuntime::DisconnectFromHost() {
  218. DCHECK(ui_task_runner_->BelongsToCurrentThread());
  219. if (session_.get()) {
  220. session_->Disconnect();
  221. session_ = nullptr;
  222. }
  223. }
  224. void ChromotingJniRuntime::OnConnectionState(
  225. protocol::ConnectionToHost::State state,
  226. protocol::ErrorCode error) {
  227. DCHECK(ui_task_runner_->BelongsToCurrentThread());
  228. JNIEnv* env = base::android::AttachCurrentThread();
  229. Java_JniInterface_onConnectionState(env, state, error);
  230. }
  231. void ChromotingJniRuntime::DisplayAuthenticationPrompt(bool pairing_supported) {
  232. DCHECK(ui_task_runner_->BelongsToCurrentThread());
  233. JNIEnv* env = base::android::AttachCurrentThread();
  234. Java_JniInterface_displayAuthenticationPrompt(env, pairing_supported);
  235. }
  236. void ChromotingJniRuntime::CommitPairingCredentials(const std::string& host,
  237. const std::string& id,
  238. const std::string& secret) {
  239. DCHECK(ui_task_runner_->BelongsToCurrentThread());
  240. JNIEnv* env = base::android::AttachCurrentThread();
  241. ScopedJavaLocalRef<jstring> j_host = ConvertUTF8ToJavaString(env, host);
  242. ScopedJavaLocalRef<jstring> j_id = ConvertUTF8ToJavaString(env, id);
  243. ScopedJavaLocalRef<jstring> j_secret = ConvertUTF8ToJavaString(env,secret);
  244. Java_JniInterface_commitPairingCredentials(
  245. env, j_host.obj(), j_id.obj(), j_secret.obj());
  246. }
  247. void ChromotingJniRuntime::FetchThirdPartyToken(const GURL& token_url,
  248. const std::string& client_id,
  249. const std::string& scope) {
  250. DCHECK(ui_task_runner_->BelongsToCurrentThread());
  251. JNIEnv* env = base::android::AttachCurrentThread();
  252. ScopedJavaLocalRef<jstring> j_url =
  253. ConvertUTF8ToJavaString(env, token_url.spec());
  254. ScopedJavaLocalRef<jstring> j_client_id =
  255. ConvertUTF8ToJavaString(env, client_id);
  256. ScopedJavaLocalRef<jstring> j_scope = ConvertUTF8ToJavaString(env, scope);
  257. Java_JniInterface_fetchThirdPartyToken(
  258. env, j_url.obj(), j_client_id.obj(), j_scope.obj());
  259. }
  260. void ChromotingJniRuntime::SetCapabilities(const std::string& capabilities) {
  261. DCHECK(ui_task_runner_->BelongsToCurrentThread());
  262. JNIEnv* env = base::android::AttachCurrentThread();
  263. ScopedJavaLocalRef<jstring> j_cap =
  264. ConvertUTF8ToJavaString(env, capabilities);
  265. Java_JniInterface_setCapabilities(env, j_cap.obj());
  266. }
  267. void ChromotingJniRuntime::HandleExtensionMessage(const std::string& type,
  268. const std::string& message) {
  269. DCHECK(ui_task_runner_->BelongsToCurrentThread());
  270. JNIEnv* env = base::android::AttachCurrentThread();
  271. ScopedJavaLocalRef<jstring> j_type = ConvertUTF8ToJavaString(env, type);
  272. ScopedJavaLocalRef<jstring> j_message = ConvertUTF8ToJavaString(env, message);
  273. Java_JniInterface_handleExtensionMessage(env, j_type.obj(), j_message.obj());
  274. }
  275. base::android::ScopedJavaLocalRef<jobject> ChromotingJniRuntime::NewBitmap(
  276. int width, int height) {
  277. JNIEnv* env = base::android::AttachCurrentThread();
  278. return Java_JniInterface_newBitmap(env, width, height);
  279. }
  280. void ChromotingJniRuntime::UpdateFrameBitmap(jobject bitmap) {
  281. DCHECK(display_task_runner_->BelongsToCurrentThread());
  282. JNIEnv* env = base::android::AttachCurrentThread();
  283. Java_JniInterface_setVideoFrame(env, bitmap);
  284. }
  285. void ChromotingJniRuntime::UpdateCursorShape(
  286. const protocol::CursorShapeInfo& cursor_shape) {
  287. DCHECK(display_task_runner_->BelongsToCurrentThread());
  288. // const_cast<> is safe as long as the Java updateCursorShape() method copies
  289. // the data out of the buffer without mutating it, and doesn't keep any
  290. // reference to the buffer afterwards. Unfortunately, there seems to be no way
  291. // to create a read-only ByteBuffer from a pointer-to-const.
  292. char* data = string_as_array(const_cast<std::string*>(&cursor_shape.data()));
  293. int cursor_total_bytes =
  294. cursor_shape.width() * cursor_shape.height() * kBytesPerPixel;
  295. JNIEnv* env = base::android::AttachCurrentThread();
  296. base::android::ScopedJavaLocalRef<jobject> buffer(env,
  297. env->NewDirectByteBuffer(data, cursor_total_bytes));
  298. Java_JniInterface_updateCursorShape(env,
  299. cursor_shape.width(),
  300. cursor_shape.height(),
  301. cursor_shape.hotspot_x(),
  302. cursor_shape.hotspot_y(),
  303. buffer.obj());
  304. }
  305. void ChromotingJniRuntime::RedrawCanvas() {
  306. DCHECK(display_task_runner_->BelongsToCurrentThread());
  307. JNIEnv* env = base::android::AttachCurrentThread();
  308. Java_JniInterface_redrawGraphicsInternal(env);
  309. }
  310. void ChromotingJniRuntime::DetachFromVmAndSignal(base::WaitableEvent* waiter) {
  311. base::android::DetachFromVM();
  312. waiter->Signal();
  313. }
  314. } // namespace remoting