| 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_instance.h" | 5 #include "remoting/client/jni/chromoting_jni_instance.h" |
| 6 | 6 |
| 7 #include "base/android/base_jni_registrar.h" | |
| 8 #include "base/android/jni_android.h" | |
| 9 #include "base/bind.h" | 7 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | |
| 11 #include "base/logging.h" | 8 #include "base/logging.h" |
| 12 #include "base/memory/singleton.h" | |
| 13 #include "net/android/net_jni_registrar.h" | |
| 14 #include "remoting/base/url_request_context.h" | |
| 15 #include "remoting/client/audio_player.h" | 9 #include "remoting/client/audio_player.h" |
| 10 #include "remoting/client/jni/chromoting_jni.h" |
| 16 #include "remoting/protocol/libjingle_transport_factory.h" | 11 #include "remoting/protocol/libjingle_transport_factory.h" |
| 17 | 12 |
| 18 namespace remoting { | 13 namespace remoting { |
| 19 | 14 |
| 20 // static | 15 ChromotingJNIInstance::ChromotingJNIInstance(const char* username, |
| 21 ChromotingJNIInstance* ChromotingJNIInstance::GetInstance() { | 16 const char* auth_token, |
| 22 return Singleton<ChromotingJNIInstance>::get(); | 17 const char* host_jid, |
| 23 } | 18 const char* host_id, |
| 24 | 19 const char* host_pubkey) { |
| 25 ChromotingJNIInstance::ChromotingJNIInstance() | 20 DCHECK(ChromotingJNI::GetInstance()-> |
| 26 : connected_(false) { | 21 ui_task_runner()->BelongsToCurrentThread()); |
| 27 JNIEnv* env = base::android::AttachCurrentThread(); | |
| 28 | |
| 29 // The base and networks stacks must be registered with JNI in order to work | |
| 30 // on Android. An AtExitManager cleans this up at world's end. | |
| 31 collector_.reset(new base::AtExitManager()); | |
| 32 base::android::RegisterJni(env); | |
| 33 net::android::RegisterJni(env); | |
| 34 | |
| 35 // On Android, the UI thread is managed by Java, so we need to attach and | |
| 36 // start a special type of message loop to allow Chromium code to run tasks. | |
| 37 LOG(INFO) << "Starting main message loop"; | |
| 38 ui_loop_.reset(new base::MessageLoopForUI()); | |
| 39 ui_loop_->Start(); | |
| 40 | |
| 41 LOG(INFO) << "Spawning additional threads"; | |
| 42 // TODO(solb) Stop pretending to control the managed UI thread's lifetime. | |
| 43 ui_task_runner_ = new AutoThreadTaskRunner(ui_loop_->message_loop_proxy(), | |
| 44 base::MessageLoop::QuitClosure()); | |
| 45 network_task_runner_ = AutoThread::CreateWithType("native_net", | |
| 46 ui_task_runner_, | |
| 47 base::MessageLoop::TYPE_IO); | |
| 48 display_task_runner_ = AutoThread::Create("native_disp", | |
| 49 ui_task_runner_); | |
| 50 | |
| 51 url_requester_ = new URLRequestContextGetter(ui_task_runner_, | |
| 52 network_task_runner_); | |
| 53 | |
| 54 class_ = static_cast<jclass>(env->NewGlobalRef(env->FindClass(JAVA_CLASS))); | |
| 55 } | |
| 56 | |
| 57 ChromotingJNIInstance::~ChromotingJNIInstance() { | |
| 58 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | |
| 59 DCHECK(!connected_); | |
| 60 | |
| 61 JNIEnv* env = base::android::AttachCurrentThread(); | |
| 62 env->DeleteGlobalRef(class_); | |
| 63 // TODO(solb): crbug.com/259594 Detach all threads from JVM here. | |
| 64 } | |
| 65 | |
| 66 void ChromotingJNIInstance::ConnectToHost(const char* username, | |
| 67 const char* auth_token, | |
| 68 const char* host_jid, | |
| 69 const char* host_id, | |
| 70 const char* host_pubkey) { | |
| 71 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | |
| 72 DCHECK(!connected_); | |
| 73 connected_ = true; | |
| 74 | 22 |
| 75 username_ = username; | 23 username_ = username; |
| 76 auth_token_ = auth_token; | 24 auth_token_ = auth_token; |
| 77 host_jid_ = host_jid; | 25 host_jid_ = host_jid; |
| 78 host_id_ = host_id; | 26 host_id_ = host_id; |
| 79 host_pubkey_ = host_pubkey; | 27 host_pubkey_ = host_pubkey; |
| 80 | 28 |
| 81 display_task_runner_->PostTask(FROM_HERE, base::Bind( | 29 ChromotingJNI::GetInstance()->display_task_runner()->PostTask( |
| 82 &ChromotingJNIInstance::ConnectToHostOnDisplayThread, | 30 FROM_HERE, |
| 83 base::Unretained(this))); | 31 base::Bind(&ChromotingJNIInstance::ConnectToHostOnDisplayThread, |
| 32 this)); |
| 84 } | 33 } |
| 85 | 34 |
| 86 void ChromotingJNIInstance::DisconnectFromHost() { | 35 ChromotingJNIInstance::~ChromotingJNIInstance() {} |
| 87 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | |
| 88 DCHECK(connected_); | |
| 89 connected_ = false; | |
| 90 | 36 |
| 91 network_task_runner_->PostTask(FROM_HERE, base::Bind( | 37 void ChromotingJNIInstance::Cleanup() { |
| 92 &ChromotingJNIInstance::DisconnectFromHostOnNetworkThread, | 38 if (!ChromotingJNI::GetInstance()-> |
| 93 base::Unretained(this))); | 39 network_task_runner()->BelongsToCurrentThread()) { |
| 40 ChromotingJNI::GetInstance()->network_task_runner()->PostTask( |
| 41 FROM_HERE, |
| 42 base::Bind(&ChromotingJNIInstance::Cleanup, this)); |
| 43 return; |
| 44 } |
| 45 |
| 46 username_ = ""; |
| 47 auth_token_ = ""; |
| 48 host_jid_ = ""; |
| 49 host_id_ = ""; |
| 50 host_pubkey_ = ""; |
| 51 |
| 52 // |client_| must be torn down before |signaling_|. |
| 53 pin_callback_.Reset(); |
| 54 client_.reset(); |
| 55 connection_.reset(); |
| 56 client_context_.reset(); |
| 57 client_config_.reset(); |
| 58 signaling_.reset(); |
| 59 signaling_config_.reset(); |
| 60 network_settings_.reset(); |
| 94 } | 61 } |
| 95 | 62 |
| 96 void ChromotingJNIInstance::ProvideSecret(const char* pin) { | 63 void ChromotingJNIInstance::ProvideSecret(const char* pin) { |
| 97 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 64 DCHECK(ChromotingJNI::GetInstance()-> |
| 65 ui_task_runner()->BelongsToCurrentThread()); |
| 98 DCHECK(!pin_callback_.is_null()); | 66 DCHECK(!pin_callback_.is_null()); |
| 99 | 67 |
| 100 // We invoke the string constructor to ensure |pin| gets copied *before* the | 68 // We invoke the string constructor to ensure |pin| gets copied *before* the |
| 101 // asynchronous run, since Java might want it back as soon as we return. | 69 // asynchronous run, since Java might want it back as soon as we return. |
| 102 network_task_runner_->PostTask(FROM_HERE, | 70 ChromotingJNI::GetInstance()->network_task_runner()->PostTask(FROM_HERE, |
| 103 base::Bind(pin_callback_, std::string(pin))); | 71 base::Bind(pin_callback_, std::string(pin))); |
| 104 } | 72 } |
| 105 | 73 |
| 106 void ChromotingJNIInstance::OnConnectionState( | 74 void ChromotingJNIInstance::OnConnectionState( |
| 107 protocol::ConnectionToHost::State state, | 75 protocol::ConnectionToHost::State state, |
| 108 protocol::ErrorCode error) { | 76 protocol::ErrorCode error) { |
| 109 if (!ui_task_runner_->BelongsToCurrentThread()) { | 77 if (!ChromotingJNI::GetInstance()-> |
| 110 ui_task_runner_->PostTask(FROM_HERE, base::Bind( | 78 ui_task_runner()->BelongsToCurrentThread()) { |
| 111 &ChromotingJNIInstance::OnConnectionState, | 79 ChromotingJNI::GetInstance()-> |
| 112 base::Unretained(this), | 80 ui_task_runner()->PostTask( |
| 113 state, | 81 FROM_HERE, |
| 114 error)); | 82 base::Bind(&ChromotingJNIInstance::OnConnectionState, |
| 83 this, |
| 84 state, |
| 85 error)); |
| 115 return; | 86 return; |
| 116 } | 87 } |
| 117 | 88 |
| 118 JNIEnv* env = base::android::AttachCurrentThread(); | 89 ChromotingJNI::GetInstance()->ReportConnectionStatus(state, error); |
| 119 env->CallStaticVoidMethod( | |
| 120 class_, | |
| 121 env->GetStaticMethodID(class_, "reportConnectionStatus", "(II)V"), | |
| 122 state, | |
| 123 error); | |
| 124 } | 90 } |
| 125 | 91 |
| 126 void ChromotingJNIInstance::OnConnectionReady(bool ready) { | 92 void ChromotingJNIInstance::OnConnectionReady(bool ready) { |
| 127 // We ignore this message, since OnConnectionState() tells us the same thing. | 93 // We ignore this message, since OnConnectionState() tells us the same thing. |
| 128 } | 94 } |
| 129 | 95 |
| 130 void ChromotingJNIInstance::SetCapabilities(const std::string& capabilities) {} | 96 void ChromotingJNIInstance::SetCapabilities(const std::string& capabilities) {} |
| 131 | 97 |
| 132 void ChromotingJNIInstance::SetPairingResponse( | 98 void ChromotingJNIInstance::SetPairingResponse( |
| 133 const protocol::PairingResponse& response) { | 99 const protocol::PairingResponse& response) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 144 return NULL; | 110 return NULL; |
| 145 } | 111 } |
| 146 | 112 |
| 147 scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher> | 113 scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher> |
| 148 ChromotingJNIInstance::GetTokenFetcher(const std::string& host_public_key) { | 114 ChromotingJNIInstance::GetTokenFetcher(const std::string& host_public_key) { |
| 149 // Return null to indicate that third-party authentication is unsupported. | 115 // Return null to indicate that third-party authentication is unsupported. |
| 150 return scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher>(); | 116 return scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher>(); |
| 151 } | 117 } |
| 152 | 118 |
| 153 void ChromotingJNIInstance::ConnectToHostOnDisplayThread() { | 119 void ChromotingJNIInstance::ConnectToHostOnDisplayThread() { |
| 154 DCHECK(display_task_runner_->BelongsToCurrentThread()); | 120 DCHECK(ChromotingJNI::GetInstance()-> |
| 121 display_task_runner()->BelongsToCurrentThread()); |
| 155 | 122 |
| 156 if (!frame_consumer_.get()) { | 123 if (!frame_consumer_.get()) { |
| 157 frame_consumer_ = new FrameConsumerProxy(display_task_runner_); | 124 frame_consumer_ = new FrameConsumerProxy( |
| 125 ChromotingJNI::GetInstance()->display_task_runner()); |
| 158 // TODO(solb) Instantiate some FrameConsumer implementation and attach it. | 126 // TODO(solb) Instantiate some FrameConsumer implementation and attach it. |
| 159 } | 127 } |
| 160 | 128 |
| 161 network_task_runner_->PostTask(FROM_HERE, base::Bind( | 129 ChromotingJNI::GetInstance()->network_task_runner()->PostTask( |
| 162 &ChromotingJNIInstance::ConnectToHostOnNetworkThread, | 130 FROM_HERE, |
| 163 base::Unretained(this))); | 131 base::Bind(&ChromotingJNIInstance::ConnectToHostOnNetworkThread, |
| 132 this)); |
| 164 } | 133 } |
| 165 | 134 |
| 166 void ChromotingJNIInstance::ConnectToHostOnNetworkThread() { | 135 void ChromotingJNIInstance::ConnectToHostOnNetworkThread() { |
| 167 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 136 DCHECK(ChromotingJNI::GetInstance()-> |
| 137 network_task_runner()->BelongsToCurrentThread()); |
| 168 | 138 |
| 169 client_config_.reset(new ClientConfig()); | 139 client_config_.reset(new ClientConfig()); |
| 170 client_config_->host_jid = host_jid_; | 140 client_config_->host_jid = host_jid_; |
| 171 client_config_->host_public_key = host_pubkey_; | 141 client_config_->host_public_key = host_pubkey_; |
| 172 | 142 |
| 173 client_config_->fetch_secret_callback = base::Bind( | 143 client_config_->fetch_secret_callback = base::Bind( |
| 174 &ChromotingJNIInstance::FetchSecret, | 144 &ChromotingJNIInstance::FetchSecret, |
| 175 base::Unretained(this)); | 145 this); |
| 176 client_config_->authentication_tag = host_id_; | 146 client_config_->authentication_tag = host_id_; |
| 177 | 147 |
| 178 // TODO(solb) Move these hardcoded values elsewhere: | 148 // TODO(solb) Move these hardcoded values elsewhere: |
| 179 client_config_->authentication_methods.push_back( | 149 client_config_->authentication_methods.push_back( |
| 180 protocol::AuthenticationMethod::FromString("spake2_hmac")); | 150 protocol::AuthenticationMethod::FromString("spake2_hmac")); |
| 181 client_config_->authentication_methods.push_back( | 151 client_config_->authentication_methods.push_back( |
| 182 protocol::AuthenticationMethod::FromString("spake2_plain")); | 152 protocol::AuthenticationMethod::FromString("spake2_plain")); |
| 183 | 153 |
| 184 client_context_.reset(new ClientContext(network_task_runner_.get())); | 154 client_context_.reset(new ClientContext( |
| 155 ChromotingJNI::GetInstance()->network_task_runner().get())); |
| 185 client_context_->Start(); | 156 client_context_->Start(); |
| 186 | 157 |
| 187 connection_.reset(new protocol::ConnectionToHost(true)); | 158 connection_.reset(new protocol::ConnectionToHost(true)); |
| 188 | 159 |
| 189 client_.reset(new ChromotingClient(*client_config_, | 160 client_.reset(new ChromotingClient(*client_config_, |
| 190 client_context_.get(), | 161 client_context_.get(), |
| 191 connection_.get(), | 162 connection_.get(), |
| 192 this, | 163 this, |
| 193 frame_consumer_, | 164 frame_consumer_, |
| 194 scoped_ptr<AudioPlayer>())); | 165 scoped_ptr<AudioPlayer>())); |
| 195 | 166 |
| 196 signaling_config_.reset(new XmppSignalStrategy::XmppServerConfig()); | 167 signaling_config_.reset(new XmppSignalStrategy::XmppServerConfig()); |
| 197 signaling_config_->host = CHAT_SERVER; | 168 signaling_config_->host = CHAT_SERVER; |
| 198 signaling_config_->port = CHAT_PORT; | 169 signaling_config_->port = CHAT_PORT; |
| 199 signaling_config_->use_tls = CHAT_USE_TLS; | 170 signaling_config_->use_tls = CHAT_USE_TLS; |
| 200 | 171 |
| 201 signaling_.reset(new XmppSignalStrategy(url_requester_, | 172 signaling_.reset(new XmppSignalStrategy( |
| 202 username_, | 173 ChromotingJNI::GetInstance()->url_requester(), |
| 203 auth_token_, | 174 username_, |
| 204 CHAT_AUTH_METHOD, | 175 auth_token_, |
| 205 *signaling_config_)); | 176 CHAT_AUTH_METHOD, |
| 177 *signaling_config_)); |
| 206 | 178 |
| 207 network_settings_.reset(new NetworkSettings( | 179 network_settings_.reset(new NetworkSettings( |
| 208 NetworkSettings::NAT_TRAVERSAL_OUTGOING)); | 180 NetworkSettings::NAT_TRAVERSAL_OUTGOING)); |
| 209 scoped_ptr<protocol::TransportFactory> fact( | 181 scoped_ptr<protocol::TransportFactory> fact( |
| 210 protocol::LibjingleTransportFactory::Create(*network_settings_, | 182 protocol::LibjingleTransportFactory::Create( |
| 211 url_requester_)); | 183 *network_settings_, |
| 184 ChromotingJNI::GetInstance()->url_requester())); |
| 212 | 185 |
| 213 client_->Start(signaling_.get(), fact.Pass()); | 186 client_->Start(signaling_.get(), fact.Pass()); |
| 214 } | 187 } |
| 215 | 188 |
| 216 void ChromotingJNIInstance::DisconnectFromHostOnNetworkThread() { | |
| 217 DCHECK(network_task_runner_->BelongsToCurrentThread()); | |
| 218 | |
| 219 username_ = ""; | |
| 220 auth_token_ = ""; | |
| 221 host_jid_ = ""; | |
| 222 host_id_ = ""; | |
| 223 host_pubkey_ = ""; | |
| 224 | |
| 225 // |client_| must be torn down before |signaling_|. | |
| 226 pin_callback_.Reset(); | |
| 227 client_.reset(); | |
| 228 connection_.reset(); | |
| 229 client_context_.reset(); | |
| 230 client_config_.reset(); | |
| 231 signaling_.reset(); | |
| 232 signaling_config_.reset(); | |
| 233 network_settings_.reset(); | |
| 234 } | |
| 235 | |
| 236 void ChromotingJNIInstance::FetchSecret( | 189 void ChromotingJNIInstance::FetchSecret( |
| 237 bool pairable, | 190 bool pairable, |
| 238 const protocol::SecretFetchedCallback& callback) { | 191 const protocol::SecretFetchedCallback& callback) { |
| 239 if (!ui_task_runner_->BelongsToCurrentThread()) { | 192 if (!ChromotingJNI::GetInstance()-> |
| 240 ui_task_runner_->PostTask(FROM_HERE, base::Bind( | 193 ui_task_runner()->BelongsToCurrentThread()) { |
| 241 &ChromotingJNIInstance::FetchSecret, | 194 ChromotingJNI::GetInstance()->ui_task_runner()->PostTask( |
| 242 base::Unretained(this), | 195 FROM_HERE, |
| 243 pairable, | 196 base::Bind(&ChromotingJNIInstance::FetchSecret, |
| 244 callback)); | 197 this, |
| 198 pairable, |
| 199 callback)); |
| 245 return; | 200 return; |
| 246 } | 201 } |
| 247 | 202 |
| 248 pin_callback_ = callback; | 203 pin_callback_ = callback; |
| 249 JNIEnv* env = base::android::AttachCurrentThread(); | 204 ChromotingJNI::GetInstance()->DisplayAuthenticationPrompt(); |
| 250 env->CallStaticVoidMethod( | |
| 251 class_, | |
| 252 env->GetStaticMethodID(class_, "displayAuthenticationPrompt", "()V")); | |
| 253 } | 205 } |
| 254 | 206 |
| 255 } // namespace remoting | 207 } // namespace remoting |
| OLD | NEW |