android/lib/src/main/cpp/androidapp.cpp  |   54 +++++++++++++++++++++----------
 android/lib/src/main/cpp/androidapp.hpp  |    3 +
 kit/ChildSession.cpp                     |   11 +++++-
 loleaflet/src/control/Control.Toolbar.js |    6 ---
 4 files changed, 52 insertions(+), 22 deletions(-)

New commits:
commit a2116cbade24e9a8d46e7d6616f502b69a301b7d
Author:     Jan Holesovsky <ke...@collabora.com>
AuthorDate: Tue Jul 14 14:27:03 2020 +0200
Commit:     Jan Holesovsky <ke...@collabora.com>
CommitDate: Wed Jul 15 23:33:46 2020 +0200

    android: Call the SAVE directly from the native code.
    
    Until now, for the "local save has completed, upload it back to the
    content: URI" messages we were relying on the "local save" -> JavaScript
    -> Java -> "upload to content:/ URI" chain.
    
    It turns out though, that the WebView can be dead by the time we need
    the notification that the save has completed.  This was particularly
    seen on ChromeOS when the document was closed using the [x] in the
    window decoration.
    
    As a solution, we need to pass the info that the "local save" has
    completed directly to Java.  So far this uses the same semantics as the
    postMobileMessage() and reuse its code; but maybe in the future we'll
    need to split this.
    
    Change-Id: If1b93e4f76cee3abc6aebfc3e9072810ab73bb42
    Reviewed-on: https://gerrit.libreoffice.org/c/online/+/98771
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Jan Holesovsky <ke...@collabora.com>

diff --git a/android/lib/src/main/cpp/androidapp.cpp 
b/android/lib/src/main/cpp/androidapp.cpp
index a3f847135..f3405f374 100644
--- a/android/lib/src/main/cpp/androidapp.cpp
+++ b/android/lib/src/main/cpp/androidapp.cpp
@@ -35,6 +35,10 @@ static int closeNotificationPipeForForwardingThread[2] = 
{-1, -1};
 static JavaVM* javaVM = nullptr;
 static bool lokInitialized = false;
 
+// Remember the reference to the LOActivity
+jclass g_loActivityClz = nullptr;
+jobject g_loActivityObj = nullptr;
+
 extern "C" JNIEXPORT jint JNICALL
 JNI_OnLoad(JavaVM* vm, void*) {
     javaVM = vm;
@@ -89,7 +93,7 @@ public:
     JNIEnv *getEnv() const { return _env; }
 };
 
-static void send2JS(const JNIThreadContext &jctx, jclass loActivityClz, 
jobject loActivityObj, const std::vector<char>& buffer)
+static void send2JS(const JNIThreadContext &jctx, const std::vector<char>& 
buffer)
 {
     LOG_DBG("Send to JS: " << 
LOOLProtocol::getAbbreviatedMessage(buffer.data(), buffer.size()));
 
@@ -149,8 +153,22 @@ static void send2JS(const JNIThreadContext &jctx, jclass 
loActivityClz, jobject
 
     JNIEnv *env = jctx.getEnv();
     jstring jstr = env->NewStringUTF(js.c_str());
-    jmethodID callFakeWebsocket = env->GetMethodID(loActivityClz, 
"callFakeWebsocketOnMessage", "(Ljava/lang/String;)V");
-    env->CallVoidMethod(loActivityObj, callFakeWebsocket, jstr);
+    jmethodID callFakeWebsocket = env->GetMethodID(g_loActivityClz, 
"callFakeWebsocketOnMessage", "(Ljava/lang/String;)V");
+    env->CallVoidMethod(g_loActivityObj, callFakeWebsocket, jstr);
+    env->DeleteLocalRef(jstr);
+
+    if (env->ExceptionCheck())
+        env->ExceptionDescribe();
+}
+
+void postDirectMessage(std::string message)
+{
+    JNIThreadContext ctx;
+    JNIEnv *env = ctx.getEnv();
+
+    jstring jstr = env->NewStringUTF(message.c_str());
+    jmethodID callPostMobileMessage = env->GetMethodID(g_loActivityClz, 
"postMobileMessage", "(Ljava/lang/String;)V");
+    env->CallVoidMethod(g_loActivityObj, callPostMobileMessage, jstr);
     env->DeleteLocalRef(jstr);
 
     if (env->ExceptionCheck())
@@ -170,7 +188,7 @@ void closeDocument()
 
 /// Handle a message from JavaScript.
 extern "C" JNIEXPORT void JNICALL
-Java_org_libreoffice_androidlib_LOActivity_postMobileMessageNative(JNIEnv 
*env, jobject instance, jstring message)
+Java_org_libreoffice_androidlib_LOActivity_postMobileMessageNative(JNIEnv 
*env, jobject, jstring message)
 {
     const char *string_value = env->GetStringUTFChars(message, nullptr);
 
@@ -197,11 +215,7 @@ 
Java_org_libreoffice_androidlib_LOActivity_postMobileMessageNative(JNIEnv *env,
             fakeSocketPipe2(closeNotificationPipeForForwardingThread);
 
             // Start another thread to read responses and forward them to the 
JavaScript
-            jclass clz = env->GetObjectClass(instance);
-            jclass loActivityClz = (jclass) env->NewGlobalRef(clz);
-            jobject loActivityObj = env->NewGlobalRef(instance);
-
-            std::thread([loActivityClz, loActivityObj, currentFakeClientFd]
+            std::thread([currentFakeClientFd]
                         {
                             Util::setThreadName("app2js");
                             JNIThreadContext ctx;
@@ -242,7 +256,7 @@ 
Java_org_libreoffice_androidlib_LOActivity_postMobileMessageNative(JNIEnv *env,
                                            return;
                                        std::vector<char> buf(n);
                                        n = fakeSocketRead(currentFakeClientFd, 
buf.data(), n);
-                                       send2JS(ctx, loActivityClz, 
loActivityObj, buf);
+                                       send2JS(ctx, buf);
                                    }
                                }
                                else
@@ -290,10 +304,18 @@ extern "C" jboolean libreofficekit_initialize(JNIEnv* 
env, jstring dataDir, jstr
 
 /// Create the LOOLWSD instance.
 extern "C" JNIEXPORT void JNICALL
-Java_org_libreoffice_androidlib_LOActivity_createLOOLWSD(JNIEnv *env, jobject, 
jstring dataDir, jstring cacheDir, jstring apkFile, jobject assetManager, 
jstring loadFileURL)
+Java_org_libreoffice_androidlib_LOActivity_createLOOLWSD(JNIEnv *env, jobject 
instance, jstring dataDir, jstring cacheDir, jstring apkFile, jobject 
assetManager, jstring loadFileURL)
 {
     fileURL = std::string(env->GetStringUTFChars(loadFileURL, nullptr));
 
+    // remember the LOActivity class and object to be able to call back
+    env->DeleteGlobalRef(g_loActivityClz);
+    env->DeleteGlobalRef(g_loActivityObj);
+
+    jclass clz = env->GetObjectClass(instance);
+    g_loActivityClz = (jclass) env->NewGlobalRef(clz);
+    g_loActivityObj = env->NewGlobalRef(instance);
+
     // already initialized?
     if (lokInitialized)
     {
@@ -335,7 +357,7 @@ 
Java_org_libreoffice_androidlib_LOActivity_createLOOLWSD(JNIEnv *env, jobject, j
 
 extern "C"
 JNIEXPORT void JNICALL
-Java_org_libreoffice_androidlib_LOActivity_saveAs(JNIEnv *env, jobject 
instance,
+Java_org_libreoffice_androidlib_LOActivity_saveAs(JNIEnv *env, jobject,
                                                   jstring fileUri_, jstring 
format_) {
     const char *fileUri = env->GetStringUTFChars(fileUri_, 0);
     const char *format = env->GetStringUTFChars(format_, 0);
@@ -348,7 +370,7 @@ Java_org_libreoffice_androidlib_LOActivity_saveAs(JNIEnv 
*env, jobject instance,
 
 extern "C"
 JNIEXPORT void JNICALL
-Java_org_libreoffice_androidlib_LOActivity_postUnoCommand(JNIEnv* pEnv, 
jobject instance,
+Java_org_libreoffice_androidlib_LOActivity_postUnoCommand(JNIEnv* pEnv, 
jobject,
                                                           jstring command, 
jstring arguments, jboolean bNotifyWhenFinished)
 {
     const char* pCommand = pEnv->GetStringUTFChars(command, nullptr);
@@ -382,7 +404,7 @@ const char* copyJavaString(JNIEnv* pEnv, jstring 
aJavaString)
 
 extern "C"
 JNIEXPORT jboolean JNICALL
-Java_org_libreoffice_androidlib_LOActivity_getClipboardContent(JNIEnv *env, 
jobject instance, jobject lokClipboardData)
+Java_org_libreoffice_androidlib_LOActivity_getClipboardContent(JNIEnv *env, 
jobject, jobject lokClipboardData)
 {
     const char** mimeTypes = nullptr;
     size_t outCount = 0;
@@ -481,7 +503,7 @@ 
Java_org_libreoffice_androidlib_LOActivity_getClipboardContent(JNIEnv *env, jobj
 
 extern "C"
 JNIEXPORT void JNICALL
-Java_org_libreoffice_androidlib_LOActivity_setClipboardContent(JNIEnv *env, 
jobject instance, jobject lokClipboardData) {
+Java_org_libreoffice_androidlib_LOActivity_setClipboardContent(JNIEnv *env, 
jobject, jobject lokClipboardData) {
     jclass class_ArrayList= env->FindClass("java/util/ArrayList");
     jmethodID methodId_ArrayList_ToArray = env->GetMethodID(class_ArrayList, 
"toArray", "()[Ljava/lang/Object;");
 
@@ -527,7 +549,7 @@ 
Java_org_libreoffice_androidlib_LOActivity_setClipboardContent(JNIEnv *env, jobj
 
 extern "C"
 JNIEXPORT void JNICALL
-Java_org_libreoffice_androidlib_LOActivity_paste(JNIEnv *env, jobject 
instance, jstring inMimeType, jbyteArray inData) {
+Java_org_libreoffice_androidlib_LOActivity_paste(JNIEnv *env, jobject, jstring 
inMimeType, jbyteArray inData) {
     const char* mimeType = env->GetStringUTFChars(inMimeType, nullptr);
 
     size_t dataArrayLength = env->GetArrayLength(inData);
diff --git a/android/lib/src/main/cpp/androidapp.hpp 
b/android/lib/src/main/cpp/androidapp.hpp
index 59a9faa5b..ef48bf137 100644
--- a/android/lib/src/main/cpp/androidapp.hpp
+++ b/android/lib/src/main/cpp/androidapp.hpp
@@ -9,4 +9,7 @@
 
 extern int loolwsd_server_socket_fd;
 
+/** Equivalent of postMobileMessage(), but called directly from the native 
code. */
+void postDirectMessage(std::string message);
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/kit/ChildSession.cpp b/kit/ChildSession.cpp
index 4b27da4c8..b11763a05 100644
--- a/kit/ChildSession.cpp
+++ b/kit/ChildSession.cpp
@@ -36,6 +36,10 @@
 #import "DocumentViewController.h"
 #endif
 
+#ifdef __ANDROID__
+#include <androidapp.hpp>
+#endif
+
 #include <common/FileUtil.hpp>
 #include <common/JsonUtil.hpp>
 #include <common/Authorization.hpp>
@@ -2471,7 +2475,7 @@ void ChildSession::loKitCallback(const int type, const 
std::string& payload)
         break;
     case LOK_CALLBACK_UNO_COMMAND_RESULT:
         sendTextFrame("unocommandresult: " + payload);
-#ifdef IOS
+#if MOBILEAPP
         {
             // After the document has been saved (into the temporary copy that 
we set up in
             // -[CODocument loadFromContents:ofType:error:]), save it also 
using the system API so
@@ -2486,6 +2490,7 @@ void ChildSession::loKitCallback(const int type, const 
std::string& payload)
 
             if (!commandName.isEmpty() && commandName.toString() == 
".uno:Save" && !success.isEmpty() && success.toString() == "true")
             {
+#ifdef IOS
                 CODocument *document = [[DocumentViewController singleton] 
document];
 
                 [document saveToURL:[document fileURL]
@@ -2493,6 +2498,10 @@ void ChildSession::loKitCallback(const int type, const 
std::string& payload)
                  completionHandler:^(BOOL success) {
                         LOG_TRC("ChildSession::loKitCallback() save completion 
handler gets " << (success?"YES":"NO"));
                     }];
+#endif
+#ifdef __ANDROID__
+                postDirectMessage("SAVE " + payload);
+#endif
             }
         }
 #endif
diff --git a/loleaflet/src/control/Control.Toolbar.js 
b/loleaflet/src/control/Control.Toolbar.js
index 6a52c4ec1..bb7776109 100644
--- a/loleaflet/src/control/Control.Toolbar.js
+++ b/loleaflet/src/control/Control.Toolbar.js
@@ -936,11 +936,7 @@ function onCommandResult(e) {
                        postMessageObj['result'] = e.result && e.result.value;
                }
 
-               if (window.ThisIsTheAndroidApp) {
-                       window.postMobileMessage('SAVE ' + 
JSON.stringify(postMessageObj));
-               } else {
-                       map.fire('postMessage', {msgId: 'Action_Save_Resp', 
args: postMessageObj});
-               }
+               map.fire('postMessage', {msgId: 'Action_Save_Resp', args: 
postMessageObj});
        }
        else if ((commandName === '.uno:Undo' || commandName === '.uno:Redo') &&
                e.success === true && e.result.value && !isNaN(e.result.value)) 
{ /*UNDO_CONFLICT*/
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to