diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 4661625ae7..9c3b704346 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -114,6 +114,7 @@ LOCAL_SRC_FILES := \ com/mapswithme/platform/MarketingService.cpp \ com/mapswithme/platform/Platform.cpp \ com/mapswithme/platform/PThreadImpl.cpp \ + com/mapswithme/platform/SecureStorage.cpp \ com/mapswithme/platform/SocketImpl.cpp \ com/mapswithme/util/Config.cpp \ com/mapswithme/util/HttpClient.cpp \ diff --git a/android/jni/com/mapswithme/platform/Platform.cpp b/android/jni/com/mapswithme/platform/Platform.cpp index 24ea7273c6..844458f001 100644 --- a/android/jni/com/mapswithme/platform/Platform.cpp +++ b/android/jni/com/mapswithme/platform/Platform.cpp @@ -99,6 +99,8 @@ void Platform::Initialize(JNIEnv * env, m_sendPushWooshTagsMethod = env->GetMethodID(functorProcessClass, "sendPushWooshTags", "(Ljava/lang/String;[Ljava/lang/String;)V"); m_myTrackerTrackMethod = env->GetStaticMethodID(g_myTrackerClazz, "trackEvent", "(Ljava/lang/String;)V"); + m_secureStorage.Init(); + m_guiThread = my::make_unique(m_functorProcessObject); std::string const flavor = jni::ToNativeString(env, flavorName); @@ -223,6 +225,61 @@ void Platform::SetGuiThread(unique_ptr guiThread) m_guiThread = std::move(guiThread); } +void Platform::AndroidSecureStorage::Init() +{ + JNIEnv * env = jni::GetEnv(); + if (env == nullptr) + return; + + m_secureStorageClass = jni::GetGlobalClassRef(env, "com/mapswithme/util/SecureStorage"); + ASSERT(m_secureStorageClass, ()); +} + +void Platform::AndroidSecureStorage::Save(std::string const & key, std::string const & value) +{ + JNIEnv * env = jni::GetEnv(); + if (env == nullptr) + return; + + static jmethodID const saveMethodId = + jni::GetStaticMethodID(env, m_secureStorageClass, "save", "(Ljava/lang/String;Ljava/lang/String;)V"); + + env->CallStaticVoidMethod(m_secureStorageClass, saveMethodId, + jni::TScopedLocalRef(env, jni::ToJavaString(env, key)).get(), + jni::TScopedLocalRef(env, jni::ToJavaString(env, value)).get()); +} + +bool Platform::AndroidSecureStorage::Load(std::string const & key, std::string & value) +{ + JNIEnv * env = jni::GetEnv(); + if (env == nullptr) + return false; + + static jmethodID const loadMethodId = + jni::GetStaticMethodID(env, m_secureStorageClass, "load", "(Ljava/lang/String;)Ljava/lang/String;"); + + auto const resultString = static_cast(env->CallStaticObjectMethod(m_secureStorageClass, loadMethodId), + jni::TScopedLocalRef(env, jni::ToJavaString(env, key)).get()); + if (resultString == nullptr) + return false; + + value = jni::ToNativeString(env, resultString); + return true; +} + +void Platform::AndroidSecureStorage::Remove(std::string const & key) +{ + JNIEnv * env = jni::GetEnv(); + if (env == nullptr) + return; + + static jmethodID const removeMethodId = + jni::GetStaticMethodID(env, m_secureStorageClass, "remove", "(Ljava/lang/String;)V"); + + env->CallStaticVoidMethod(m_secureStorageClass, removeMethodId, + jni::TScopedLocalRef(env, jni::ToJavaString(env, key)).get()); +} + int GetAndroidSdkVersion() { char osVersion[PROP_VALUE_MAX + 1]; diff --git a/android/jni/com/mapswithme/platform/Platform.hpp b/android/jni/com/mapswithme/platform/Platform.hpp index 1898938ccb..5c9cf05427 100644 --- a/android/jni/com/mapswithme/platform/Platform.hpp +++ b/android/jni/com/mapswithme/platform/Platform.hpp @@ -5,6 +5,7 @@ #include "platform/platform.hpp" #include +#include namespace base { @@ -49,12 +50,27 @@ public: void SetGuiThread(std::unique_ptr guiThread); + class AndroidSecureStorage + { + public: + void Init(); + void Save(std::string const & key, std::string const & value); + bool Load(std::string const & key, std::string & value); + void Remove(std::string const & key); + + private: + jclass m_secureStorageClass = nullptr; + }; + + AndroidSecureStorage & GetSecureStorage() { return m_secureStorage; } + static Platform & Instance(); private: jobject m_functorProcessObject = nullptr; jmethodID m_sendPushWooshTagsMethod = nullptr; jmethodID m_myTrackerTrackMethod = nullptr; + AndroidSecureStorage m_secureStorage; std::unique_ptr m_guiThread; }; diff --git a/android/jni/com/mapswithme/platform/SecureStorage.cpp b/android/jni/com/mapswithme/platform/SecureStorage.cpp new file mode 100644 index 0000000000..f066654c90 --- /dev/null +++ b/android/jni/com/mapswithme/platform/SecureStorage.cpp @@ -0,0 +1,21 @@ +#include "platform/secure_storage.hpp" + +#include "Platform.hpp" + +namespace platform +{ +void SecureStorage::Save(std::string const & key, std::string const & value) +{ + android::Platform::Instance().GetSecureStorage().Save(key, value); +} + +bool SecureStorage::Load(std::string const & key, std::string & value) +{ + return android::Platform::Instance().GetSecureStorage().Load(key, value); +} + +void SecureStorage::Remove(std::string const & key) +{ + android::Platform::Instance().GetSecureStorage().Remove(key); +} +} // namespace platform diff --git a/android/src/com/mapswithme/util/SecureStorage.java b/android/src/com/mapswithme/util/SecureStorage.java new file mode 100644 index 0000000000..7709c1b4a5 --- /dev/null +++ b/android/src/com/mapswithme/util/SecureStorage.java @@ -0,0 +1,26 @@ +package com.mapswithme.util; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +public final class SecureStorage +{ + private SecureStorage() {} + + public static void save(@NonNull String key, @NonNull String value) + { + // TODO: implement @alexzatsepin + } + + @Nullable + public static String load(@NonNull String key) + { + // TODO: implement @alexzatsepin + return null; + } + + public static void remove(@NonNull String key) + { + // TODO: implement @alexzatsepin + } +} diff --git a/platform/CMakeLists.txt b/platform/CMakeLists.txt index 569c8e9021..ee7ee539bb 100644 --- a/platform/CMakeLists.txt +++ b/platform/CMakeLists.txt @@ -40,6 +40,7 @@ set( platform.hpp preferred_languages.cpp preferred_languages.hpp + secure_storage.hpp servers_list.cpp servers_list.hpp settings.cpp @@ -60,6 +61,7 @@ if(${PLATFORM_IPHONE}) platform_ios.mm platform_unix_impl.cpp platform_unix_impl.hpp + secure_storage_ios.mm socket_apple.mm ) elseif(${PLATFORM_ANDROID}) @@ -88,6 +90,7 @@ else() # neither iPhone nor Android http_thread_qt.hpp marketing_service_dummy.cpp platform_win.cpp + secure_storage_dummy.cpp wifi_info_windows.cpp ) elseif(${PLATFORM_MAC}) @@ -102,6 +105,7 @@ else() # neither iPhone nor Android platform_mac.mm platform_unix_impl.cpp platform_unix_impl.hpp + secure_storage_qt.cpp socket_apple.mm ) elseif(${PLATFORM_LINUX}) @@ -115,6 +119,7 @@ else() # neither iPhone nor Android platform_linux.cpp platform_unix_impl.cpp platform_unix_impl.hpp + secure_storage_qt.cpp ) endif() endif() diff --git a/platform/platform.hpp b/platform/platform.hpp index 3b64c0bdd6..86b9b1ecfa 100644 --- a/platform/platform.hpp +++ b/platform/platform.hpp @@ -3,6 +3,7 @@ #include "platform/country_defines.hpp" #include "platform/gui_thread.hpp" #include "platform/marketing_service.hpp" +#include "platform/secure_storage.hpp" #include "coding/reader.hpp" @@ -95,6 +96,9 @@ protected: /// Platform-dependent marketing services. MarketingService m_marketingService; + /// Platform-dependent secure storage. + platform::SecureStorage m_secureStorage; + unique_ptr m_guiThread; base::WorkerThread m_networkThread; @@ -254,6 +258,7 @@ public: void SetupMeasurementSystem() const; MarketingService & GetMarketingService() { return m_marketingService; } + platform::SecureStorage & GetSecureStorage() { return m_secureStorage; } // Use this method for testing purposes only. void SetGuiThread(unique_ptr guiThread); diff --git a/platform/platform.pro b/platform/platform.pro index e5781f82b3..3dcb58833d 100644 --- a/platform/platform.pro +++ b/platform/platform.pro @@ -27,19 +27,23 @@ INCLUDEPATH += $$ROOT_DIR/3party/jansson/src win32* { SOURCES += platform_win.cpp \ + secure_storage_dummy.cpp \ wifi_info_windows.cpp } else:macx-* { OBJECTIVE_SOURCES += apple_location_service.mm \ gui_thread_apple.mm \ - platform_mac.mm + platform_mac.mm \ + secure_storage_qt.cpp } else:linux* { SOURCES += gui_thread_linux.cpp \ - platform_linux.cpp + platform_linux.cpp \ + secure_storage_qt.cpp } } else:iphone* { OBJECTIVE_SOURCES += marketing_service_ios.mm \ platform_ios.mm \ - gui_thread_apple.mm + gui_thread_apple.mm \ + secure_storage_ios.mm } else:android* { SOURCES += platform_android.cpp } else:tizen* { @@ -48,6 +52,7 @@ INCLUDEPATH += $$ROOT_DIR/3party/jansson/src SOURCES += http_thread_tizen.cpp \ marketing_service_dummy.cpp \ platform_tizen.cpp \ + secure_storage_dummy.cpp \ tizen_utils.cpp } @@ -93,6 +98,7 @@ HEADERS += \ network_policy.hpp \ platform.hpp \ preferred_languages.hpp \ + secure_storage.hpp \ safe_callback.hpp \ servers_list.hpp \ settings.hpp \ diff --git a/platform/secure_storage.hpp b/platform/secure_storage.hpp new file mode 100644 index 0000000000..35d9410c3b --- /dev/null +++ b/platform/secure_storage.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include + +namespace platform +{ +class SecureStorage +{ +public: + void Save(std::string const & key, std::string const & value); + bool Load(std::string const & key, std::string & value); + void Remove(std::string const & key); +}; +} // namespace platform diff --git a/platform/secure_storage_dummy.cpp b/platform/secure_storage_dummy.cpp new file mode 100644 index 0000000000..9a185dfd93 --- /dev/null +++ b/platform/secure_storage_dummy.cpp @@ -0,0 +1,20 @@ +#include "platform/secure_storage.hpp" + +namespace platform +{ +void SecureStorage::Save(std::string const & key, std::string const & value) +{ + // Unimplemented on this platform. +} + +bool SecureStorage::Load(std::string const & key, std::string & value) +{ + // Unimplemented on this platform. + return false; +} + +void SecureStorage::Remove(std::string const & key) +{ + // Unimplemented on this platform. +} +} // namespace platform diff --git a/platform/secure_storage_ios.mm b/platform/secure_storage_ios.mm new file mode 100644 index 0000000000..e738590b14 --- /dev/null +++ b/platform/secure_storage_ios.mm @@ -0,0 +1,20 @@ +#include "platform/secure_storage.hpp" + +namespace platform +{ +void SecureStorage::Save(std::string const & key, std::string const & value) +{ + // TODO: implement @igrechuhin +} + +bool SecureStorage::Load(std::string const & key, std::string & value) +{ + // TODO: implement @igrechuhin + return false; +} + +void SecureStorage::Remove(std::string const & key) +{ + // TODO: implement @igrechuhin +} +} // namespace platform diff --git a/platform/secure_storage_qt.cpp b/platform/secure_storage_qt.cpp new file mode 100644 index 0000000000..089edb0db1 --- /dev/null +++ b/platform/secure_storage_qt.cpp @@ -0,0 +1,21 @@ +#include "platform/secure_storage.hpp" +#include "platform/settings.hpp" + +namespace platform +{ +void SecureStorage::Save(std::string const & key, std::string const & value) +{ + settings::Set(key, value); +} + +bool SecureStorage::Load(std::string const & key, std::string & value) +{ + bool const result = settings::Get(key, value); + return result && !value.empty(); +} + +void SecureStorage::Remove(std::string const & key) +{ + settings::Set(key, std::string()); +} +} // namespace platform diff --git a/xcode/platform/platform.xcodeproj/project.pbxproj b/xcode/platform/platform.xcodeproj/project.pbxproj index 54b6f63a87..5498dd2743 100644 --- a/xcode/platform/platform.xcodeproj/project.pbxproj +++ b/xcode/platform/platform.xcodeproj/project.pbxproj @@ -20,6 +20,9 @@ 3D78157D1F3D8A0A0068B6AC /* safe_callback.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 3D78157C1F3D8A0A0068B6AC /* safe_callback.hpp */; }; 3D97F64B1D9C05E800380945 /* http_client.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D97F64A1D9C05E800380945 /* http_client.cpp */; }; 3DE8B98F1DEC3115000E6083 /* network_policy.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 3DE8B98E1DEC3115000E6083 /* network_policy.hpp */; }; + 451E32A01F73A8B000964C9F /* secure_storage_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 451E329D1F73A8B000964C9F /* secure_storage_ios.mm */; }; + 451E32A11F73A8B000964C9F /* secure_storage_qt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 451E329E1F73A8B000964C9F /* secure_storage_qt.cpp */; }; + 451E32A21F73A8B000964C9F /* secure_storage.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 451E329F1F73A8B000964C9F /* secure_storage.hpp */; }; 56EB1EDC1C6B6E6C0022D831 /* file_logging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 56EB1ED81C6B6E6C0022D831 /* file_logging.cpp */; }; 56EB1EDD1C6B6E6C0022D831 /* file_logging.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 56EB1ED91C6B6E6C0022D831 /* file_logging.hpp */; }; 56EB1EDE1C6B6E6C0022D831 /* mwm_traits.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 56EB1EDA1C6B6E6C0022D831 /* mwm_traits.cpp */; }; @@ -123,6 +126,9 @@ 3D78157C1F3D8A0A0068B6AC /* safe_callback.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = safe_callback.hpp; sourceTree = ""; }; 3D97F64A1D9C05E800380945 /* http_client.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = http_client.cpp; sourceTree = ""; }; 3DE8B98E1DEC3115000E6083 /* network_policy.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = network_policy.hpp; sourceTree = ""; }; + 451E329D1F73A8B000964C9F /* secure_storage_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = secure_storage_ios.mm; sourceTree = ""; }; + 451E329E1F73A8B000964C9F /* secure_storage_qt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = secure_storage_qt.cpp; sourceTree = ""; }; + 451E329F1F73A8B000964C9F /* secure_storage.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = secure_storage.hpp; sourceTree = ""; }; 56EB1ED81C6B6E6C0022D831 /* file_logging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_logging.cpp; sourceTree = ""; }; 56EB1ED91C6B6E6C0022D831 /* file_logging.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = file_logging.hpp; sourceTree = ""; }; 56EB1EDA1C6B6E6C0022D831 /* mwm_traits.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mwm_traits.cpp; sourceTree = ""; }; @@ -198,7 +204,6 @@ 675E889F1DB7B0F200F8EBDA /* test_socket.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = test_socket.hpp; sourceTree = ""; }; 676C841F1C64CD3300DC9603 /* mwm_traits.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = mwm_traits.hpp; sourceTree = ""; }; 6783387E1C6DE54700FD6263 /* platform_tests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = platform_tests.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 678338AA1C6DF4F200FD6263 /* resources-ldpi_legacy */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "resources-ldpi_legacy"; sourceTree = ""; }; 678338AB1C6DF50700FD6263 /* classificator.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = classificator.txt; sourceTree = ""; }; 678338AC1C6DF50700FD6263 /* minsk-pass.mwm */ = {isa = PBXFileReference; lastKnownFileType = file; path = "minsk-pass.mwm"; sourceTree = ""; }; 678338B01C6E016700FD6263 /* World.mwm */ = {isa = PBXFileReference; lastKnownFileType = file; path = World.mwm; sourceTree = ""; }; @@ -330,6 +335,9 @@ 6753437A1A3F5CF500A0A8C3 /* platform */ = { isa = PBXGroup; children = ( + 451E329F1F73A8B000964C9F /* secure_storage.hpp */, + 451E329D1F73A8B000964C9F /* secure_storage_ios.mm */, + 451E329E1F73A8B000964C9F /* secure_storage_qt.cpp */, 3D78157C1F3D8A0A0068B6AC /* safe_callback.hpp */, 3D78156B1F3A14090068B6AC /* gui_thread_apple.mm */, 3D78156C1F3A14090068B6AC /* gui_thread.hpp */, @@ -405,7 +413,6 @@ 678338B11C6E016700FD6263 /* WorldCoasts.mwm */, 678338AB1C6DF50700FD6263 /* classificator.txt */, 678338AC1C6DF50700FD6263 /* minsk-pass.mwm */, - 678338AA1C6DF4F200FD6263 /* resources-ldpi_legacy */, ); name = Resources; path = ../../data; @@ -449,6 +456,7 @@ 67247FFE1C60BD6500EDE56A /* writable_dir_changer.hpp in Headers */, 3D78157D1F3D8A0A0068B6AC /* safe_callback.hpp in Headers */, 3D78156F1F3A14090068B6AC /* gui_thread.hpp in Headers */, + 451E32A21F73A8B000964C9F /* secure_storage.hpp in Headers */, 674125091B4C00CC00A3E828 /* country_defines.hpp in Headers */, 675343CD1A3F5D5A00A0A8C3 /* platform.hpp in Headers */, 6741250F1B4C00CC00A3E828 /* local_country_file.hpp in Headers */, @@ -610,9 +618,11 @@ 3D97F64B1D9C05E800380945 /* http_client.cpp in Sources */, 67AB92EA1B7B3E9100AB5194 /* get_text_by_id.cpp in Sources */, 34C624BD1DABCCD100510300 /* socket_apple.mm in Sources */, + 451E32A11F73A8B000964C9F /* secure_storage_qt.cpp in Sources */, 671C62061AE9014C00076BD0 /* measurement_utils.cpp in Sources */, 675343B61A3F5D5A00A0A8C3 /* http_request.cpp in Sources */, 675343CC1A3F5D5A00A0A8C3 /* platform.cpp in Sources */, + 451E32A01F73A8B000964C9F /* secure_storage_ios.mm in Sources */, 675343DB1A3F5D5A00A0A8C3 /* wifi_location_service.cpp in Sources */, 56EB1EDC1C6B6E6C0022D831 /* file_logging.cpp in Sources */, 675343B11A3F5D5A00A0A8C3 /* apple_location_service.mm in Sources */, @@ -667,11 +677,18 @@ baseConfigurationReference = 34F558331DBF273C00A4FC11 /* common-debug.xcconfig */; buildSettings = { EXCLUDED_SOURCE_FILE_NAMES = ""; - "EXCLUDED_SOURCE_FILE_NAMES[sdk=iphoneos*]" = platform_mac.mm; - "EXCLUDED_SOURCE_FILE_NAMES[sdk=iphonesimulator*]" = platform_mac.mm; + "EXCLUDED_SOURCE_FILE_NAMES[sdk=iphoneos*]" = ( + platform_mac.mm, + secure_storage_qt.cpp, + ); + "EXCLUDED_SOURCE_FILE_NAMES[sdk=iphonesimulator*]" = ( + platform_mac.mm, + secure_storage_qt.cpp, + ); "EXCLUDED_SOURCE_FILE_NAMES[sdk=macosx*]" = ( "ios_*", platform_ios.mm, + secure_storage_ios.mm, ); HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -686,11 +703,18 @@ baseConfigurationReference = 34F558341DBF273C00A4FC11 /* common-release.xcconfig */; buildSettings = { EXCLUDED_SOURCE_FILE_NAMES = ""; - "EXCLUDED_SOURCE_FILE_NAMES[sdk=iphoneos*]" = platform_mac.mm; - "EXCLUDED_SOURCE_FILE_NAMES[sdk=iphonesimulator*]" = platform_mac.mm; + "EXCLUDED_SOURCE_FILE_NAMES[sdk=iphoneos*]" = ( + platform_mac.mm, + secure_storage_qt.cpp, + ); + "EXCLUDED_SOURCE_FILE_NAMES[sdk=iphonesimulator*]" = ( + platform_mac.mm, + secure_storage_qt.cpp, + ); "EXCLUDED_SOURCE_FILE_NAMES[sdk=macosx*]" = ( "ios_*", platform_ios.mm, + secure_storage_ios.mm, ); HEADER_SEARCH_PATHS = ( "$(inherited)",