Commit dc183842 authored by DanmeiChen's avatar DanmeiChen

Merge branch 'feature/auto_download_incoming_messages_files' into dev_lime_v2

parents f96d2d85 54cd32b9
......@@ -1443,6 +1443,8 @@ static void sip_config_read(LinphoneCore *lc) {
tmp=lp_config_get_int(lc->config,"sip","delayed_timeout",4);
linphone_core_set_delayed_timeout(lc,tmp);
tmp=lp_config_get_int(lc->config,"app","auto_download_incoming_files_max_size",-1);
linphone_core_set_max_size_for_auto_download_incoming_files(lc, tmp);
/*In case of remote provisionning, function sip_config_read is initialy called in core_init, then in state ConfiguringSuccessfull*/
/*Accordingly, to avoid proxy_config to be added twice, it is mandatory to reset proxy config list from LinphoneCore*/
......@@ -3978,6 +3980,15 @@ void linphone_core_set_delayed_timeout(LinphoneCore *lc, int seconds){
lc->sip_conf.delayed_timeout=seconds;
}
int linphone_core_get_max_size_for_auto_download_incoming_files(LinphoneCore *lc) {
return lc->auto_download_incoming_files_max_size;
}
void linphone_core_set_max_size_for_auto_download_incoming_files(LinphoneCore *lc, int size) {
lc->auto_download_incoming_files_max_size = size;
lp_config_set_int(lc->config, "app", "auto_download_incoming_files_max_size", size);
}
void linphone_core_set_presence_info(LinphoneCore *lc, int minutes_away, const char *contact, LinphoneOnlineStatus os) {
LinphonePresenceModel *presence = NULL;
LinphonePresenceActivity *activity = NULL;
......
......@@ -821,6 +821,7 @@ namespace LinphonePrivate {
bctbx_list_t *chat_rooms; \
bctbx_list_t *callsCache; \
bool_t dns_set_by_app; \
int auto_download_incoming_files_max_size; \
#define LINPHONE_CORE_STRUCT_FIELDS \
LINPHONE_CORE_STRUCT_BASE_FIELDS \
......
......@@ -5675,7 +5675,21 @@ LINPHONE_PUBLIC void linphone_core_notify_notify_presence_received(LinphoneCore
*/
LINPHONE_PUBLIC void linphone_core_notify_notify_presence_received_for_uri_or_tel(LinphoneCore *lc, LinphoneFriend *lf, const char *uri_or_tel, const LinphonePresenceModel *presence_model);
/**
* Sets the size under which incoming files in chat messages will be downloaded automatically.
* @param[in] lc #LinphoneCore object
* @param[in] size The size in bytes, -1 to disable the autodownload feature, 0 to download them all no matter the size
* @ingroup chat
**/
LINPHONE_PUBLIC void linphone_core_set_max_size_for_auto_download_incoming_files(LinphoneCore *lc, int size);
/**
* Gets the size under which incoming files in chat messages will be downloaded automatically.
* @param[in] lc #LinphoneCore object
* @return The size in bytes, -1 if autodownload feature is disabled, 0 to download them all no matter the size
* @ingroup chat
**/
LINPHONE_PUBLIC int linphone_core_get_max_size_for_auto_download_incoming_files(LinphoneCore *lc);
/**
* @}
......
......@@ -54,8 +54,9 @@ public:
Encryption = 1 << 3,
Cpim = 1 << 4,
Started = 1 << 5,
FileDownload = 1 << 6,
AutoFileDownload = 1 << 7,
Sent = 1 << 6,
FileDownload = 1 << 7,
};
void setApplyModifiers (bool value) { applyModifiers = value; }
......@@ -103,6 +104,14 @@ public:
return contents;
}
void setAutoFileTransferDownloadHappened(bool yesno) {
isAutoDownloadAttachedFilesHappened = yesno;
}
bool isAutoFileTransferDownloadHappened() const {
return isAutoDownloadAttachedFilesHappened;
}
belle_http_request_t *getHttpRequest () const;
void setHttpRequest (belle_http_request_t *request);
......@@ -133,6 +142,9 @@ public:
void setEncryptionPrevented (bool value) { encryptionPrevented = value; }
void doNotRetryAutoDownload() {
currentRecvStep |= ChatMessagePrivate::Step::AutoFileDownload;
}
void enableSenderAuthentication (bool value) { senderAuthenticationEnabled = value; }
void setUnencryptedContentWarning (bool value) { unencryptedContentWarning = value; }
......@@ -202,6 +214,7 @@ private:
bool isSecured = false;
mutable bool isReadOnly = false;
Content internalContent;
bool isAutoDownloadAttachedFilesHappened = false;
// TODO: to replace salCustomheaders
std::unordered_map<std::string, std::string> customHeaders;
......
......@@ -586,6 +586,27 @@ LinphoneReason ChatMessagePrivate::receive () {
currentRecvStep |= ChatMessagePrivate::Step::FileDownload;
}
if ((currentRecvStep & ChatMessagePrivate::Step::AutoFileDownload) == ChatMessagePrivate::Step::AutoFileDownload) {
lInfo() << "Auto file download step already done, skipping";
} else {
for (Content *c : contents) {
if (c->isFileTransfer()) {
int max_size = linphone_core_get_max_size_for_auto_download_incoming_files(q->getCore()->getCCore());
if (max_size >= 0) {
FileTransferContent *ftc = static_cast<FileTransferContent *>(c);
if (max_size == 0 || ftc->getFileSize() <= (size_t)max_size) {
ftc->setFilePath(q->getCore()->getDownloadPath() + ftc->getFileName());
setAutoFileTransferDownloadHappened(true);
q->downloadFile(ftc);
return LinphoneReasonNone;
}
}
}
}
currentRecvStep |= ChatMessagePrivate::Step::AutoFileDownload;
q->getChatRoom()->getPrivate()->removeTransientChatMessage(q->getSharedFromThis());
}
if (contents.size() == 0) {
// All previous modifiers only altered the internal content, let's fill the content list
contents.push_back(new Content(internalContent));
......@@ -606,7 +627,9 @@ LinphoneReason ChatMessagePrivate::receive () {
setState(ChatMessage::State::Delivered);
if (errorCode <= 0) {
if (errorCode <= 0 && !isAutoFileTransferDownloadHappened()) {
// if auto download happened and message contains only file transfer,
// the following will state that the content type of the file is unsupported
bool foundSupportContentType = false;
for (Content *c : contents) {
ContentType ct(c->getContentType());
......@@ -623,6 +646,8 @@ LinphoneReason ChatMessagePrivate::receive () {
lError() << "No content-type in the contents list is supported...";
}
}
// If auto download failed, reset this flag so the user can normally download the file later
setAutoFileTransferDownloadHappened(false);
// Check if this is in fact an outgoing message (case where this is a message sent by us from an other device).
if (
......
......@@ -54,6 +54,9 @@ public:
virtual LinphoneReason onSipMessageReceived (SalOp *op, const SalMessage *message) = 0;
virtual void onChatMessageReceived (const std::shared_ptr<ChatMessage> &chatMessage) = 0;
virtual void addTransientChatMessage (const std::shared_ptr<ChatMessage> &message) = 0;
virtual void removeTransientChatMessage (const std::shared_ptr<ChatMessage> &message) = 0;
};
LINPHONE_END_NAMESPACE
......
......@@ -57,6 +57,9 @@ public:
void addTransientEvent (const std::shared_ptr<EventLog> &eventLog) override;
void removeTransientEvent (const std::shared_ptr<EventLog> &eventLog) override;
void addTransientChatMessage (const std::shared_ptr<ChatMessage> &message) override;
void removeTransientChatMessage (const std::shared_ptr<ChatMessage> &message) override;
std::shared_ptr<ChatMessage> createChatMessage (ChatMessage::Direction direction);
std::shared_ptr<ImdnMessage> createImdnMessage (
const std::list<std::shared_ptr<ChatMessage>> &deliveredMessages,
......@@ -91,6 +94,7 @@ public:
std::list<IdentityAddress> remoteIsComposing;
std::list<std::shared_ptr<EventLog>> transientEvents;
std::list<std::shared_ptr<ChatMessage>> transientMessages;
ConferenceId conferenceId;
......
......@@ -20,6 +20,7 @@
#include <algorithm>
#include "linphone/utils/utils.h"
#include "linphone/utils/algorithm.h"
#include "c-wrapper/c-wrapper.h"
#include "chat/chat-message/chat-message-p.h"
......@@ -92,17 +93,29 @@ void ChatRoomPrivate::addEvent (const shared_ptr<EventLog> &eventLog) {
}
void ChatRoomPrivate::addTransientEvent (const shared_ptr<EventLog> &eventLog) {
auto it = find(transientEvents.begin(), transientEvents.end(), eventLog);
auto it = find(transientEvents, eventLog);
if (it == transientEvents.end())
transientEvents.push_back(eventLog);
}
void ChatRoomPrivate::removeTransientEvent (const shared_ptr<EventLog> &eventLog) {
auto it = find(transientEvents.begin(), transientEvents.end(), eventLog);
auto it = find(transientEvents, eventLog);
if (it != transientEvents.end())
transientEvents.erase(it);
}
void ChatRoomPrivate::addTransientChatMessage (const shared_ptr<ChatMessage> &message) {
auto it = find(transientMessages, message);
if (it == transientMessages.end())
transientMessages.push_back(message);
}
void ChatRoomPrivate::removeTransientChatMessage (const shared_ptr<ChatMessage> &message) {
auto it = find(transientMessages, message);
if (it != transientMessages.end())
transientMessages.erase(it);
}
// -----------------------------------------------------------------------------
shared_ptr<ChatMessage> ChatRoomPrivate::createChatMessage (ChatMessage::Direction direction) {
......@@ -278,6 +291,7 @@ LinphoneReason ChatRoomPrivate::onSipMessageReceived (SalOp *op, const SalMessag
if (ch)
msg->getPrivate()->setSalCustomHeaders(sal_custom_header_clone(ch));
addTransientChatMessage(msg);
reason = msg->getPrivate()->receive();
return reason;
}
......
......@@ -57,6 +57,14 @@ public:
chatRoom->getPrivate()->removeTransientEvent(eventLog);
}
inline void addTransientChatMessage (const std::shared_ptr<ChatMessage> &message) override {
chatRoom->getPrivate()->addTransientChatMessage(message);
}
inline void removeTransientChatMessage (const std::shared_ptr<ChatMessage> &message) override {
chatRoom->getPrivate()->removeTransientChatMessage(message);
}
inline void sendDeliveryNotifications () override {
chatRoom->getPrivate()->sendDeliveryNotifications();
}
......
......@@ -800,7 +800,12 @@ void FileTransferChatMessageModifier::onRecvEnd (belle_sip_user_body_handler_t *
}
}
}
message->getPrivate()->setState(ChatMessage::State::FileTransferDone);
if (message->getPrivate()->isAutoFileTransferDownloadHappened()) {
releaseHttpRequest();
message->getPrivate()->receive();
} else {
message->getPrivate()->setState(ChatMessage::State::FileTransferDone);
}
}
}
......@@ -873,6 +878,20 @@ void FileTransferChatMessageModifier::processResponseHeadersFromGetFile (const b
}
}
void FileTransferChatMessageModifier::onDownloadFailed() {
shared_ptr<ChatMessage> message = chatMessage.lock();
if (!message)
return;
if (message->getPrivate()->isAutoFileTransferDownloadHappened()) {
message->getPrivate()->doNotRetryAutoDownload();
releaseHttpRequest();
message->getPrivate()->receive();
} else {
message->getPrivate()->setState(ChatMessage::State::FileTransferError);
releaseHttpRequest();
}
}
static void _chat_message_process_auth_requested_download (void *data, belle_sip_auth_event *event) {
FileTransferChatMessageModifier *d = (FileTransferChatMessageModifier *)data;
d->processAuthRequestedDownload(event);
......@@ -880,11 +899,7 @@ static void _chat_message_process_auth_requested_download (void *data, belle_sip
void FileTransferChatMessageModifier::processAuthRequestedDownload (const belle_sip_auth_event *event) {
lError() << "Error during file download : auth requested for msg [" << this << "]";
shared_ptr<ChatMessage> message = chatMessage.lock();
if (!message)
return;
message->getPrivate()->setState(ChatMessage::State::FileTransferError);
releaseHttpRequest();
onDownloadFailed();
}
static void _chat_message_process_io_error_download (void *data, const belle_sip_io_error_event_t *event) {
......@@ -894,11 +909,7 @@ static void _chat_message_process_io_error_download (void *data, const belle_sip
void FileTransferChatMessageModifier::processIoErrorDownload (const belle_sip_io_error_event_t *event) {
lError() << "I/O Error during file download msg [" << this << "]";
shared_ptr<ChatMessage> message = chatMessage.lock();
if (!message)
return;
message->getPrivate()->setState(ChatMessage::State::FileTransferError);
releaseHttpRequest();
onDownloadFailed();
}
static void _chat_message_process_response_from_get_file (void *data, const belle_http_response_event_t *event) {
......@@ -916,11 +927,10 @@ void FileTransferChatMessageModifier::processResponseFromGetFile (const belle_ht
int code = belle_http_response_get_status_code(event->response);
if (code >= 400 && code < 500) {
lWarning() << "File transfer failed with code " << code;
message->getPrivate()->setState(ChatMessage::State::FileTransferError);
onDownloadFailed();
} else if (code != 200) {
lWarning() << "Unhandled HTTP code response " << code << " for file transfer";
}
releaseHttpRequest();
}
}
......
......@@ -71,6 +71,7 @@ private:
void fileUploadBeginBackgroundTask ();
void fileUploadEndBackgroundTask ();
void onDownloadFailed ();
void releaseHttpRequest ();
std::weak_ptr<ChatMessage> chatMessage;
......
This diff is collapsed.
......@@ -127,8 +127,9 @@ public:
// Paths.
// ---------------------------------------------------------------------------
std::string getDataPath () const;
std::string getConfigPath () const;
std::string getDataPath() const;
std::string getConfigPath() const;
std::string getDownloadPath() const;
// ---------------------------------------------------------------------------
// EncryptionEngine.
......
......@@ -41,4 +41,10 @@ string SysPaths::getConfigPath (PlatformHelpers *platformHelpers) {
return platformHelpers->getConfigPath();
}
string SysPaths::getDownloadPath (PlatformHelpers *platformHelpers) {
if (!platformHelpers)
return "";
return platformHelpers->getDownloadPath();
}
LINPHONE_END_NAMESPACE
......@@ -33,6 +33,7 @@ class PlatformHelpers;
namespace SysPaths {
LINPHONE_PUBLIC std::string getDataPath (PlatformHelpers *platformHelpers);
LINPHONE_PUBLIC std::string getConfigPath (PlatformHelpers *platformHelpers);
LINPHONE_PUBLIC std::string getDownloadPath (PlatformHelpers *platformHelpers);
}
LINPHONE_END_NAMESPACE
......
......@@ -33,6 +33,7 @@ class PlatformHelpers;
namespace SysPaths {
LINPHONE_PUBLIC std::string getDataPath (PlatformHelpers *platformHelpers);
LINPHONE_PUBLIC std::string getConfigPath (PlatformHelpers *platformHelpers);
LINPHONE_PUBLIC std::string getDownloadPath (PlatformHelpers *platformHelpers);
}
LINPHONE_END_NAMESPACE
......
......@@ -63,4 +63,22 @@ std::string SysPaths::getConfigPath (PlatformHelpers *) {
return fullPath.UTF8String;
}
std::string SysPaths::getDownloadPath (PlatformHelpers *) {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *configPath = [paths objectAtIndex:0];
NSString *fullPath = [configPath stringByAppendingString:@"/"];
if (![[NSFileManager defaultManager] fileExistsAtPath:fullPath]) {
NSError *error;
lInfo() << "Download path " << fullPath.UTF8String << " does not exist, creating it.";
if (![[NSFileManager defaultManager] createDirectoryAtPath:fullPath
withIntermediateDirectories:YES
attributes:nil
error:&error]) {
lError() << "Create download path directory error: " << error.description;
}
}
return fullPath.UTF8String;
}
LINPHONE_END_NAMESPACE
......@@ -48,4 +48,10 @@ string SysPaths::getConfigPath (PlatformHelpers *) {
return configPath;
}
string SysPaths::getDownloadPath (PlatformHelpers *) {
//TODO
static string downloadPath = getBaseDirectory() + "/.config/linphone/";
return downloadPath;
}
LINPHONE_END_NAMESPACE
......@@ -33,6 +33,7 @@ class PlatformHelpers;
namespace SysPaths {
LINPHONE_PUBLIC std::string getDataPath (PlatformHelpers *platformHelpers);
LINPHONE_PUBLIC std::string getConfigPath (PlatformHelpers *platformHelpers);
LINPHONE_PUBLIC std::string getDownloadPath (PlatformHelpers *platformHelpers);
}
LINPHONE_END_NAMESPACE
......
......@@ -58,4 +58,9 @@ string SysPaths::getConfigPath (PlatformHelpers *platformHelpers) {
return getDataPath(platformHelpers);
}
string SysPaths::getDownloadPath (PlatformHelpers *platformHelpers) {
// TODO
return getDataPath(platformHelpers);
}
LINPHONE_END_NAMESPACE
......@@ -33,6 +33,7 @@ class PlatformHelpers;
namespace SysPaths {
LINPHONE_PUBLIC std::string getDataPath (PlatformHelpers *platformHelpers);
LINPHONE_PUBLIC std::string getConfigPath (PlatformHelpers *platformHelpers);
LINPHONE_PUBLIC std::string getDownloadPath (PlatformHelpers *platformHelpers);
}
LINPHONE_END_NAMESPACE
......
......@@ -44,6 +44,8 @@ string Paths::getPath (Paths::Type type, PlatformHelpers *platformHelpers) {
return SysPaths::getDataPath(platformHelpers);
case Config:
return SysPaths::getConfigPath(platformHelpers);
case Download:
return SysPaths::getDownloadPath(platformHelpers);
}
L_ASSERT(false);
......
......@@ -32,7 +32,8 @@ class PlatformHelpers;
namespace Paths {
enum Type {
Data,
Config
Config,
Download
};
LINPHONE_PUBLIC std::string getPath (Type type, PlatformHelpers *platformHelpers);
......
......@@ -46,11 +46,10 @@ public:
void releaseCpuLock () override;
string getDataPath () override;
string getConfigPath () override;
void setVideoWindow (void *windowId) override;
void setVideoPreviewWindow (void *windowId) override;
void _setPreviewVideoWindow(jobject window);
void _setVideoWindow(jobject window);
string getDownloadPath() override;
private:
int callVoidMethod (jmethodID id);
......@@ -67,6 +66,7 @@ private:
jmethodID mGetPowerManagerId;
jmethodID mGetDataPathId;
jmethodID mGetConfigPathId;
jmethodID mGetDownloadPathId;
jmethodID mGetNativeLibraryDirId;
jmethodID mSetNativeVideoWindowId;
jmethodID mSetNativePreviewVideoWindowId;
......@@ -114,6 +114,7 @@ AndroidPlatformHelpers::AndroidPlatformHelpers (LinphoneCore *lc, void *systemCo
mGetPowerManagerId = getMethodId(env, klass, "getPowerManager", "()Ljava/lang/Object;");
mGetDataPathId = getMethodId(env, klass, "getDataPath", "()Ljava/lang/String;");
mGetConfigPathId = getMethodId(env, klass, "getConfigPath", "()Ljava/lang/String;");
mGetDownloadPathId = getMethodId(env, klass, "getDownloadPath", "()Ljava/lang/String;");
mGetNativeLibraryDirId = getMethodId(env, klass, "getNativeLibraryDir", "()Ljava/lang/String;");
mSetNativeVideoWindowId = getMethodId(env, klass, "setVideoRenderingView", "(Ljava/lang/Object;)V");
mSetNativePreviewVideoWindowId = getMethodId(env, klass, "setVideoPreviewView", "(Ljava/lang/Object;)V");
......@@ -227,6 +228,15 @@ string AndroidPlatformHelpers::getConfigPath () {
return configPath + "/";
}
string AndroidPlatformHelpers::getDownloadPath () {
JNIEnv *env = ms_get_jni_env();
jstring jdownload_path = (jstring)env->CallObjectMethod(mJavaHelper, mGetDownloadPathId);
const char *download_path = GetStringUTFChars(env, jdownload_path);
string downloadPath = download_path;
ReleaseStringUTFChars(env, jdownload_path, download_path);
return downloadPath + "/";
}
int AndroidPlatformHelpers::callVoidMethod (jmethodID id) {
JNIEnv *env = ms_get_jni_env();
if (env && mJavaHelper) {
......
......@@ -57,6 +57,7 @@ public:
string getConfigPath () override {return Utils::getEmptyConstRefObject<string>();}
void setVideoWindow (void *windowId) override {}
void setVideoPreviewWindow (void *windowId) override {}
string getDownloadPath () override {return Utils::getEmptyConstRefObject<string>();}
private:
void bgTaskTimeout ();
......
......@@ -57,4 +57,8 @@ void StubbedPlatformHelpers::setVideoWindow (void *windowId) {
}
string StubbedPlatformHelpers::getDownloadPath () {
return "";
}
LINPHONE_END_NAMESPACE
......@@ -52,6 +52,7 @@ public:
virtual std::string getConfigPath () = 0;
virtual void setVideoWindow (void *windowId) = 0;
virtual void setVideoPreviewWindow (void *windowId) = 0;
virtual std::string getDownloadPath () = 0;
protected:
inline explicit PlatformHelpers (LinphoneCore *lc) : mCore(lc) {}
......@@ -75,6 +76,7 @@ public:
std::string getConfigPath () override;
void setVideoWindow (void *windowId) override;
void setVideoPreviewWindow (void *windowId) override;
std::string getDownloadPath () override;
};
PlatformHelpers *createAndroidPlatformHelpers (LinphoneCore *lc, void *systemContext);
......
This diff is collapsed.
......@@ -28,13 +28,10 @@ import org.linphone.mediastream.Version;
import android.content.res.Resources;
import android.graphics.SurfaceTexture;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.MulticastLock;
import android.net.wifi.WifiManager.WifiLock;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
import android.os.Environment;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.Build;
......@@ -44,7 +41,6 @@ import android.view.TextureView;
import java.net.InetAddress;
import java.util.List;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
......@@ -146,6 +142,15 @@ public class AndroidPlatformHelper {
public String getCachePath() {
return mContext.getCacheDir().getAbsolutePath();
}
public String getDownloadPath() {
String downloadPath = Environment.getExternalStorageDirectory() + "/" + mContext.getString(mResources.getIdentifier("app_name", "string", mContext.getPackageName()));
File dir = new File(downloadPath);
if (!dir.exists()) {
dir.mkdirs();
}
return downloadPath;
}
public String getNativeLibraryDir(){
ApplicationInfo info = mContext.getApplicationInfo();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment