summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2023-10-15 13:10:34 +0800
committerPo Lu <luangruo@yahoo.com>2023-10-15 13:11:37 +0800
commit93104cff532f932bcea65d02a59c916767a31645 (patch)
tree20070ee4cb8500824fceef285bd4b104ada3748b /java
parenta3fd382f3fe803e0b61c5353e9b5bdaf4d1e564e (diff)
downloademacs-93104cff532f932bcea65d02a59c916767a31645.tar.gz
Correctly receive files through Android DND
* java/org/gnu/emacs/EmacsService.java (getUsefulContentResolver) (getContentResolverContext): New functions which return a content resolver from an EmacsActivity, if at all possible. (openContentUri, checkContentUri): Probe or open URIs through such content resolvers. Probe URIs by opening them if merely testing permissions fails, for DND URIs do not make checkCallingUriPermission return true. * java/org/gnu/emacs/EmacsWindow.java (onDragEvent): Address potential crash. * src/androidvfs.c (android_check_content_access): Circumvent JNI dynamic method dispatch. (android_authority_name): Guarantee NAME is never a directory.
Diffstat (limited to 'java')
-rw-r--r--java/org/gnu/emacs/EmacsService.java89
-rw-r--r--java/org/gnu/emacs/EmacsWindow.java9
2 files changed, 93 insertions, 5 deletions
diff --git a/java/org/gnu/emacs/EmacsService.java b/java/org/gnu/emacs/EmacsService.java
index 6fa2ebb3fdb..1325cd85e9b 100644
--- a/java/org/gnu/emacs/EmacsService.java
+++ b/java/org/gnu/emacs/EmacsService.java
@@ -921,6 +921,48 @@ public final class EmacsService extends Service
/* Content provider functions. */
+ /* Return a ContentResolver capable of accessing as many files as
+ possible, namely the content resolver of the last selected
+ activity if available: only they posses the rights to access drag
+ and drop files. */
+
+ public ContentResolver
+ getUsefulContentResolver ()
+ {
+ EmacsActivity activity;
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
+ /* Since the system predates drag and drop, return this resolver
+ to avoid any unforseen difficulties. */
+ return resolver;
+
+ activity = EmacsActivity.lastFocusedActivity;
+ if (activity == null)
+ return resolver;
+
+ return activity.getContentResolver ();
+ }
+
+ /* Return a context whose ContentResolver is granted access to most
+ files, as in `getUsefulContentResolver'. */
+
+ public Context
+ getContentResolverContext ()
+ {
+ EmacsActivity activity;
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
+ /* Since the system predates drag and drop, return this resolver
+ to avoid any unforseen difficulties. */
+ return this;
+
+ activity = EmacsActivity.lastFocusedActivity;
+ if (activity == null)
+ return this;
+
+ return activity;
+ }
+
/* Open a content URI described by the bytes BYTES, a non-terminated
string; make it writable if WRITABLE, and readable if READABLE.
Truncate the file if TRUNCATE.
@@ -934,6 +976,9 @@ public final class EmacsService extends Service
String name, mode;
ParcelFileDescriptor fd;
int i;
+ ContentResolver resolver;
+
+ resolver = getUsefulContentResolver ();
/* Figure out the file access mode. */
@@ -978,6 +1023,7 @@ public final class EmacsService extends Service
}
catch (Exception exception)
{
+ exception.printStackTrace ();
return -1;
}
}
@@ -994,6 +1040,11 @@ public final class EmacsService extends Service
ParcelFileDescriptor fd;
Uri uri;
int rc, flags;
+ Context context;
+ ContentResolver resolver;
+ ParcelFileDescriptor descriptor;
+
+ context = getContentResolverContext ();
uri = Uri.parse (name);
flags = 0;
@@ -1004,8 +1055,42 @@ public final class EmacsService extends Service
if (writable)
flags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
- rc = checkCallingUriPermission (uri, flags);
- return rc == PackageManager.PERMISSION_GRANTED;
+ rc = context.checkCallingUriPermission (uri, flags);
+
+ if (rc == PackageManager.PERMISSION_GRANTED)
+ return true;
+
+ /* In the event checkCallingUriPermission fails and only read
+ permissions are being verified, attempt to query the URI. This
+ enables ascertaining whether drag and drop URIs can be
+ accessed, something otherwise not provided for. */
+
+ descriptor = null;
+
+ try
+ {
+ resolver = context.getContentResolver ();
+ descriptor = resolver.openFileDescriptor (uri, "r");
+ return true;
+ }
+ catch (Exception exception)
+ {
+ /* Ignored. */
+ }
+ finally
+ {
+ try
+ {
+ if (descriptor != null)
+ descriptor.close ();
+ }
+ catch (IOException exception)
+ {
+ /* Ignored. */
+ }
+ }
+
+ return false;
}
/* Build a content file name for URI.
diff --git a/java/org/gnu/emacs/EmacsWindow.java b/java/org/gnu/emacs/EmacsWindow.java
index 3d2d86624a7..386eaca8c41 100644
--- a/java/org/gnu/emacs/EmacsWindow.java
+++ b/java/org/gnu/emacs/EmacsWindow.java
@@ -1601,7 +1601,7 @@ public final class EmacsWindow extends EmacsHandleObject
{
ClipData data;
ClipDescription description;
- int i, x, y;
+ int i, j, x, y, itemCount;
String type;
Uri uri;
EmacsActivity activity;
@@ -1626,11 +1626,12 @@ public final class EmacsWindow extends EmacsHandleObject
data = event.getClipData ();
description = data.getDescription ();
+ itemCount = data.getItemCount ();
/* If there are insufficient items within the clip data,
return false. */
- if (data.getItemCount () < 1)
+ if (itemCount < 1)
return false;
/* Search for plain text data within the clipboard. */
@@ -1662,12 +1663,14 @@ public final class EmacsWindow extends EmacsHandleObject
{
/* If the item dropped is a URI, send it to the main
thread. */
+
uri = data.getItemAt (0).getUri ();
/* Attempt to acquire permissions for this URI;
failing which, insert it as text instead. */
- if (uri.getScheme () != null
+ if (uri != null
+ && uri.getScheme () != null
&& uri.getScheme ().equals ("content")
&& (activity = EmacsActivity.lastFocusedActivity) != null)
{