// 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 #include #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; namespace gcm { GCMDriverAndroid::GCMDriverAndroid( const base::FilePath& store_path, const scoped_refptr& blocking_task_runner) : GCMDriver(store_path, blocking_task_runner), recorder_(this) { JNIEnv* env = AttachCurrentThread(); java_ref_.Reset( Java_GCMDriver_create(env, reinterpret_cast(this), base::android::GetApplicationContext())); } GCMDriverAndroid::~GCMDriverAndroid() { JNIEnv* env = AttachCurrentThread(); Java_GCMDriver_destroy(env, java_ref_.obj()); } void GCMDriverAndroid::OnRegisterFinished( JNIEnv* env, const JavaParamRef& obj, const JavaParamRef& j_app_id, const JavaParamRef& 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& obj, const JavaParamRef& 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& obj, const JavaParamRef& j_app_id, const JavaParamRef& j_sender_id, const JavaParamRef& j_collapse_key, const JavaParamRef& j_raw_data, const JavaParamRef& 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); message.collapse_key = ConvertJavaStringToUTF8(env, j_collapse_key); // Expand j_data_keys_and_values from array to map. std::vector 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 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_byte_size); DispatchMessage(app_id, message); } // static bool GCMDriverAndroid::RegisterBindings(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& 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::GetInstanceIDHandler() { // 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& sender_ids) { DCHECK_EQ(1u, sender_ids.size()); JNIEnv* env = AttachCurrentThread(); recorder_.RecordRegistrationSent(app_id); Java_GCMDriver_register(env, java_ref_.obj(), ConvertUTF8ToJavaString(env, app_id).obj(), ConvertUTF8ToJavaString(env, sender_ids[0]).obj()); } 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_.obj(), ConvertUTF8ToJavaString(env, app_id).obj(), ConvertUTF8ToJavaString(env, sender_id).obj()); } 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