Detailed changes
@@ -18,13 +18,15 @@ import android.view.LayoutInflater;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
import android.webkit.JavascriptInterface;
+import android.webkit.ValueCallback;
+import android.webkit.WebChromeClient;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
+import android.widget.ArrayAdapter;
import android.widget.TextView;
import androidx.annotation.RequiresApi;
@@ -64,6 +66,7 @@ import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.persistance.FileBackend;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.ui.ConversationsActivity;
+import eu.siacs.conversations.ui.XmppActivity;
import eu.siacs.conversations.utils.MimeUtils;
import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.xml.Element;
@@ -77,10 +80,12 @@ public class WebxdcPage implements ConversationPage {
protected String baseUrl;
protected Message source;
protected WebxdcUpdate lastUpdate = null;
+ protected WeakReference<XmppActivity> activity;
- public WebxdcPage(Cid cid, Message source, XmppConnectionService xmppConnectionService) {
+ public WebxdcPage(final XmppActivity activity, Cid cid, Message source, XmppConnectionService xmppConnectionService) {
this.xmppConnectionService = xmppConnectionService;
this.source = source;
+ this.activity = new WeakReference(activity);
File f = xmppConnectionService.getFileForCid(cid);
try {
if (f != null) zip = new ZipFile(xmppConnectionService.getFileForCid(cid));
@@ -252,6 +257,20 @@ public class WebxdcPage implements ConversationPage {
}
});
+ binding.webview.setWebChromeClient(new WebChromeClient() {
+ @Override
+ public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
+ // WebxdcActivity.this.filePathCallback = filePathCallback;
+ Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("*/*");
+ intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, fileChooserParams.getMode() == FileChooserParams.MODE_OPEN_MULTIPLE);
+ final XmppActivity activity = WebxdcPage.this.activity.get();
+ if (activity != null) activity.startActivityWithCallback(Intent.createChooser(intent, "Choose a file"), filePathCallback);
+ return activity != null;
+ }
+ });
+
// disable "safe browsing" as this has privacy issues,
// eg. at least false positives are sent to the "Safe Browsing Lookup API".
// as all URLs opened in the WebView are local anyway,
@@ -36,5 +36,26 @@ window.webxdc = (() => {
sendUpdate: (payload, descr) => {
InternalJSApi.sendStatusUpdate(JSON.stringify(payload), descr);
},
+
+ importFiles: (filters) => {
+ var element = document.createElement("input");
+ element.type = "file";
+ element.accept = [
+ ...(filters.extensions || []),
+ ...(filters.mimeTypes || []),
+ ].join(",");
+ element.multiple = filters.multiple || false;
+ const promise = new Promise((resolve, _reject) => {
+ element.onchange = (_ev) => {
+ const files = Array.from(element.files || []);
+ document.body.removeChild(element);
+ resolve(files);
+ };
+ });
+ element.style.display = "none";
+ document.body.appendChild(element);
+ element.click();
+ return promise;
+ },
};
})();
@@ -3213,7 +3213,7 @@ public class ConversationFragment extends XmppFragment
if (message == null) return;
Cid webxdcCid = message.getFileParams().getCids().get(0);
- WebxdcPage webxdc = new WebxdcPage(webxdcCid, message, activity.xmppConnectionService);
+ WebxdcPage webxdc = new WebxdcPage(activity, webxdcCid, message, activity.xmppConnectionService);
Conversation conversation = (Conversation) message.getConversation();
if (!conversation.switchToSession("webxdc\0" + message.getUuid())) {
conversation.startWebxdc(webxdc);
@@ -41,9 +41,11 @@ import android.text.Html;
import android.text.InputType;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.util.Pair;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
+import android.webkit.ValueCallback;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView;
@@ -65,6 +67,7 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import java.util.PriorityQueue;
import java.util.concurrent.RejectedExecutionException;
import eu.siacs.conversations.Config;
@@ -117,6 +120,7 @@ public abstract class XmppActivity extends ActionBarActivity {
protected Toast mToast;
public Runnable onOpenPGPKeyPublished = () -> Toast.makeText(XmppActivity.this, R.string.openpgp_has_been_published, Toast.LENGTH_SHORT).show();
protected ConferenceInvite mPendingConferenceInvite = null;
+ protected PriorityQueue<Pair<Integer, ValueCallback<Uri[]>>> activityCallbacks = new PriorityQueue<>((x, y) -> y.first.compareTo(x.first));
protected ServiceConnection mConnection = new ServiceConnection() {
@Override
@@ -854,6 +858,13 @@ public abstract class XmppActivity extends ActionBarActivity {
}
}
+ public synchronized void startActivityWithCallback(Intent intent, ValueCallback<Uri[]> cb) {
+ Pair<Integer, ValueCallback<Uri[]>> peek = activityCallbacks.peek();
+ int index = peek == null ? 1 : peek.first + 1;
+ activityCallbacks.add(new Pair<>(index, cb));
+ startActivityForResult(intent, index);
+ }
+
protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_INVITE_TO_CONVERSATION && resultCode == RESULT_OK) {
@@ -865,6 +876,21 @@ public abstract class XmppActivity extends ActionBarActivity {
}
mPendingConferenceInvite = null;
}
+ } else if (resultCode == RESULT_OK) {
+ for (Pair<Integer, ValueCallback<Uri[]>> cb : new ArrayList<>(activityCallbacks)) {
+ if (cb.first == requestCode) {
+ activityCallbacks.remove(cb);
+ ArrayList<Uri> dataUris = new ArrayList<>();
+ if (data.getDataString() != null) {
+ dataUris.add(Uri.parse(data.getDataString()));
+ } else if (data.getClipData() != null) {
+ for (int i = 0; i < data.getClipData().getItemCount(); i++) {
+ dataUris.add(data.getClipData().getItemAt(i).getUri());
+ }
+ }
+ cb.second.onReceiveValue(dataUris.toArray(new Uri[0]));
+ }
+ }
}
}
@@ -689,7 +689,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
private void displayWebxdcMessage(ViewHolder viewHolder, final Message message, final boolean darkBackground, final int type) {
Cid webxdcCid = message.getFileParams().getCids().get(0);
- WebxdcPage webxdc = new WebxdcPage(webxdcCid, message, activity.xmppConnectionService);
+ WebxdcPage webxdc = new WebxdcPage(activity, webxdcCid, message, activity.xmppConnectionService);
displayTextMessage(viewHolder, message, darkBackground, type);
viewHolder.image.setVisibility(View.GONE);
viewHolder.audioPlayer.setVisibility(View.GONE);