diff options
-rw-r--r-- | build/all_android.gyp | 1 | ||||
-rw-r--r-- | remoting/client/jni/OWNERS | 3 | ||||
-rw-r--r-- | remoting/client/jni/chromoting_jni_instance.cc | 137 | ||||
-rw-r--r-- | remoting/client/jni/chromoting_jni_instance.h | 91 | ||||
-rw-r--r-- | remoting/client/jni/jni_interface.cc | 57 | ||||
-rw-r--r-- | remoting/remoting.gyp | 20 |
6 files changed, 309 insertions, 0 deletions
diff --git a/build/all_android.gyp b/build/all_android.gyp index 79bbcdd..eaac50c8 100644 --- a/build/all_android.gyp +++ b/build/all_android.gyp @@ -22,6 +22,7 @@ 'android_builder_tests', '../android_webview/android_webview.gyp:android_webview_apk', '../chrome/chrome.gyp:chromium_testshell', + '../remoting/remoting.gyp:remoting_client_jni', # TODO(nyquist) This should instead by a target for sync when all of # the sync-related code for Android has been upstreamed. # See http://crbug.com/159203 diff --git a/remoting/client/jni/OWNERS b/remoting/client/jni/OWNERS new file mode 100644 index 0000000..f94f63b --- /dev/null +++ b/remoting/client/jni/OWNERS @@ -0,0 +1,3 @@ +garykac@chromium.org +solb@chromium.org +wez@chromium.org diff --git a/remoting/client/jni/chromoting_jni_instance.cc b/remoting/client/jni/chromoting_jni_instance.cc new file mode 100644 index 0000000..99743a6 --- /dev/null +++ b/remoting/client/jni/chromoting_jni_instance.cc @@ -0,0 +1,137 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/client/jni/chromoting_jni_instance.h" + +#include "base/android/base_jni_registrar.h" +#include "base/android/jni_android.h" +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/logging.h" +#include "base/memory/singleton.h" +#include "net/android/net_jni_registrar.h" +#include "remoting/base/url_request_context.h" + +namespace remoting { + +ChromotingJNIInstance* ChromotingJNIInstance::GetInstance() { + return Singleton<ChromotingJNIInstance>::get(); +} + +// For now, this just gives us access to the strings supplied from Java. +void ChromotingJNIInstance::ConnectToHost(jstring username, + jstring auth_token, + jstring host_jid, + jstring host_id, + jstring host_pubkey) { + JNIEnv* env = base::android::AttachCurrentThread(); + + username_jstr_ = static_cast<jstring>(env->NewGlobalRef(username)); + auth_token_jstr_ = static_cast<jstring>(env->NewGlobalRef(auth_token)); + host_jid_jstr_ = static_cast<jstring>(env->NewGlobalRef(host_jid)); + host_id_jstr_ = static_cast<jstring>(env->NewGlobalRef(host_id)); + host_pubkey_jstr_ = static_cast<jstring>(env->NewGlobalRef(host_pubkey)); + + username_cstr_ = env->GetStringUTFChars(username_jstr_, NULL); + auth_token_cstr_ = env->GetStringUTFChars(auth_token_jstr_, NULL); + host_jid_cstr_ = env->GetStringUTFChars(host_jid_jstr_, NULL); + host_id_cstr_ = env->GetStringUTFChars(host_id_jstr_, NULL); + host_pubkey_cstr_ = env->GetStringUTFChars(host_pubkey_jstr_, NULL); + + // TODO(solb) Initiate connection from here. +} + +// For the moment, this only releases the Java string references. +void ChromotingJNIInstance::DisconnectFromHost() { + JNIEnv* env = base::android::AttachCurrentThread(); + + env->ReleaseStringUTFChars(username_jstr_, username_cstr_); + env->ReleaseStringUTFChars(auth_token_jstr_, auth_token_cstr_); + env->ReleaseStringUTFChars(host_jid_jstr_, host_jid_cstr_); + env->ReleaseStringUTFChars(host_id_jstr_, host_id_cstr_); + env->ReleaseStringUTFChars(host_pubkey_jstr_, host_pubkey_cstr_); + + username_cstr_ = NULL; + auth_token_cstr_ = NULL; + host_jid_cstr_ = NULL; + host_id_cstr_ = NULL; + host_pubkey_cstr_ = NULL; + + env->DeleteGlobalRef(username_jstr_); + env->DeleteGlobalRef(auth_token_jstr_); + env->DeleteGlobalRef(host_jid_jstr_); + env->DeleteGlobalRef(host_id_jstr_); + env->DeleteGlobalRef(host_pubkey_jstr_); +} + +void ChromotingJNIInstance::OnConnectionState( + protocol::ConnectionToHost::State state, + protocol::ErrorCode error) {} + +void ChromotingJNIInstance::OnConnectionReady(bool ready) {} + +void ChromotingJNIInstance::SetCapabilities(const std::string& capabilities) {} + +void ChromotingJNIInstance::SetPairingResponse( + const protocol::PairingResponse& response) {} + +protocol::ClipboardStub* ChromotingJNIInstance::GetClipboardStub() { + NOTIMPLEMENTED(); + return NULL; +} + +protocol::CursorShapeStub* ChromotingJNIInstance::GetCursorShapeStub() { + NOTIMPLEMENTED(); + return NULL; +} + +// We don't use NOTIMPLEMENTED() here because NegotiatingClientAuthenticator +// calls this even if it doesn't use the configuration method, and we don't +// want to print an error on every run. +scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher> + ChromotingJNIInstance::GetTokenFetcher(const std::string& host_public_key) { + LOG(INFO) << "ChromotingJNIInstance::GetTokenFetcher(...) [unimplemented]"; + return scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher>(); +} + +// This currently only spins up the threads. +ChromotingJNIInstance::ChromotingJNIInstance() + : username_cstr_(NULL), + auth_token_cstr_(NULL), + host_jid_cstr_(NULL), + host_id_cstr_(NULL), + host_pubkey_cstr_(NULL), + pin_cstr_(NULL) { + JNIEnv* env = base::android::AttachCurrentThread(); + + collector_.reset(new base::AtExitManager()); + base::android::RegisterJni(env); + net::android::RegisterJni(env); + + LOG(INFO) << "starting main message loop"; + ui_loop_.reset(new base::MessageLoopForUI()); + ui_loop_->Start(); + + LOG(INFO) << "spawning additional threads"; + ui_runner_ = new AutoThreadTaskRunner(ui_loop_->message_loop_proxy(), + base::MessageLoop::QuitClosure()); + net_runner_ = AutoThread::CreateWithType("native_net", + ui_runner_, + base::MessageLoop::TYPE_IO); + disp_runner_ = AutoThread::CreateWithType("native_disp", + ui_runner_, + base::MessageLoop::TYPE_DEFAULT); + + url_requester_ = new URLRequestContextGetter(ui_runner_, net_runner_); + + class_ = static_cast<jclass>(env->NewGlobalRef(env->FindClass(JAVA_CLASS))); +} + +ChromotingJNIInstance::~ChromotingJNIInstance() { + JNIEnv* env = base::android::AttachCurrentThread(); + env->DeleteGlobalRef(class_); + // TODO(solb) detach all threads from JVM +} + +} // namespace remoting diff --git a/remoting/client/jni/chromoting_jni_instance.h b/remoting/client/jni/chromoting_jni_instance.h new file mode 100644 index 0000000..7326b4f --- /dev/null +++ b/remoting/client/jni/chromoting_jni_instance.h @@ -0,0 +1,91 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef REMOTING_CLIENT_CHROMOTING_JNI_INSTANCE_H_ +#define REMOTING_CLIENT_CHROMOTING_JNI_INSTANCE_H_ + +#include <jni.h> +#include <string> + +#include "base/at_exit.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "net/url_request/url_request_context_getter.h" +#include "remoting/base/auto_thread.h" +#include "remoting/client/client_user_interface.h" + +template<typename T> struct DefaultSingletonTraits; + +// Class and package name of the Java class supporting the methods we call. +const char* const JAVA_CLASS="org/chromium/chromoting/jni/JNIInterface"; + +namespace remoting { + +// ClientUserInterface that makes and (indirectly) receives JNI calls. +class ChromotingJNIInstance : public ClientUserInterface { + public: + static ChromotingJNIInstance* GetInstance(); + + // Call from UI thread. + void ConnectToHost( + jstring username, + jstring auth_token, + jstring host_jid, + jstring host_id, + jstring host_pubkey); + + // Call from UI thread. + void DisconnectFromHost(); + + // ClientUserInterface implementation: + virtual void OnConnectionState( + protocol::ConnectionToHost::State state, + protocol::ErrorCode error) OVERRIDE; + virtual void OnConnectionReady(bool ready) OVERRIDE; + virtual void SetCapabilities(const std::string& capabilities) OVERRIDE; + virtual void SetPairingResponse( + const protocol::PairingResponse& response) OVERRIDE; + virtual protocol::ClipboardStub* GetClipboardStub() OVERRIDE; + virtual protocol::CursorShapeStub* GetCursorShapeStub() OVERRIDE; + virtual scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher> + GetTokenFetcher(const std::string& host_public_key) OVERRIDE; + + private: + ChromotingJNIInstance(); + virtual ~ChromotingJNIInstance(); + + // Reusable between sessions: + jclass class_; // Reference to the Java class into which we make JNI calls. + scoped_ptr<base::AtExitManager> collector_; + scoped_ptr<base::MessageLoopForUI> ui_loop_; + scoped_refptr<AutoThreadTaskRunner> ui_runner_; + scoped_refptr<AutoThreadTaskRunner> net_runner_; + scoped_refptr<AutoThreadTaskRunner> disp_runner_; + scoped_refptr<net::URLRequestContextGetter> url_requester_; + + // Java string handles: + jstring username_jstr_; + jstring auth_token_jstr_; + jstring host_jid_jstr_; + jstring host_id_jstr_; + jstring host_pubkey_jstr_; + jstring pin_jstr_; + + // C string pointers: + const char* username_cstr_; + const char* auth_token_cstr_; + const char* host_jid_cstr_; + const char* host_id_cstr_; + const char* host_pubkey_cstr_; + const char* pin_cstr_; + + friend struct DefaultSingletonTraits<ChromotingJNIInstance>; + + DISALLOW_COPY_AND_ASSIGN(ChromotingJNIInstance); +}; + +} // namespace remoting + +#endif diff --git a/remoting/client/jni/jni_interface.cc b/remoting/client/jni/jni_interface.cc new file mode 100644 index 0000000..cb7f6c2 --- /dev/null +++ b/remoting/client/jni/jni_interface.cc @@ -0,0 +1,57 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file defines functions that implement the static methods declared in a +// closely-related Java class in the platform-specific user interface +// implementation. In effect, it is the entry point for all JNI calls *into* +// the C++ codebase from Java. The separate ChromotingJNIInstance class serves +// as the corresponding exit point, and is responsible for making all JNI calls +// *out of* the C++ codebase into Java. + +#include <jni.h> + +#include "base/android/jni_android.h" +#include "base/memory/ref_counted.h" +#include "remoting/client/jni/chromoting_jni_instance.h" + +// Class and package name of the Java class that declares this file's functions. +#define JNI_IMPLEMENTATION(method) \ + Java_org_chromium_chromoting_jni_JNIInterface_##method + +extern "C" { + +JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { + base::android::InitVM(vm); + return JNI_VERSION_1_2; +} + +JNIEXPORT void JNICALL JNI_IMPLEMENTATION(loadNative)(JNIEnv* env, + jobject that, + jobject context) { + base::android::ScopedJavaLocalRef<jobject> context_activity(env, context); + base::android::InitApplicationContext(context_activity); + + remoting::ChromotingJNIInstance::GetInstance(); // Initialize threads now. +} + +JNIEXPORT void JNICALL JNI_IMPLEMENTATION(connectNative)(JNIEnv* env, + jobject that, + jstring username, + jstring auth_token, + jstring host_jid, + jstring host_id, + jstring host_pubkey) { + remoting::ChromotingJNIInstance::GetInstance()->ConnectToHost(username, + auth_token, + host_jid, + host_id, + host_pubkey); +} + +JNIEXPORT void JNICALL JNI_IMPLEMENTATION(disconnectNative)(JNIEnv* env, + jobject that) { + remoting::ChromotingJNIInstance::GetInstance()->DisconnectFromHost(); +} + +} // extern "C" diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp index 9885a4b..375f562 100644 --- a/remoting/remoting.gyp +++ b/remoting/remoting.gyp @@ -1880,6 +1880,26 @@ ], # end of 'targets' }], # 'OS=="win"' + ['OS=="android"', { + 'targets': [ + { + 'target_name': 'remoting_client_jni', + 'type': 'shared_library', + 'dependencies': [ + 'remoting_base', + 'remoting_client', + 'remoting_jingle_glue', + 'remoting_protocol', + ], + 'sources': [ + 'client/jni/chromoting_jni_instance.cc', + 'client/jni/chromoting_jni_instance.h', + 'client/jni/jni_interface.cc', + ], + }, # end of target 'remoting_client_jni' + ], # end of 'targets' + }], # 'OS=="android"' + # The host installation is generated only if WiX is available. If # component build is used the produced installation will not work due to # missing DLLs. We build it anyway to make sure the GYP scripts are executed |