blob: f48eee5fe22fbe7753c8ee349a9ab468bab52360 [file] [log] [blame]
/*
* Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.browser.trusted.sharing;
import android.annotation.SuppressLint;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.annotation.StringDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Describes a Web Share Target associated with a Trusted Web Activity.
*
* The structure of a ShareTarget object follows the specification [1] of the "share_target" object
* within web manifest json, with the following exceptions:
* - The "action" field specifies the full URL of the Share Target, and not only the path.
* - There is no "url" field in the "params" object, since urls are not supplied separately from
* text in Android's ACTION_SEND and ACTION_SEND_MULTIPLE intents.
*
* [1] https://wicg.github.io/web-share-target/level-2/
*/
public final class ShareTarget {
/** Bundle key for {@link #action}. */
@SuppressLint("IntentName")
public static final String KEY_ACTION = "androidx.browser.trusted.sharing.KEY_ACTION";
/** Bundle key for {@link #method}. */
public static final String KEY_METHOD = "androidx.browser.trusted.sharing.KEY_METHOD";
/** Bundle key for {@link #encodingType}. */
public static final String KEY_ENCTYPE = "androidx.browser.trusted.sharing.KEY_ENCTYPE";
/** Bundle key for {@link #params}. */
public static final String KEY_PARAMS = "androidx.browser.trusted.sharing.KEY_PARAMS";
/** @hide */
@RestrictTo(RestrictTo.Scope.LIBRARY)
@StringDef({METHOD_GET, METHOD_POST})
@Retention(RetentionPolicy.SOURCE)
public @interface RequestMethod {}
/** See {@link #method}. */
public static final String METHOD_GET = "GET";
/** See {@link #method}. */
public static final String METHOD_POST = "POST";
/** @hide */
@RestrictTo(RestrictTo.Scope.LIBRARY)
@StringDef({ENCODING_TYPE_URL_ENCODED, ENCODING_TYPE_MULTIPART})
@Retention(RetentionPolicy.SOURCE)
public @interface EncodingType {}
/**
* An encoding type to be used with POST requests (see {@link #encodingType}) corresponding to
* {@code application/x-www-form-urlencoded} of the HTTP POST standard [1].
*
* [1]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST
*/
public static final String ENCODING_TYPE_URL_ENCODED = "application/x-www-form-urlencoded";
/**
* An encoding type to be used with POST requests (see {@link #encodingType}) corresponding to
* {@code multipart/form-data} of the HTTP POST standard [1].
*/
public static final String ENCODING_TYPE_MULTIPART = "multipart/form-data";
/**
* URL of the Web Share Target. Must belong to an origin associated with the Trusted Web
* Activity. For example, assuming the origin is "https://mypwa.com", the action could be
* "https://mypwa.com/share.html".
*/
@NonNull
public final String action;
/**
* HTTP request method for the Web Share Target. Must be {@link #METHOD_GET} or
* {@link #METHOD_POST}. Default is {@link #METHOD_GET}.
*/
@Nullable
@RequestMethod
public final String method;
/**
* Specifies how the shared data should be encoded in the body of a POST request. Must be
* {@link #ENCODING_TYPE_MULTIPART} or {@link #ENCODING_TYPE_URL_ENCODED}. Default is
* {@link #ENCODING_TYPE_URL_ENCODED}.
*/
@Nullable
@EncodingType
public final String encodingType;
/**
* Contains the parameter names, see {@link Params}.
*/
@NonNull
public final Params params;
/**
* Creates a {@link ShareTarget} with the given parameters.
* @param action The {@link #action}.
* @param method The {@link #method}.
* @param encodingType The {@link #encodingType}.
* @param params The {@link #params}.
*/
public ShareTarget(@NonNull String action, @Nullable @RequestMethod String method,
@Nullable @EncodingType String encodingType, @NonNull Params params) {
this.action = action;
this.method = method;
this.encodingType = encodingType;
this.params = params;
}
/** Packs the object into a {@link Bundle}. */
@NonNull
public Bundle toBundle() {
Bundle bundle = new Bundle();
bundle.putString(KEY_ACTION, action);
bundle.putString(KEY_METHOD, method);
bundle.putString(KEY_ENCTYPE, encodingType);
bundle.putBundle(KEY_PARAMS, params.toBundle());
return bundle;
}
/** Unpacks the object from a {@link Bundle}. */
@Nullable
public static ShareTarget fromBundle(@NonNull Bundle bundle) {
String action = bundle.getString(KEY_ACTION);
String method = bundle.getString(KEY_METHOD);
String encType = bundle.getString(KEY_ENCTYPE);
Params params = Params.fromBundle(bundle.getBundle(KEY_PARAMS));
if (action == null || params == null) {
return null;
}
return new ShareTarget(action, method, encType, params);
}
/** Contains parameter names to be used for the data being shared. */
public static class Params {
/** Bundle key for {@link #title}. */
public static final String KEY_TITLE = "androidx.browser.trusted.sharing.KEY_TITLE";
/** Bundle key for {@link #text}. */
public static final String KEY_TEXT = "androidx.browser.trusted.sharing.KEY_TEXT";
/** Bundle key for {@link #files}. */
public static final String KEY_FILES = "androidx.browser.trusted.sharing.KEY_FILES";
/** The name of the query parameter used for the title of the message being shared. */
@Nullable
public final String title;
/** The name of the query parameter used for the body of the message being shared. */
@Nullable
public final String text;
/**
* Defines form fields for the files being shared, see {@link FileFormField}.
* Web Share Target can have multiple form fields associated with different MIME types.
* If a file passes the MIME type filters of several {@link FileFormField}s,
* the one that has the lowest index in this list is picked; see [1] for details.
*
* [1] https://wicg.github.io/web-share-target/level-2/#launching-the-web-share-target
*/
@Nullable
public final List<FileFormField> files;
/**
* Creates a {@link Params} with the given parameters.
* @param title The {@link #title}.
* @param text The {@link #text}.
* @param files The {@link #files}.
*/
public Params(@Nullable String title, @Nullable String text,
@Nullable List<FileFormField> files) {
this.title = title;
this.text = text;
this.files = files;
}
@SuppressWarnings("WeakerAccess") /* synthetic access */
@NonNull
Bundle toBundle() {
Bundle bundle = new Bundle();
bundle.putString(KEY_TITLE, title);
bundle.putString(KEY_TEXT, text);
if (files != null) {
ArrayList<Bundle> fileBundles = new ArrayList<>();
for (FileFormField file : files) {
fileBundles.add(file.toBundle());
}
bundle.putParcelableArrayList(KEY_FILES, fileBundles);
}
return bundle;
}
@SuppressWarnings("WeakerAccess") /* synthetic access */
@Nullable
static Params fromBundle(@Nullable Bundle bundle) {
if (bundle == null) {
return null;
}
List<FileFormField> files = null;
List<Bundle> fileBundles = bundle.getParcelableArrayList(KEY_FILES);
if (fileBundles != null) {
files = new ArrayList<>();
for (Bundle fileBundle : fileBundles) {
files.add(FileFormField.fromBundle(fileBundle));
}
}
return new Params(bundle.getString(KEY_TITLE), bundle.getString(KEY_TEXT),
files);
}
}
/** Defines a form field for sharing files. */
public static final class FileFormField {
/** Bundle key for {@link #name}. */
public static final String KEY_NAME = "androidx.browser.trusted.sharing.KEY_FILE_NAME";
/** Bundle key for {@link #acceptedTypes}. */
public static final String KEY_ACCEPTED_TYPES =
"androidx.browser.trusted.sharing.KEY_ACCEPTED_TYPES";
/** Name of the form field. */
@NonNull
public final String name;
/**
* List of MIME types or file extensions to be sent in this field. The MIME type matching
* algorithm is specified by
* https://wicg.github.io/web-share-target/level-2/#determining-if-a-file-is-accepted.
*/
@NonNull
public final List<String> acceptedTypes;
/**
* Creates a {@link FileFormField} with the given parameters.
* @param name The {@link #name}.
* @param acceptedTypes The {@link #acceptedTypes}.
*/
public FileFormField(@NonNull String name, @NonNull List<String> acceptedTypes) {
this.name = name;
this.acceptedTypes = Collections.unmodifiableList(acceptedTypes);
}
@SuppressWarnings("WeakerAccess") /* synthetic access */
@NonNull
Bundle toBundle() {
Bundle bundle = new Bundle();
bundle.putString(KEY_NAME, name);
bundle.putStringArrayList(KEY_ACCEPTED_TYPES, new ArrayList<>(acceptedTypes));
return bundle;
}
@SuppressWarnings("WeakerAccess") /* synthetic access */
@Nullable
static FileFormField fromBundle(@Nullable Bundle bundle) {
if (bundle == null) {
return null;
}
String name = bundle.getString(KEY_NAME);
ArrayList<String> acceptedTypes = bundle.getStringArrayList(KEY_ACCEPTED_TYPES);
if (name == null || acceptedTypes == null) {
return null;
}
return new FileFormField(name, acceptedTypes);
}
}
}