| // Copyright 2014 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 "components/gcm_driver/gcm_driver_android.h" |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include "base/android/context_utils.h" |
| #include "base/android/jni_android.h" |
| #include "base/android/jni_array.h" |
| #include "base/android/jni_string.h" |
| #include "base/compiler_specific.h" |
| #include "base/logging.h" |
| #include "jni/GCMDriver_jni.h" |
| |
| using base::android::AppendJavaStringArrayToStringVector; |
| using base::android::AttachCurrentThread; |
| using base::android::ConvertJavaStringToUTF8; |
| using base::android::ConvertUTF8ToJavaString; |
| using base::android::JavaByteArrayToByteVector; |
| using base::android::JavaParamRef; |
| |
| namespace gcm { |
| |
| GCMDriverAndroid::GCMDriverAndroid( |
| const base::FilePath& store_path, |
| const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner) |
| : GCMDriver(store_path, blocking_task_runner), |
| recorder_(this) { |
| JNIEnv* env = AttachCurrentThread(); |
| java_ref_.Reset( |
| Java_GCMDriver_create(env, |
| reinterpret_cast<intptr_t>(this), |
| base::android::GetApplicationContext())); |
| } |
| |
| GCMDriverAndroid::~GCMDriverAndroid() { |
| JNIEnv* env = AttachCurrentThread(); |
| Java_GCMDriver_destroy(env, java_ref_); |
| } |
| |
| void GCMDriverAndroid::OnRegisterFinished( |
| JNIEnv* env, |
| const JavaParamRef<jobject>& obj, |
| const JavaParamRef<jstring>& j_app_id, |
| const JavaParamRef<jstring>& j_registration_id, |
| jboolean success) { |
| std::string app_id = ConvertJavaStringToUTF8(env, j_app_id); |
| std::string registration_id = ConvertJavaStringToUTF8(env, j_registration_id); |
| GCMClient::Result result = success ? GCMClient::SUCCESS |
| : GCMClient::UNKNOWN_ERROR; |
| |
| recorder_.RecordRegistrationResponse(app_id, success); |
| |
| RegisterFinished(app_id, registration_id, result); |
| } |
| |
| void GCMDriverAndroid::OnUnregisterFinished( |
| JNIEnv* env, |
| const JavaParamRef<jobject>& obj, |
| const JavaParamRef<jstring>& j_app_id, |
| jboolean success) { |
| std::string app_id = ConvertJavaStringToUTF8(env, j_app_id); |
| GCMClient::Result result = success ? GCMClient::SUCCESS |
| : GCMClient::UNKNOWN_ERROR; |
| |
| recorder_.RecordUnregistrationResponse(app_id, success); |
| |
| RemoveEncryptionInfoAfterUnregister(app_id, result); |
| } |
| |
| void GCMDriverAndroid::OnMessageReceived( |
| JNIEnv* env, |
| const JavaParamRef<jobject>& obj, |
| const JavaParamRef<jstring>& j_app_id, |
| const JavaParamRef<jstring>& j_sender_id, |
| const JavaParamRef<jstring>& j_collapse_key, |
| const JavaParamRef<jbyteArray>& j_raw_data, |
| const JavaParamRef<jobjectArray>& j_data_keys_and_values) { |
| std::string app_id = ConvertJavaStringToUTF8(env, j_app_id); |
| |
| int message_byte_size = 0; |
| |
| IncomingMessage message; |
| message.sender_id = ConvertJavaStringToUTF8(env, j_sender_id); |
| if (!j_collapse_key.is_null()) |
| ConvertJavaStringToUTF8(env, j_collapse_key, &message.collapse_key); |
| |
| // Expand j_data_keys_and_values from array to map. |
| std::vector<std::string> data_keys_and_values; |
| AppendJavaStringArrayToStringVector(env, |
| j_data_keys_and_values, |
| &data_keys_and_values); |
| for (size_t i = 0; i + 1 < data_keys_and_values.size(); i += 2) { |
| message.data[data_keys_and_values[i]] = data_keys_and_values[i+1]; |
| message_byte_size += data_keys_and_values[i+1].size(); |
| } |
| // Convert j_raw_data from byte[] to binary std::string. |
| if (j_raw_data) { |
| std::vector<uint8_t> raw_data; |
| JavaByteArrayToByteVector(env, j_raw_data, &raw_data); |
| message.raw_data.assign(raw_data.begin(), raw_data.end()); |
| |
| message_byte_size += message.raw_data.size(); |
| } |
| |
| recorder_.RecordDataMessageReceived(app_id, message.sender_id, |
| message_byte_size); |
| |
| DispatchMessage(app_id, message); |
| } |
| |
| // static |
| bool GCMDriverAndroid::RegisterJni(JNIEnv* env) { |
| return RegisterNativesImpl(env); |
| } |
| |
| void GCMDriverAndroid::OnSignedIn() { |
| } |
| |
| void GCMDriverAndroid::OnSignedOut() { |
| } |
| |
| void GCMDriverAndroid::AddConnectionObserver(GCMConnectionObserver* observer) { |
| } |
| |
| void GCMDriverAndroid::RemoveConnectionObserver( |
| GCMConnectionObserver* observer) { |
| } |
| |
| void GCMDriverAndroid::Enable() { |
| } |
| |
| void GCMDriverAndroid::Disable() { |
| } |
| |
| GCMClient* GCMDriverAndroid::GetGCMClientForTesting() const { |
| NOTIMPLEMENTED(); |
| return NULL; |
| } |
| |
| bool GCMDriverAndroid::IsStarted() const { |
| return true; |
| } |
| |
| bool GCMDriverAndroid::IsConnected() const { |
| // TODO(gcm): hook up to GCM connected status |
| return true; |
| } |
| |
| void GCMDriverAndroid::GetGCMStatistics( |
| const GetGCMStatisticsCallback& callback, |
| ClearActivityLogs clear_logs) { |
| DCHECK(!callback.is_null()); |
| |
| get_gcm_statistics_callback_ = callback; |
| |
| if (clear_logs == CLEAR_LOGS) |
| recorder_.Clear(); |
| |
| GCMClient::GCMStatistics stats; |
| stats.is_recording = recorder_.is_recording(); |
| |
| recorder_.CollectActivities(&stats.recorded_activities); |
| |
| callback.Run(stats); |
| } |
| |
| void GCMDriverAndroid::SetGCMRecording(const GetGCMStatisticsCallback& callback, |
| bool recording) { |
| DCHECK(!callback.is_null()); |
| |
| recorder_.set_is_recording(recording); |
| |
| GetGCMStatistics(callback, recording ? KEEP_LOGS : CLEAR_LOGS); |
| } |
| |
| void GCMDriverAndroid::SetAccountTokens( |
| const std::vector<GCMClient::AccountTokenInfo>& account_tokens) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void GCMDriverAndroid::UpdateAccountMapping( |
| const AccountMapping& account_mapping) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void GCMDriverAndroid::RemoveAccountMapping(const std::string& account_id) { |
| NOTIMPLEMENTED(); |
| } |
| |
| base::Time GCMDriverAndroid::GetLastTokenFetchTime() { |
| NOTIMPLEMENTED(); |
| return base::Time(); |
| } |
| |
| void GCMDriverAndroid::SetLastTokenFetchTime(const base::Time& time) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void GCMDriverAndroid::WakeFromSuspendForHeartbeat(bool wake) { |
| } |
| |
| InstanceIDHandler* GCMDriverAndroid::GetInstanceIDHandlerInternal() { |
| // Not supported for Android. |
| return NULL; |
| } |
| |
| void GCMDriverAndroid::AddHeartbeatInterval(const std::string& scope, |
| int interval_ms) { |
| } |
| |
| void GCMDriverAndroid::RemoveHeartbeatInterval(const std::string& scope) { |
| } |
| |
| void GCMDriverAndroid::OnActivityRecorded() { |
| DCHECK(!get_gcm_statistics_callback_.is_null()); |
| |
| GetGCMStatistics(get_gcm_statistics_callback_, KEEP_LOGS); |
| } |
| |
| GCMClient::Result GCMDriverAndroid::EnsureStarted( |
| GCMClient::StartMode start_mode) { |
| // TODO(johnme): Maybe we should check if GMS is available? |
| return GCMClient::SUCCESS; |
| } |
| |
| void GCMDriverAndroid::RegisterImpl( |
| const std::string& app_id, const std::vector<std::string>& sender_ids) { |
| DCHECK_EQ(1u, sender_ids.size()); |
| JNIEnv* env = AttachCurrentThread(); |
| |
| recorder_.RecordRegistrationSent(app_id); |
| |
| Java_GCMDriver_register(env, java_ref_, ConvertUTF8ToJavaString(env, app_id), |
| ConvertUTF8ToJavaString(env, sender_ids[0])); |
| } |
| |
| void GCMDriverAndroid::UnregisterImpl(const std::string& app_id) { |
| NOTREACHED(); |
| } |
| |
| void GCMDriverAndroid::UnregisterWithSenderIdImpl( |
| const std::string& app_id, |
| const std::string& sender_id) { |
| JNIEnv* env = AttachCurrentThread(); |
| |
| recorder_.RecordUnregistrationSent(app_id); |
| |
| Java_GCMDriver_unregister(env, java_ref_, |
| ConvertUTF8ToJavaString(env, app_id), |
| ConvertUTF8ToJavaString(env, sender_id)); |
| } |
| |
| void GCMDriverAndroid::SendImpl(const std::string& app_id, |
| const std::string& receiver_id, |
| const OutgoingMessage& message) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void GCMDriverAndroid::RecordDecryptionFailure( |
| const std::string& app_id, |
| GCMEncryptionProvider::DecryptionResult result) { |
| recorder_.RecordDecryptionFailure(app_id, result); |
| } |
| |
| } // namespace gcm |