Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cf31656c authored by Tomasz Mikolajewski's avatar Tomasz Mikolajewski
Browse files

Add Web Links API to framework.

Test: CTS in a separate CL.
Bug: 30152711
Change-Id: Ia256422d50110d6adcd1984f6481ab825dbf30b1
parent 0e39a438
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -32674,6 +32674,7 @@ package android.provider {
    method public static android.net.Uri buildTreeDocumentUri(java.lang.String, java.lang.String);
    method public static android.net.Uri copyDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri);
    method public static android.net.Uri createDocument(android.content.ContentResolver, android.net.Uri, java.lang.String, java.lang.String);
    method public static android.content.IntentSender createWebLinkIntent(android.content.ContentResolver, android.net.Uri, android.os.Bundle);
    method public static boolean deleteDocument(android.content.ContentResolver, android.net.Uri);
    method public static java.util.List<java.lang.String> findDocumentPath(android.content.ContentResolver, android.net.Uri);
    method public static java.lang.String getDocumentId(android.net.Uri);
@@ -32718,6 +32719,7 @@ package android.provider {
    field public static final int FLAG_SUPPORTS_THUMBNAIL = 1; // 0x1
    field public static final int FLAG_SUPPORTS_WRITE = 2; // 0x2
    field public static final int FLAG_VIRTUAL_DOCUMENT = 512; // 0x200
    field public static final int FLAG_WEB_LINKABLE = 4096; // 0x1000
    field public static final java.lang.String MIME_TYPE_DIR = "vnd.android.document/directory";
  }
@@ -32751,6 +32753,7 @@ package android.provider {
    ctor public DocumentsProvider();
    method public java.lang.String copyDocument(java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
    method public java.lang.String createDocument(java.lang.String, java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
    method public android.content.IntentSender createWebLinkIntent(java.lang.String, android.os.Bundle) throws java.io.FileNotFoundException;
    method public final int delete(android.net.Uri, java.lang.String, java.lang.String[]);
    method public void deleteDocument(java.lang.String) throws java.io.FileNotFoundException;
    method public android.provider.DocumentsContract.Path findDocumentPath(java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
+3 −0
Original line number Diff line number Diff line
@@ -35459,6 +35459,7 @@ package android.provider {
    method public static android.net.Uri buildTreeDocumentUri(java.lang.String, java.lang.String);
    method public static android.net.Uri copyDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri);
    method public static android.net.Uri createDocument(android.content.ContentResolver, android.net.Uri, java.lang.String, java.lang.String);
    method public static android.content.IntentSender createWebLinkIntent(android.content.ContentResolver, android.net.Uri, android.os.Bundle);
    method public static boolean deleteDocument(android.content.ContentResolver, android.net.Uri);
    method public static java.util.List<java.lang.String> findDocumentPath(android.content.ContentResolver, android.net.Uri);
    method public static java.lang.String getDocumentId(android.net.Uri);
@@ -35503,6 +35504,7 @@ package android.provider {
    field public static final int FLAG_SUPPORTS_THUMBNAIL = 1; // 0x1
    field public static final int FLAG_SUPPORTS_WRITE = 2; // 0x2
    field public static final int FLAG_VIRTUAL_DOCUMENT = 512; // 0x200
    field public static final int FLAG_WEB_LINKABLE = 4096; // 0x1000
    field public static final java.lang.String MIME_TYPE_DIR = "vnd.android.document/directory";
  }
@@ -35536,6 +35538,7 @@ package android.provider {
    ctor public DocumentsProvider();
    method public java.lang.String copyDocument(java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
    method public java.lang.String createDocument(java.lang.String, java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
    method public android.content.IntentSender createWebLinkIntent(java.lang.String, android.os.Bundle) throws java.io.FileNotFoundException;
    method public final int delete(android.net.Uri, java.lang.String, java.lang.String[]);
    method public void deleteDocument(java.lang.String) throws java.io.FileNotFoundException;
    method public android.provider.DocumentsContract.Path findDocumentPath(java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
+3 −0
Original line number Diff line number Diff line
@@ -32788,6 +32788,7 @@ package android.provider {
    method public static android.net.Uri buildTreeDocumentUri(java.lang.String, java.lang.String);
    method public static android.net.Uri copyDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri);
    method public static android.net.Uri createDocument(android.content.ContentResolver, android.net.Uri, java.lang.String, java.lang.String);
    method public static android.content.IntentSender createWebLinkIntent(android.content.ContentResolver, android.net.Uri, android.os.Bundle);
    method public static boolean deleteDocument(android.content.ContentResolver, android.net.Uri);
    method public static java.util.List<java.lang.String> findDocumentPath(android.content.ContentResolver, android.net.Uri);
    method public static java.lang.String getDocumentId(android.net.Uri);
@@ -32832,6 +32833,7 @@ package android.provider {
    field public static final int FLAG_SUPPORTS_THUMBNAIL = 1; // 0x1
    field public static final int FLAG_SUPPORTS_WRITE = 2; // 0x2
    field public static final int FLAG_VIRTUAL_DOCUMENT = 512; // 0x200
    field public static final int FLAG_WEB_LINKABLE = 4096; // 0x1000
    field public static final java.lang.String MIME_TYPE_DIR = "vnd.android.document/directory";
  }
@@ -32865,6 +32867,7 @@ package android.provider {
    ctor public DocumentsProvider();
    method public java.lang.String copyDocument(java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
    method public java.lang.String createDocument(java.lang.String, java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
    method public android.content.IntentSender createWebLinkIntent(java.lang.String, android.os.Bundle) throws java.io.FileNotFoundException;
    method public final int delete(android.net.Uri, java.lang.String, java.lang.String[]);
    method public void deleteDocument(java.lang.String) throws java.io.FileNotFoundException;
    method public android.provider.DocumentsContract.Path findDocumentPath(java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
+96 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ResolveInfo;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
@@ -421,6 +422,14 @@ public final class DocumentsContract {
         */
        public static final int FLAG_SUPPORTS_SETTINGS = 1 << 11;

        /**
         * Flag indicating that a Web link can be obtained for the document.
         *
         * @see #COLUMN_FLAGS
         * @see DocumentsContract#createWebLinkIntent(PackageManager, Uri, Bundle)
         */
        public static final int FLAG_WEB_LINKABLE = 1 << 12;

        /**
         * Flag indicating that a document is not complete, likely its
         * contents are being downloaded. Partial files cannot be opened,
@@ -685,12 +694,20 @@ public final class DocumentsContract {
    public static final String METHOD_EJECT_ROOT = "android:ejectRoot";
    /** {@hide} */
    public static final String METHOD_FIND_DOCUMENT_PATH = "android:findDocumentPath";
    /** {@hide} */
    public static final String METHOD_CREATE_WEB_LINK_INTENT = "android:createWebLinkIntent";

    /** {@hide} */
    public static final String EXTRA_PARENT_URI = "parentUri";
    /** {@hide} */
    public static final String EXTRA_URI = "uri";

    /**
     * @see #createWebLinkIntent(ContentResolver, Uri, Bundle)
     * {@hide}
     */
    public static final String EXTRA_OPTIONS = "options";

    private static final String PATH_ROOT = "root";
    private static final String PATH_RECENT = "recent";
    private static final String PATH_DOCUMENT = "document";
@@ -1400,6 +1417,85 @@ public final class DocumentsContract {
        return out.getParcelable(DocumentsContract.EXTRA_RESULT);
    }

    /**
     * Creates an intent for obtaining a web link for the specified document.
     *
     * <p>Note, that due to internal limitations, if there is already a web link
     * intent created for the specified document but with different options,
     * then it may be overriden.
     *
     * <p>Providers are required to show confirmation UI for all new permissions granted
     * for the linked document.
     *
     * <p>If list of recipients is known, then it should be passed in options as
     * {@link Intent#EXTRA_EMAIL} as either a string or list of strings. Note, that
     * this is just a hint for the provider, which can ignore the list. In either
     * case the provider is required to show a UI for letting the user confirm
     * any new permission grants.
     *
     * <p>Since this API may show a UI, it cannot be called from background.
     *
     * <p>In order to obtain the Web Link use code like this:
     * <pre><code>
     * void onSomethingHappened() {
     *   IntentSender sender = DocumentsContract.createWebLinkIntent(<i>...</i>);
     *   if (sender != null) {
     *     startIntentSenderForResult(
     *         DocumentsContract.createWebLinkIntent(<i>...</i>),
     *         WEB_LINK_REQUEST_CODE,
     *         null, 0, 0, 0, null);
     *   }
     * }
     *
     * <i>(...)</i>
     *
     * void onActivityResult(int requestCode, int resultCode, Intent data) {
     *   if (requestCode == WEB_LINK_REQUEST_CODE && resultCode == RESULT_OK) {
     *     Uri weblinkUri = data.getData();
     *     <i>...</i>
     *   }
     * }
     * </code></pre>
     *
     * @param uri uri for the document to create a link to.
     * @param options Extra information for generating the link.
     * @return an intent sender to obtain the web link, or null if the document
     *      is not linkable, or creating the intent sender failed.
     * @see DocumentsProvider#createWebLinkIntent(String, Bundle)
     * @see Intent#EXTRA_EMAIL
     */
    public static IntentSender createWebLinkIntent(ContentResolver resolver, Uri uri,
            Bundle options) {
        final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
                uri.getAuthority());
        try {
            return createWebLinkIntent(client, uri, options);
        } catch (Exception e) {
            Log.w(TAG, "Failed to create a web link intent", e);
            return null;
        } finally {
            ContentProviderClient.releaseQuietly(client);
        }
    }

    /**
     * {@hide}
     */
    public static IntentSender createWebLinkIntent(ContentProviderClient client, Uri uri,
            Bundle options) throws RemoteException {
        final Bundle in = new Bundle();
        in.putParcelable(DocumentsContract.EXTRA_URI, uri);

        // Options may be provider specific, so put them in a separate bundle to
        // avoid overriding the Uri.
        if (options != null) {
            in.putBundle(EXTRA_OPTIONS, options);
        }

        final Bundle out = client.call(METHOD_CREATE_WEB_LINK_INTENT, null, in);
        return out.getParcelable(DocumentsContract.EXTRA_RESULT);
    }

    /**
     * Open the given image for thumbnail purposes, using any embedded EXIF
     * thumbnail if available, and providing orientation hints from the parent
+37 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.provider;

import static android.provider.DocumentsContract.METHOD_COPY_DOCUMENT;
import static android.provider.DocumentsContract.METHOD_CREATE_DOCUMENT;
import static android.provider.DocumentsContract.METHOD_CREATE_WEB_LINK_INTENT;
import static android.provider.DocumentsContract.METHOD_DELETE_DOCUMENT;
import static android.provider.DocumentsContract.METHOD_EJECT_ROOT;
import static android.provider.DocumentsContract.METHOD_FIND_DOCUMENT_PATH;
@@ -43,6 +44,7 @@ import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.UriMatcher;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
@@ -362,6 +364,33 @@ public abstract class DocumentsProvider extends ContentProvider {
        throw new UnsupportedOperationException("findDocumentPath not supported.");
    }

    /**
     * Creates an intent sender for a web link, if the document is web linkable.
     * <p>
     * Before any new permissions are granted for the linked document, a visible
     * UI must be shown, so the user can explicitly confirm whether the permission
     * grants are expected. The user must be able to cancel the operation.
     * <p>
     * Options passed as an argument may include a list of recipients, such
     * as email addresses. The provider should reflect these options if possible,
     * but it's acceptable to ignore them. In either case, confirmation UI must
     * be shown before any new permission grants are granted.
     * <p>
     * It is all right to generate a web link without granting new permissions,
     * if opening the link would result in a page for requesting permission
     * access. If it's impossible then the operation must fail by throwing an exception.
     *
     * @param documentId the document to create a web link intent for.
     * @param options additional information, such as list of recipients. Optional.
     *
     * @see DocumentsContract.Document#FLAG_WEB_LINKABLE
     * @see android.app.PendingIntent#getIntentSender
     */
    public IntentSender createWebLinkIntent(String documentId, @Nullable Bundle options)
            throws FileNotFoundException {
        throw new UnsupportedOperationException("createWebLink is not supported.");
    }

    /**
     * Return all roots currently provided. To display to users, you must define
     * at least one root. You should avoid making network requests to keep this
@@ -900,6 +929,14 @@ public abstract class DocumentsProvider extends ContentProvider {
                    newDocumentId);
            out.putParcelable(DocumentsContract.EXTRA_URI, newDocumentUri);

        } else if (METHOD_CREATE_WEB_LINK_INTENT.equals(method)) {
            enforceWritePermissionInner(documentUri, getCallingPackage(), null);

            final Bundle options = extras.getBundle(DocumentsContract.EXTRA_OPTIONS);
            final IntentSender intentSender = createWebLinkIntent(documentId, options);

            out.putParcelable(DocumentsContract.EXTRA_RESULT, intentSender);

        } else if (METHOD_RENAME_DOCUMENT.equals(method)) {
            enforceWritePermissionInner(documentUri, getCallingPackage(), null);