Added bookmarks catalog support

This commit is contained in:
r.kuznetsov 2018-04-26 15:33:58 +03:00 committed by Aleksandr Zatsepin
parent e41c74ae48
commit 3aad4f4185
19 changed files with 647 additions and 60 deletions

View file

@ -26,6 +26,8 @@ jmethodID g_onSynchronizationStartedMethod;
jmethodID g_onSynchronizationFinishedMethod;
jmethodID g_onRestoreRequestedMethod;
jmethodID g_onRestoredFilesPreparedMethod;
jmethodID g_onImportStartedMethod;
jmethodID g_onImportFinishedMethod;
void PrepareClassRefs(JNIEnv * env)
{
@ -60,6 +62,10 @@ void PrepareClassRefs(JNIEnv * env)
jni::GetMethodID(env, bookmarkManagerInstance, "onRestoreRequested", "(IJ)V");
g_onRestoredFilesPreparedMethod =
jni::GetMethodID(env, bookmarkManagerInstance, "onRestoredFilesPrepared", "()V");
g_onImportStartedMethod =
jni::GetMethodID(env, bookmarkManagerInstance, "onImportStarted", "(Ljava/lang/String;)V");
g_onImportFinishedMethod =
jni::GetMethodID(env, bookmarkManagerInstance, "onImportFinished", "(Ljava/lang/String;Z)V");
}
void OnAsyncLoadingStarted(JNIEnv * env)
@ -178,6 +184,26 @@ void OnRestoredFilesPrepared(JNIEnv * env)
env->CallVoidMethod(bookmarkManagerInstance, g_onRestoredFilesPreparedMethod);
jni::HandleJavaException(env);
}
void OnImportStarted(JNIEnv * env, std::string const & serverId)
{
ASSERT(g_bookmarkManagerClass, ());
jobject bookmarkManagerInstance = env->GetStaticObjectField(g_bookmarkManagerClass,
g_bookmarkManagerInstanceField);
env->CallVoidMethod(bookmarkManagerInstance, g_onImportStartedMethod,
jni::ToJavaString(env, serverId));
jni::HandleJavaException(env);
}
void OnImportFinished(JNIEnv * env, std::string const & serverId, bool successful)
{
ASSERT(g_bookmarkManagerClass, ());
jobject bookmarkManagerInstance = env->GetStaticObjectField(g_bookmarkManagerClass,
g_bookmarkManagerInstanceField);
env->CallVoidMethod(bookmarkManagerInstance, g_onImportFinishedMethod,
jni::ToJavaString(env, serverId), static_cast<jboolean>(successful));
jni::HandleJavaException(env);
}
} // namespace
extern "C"
@ -208,11 +234,15 @@ Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeLoadBookmarks(JNIE
std::bind(&OnRestoreRequested, env, _1, _2),
std::bind(&OnRestoredFilesPrepared, env));
frm()->GetBookmarkManager().SetCatalogHandlers(nullptr, nullptr,
std::bind(&OnImportStarted, env, _1),
std::bind(&OnImportFinished, env, _1, _2));
frm()->LoadBookmarks();
}
JNIEXPORT jint JNICALL
Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeGetCategoriesCount(JNIEnv * env, jobject thiz)
Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeGetCategoriesCount(
JNIEnv * env, jobject thiz)
{
return frm()->GetBookmarkManager().GetBmGroupsIdList().size();
}
@ -546,4 +576,28 @@ Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeAreNotificationsEn
{
return static_cast<jboolean>(frm()->GetBookmarkManager().AreNotificationsEnabled());
}
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeImportFromCatalog(
JNIEnv * env, jobject thiz, jstring serverId, jstring filePath)
{
auto & bm = frm()->GetBookmarkManager();
bm.ImportDownloadedFromCatalog(ToNativeString(env, serverId), ToNativeString(env, filePath));
}
JNIEXPORT jstring JNICALL
Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeGetCatalogDeeplink(
JNIEnv * env, jobject thiz, jlong catId)
{
auto & bm = frm()->GetBookmarkManager();
return ToJavaString(env, bm.GetCategoryCatalogDeeplink(static_cast<kml::MarkGroupId>(catId)));
}
JNIEXPORT jboolean JNICALL
Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeIsCategoryFromCatalog(
JNIEnv * env, jobject thiz, jlong catId)
{
auto & bm = frm()->GetBookmarkManager();
return static_cast<jboolean>(bm.IsCategoryFromCatalog(static_cast<kml::MarkGroupId>(catId)));
}
} // extern "C"

View file

@ -58,6 +58,9 @@ public enum BookmarkManager
@NonNull
private List<BookmarksCloudListener> mCloudListeners = new ArrayList<>();
@NonNull
private List<BookmarksCatalogListener> mCatalogListeners = new ArrayList<>();
static
{
@ -136,6 +139,16 @@ public enum BookmarkManager
mCloudListeners.remove(listener);
}
public void addCatalogListener(@NonNull BookmarksCatalogListener listener)
{
mCatalogListeners.add(listener);
}
public void removeCatalogListener(@NonNull BookmarksCatalogListener listener)
{
mCatalogListeners.remove(listener);
}
// Called from JNI.
@MainThread
public void onBookmarksLoadingStarted()
@ -220,6 +233,22 @@ public enum BookmarkManager
listener.onRestoredFilesPrepared();
}
// Called from JNI.
@MainThread
public void onImportStarted(@NonNull String id)
{
for (BookmarksCatalogListener listener : mCatalogListeners)
listener.onImportStarted(id);
}
// Called from JNI.
@MainThread
public void onImportFinished(@NonNull String id, boolean successful)
{
for (BookmarksCatalogListener listener : mCatalogListeners)
listener.onImportFinished(id, successful);
}
public boolean isVisible(long catId)
{
return nativeIsVisible(catId);
@ -405,6 +434,22 @@ public enum BookmarkManager
return nativeAreNotificationsEnabled();
}
public void importFromCatalog(@NonNull String serverId, @NonNull String filePath)
{
nativeImportFromCatalog(serverId, filePath);
}
@NonNull
public String getCatalogDeeplink(long catId)
{
return nativeGetCatalogDeeplink(catId);
}
public boolean isCategoryFromCatalog(long catId)
{
return nativeIsCategoryFromCatalog(catId);
}
private native int nativeGetCategoriesCount();
private native int nativeGetCategoryPositionById(long catId);
@ -493,6 +538,14 @@ public enum BookmarkManager
private static native boolean nativeAreNotificationsEnabled();
private static native void nativeImportFromCatalog(@NonNull String serverId,
@NonNull String filePath);
@NonNull
private static native String nativeGetCatalogDeeplink(long catId);
private static native boolean nativeIsCategoryFromCatalog(long catId);
public interface BookmarksLoadingListener
{
void onBookmarksLoadingStarted();
@ -545,4 +598,22 @@ public enum BookmarkManager
*/
void onRestoredFilesPrepared();
}
public interface BookmarksCatalogListener
{
/**
* The method is called when the importing of a file from the catalog is started.
*
* @param serverId is server identifier of the file.
*/
void onImportStarted(@NonNull String serverId);
/**
* The method is called when the importing of a file from the catalog is finished.
*
* @param serverId is server identifier of the file.
* @param successful is result of the importing.
*/
void onImportFinished(@NonNull String serverId, boolean successful);
}
}

View file

@ -22,6 +22,8 @@ set(
booking_filter_cache.hpp
bookmark.cpp
bookmark.hpp
bookmark_catalog.cpp
bookmark_catalog.hpp
bookmark_helpers.cpp
bookmark_helpers.hpp
bookmark_manager.cpp

View file

@ -1,6 +1,10 @@
#include "map/bookmark.hpp"
#include "map/bookmark_helpers.hpp"
#include "coding/url_encode.hpp"
#include <sstream>
namespace
{
std::string GetBookmarkIconType(kml::BookmarkIcon const & icon)
@ -222,10 +226,6 @@ BookmarkCategory::BookmarkCategory(kml::CategoryData && data, bool autoSave)
Base::SetIsVisible(m_data.m_visible);
}
BookmarkCategory::~BookmarkCategory()
{
}
void BookmarkCategory::SetIsVisible(bool isVisible)
{
Base::SetIsVisible(isVisible);
@ -238,11 +238,32 @@ void BookmarkCategory::SetName(std::string const & name)
kml::SetDefaultStr(m_data.m_name, name);
}
void BookmarkCategory::SetServerId(std::string const & serverId)
{
if (m_serverId == serverId)
return;
SetDirty();
m_serverId = serverId;
}
std::string BookmarkCategory::GetName() const
{
return kml::GetDefaultStr(m_data.m_name);
}
bool BookmarkCategory::IsCategoryFromCatalog() const
{
return FromCatalog(m_data, m_serverId);
}
std::string BookmarkCategory::GetCatalogDeeplink() const
{
std::ostringstream ss;
ss << "mapsme://dlink.maps.me/catalogue?id=" << m_serverId << "&name=" << UrlEncode(GetName());
return ss.str();
}
// static
kml::PredefinedColor BookmarkCategory::GetDefaultColor()
{

View file

@ -66,7 +66,6 @@ class BookmarkCategory : public UserMarkLayer
public:
BookmarkCategory(std::string const & name, kml::MarkGroupId groupId, bool autoSave);
BookmarkCategory(kml::CategoryData && data, bool autoSave);
~BookmarkCategory() override;
static kml::PredefinedColor GetDefaultColor();
@ -83,6 +82,12 @@ public:
kml::CategoryData const & GetCategoryData() const { return m_data; }
void SetServerId(std::string const & serverId);
std::string const & GetServerId() const { return m_serverId; }
bool IsCategoryFromCatalog() const;
std::string GetCatalogDeeplink() const;
private:
void SetDirty() override;
@ -90,4 +95,5 @@ private:
std::string m_file;
bool m_autoSave = true;
kml::CategoryData m_data;
std::string m_serverId;
};

79
map/bookmark_catalog.cpp Normal file
View file

@ -0,0 +1,79 @@
#include "map/bookmark_catalog.hpp"
#include "platform/platform.hpp"
#include "coding/file_name_utils.hpp"
#include "base/string_utils.hpp"
#include <utility>
namespace
{
std::string BuildCatalogUrl(std::string const & serverId)
{
//TODO: This code is temporary.
return "https://bookcat.demo.mapsme1.devmail.ru/static/" + serverId + "/" + serverId;
}
} // namespace
BookmarkCatalog::BookmarkCatalog(std::string const & catalogDir)
{
Platform::FilesList files;
Platform::GetFilesRecursively(catalogDir, files);
for (auto const & f : files)
m_downloadedIds.insert(my::GetNameFromFullPathWithoutExt(f));
}
void BookmarkCatalog::RegisterDownloadedId(std::string const & id)
{
if (id.empty())
return;
m_downloadedIds.insert(id);
m_downloadingIds.erase(id);
}
void BookmarkCatalog::UnregisterDownloadedId(std::string const & id)
{
if (id.empty())
return;
m_downloadedIds.erase(id);
}
std::vector<std::string> BookmarkCatalog::GetDownloadingNames() const
{
std::vector<std::string> names;
names.reserve(m_downloadingIds.size());
for (auto const & p : m_downloadingIds)
names.push_back(p.second);
return names;
}
void BookmarkCatalog::Download(std::string const & id, std::string const & name,
std::function<void()> && startHandler,
platform::RemoteFile::ResultHandler && finishHandler)
{
if (m_downloadingIds.find(id) != m_downloadingIds.cend() ||
m_downloadedIds.find(id) != m_downloadedIds.cend())
{
return;
}
m_downloadingIds.insert(std::make_pair(id, name));
if (startHandler)
startHandler();
static uint32_t counter = 0;
auto const path = my::JoinPath(GetPlatform().TmpDir(), "file" + strings::to_string(++counter));
platform::RemoteFile remoteFile(BuildCatalogUrl(id));
remoteFile.DownloadAsync(path, [finishHandler = std::move(finishHandler)]
(platform::RemoteFile::Result && result, std::string const & filePath) mutable
{
if (finishHandler)
finishHandler(std::move(result), filePath);
});
}

28
map/bookmark_catalog.hpp Normal file
View file

@ -0,0 +1,28 @@
#pragma once
#include "platform/remote_file.hpp"
#include <functional>
#include <map>
#include <set>
#include <string>
#include <vector>
class BookmarkCatalog
{
public:
explicit BookmarkCatalog(std::string const & catalogDir);
void RegisterDownloadedId(std::string const & id);
void UnregisterDownloadedId(std::string const & id);
void Download(std::string const & id, std::string const & name,
std::function<void()> && startHandler,
platform::RemoteFile::ResultHandler && finishHandler);
size_t GetDownloadingCount() const { return m_downloadingIds.size(); }
std::vector<std::string> GetDownloadingNames() const;
private:
std::map<std::string, std::string> m_downloadingIds;
std::set<std::string> m_downloadedIds;
};

View file

@ -427,3 +427,13 @@ std::string GetPreferredBookmarkName(kml::BookmarkData const & bmData)
name = GetLocalizedBookmarkType(bmData.m_featureTypes);
return name;
}
bool FromCatalog(kml::FileData const & kmlData)
{
return FromCatalog(kmlData.m_categoryData, kmlData.m_serverId);
}
bool FromCatalog(kml::CategoryData const & categoryData, std::string const & serverId)
{
return !serverId.empty() && categoryData.m_accessRules == kml::AccessRules::Public;
}

View file

@ -24,3 +24,6 @@ std::string GetPreferredBookmarkName(kml::BookmarkData const & bmData);
std::string GetPreferredBookmarkStr(kml::LocalizableString const & name);
std::string GetPreferredBookmarkStr(kml::LocalizableString const & name, feature::RegionData const & regionData);
std::string GetLocalizedBookmarkType(std::vector<uint32_t> const & types);
bool FromCatalog(kml::FileData const & kmlData);
bool FromCatalog(kml::CategoryData const & categoryData, std::string const & serverId);

View file

@ -74,6 +74,11 @@ std::string GetBookmarksDirectory()
return my::JoinPath(GetPlatform().SettingsDir(), "bookmarks");
}
std::string GetPrivateBookmarksDirectory()
{
return my::JoinPath(GetPlatform().PrivateDir(), "bookmarks_private");
}
bool IsBadCharForPath(strings::UniChar const & c)
{
static strings::UniChar const illegalChars[] = {':', '/', '\\', '<', '>', '\"', '|', '?', '*'};
@ -167,14 +172,14 @@ Cloud::ConvertionResult ConvertBeforeUploading(std::string const & filePath,
return result;
}
Cloud::ConvertionResult ConvertAfterDownloading(std::string const & filePath,
std::string const & convertedFilePath)
std::unique_ptr<kml::FileData> ImportAfterDownloading(std::string const & filePath,
std::string & hash)
{
ZipFileReader::FileListT files;
ZipFileReader::FilesList(filePath, files);
if (files.empty())
return {};
auto fileName = files.front().first;
for (auto const & file : files)
{
@ -188,14 +193,22 @@ Cloud::ConvertionResult ConvertAfterDownloading(std::string const & filePath,
MY_SCOPE_GUARD(fileGuard, bind(&FileWriter::DeleteFileX, unarchievedPath));
ZipFileReader::UnzipFile(filePath, fileName, unarchievedPath);
if (!GetPlatform().IsFileExistsByFullPath(unarchievedPath))
return {};
return nullptr;
hash = coding::SHA1::CalculateBase64(unarchievedPath);
return LoadKmlFile(unarchievedPath, false /* binary */);
}
auto kmlData = LoadKmlFile(unarchievedPath, false /* binary */);
Cloud::ConvertionResult ConvertAfterDownloading(std::string const & filePath,
std::string const & convertedFilePath)
{
std::string hash;
auto kmlData = ImportAfterDownloading(filePath, hash);
if (kmlData == nullptr)
return {};
Cloud::ConvertionResult result;
result.m_hash = coding::SHA1::CalculateBase64(unarchievedPath);
result.m_hash = hash;
result.m_isSuccessful = SaveKmlFile(*kmlData, convertedFilePath, true /* binary */);
return result;
}
@ -502,6 +515,7 @@ BookmarkManager::BookmarkManager(Callbacks && callbacks)
GetBookmarksDirectory(), std::string(kKmbExtension),
std::bind(&ConvertBeforeUploading, _1, _2),
std::bind(&ConvertAfterDownloading, _1, _2)))
, m_bookmarkCatalog(GetPrivateBookmarksDirectory())
{
ASSERT(m_callbacks.m_getStringsBundle != nullptr, ());
@ -793,6 +807,7 @@ void BookmarkManager::ClearGroup(kml::MarkGroupId groupId)
m_tracks.erase(trackId);
}
group->Clear();
m_changesTracker.OnDeleteGroup(groupId);
}
std::string BookmarkManager::GetCategoryName(kml::MarkGroupId categoryId) const
@ -924,10 +939,7 @@ void BookmarkManager::ClearCategories()
{
CHECK_THREAD_CHECKER(m_threadChecker, ());
for (auto groupId : m_bmGroupsIdList)
{
ClearGroup(groupId);
m_changesTracker.OnDeleteGroup(groupId);
}
m_categories.clear();
UpdateBmGroupIdList();
@ -936,8 +948,9 @@ void BookmarkManager::ClearCategories()
m_tracks.clear();
}
BookmarkManager::KMLDataCollectionPtr BookmarkManager::LoadBookmarks(std::string const & dir, std::string const & ext,
bool binary, std::vector<std::string> & filePaths)
BookmarkManager::KMLDataCollectionPtr BookmarkManager::LoadBookmarks(
std::string const & dir, std::string const & ext, bool binary,
std::vector<std::string> & filePaths)
{
Platform::FilesList files;
Platform::GetFilesByExt(dir, ext, files);
@ -978,6 +991,14 @@ void BookmarkManager::LoadBookmarks()
auto collection = LoadBookmarks(dir, filesExt, migrated, filePaths);
migration::FixUpHotelPlacemarks(collection, isMigrationCompleted);
// Load files downloaded from catalog.
std::vector<std::string> unusedFilePaths;
auto catalogCollection = LoadBookmarks(GetPrivateBookmarksDirectory(), kKmbExtension,
true /* binary */, unusedFilePaths);
collection->reserve(collection->size() + catalogCollection->size());
for (auto & p : *catalogCollection)
collection->emplace_back(p.first, std::move(p.second));
if (m_needTeardown)
return;
NotifyAboutFinishAsyncLoading(std::move(collection));
@ -1022,7 +1043,7 @@ void BookmarkManager::LoadBookmarkRoutine(std::string const & filePath, bool isT
{
auto fileSavePath = savePath.get();
auto kmlData = LoadKmlFile(fileSavePath, false /* useBinary */);
if (kmlData != nullptr)
if (kmlData && !FromCatalog(*kmlData))
{
if (m_needTeardown)
return;
@ -1361,9 +1382,9 @@ bool BookmarkManager::DeleteBmCategory(kml::MarkGroupId groupId)
return false;
ClearGroup(groupId);
m_changesTracker.OnDeleteGroup(groupId);
FileWriter::DeleteFileX(it->second->GetFileName());
m_bookmarkCatalog.UnregisterDownloadedId(it->second->GetServerId());
m_categories.erase(it);
UpdateBmGroupIdList();
@ -1375,7 +1396,8 @@ namespace
class BestUserMarkFinder
{
public:
explicit BestUserMarkFinder(BookmarkManager::TTouchRectHolder const & rectHolder, BookmarkManager const * manager)
explicit BestUserMarkFinder(BookmarkManager::TTouchRectHolder const & rectHolder,
BookmarkManager const * manager)
: m_rectHolder(rectHolder)
, m_d(numeric_limits<double>::max())
, m_mark(nullptr)
@ -1487,6 +1509,7 @@ void BookmarkManager::CreateCategories(KMLDataCollection && dataCollection, bool
loadedGroups.insert(groupId);
auto * group = GetBmCategory(groupId);
group->SetFileName(fileName);
group->SetServerId(fileData.m_serverId);
for (auto & bmData : fileData.m_bookmarksData)
{
@ -1541,12 +1564,13 @@ std::unique_ptr<kml::FileData> BookmarkManager::CollectBmGroupKMLData(BookmarkCa
{
auto kmlData = std::make_unique<kml::FileData>();
kmlData->m_deviceId = GetPlatform().UniqueClientId();
kmlData->m_serverId = group->GetServerId();
kmlData->m_categoryData = group->GetCategoryData();
auto const & markIds = group->GetUserMarks();
kmlData->m_bookmarksData.reserve(markIds.size());
for (auto it = markIds.rbegin(); it != markIds.rend(); ++it)
{
Bookmark const *bm = GetBookmark(*it);
Bookmark const * bm = GetBookmark(*it);
kmlData->m_bookmarksData.emplace_back(bm->GetData());
}
auto const & lineIds = group->GetUserLines();
@ -1567,7 +1591,7 @@ bool BookmarkManager::SaveBookmarkCategory(kml::MarkGroupId groupId)
return false;
auto const & file = collection->front().first;
auto & kmlData = *collection->front().second;
return SaveKmlFileSafe(kmlData, file, migration::IsMigrationCompleted());
return SaveKmlFileSafe(kmlData, file);
}
bool BookmarkManager::SaveBookmarkCategory(kml::MarkGroupId groupId, Writer & writer, bool useBinary) const
@ -1582,7 +1606,6 @@ BookmarkManager::KMLDataCollectionPtr BookmarkManager::PrepareToSaveBookmarks(
kml::GroupIdCollection const & groupIdCollection)
{
bool migrated = migration::IsMigrationCompleted();
std::string const fileDir = migrated ? GetBookmarksDirectory() : GetPlatform().SettingsDir();
std::string const fileExt = migrated ? kKmbExtension : kKmlExtension;
@ -1590,11 +1613,24 @@ BookmarkManager::KMLDataCollectionPtr BookmarkManager::PrepareToSaveBookmarks(
return nullptr;
auto collection = std::make_shared<KMLDataCollection>();
for (auto const groupId : groupIdCollection)
{
auto * group = GetBmCategory(groupId);
if (group->IsCategoryFromCatalog())
{
std::string const privateFileDir = GetPrivateBookmarksDirectory();
if (!GetPlatform().IsFileExistsByFullPath(privateFileDir) &&
!GetPlatform().MkDirChecked(privateFileDir))
{
return nullptr;
}
auto const fn = my::JoinPath(privateFileDir, group->GetServerId() + kKmbExtension);
group->SetFileName(fn);
collection->emplace_back(fn, CollectBmGroupKMLData(group));
continue;
}
// Get valid file name from category name
std::string const name = RemoveInvalidSymbols(group->GetName(), kDefaultBookmarksFileName);
std::string file = group->GetFileName();
@ -1610,10 +1646,11 @@ BookmarkManager::KMLDataCollectionPtr BookmarkManager::PrepareToSaveBookmarks(
return collection;
}
bool BookmarkManager::SaveKmlFileSafe(kml::FileData & kmlData, std::string const & file, bool useBinary)
bool BookmarkManager::SaveKmlFileSafe(kml::FileData & kmlData, std::string const & file)
{
auto const ext = my::GetFileExtension(file);
auto const fileTmp = file + ".tmp";
if (SaveKmlFile(kmlData, fileTmp, useBinary))
if (SaveKmlFile(kmlData, fileTmp, ext == kKmbExtension))
{
// Only after successful save we replace original file.
my::DeleteFileX(file);
@ -1635,20 +1672,19 @@ void BookmarkManager::SaveBookmarks(kml::GroupIdCollection const & groupIdCollec
if (!kmlDataCollection)
return;
bool const migrated = migration::IsMigrationCompleted();
if (m_testModeEnabled)
{
// Save bookmarks synchronously.
for (auto const & kmlItem : *kmlDataCollection)
SaveKmlFileSafe(*kmlItem.second, kmlItem.first, migrated);
SaveKmlFileSafe(*kmlItem.second, kmlItem.first);
return;
}
GetPlatform().RunTask(Platform::Thread::File, [this, migrated, kmlDataCollection = std::move(kmlDataCollection)]()
GetPlatform().RunTask(Platform::Thread::File,
[this, kmlDataCollection = std::move(kmlDataCollection)]()
{
for (auto const & kmlItem : *kmlDataCollection)
SaveKmlFileSafe(*kmlItem.second, kmlItem.first, migrated);
SaveKmlFileSafe(*kmlItem.second, kmlItem.first);
});
}
@ -1813,19 +1849,19 @@ void BookmarkManager::ConvertAllKmlFiles(ConversionHandler && handler)
bool allConverted = true;
for (auto const & f : files)
{
std::unique_ptr<kml::FileData> kmlData = LoadKmlFile(f, false /* binary */);
if (kmlData == nullptr || FromCatalog(*kmlData))
{
allConverted = false;
continue;
}
std::string fileName = my::GetNameFromFullPathWithoutExt(f);
auto kmbPath = my::JoinPath(newDir, fileName + kKmbExtension);
size_t counter = 1;
while (Platform::IsFileExistsByFullPath(kmbPath))
kmbPath = my::JoinPath(newDir, fileName + strings::to_string(counter++) + kKmbExtension);
std::unique_ptr<kml::FileData> kmlData = LoadKmlFile(f, false /* binary */);
if (kmlData == nullptr)
{
allConverted = false;
continue;
}
if (!SaveKmlFile(*kmlData, kmbPath, true /* binary */))
{
allConverted = false;
@ -1959,6 +1995,107 @@ bool BookmarkManager::AreNotificationsEnabled() const
return m_notificationsEnabled;
}
void BookmarkManager::SetCatalogHandlers(OnCatalogDownloadStartedHandler && onCatalogDownloadStarted,
OnCatalogDownloadFinishedHandler && onCatalogDownloadFinished,
OnCatalogImportStartedHandler && onCatalogImportStarted,
OnCatalogImportFinishedHandler && onCatalogImportFinished)
{
m_onCatalogDownloadStarted = std::move(onCatalogDownloadStarted);
m_onCatalogDownloadFinished = std::move(onCatalogDownloadFinished);
m_onCatalogImportStarted = std::move(onCatalogImportStarted);
m_onCatalogImportFinished = std::move(onCatalogImportFinished);
}
void BookmarkManager::DownloadFromCatalogAndImport(std::string const & id, std::string const & name)
{
m_bookmarkCatalog.Download(id, name, [this, id]()
{
if (m_onCatalogDownloadStarted)
m_onCatalogDownloadStarted(id);
},
[this, id](platform::RemoteFile::Result && result, std::string const & filePath)
{
if (m_onCatalogDownloadFinished)
m_onCatalogDownloadFinished(id, result);
if (result.m_status == platform::RemoteFile::Status::Ok)
ImportDownloadedFromCatalog(id, filePath);
});
}
void BookmarkManager::ImportDownloadedFromCatalog(std::string const & id, std::string const & filePath)
{
if (m_onCatalogImportStarted)
m_onCatalogImportStarted(id);
GetPlatform().RunTask(Platform::Thread::File, [this, id, filePath]()
{
MY_SCOPE_GUARD(fileGuard, std::bind(&FileWriter::DeleteFileX, filePath));
std::string hash;
auto kmlData = ImportAfterDownloading(filePath, hash);
if (kmlData && FromCatalog(*kmlData) && kmlData->m_serverId == id)
{
auto const p = my::JoinPath(GetPrivateBookmarksDirectory(), id, kKmbExtension);
auto collection = std::make_shared<KMLDataCollection>();
collection->emplace_back(p, std::move(kmlData));
GetPlatform().RunTask(Platform::Thread::Gui, [this, id, collection]()
{
std::vector<kml::MarkGroupId> idsToDelete;
for (auto const & group : m_categories)
{
if (id == group.second->GetServerId())
{
ClearGroup(group.first);
idsToDelete.push_back(group.first);
}
}
for (auto const & categoryId : idsToDelete)
m_categories.erase(categoryId);
CreateCategories(std::move(*collection));
m_bookmarkCatalog.RegisterDownloadedId(id);
if (m_onCatalogImportFinished)
m_onCatalogImportFinished(id, true /* successful */);
});
}
else
{
if (m_onCatalogImportFinished)
m_onCatalogImportFinished(id, false /* successful */);
}
});
}
size_t BookmarkManager::GetDownloadingFromCatalogCount() const
{
return m_bookmarkCatalog.GetDownloadingCount();
}
std::vector<std::string> BookmarkManager::GetDownloadingFromCatalogNames() const
{
return m_bookmarkCatalog.GetDownloadingNames();
}
bool BookmarkManager::IsCategoryFromCatalog(kml::MarkGroupId categoryId) const
{
auto cat = GetBmCategory(categoryId);
if (cat == nullptr)
return false;
return cat->IsCategoryFromCatalog();
}
std::string BookmarkManager::GetCategoryCatalogDeeplink(kml::MarkGroupId categoryId) const
{
auto cat = GetBmCategory(categoryId);
if (cat == nullptr)
return {};
return cat->GetCatalogDeeplink();
}
void BookmarkManager::EnableTestMode(bool enable)
{
UserMarkIdStorage::Instance().EnableSaving(!enable);

View file

@ -1,6 +1,7 @@
#pragma once
#include "map/bookmark.hpp"
#include "map/bookmark_catalog.hpp"
#include "map/cloud.hpp"
#include "map/track.hpp"
#include "map/user_mark_layer.hpp"
@ -268,6 +269,23 @@ public:
void SetNotificationsEnabled(bool enabled);
bool AreNotificationsEnabled() const;
using OnCatalogDownloadStartedHandler = platform::SafeCallback<void(std::string const & id)>;
using OnCatalogDownloadFinishedHandler = platform::SafeCallback<void(std::string const & id,
platform::RemoteFile::Result const &)>;
using OnCatalogImportStartedHandler = platform::SafeCallback<void(std::string const & id)>;
using OnCatalogImportFinishedHandler = platform::SafeCallback<void(std::string const & id,
bool successful)>;
void SetCatalogHandlers(OnCatalogDownloadStartedHandler && onCatalogDownloadStarted,
OnCatalogDownloadFinishedHandler && onCatalogDownloadFinished,
OnCatalogImportStartedHandler && onCatalogImportStarted,
OnCatalogImportFinishedHandler && onCatalogImportFinished);
void DownloadFromCatalogAndImport(std::string const & id, std::string const & name);
void ImportDownloadedFromCatalog(std::string const & id, std::string const & filePath);
size_t GetDownloadingFromCatalogCount() const;
std::vector<std::string> GetDownloadingFromCatalogNames() const;
bool IsCategoryFromCatalog(kml::MarkGroupId categoryId) const;
std::string GetCategoryCatalogDeeplink(kml::MarkGroupId categoryId) const;
/// These functions are public for unit tests only. You shouldn't call them from client code.
void EnableTestMode(bool enable);
bool SaveBookmarkCategory(kml::MarkGroupId groupId);
@ -432,7 +450,7 @@ private:
std::unique_ptr<kml::FileData> CollectBmGroupKMLData(BookmarkCategory const * group) const;
KMLDataCollectionPtr PrepareToSaveBookmarks(kml::GroupIdCollection const & groupIdCollection);
bool SaveKmlFileSafe(kml::FileData & kmlData, std::string const & file, bool useBinary);
bool SaveKmlFileSafe(kml::FileData & kmlData, std::string const & file);
void OnSynchronizationStarted(Cloud::SynchronizationType type);
void OnSynchronizationFinished(Cloud::SynchronizationType type, Cloud::SynchronizationResult result,
@ -495,6 +513,12 @@ private:
Cloud::RestoreRequestedHandler m_onRestoreRequested;
Cloud::RestoredFilesPreparedHandler m_onRestoredFilesPrepared;
BookmarkCatalog m_bookmarkCatalog;
OnCatalogDownloadStartedHandler m_onCatalogDownloadStarted;
OnCatalogDownloadFinishedHandler m_onCatalogDownloadFinished;
OnCatalogImportStartedHandler m_onCatalogImportStarted;
OnCatalogImportFinishedHandler m_onCatalogImportFinished;
bool m_testModeEnabled = false;
DISALLOW_COPY_AND_MOVE(BookmarkManager);

View file

@ -10,6 +10,7 @@
#include "platform/http_client.hpp"
#include "platform/platform.hpp"
#include "platform/preferred_languages.hpp"
#include "platform/remote_file.hpp"
#include "platform/settings.hpp"
#include "platform/http_uploader.hpp"
@ -329,7 +330,7 @@ Cloud::SnapshotResponseData ReadSnapshotFile(std::string const & filename)
return {};
}
Cloud::RequestResult DownloadFile(std::string const & url, std::string const & fileName,
/*Cloud::RequestResult DownloadFile(std::string const & url, std::string const & fileName,
bool & successfullyWritten)
{
successfullyWritten = true;
@ -361,7 +362,7 @@ Cloud::RequestResult DownloadFile(std::string const & url, std::string const & f
}
}
return {Cloud::RequestStatus::NetworkError, request.ServerResponse()};
}
}*/
bool CheckAndGetFileSize(std::string const & filePath, uint64_t & fileSize)
{
@ -1423,25 +1424,31 @@ void Cloud::DownloadingTask(std::string const & dirPath, bool useFallbackUrl,
FinishRestoring(SynchronizationResult::NetworkError, "Fallback url is absent");
return;
}
bool successfullyWritten = true;
auto const downloadResult = DownloadFile(useFallbackUrl ? result.m_response.m_fallbackUrl
: result.m_response.m_url,
filePath, successfullyWritten);
if (!successfullyWritten)
{
FinishRestoring(SynchronizationResult::DiskError, "Could not create downloaded file");
}
else if (downloadResult.m_status == RequestStatus::Ok)
platform::RemoteFile remoteFile(useFallbackUrl ? result.m_response.m_fallbackUrl
: result.m_response.m_url,
false /* allowRedirection */);
auto const downloadResult = remoteFile.Download(filePath);
if (downloadResult.m_status == platform::RemoteFile::Status::Ok)
{
// Download next file.
DownloadingTask(dirPath, false /* useFallbackUrl */, std::move(files));
}
else if (downloadResult.m_status == platform::RemoteFile::Status::DiskError)
{
FinishRestoring(SynchronizationResult::DiskError, downloadResult.m_description);
}
else if (downloadResult.m_status == platform::RemoteFile::Status::Forbidden)
{
FinishRestoring(SynchronizationResult::AuthError, downloadResult.m_description);
}
else
{
alohalytics::TStringMap details{
{"service", m_params.m_serverPathName},
{"type", useFallbackUrl ? "fallback_server" : "download_server"},
{"error", downloadResult.m_error}};
{"error", downloadResult.m_description}};
alohalytics::Stats::Instance().LogEvent("Cloud_Restore_error", details);
if (!useFallbackUrl)
@ -1452,7 +1459,7 @@ void Cloud::DownloadingTask(std::string const & dirPath, bool useFallbackUrl,
}
else
{
FinishRestoring(SynchronizationResult::NetworkError, "File downloader error");
FinishRestoring(SynchronizationResult::NetworkError, downloadResult.m_description);
}
}
}

View file

@ -41,6 +41,8 @@ set(
platform.hpp
preferred_languages.cpp
preferred_languages.hpp
remote_file.cpp
remote_file.hpp
secure_storage.hpp
servers_list.cpp
servers_list.hpp

View file

@ -187,6 +187,8 @@ Platform::Platform()
m_tmpDir = "/tmp";
m_tmpDir += '/';
m_privateDir = m_settingsDir;
m_guiThread = make_unique<platform::GuiThread>();
LOG(LDEBUG, ("Resources directory:", m_resourcesDir));

View file

@ -96,6 +96,7 @@ Platform::Platform()
m_writableDir = my::AddSlashIfNeeded(m_writableDir);
m_settingsDir = m_writableDir;
m_privateDir = m_writableDir;
NSString * tempDir = NSTemporaryDirectory();
if (tempDir == nil)

74
platform/remote_file.cpp Normal file
View file

@ -0,0 +1,74 @@
#include "platform/remote_file.hpp"
#include "platform/http_client.hpp"
#include "platform/platform.hpp"
#include "coding/file_writer.hpp"
#include "base/logging.hpp"
namespace platform
{
namespace
{
double constexpr kRequestTimeoutInSec = 5.0;
} // namespace
RemoteFile::RemoteFile(std::string url, bool allowRedirection)
: m_url(std::move(url))
, m_allowRedirection(allowRedirection)
{}
RemoteFile::Result RemoteFile::Download(std::string const & filePath) const
{
platform::HttpClient request(m_url);
request.SetTimeout(kRequestTimeoutInSec);
if (request.RunHttpRequest())
{
if (!m_allowRedirection && request.WasRedirected())
return {m_url, Status::NetworkError, "Unexpected redirection"};
auto const & response = request.ServerResponse();
int const resultCode = request.ErrorCode();
if (resultCode == 403)
{
LOG(LWARNING, ("Access denied for", m_url, "response:", response));
return {m_url, Status::Forbidden, resultCode, response};
}
else if (resultCode == 404)
{
LOG(LWARNING, ("File not found at", m_url, "response:", response));
return {m_url, Status::NotFound, resultCode, response};
}
if (resultCode >= 200 && resultCode < 300)
{
try
{
FileWriter w(filePath);
w.Write(response.data(), response.length());
}
catch (FileWriter::Exception const & exception)
{
LOG(LWARNING, ("Exception while writing file:", filePath, "reason:", exception.what()));
return {m_url, Status::DiskError, resultCode, exception.what()};
}
return {m_url, Status::Ok, resultCode, ""};
}
return {m_url, Status::NetworkError, resultCode, response};
}
return {m_url, Status::NetworkError, "Unspecified network error"};
}
void RemoteFile::DownloadAsync(std::string const & filePath, ResultHandler && handler) const
{
RemoteFile remoteFile = *this;
GetPlatform().RunTask(Platform::Thread::Network,
[filePath, remoteFile = std::move(remoteFile), handler = std::move(handler)]()
{
auto result = remoteFile.Download(filePath);
if (handler)
handler(std::move(result), filePath);
});
}
} // namespace platform

50
platform/remote_file.hpp Normal file
View file

@ -0,0 +1,50 @@
#pragma once
#include <functional>
#include <memory>
#include <string>
namespace platform
{
class RemoteFile
{
public:
enum class Status
{
Ok,
Forbidden,
NotFound,
NetworkError,
DiskError
};
struct Result
{
std::string const m_url;
Status const m_status;
int const m_httpCode;
std::string const m_description;
Result(std::string url, Status status, int httpCode, std::string description)
: m_url(std::move(url))
, m_status(status)
, m_httpCode(httpCode)
, m_description(std::move(description))
{}
Result(std::string url, Status status, std::string description)
: Result(std::move(url), status, 0, std::move(description))
{}
};
explicit RemoteFile(std::string url, bool allowRedirection = true);
Result Download(std::string const & filePath) const;
using ResultHandler = std::function<void(Result &&, std::string const & filePath)>;
void DownloadAsync(std::string const & filePath, ResultHandler && handler) const;
private:
std::string const m_url;
bool const m_allowRedirection;
};
} // namespace platform

View file

@ -44,6 +44,8 @@
454649F21F2728CE00EF4064 /* local_ads_mark.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 454649F01F2728CE00EF4064 /* local_ads_mark.hpp */; };
45580ABE1E2CBD5E00CD535D /* benchmark_tools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45580ABC1E2CBD5E00CD535D /* benchmark_tools.cpp */; };
45580ABF1E2CBD5E00CD535D /* benchmark_tools.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 45580ABD1E2CBD5E00CD535D /* benchmark_tools.hpp */; };
4564FA82209497A70043CCFB /* bookmark_catalog.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 4564FA80209497A60043CCFB /* bookmark_catalog.hpp */; };
4564FA83209497A70043CCFB /* bookmark_catalog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4564FA81209497A70043CCFB /* bookmark_catalog.cpp */; };
456E1B3A1F9A3C2A009C32E1 /* search_mark.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 456E1B381F9A3C29009C32E1 /* search_mark.cpp */; };
456E1B3B1F9A3C2A009C32E1 /* search_mark.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 456E1B391F9A3C2A009C32E1 /* search_mark.hpp */; };
45A2D9D51F7556EB003310A0 /* user.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45A2D9D31F7556EB003310A0 /* user.cpp */; };
@ -211,6 +213,8 @@
454649F01F2728CE00EF4064 /* local_ads_mark.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = local_ads_mark.hpp; sourceTree = "<group>"; };
45580ABC1E2CBD5E00CD535D /* benchmark_tools.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = benchmark_tools.cpp; sourceTree = "<group>"; };
45580ABD1E2CBD5E00CD535D /* benchmark_tools.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = benchmark_tools.hpp; sourceTree = "<group>"; };
4564FA80209497A60043CCFB /* bookmark_catalog.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = bookmark_catalog.hpp; sourceTree = "<group>"; };
4564FA81209497A70043CCFB /* bookmark_catalog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bookmark_catalog.cpp; sourceTree = "<group>"; };
456E1B381F9A3C29009C32E1 /* search_mark.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = search_mark.cpp; sourceTree = "<group>"; };
456E1B391F9A3C2A009C32E1 /* search_mark.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = search_mark.hpp; sourceTree = "<group>"; };
45A2D9D31F7556EB003310A0 /* user.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = user.cpp; sourceTree = "<group>"; };
@ -526,9 +530,6 @@
675345BD1A4054AD00A0A8C3 /* map */ = {
isa = PBXGroup;
children = (
F6D67CE22063F4980032FD38 /* framework_light.hpp */,
BBFC7E38202D29BF00531BE7 /* user_mark_layer.cpp */,
BBFC7E39202D29BF00531BE7 /* user_mark_layer.hpp */,
675345CB1A4054E800A0A8C3 /* address_finder.cpp */,
45201E921CE4AC90008A4842 /* api_mark_point.cpp */,
34921F611BFA0A6900737D6E /* api_mark_point.hpp */,
@ -539,12 +540,14 @@
3D4E999E1FB4A6400025B48C /* booking_filter_cache.hpp */,
3D4E99A01FB4A6410025B48C /* booking_filter.cpp */,
3D4E99A11FB4A6410025B48C /* booking_filter.hpp */,
675345DB1A4054E800A0A8C3 /* bookmark.cpp */,
675345DC1A4054E800A0A8C3 /* bookmark.hpp */,
4564FA81209497A70043CCFB /* bookmark_catalog.cpp */,
4564FA80209497A60043CCFB /* bookmark_catalog.hpp */,
BBA014AB2073C783007402E4 /* bookmark_helpers.cpp */,
BBA014AC2073C784007402E4 /* bookmark_helpers.hpp */,
675345D91A4054E800A0A8C3 /* bookmark_manager.cpp */,
675345DA1A4054E800A0A8C3 /* bookmark_manager.hpp */,
675345DB1A4054E800A0A8C3 /* bookmark.cpp */,
675345DC1A4054E800A0A8C3 /* bookmark.hpp */,
0831F23B200E53600034C365 /* bookmarks_search_params.hpp */,
348AB57A1D7EE0C6009F8301 /* chart_generator.cpp */,
348AB57B1D7EE0C6009F8301 /* chart_generator.hpp */,
@ -558,6 +561,7 @@
3D4E99801FB462B60025B48C /* everywhere_search_params.hpp */,
675345F31A4054E800A0A8C3 /* feature_vec_model.cpp */,
675345F41A4054E800A0A8C3 /* feature_vec_model.hpp */,
F6D67CE22063F4980032FD38 /* framework_light.hpp */,
675345F51A4054E800A0A8C3 /* framework.cpp */,
675345F61A4054E800A0A8C3 /* framework.hpp */,
675345F71A4054E800A0A8C3 /* ge0_parser.cpp */,
@ -602,10 +606,12 @@
347B60741DD9926D0050FA24 /* traffic_manager.cpp */,
347B60751DD9926D0050FA24 /* traffic_manager.hpp */,
BB4E5F201FCC663700A77250 /* transit */,
674C385F1BFF3095000D603B /* user_mark.cpp */,
675346331A4054E800A0A8C3 /* user_mark.hpp */,
BBA014B020754996007402E4 /* user_mark_id_storage.cpp */,
BBA014AF20754996007402E4 /* user_mark_id_storage.hpp */,
BBFC7E38202D29BF00531BE7 /* user_mark_layer.cpp */,
BBFC7E39202D29BF00531BE7 /* user_mark_layer.hpp */,
674C385F1BFF3095000D603B /* user_mark.cpp */,
675346331A4054E800A0A8C3 /* user_mark.hpp */,
45A2D9D31F7556EB003310A0 /* user.cpp */,
45A2D9D41F7556EB003310A0 /* user.hpp */,
3D4E99811FB462B60025B48C /* viewport_search_params.hpp */,
@ -660,6 +666,7 @@
3D4E99821FB462B60025B48C /* everywhere_search_params.hpp in Headers */,
675346751A4054E800A0A8C3 /* mwm_url.hpp in Headers */,
6753464B1A4054E800A0A8C3 /* bookmark.hpp in Headers */,
4564FA82209497A70043CCFB /* bookmark_catalog.hpp in Headers */,
3D47B2941F054BC5000828D2 /* taxi_delegate.hpp in Headers */,
3D47B2C81F20EF06000828D2 /* displayed_categories_modifiers.hpp in Headers */,
454523AA202A0068009275C1 /* cloud.hpp in Headers */,
@ -794,6 +801,7 @@
buildActionMask = 2147483647;
files = (
456E1B3A1F9A3C2A009C32E1 /* search_mark.cpp in Sources */,
4564FA83209497A70043CCFB /* bookmark_catalog.cpp in Sources */,
F6B283051C1B03320081957A /* gps_track_filter.cpp in Sources */,
675346481A4054E800A0A8C3 /* bookmark_manager.cpp in Sources */,
45F6EE9F1FB1C77600019892 /* search_api.cpp in Sources */,

View file

@ -25,6 +25,8 @@
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 */; };
4564FA7E2094978D0043CCFB /* remote_file.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 4564FA7C2094978C0043CCFB /* remote_file.hpp */; };
4564FA7F2094978D0043CCFB /* remote_file.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4564FA7D2094978D0043CCFB /* remote_file.cpp */; };
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 */; };
@ -137,6 +139,8 @@
451E329D1F73A8B000964C9F /* secure_storage_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = secure_storage_ios.mm; sourceTree = "<group>"; };
451E329E1F73A8B000964C9F /* secure_storage_qt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = secure_storage_qt.cpp; sourceTree = "<group>"; };
451E329F1F73A8B000964C9F /* secure_storage.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = secure_storage.hpp; sourceTree = "<group>"; };
4564FA7C2094978C0043CCFB /* remote_file.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = remote_file.hpp; sourceTree = "<group>"; };
4564FA7D2094978D0043CCFB /* remote_file.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = remote_file.cpp; sourceTree = "<group>"; };
56EB1ED81C6B6E6C0022D831 /* file_logging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_logging.cpp; sourceTree = "<group>"; };
56EB1ED91C6B6E6C0022D831 /* file_logging.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = file_logging.hpp; sourceTree = "<group>"; };
56EB1EDA1C6B6E6C0022D831 /* mwm_traits.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mwm_traits.cpp; sourceTree = "<group>"; };
@ -404,6 +408,8 @@
675343A21A3F5D5A00A0A8C3 /* platform.hpp */,
675343A31A3F5D5A00A0A8C3 /* preferred_languages.cpp */,
675343A41A3F5D5A00A0A8C3 /* preferred_languages.hpp */,
4564FA7D2094978D0043CCFB /* remote_file.cpp */,
4564FA7C2094978C0043CCFB /* remote_file.hpp */,
3D78157C1F3D8A0A0068B6AC /* safe_callback.hpp */,
451E329D1F73A8B000964C9F /* secure_storage_ios.mm */,
451E329E1F73A8B000964C9F /* secure_storage_qt.cpp */,
@ -483,6 +489,7 @@
675343B41A3F5D5A00A0A8C3 /* chunks_download_strategy.hpp in Headers */,
67247FFE1C60BD6500EDE56A /* writable_dir_changer.hpp in Headers */,
3D78157D1F3D8A0A0068B6AC /* safe_callback.hpp in Headers */,
4564FA7E2094978D0043CCFB /* remote_file.hpp in Headers */,
3D78156F1F3A14090068B6AC /* gui_thread.hpp in Headers */,
451E32A21F73A8B000964C9F /* secure_storage.hpp in Headers */,
674125091B4C00CC00A3E828 /* country_defines.hpp in Headers */,
@ -632,6 +639,7 @@
67AB92DC1B7B3D7300AB5194 /* mwm_version.cpp in Sources */,
67A2526B1BB40E520063F8A8 /* platform_mac.mm in Sources */,
6741250A1B4C00CC00A3E828 /* country_file.cpp in Sources */,
4564FA7F2094978D0043CCFB /* remote_file.cpp in Sources */,
674125081B4C00CC00A3E828 /* country_defines.cpp in Sources */,
EB60B4DC204C130300E4953B /* network_policy_ios.mm in Sources */,
6741250E1B4C00CC00A3E828 /* local_country_file.cpp in Sources */,