diff options
author | Po Lu <luangruo@yahoo.com> | 2023-10-15 13:10:34 +0800 |
---|---|---|
committer | Po Lu <luangruo@yahoo.com> | 2023-10-15 13:11:37 +0800 |
commit | 93104cff532f932bcea65d02a59c916767a31645 (patch) | |
tree | 20070ee4cb8500824fceef285bd4b104ada3748b /java | |
parent | a3fd382f3fe803e0b61c5353e9b5bdaf4d1e564e (diff) | |
download | emacs-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.java | 89 | ||||
-rw-r--r-- | java/org/gnu/emacs/EmacsWindow.java | 9 |
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) { |