chromium/components/browser_ui/share/android/java/src/org/chromium/components/browser_ui/share/ShareParams.java

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.components.browser_ui.share;

import android.content.ComponentName;
import android.net.Uri;
import android.text.TextUtils;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;

import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils;
import org.chromium.ui.base.WindowAndroid;

import java.util.ArrayList;

/** A container object for passing share parameters to {@link ShareHelper}. */
public class ShareParams {
    /** The window that triggered the share action. */
    private final WindowAndroid mWindow;

    /** The title of the page to be shared. */
    private final String mTitle;

    /** The text to be shared. */
    private final String mText;

    /** A format to be used when sharing |mText|. */
    private final String mTextFormat;

    /** The URL of the page to be shared. */
    private String mUrl;

    /** The common MIME type of the files to be shared. A wildcard if they have differing types. */
    private final String mFileContentType;

    /** The list of Uris of the files to be shared. */
    private final ArrayList<Uri> mFileUris;

    /** The alt-text for the shared files. */
    private final String mImageAltText;

    /** The Uri to the offline MHTML file to be shared. */
    private final Uri mOfflineUri;

    /**
     * The Uri of a single image to be shared. If multiple image are being shared, use {@link
     * #mFileUris}.
     */
    private final Uri mSingleImageUri;

    /** The Uri of the preview image (e.g. a favicon) of the text being shared. */
    private Uri mPreviewImageUri;

    /** The boolean result of link to text generation. */
    private final Boolean mLinkToTextSuccessful;

    /** The sharing hub preview text. */
    private final String mPreviewText;

    /** A format to be used when sharing |mPreviewText|. */
    private final String mPreviewTextFormat;

    /**
     * Optional callback to be called when user makes a choice. Will not be called if receiving a
     * response when the user makes a choice is not supported (on older Android versions).
     */
    private TargetChosenCallback mCallback;

    private ShareParams(
            WindowAndroid window,
            String title,
            String text,
            String textFormat,
            String url,
            @Nullable String fileContentType,
            @Nullable ArrayList<Uri> fileUris,
            @Nullable String imageAltText,
            @Nullable Uri offlineUri,
            @Nullable Uri singleImageUri,
            @Nullable Uri previewImageUri,
            @Nullable TargetChosenCallback callback,
            @Nullable Boolean linkToTextSuccessful,
            @Nullable String previewText,
            String previewTextFormat) {
        mWindow = window;
        mTitle = title;
        mText = text;
        mTextFormat = textFormat;
        mUrl = url;
        mFileContentType = fileContentType;
        mFileUris = fileUris;
        mImageAltText = imageAltText;
        mOfflineUri = offlineUri;
        mSingleImageUri = singleImageUri;
        mPreviewImageUri = previewImageUri;
        mCallback = callback;
        mLinkToTextSuccessful = linkToTextSuccessful;
        mPreviewText = previewText;
        mPreviewTextFormat = previewTextFormat;
    }

    /** @return The window that triggered share. */
    public WindowAndroid getWindow() {
        return mWindow;
    }

    /** @return The title of the page to be shared. */
    public String getTitle() {
        return mTitle;
    }

    /** @return The text concatenated with the url. */
    public String getTextAndUrl() {
        String text = getText();
        String url = getUrl();

        if (TextUtils.isEmpty(url)) {
            return text;
        }
        if (TextUtils.isEmpty(text)) {
            return url;
        }
        // Concatenate text and URL with a space.
        return text + " " + url;
    }

    /** @return The text to be shared in the format it is meant to be shared. */
    public String getText() {
        return mTextFormat == null ? mText : String.format(mTextFormat, mText);
    }

    /** @return The text to be shared, but without additional formatting. */
    public String getRawText() {
        return mText;
    }

    /** @return The URL of the page to be shared. */
    public String getUrl() {
        return mUrl;
    }

    /** @param url set URL to be shared. */
    public void setUrl(String url) {
        mUrl = url;
    }

    /** @return The MIME type to the arbitrary files to be shared. */
    @Nullable
    public String getFileContentType() {
        return mFileContentType;
    }

    /** @return The Uri to the arbitrary files to be shared. */
    @Nullable
    public ArrayList<Uri> getFileUris() {
        return mFileUris;
    }

    /** @return The alt-texts related to the single image to be shared. */
    @Nullable
    public String getImageAltText() {
        return mImageAltText;
    }

    /** @return The Uri to the offline MHTML file to be shared. */
    @Nullable
    public Uri getOfflineUri() {
        return mOfflineUri;
    }

    /** @return The Uri of a single image to be shared. */
    @Nullable
    public Uri getSingleImageUri() {
        return mSingleImageUri;
    }

    /** @return The Uri of the preview image (e.g. a favicon) of the text being shared. */
    @Nullable
    public Uri getPreviewImageUri() {
        return mPreviewImageUri;
    }

    /** @param uri The Uri of the preview image (e.g. a favicon) of the text being shared. */
    public void setPreviewImageUri(Uri uri) {
        mPreviewImageUri = uri;
    }

    /** @return The callback to be called when user makes a choice. */
    @Nullable
    public TargetChosenCallback getCallback() {
        return mCallback;
    }

    /** @param callback To be called when user makes a choice. */
    public void setCallback(@Nullable TargetChosenCallback callback) {
        mCallback = callback;
    }

    /** @return The boolean result of link to text generation. */
    @Nullable
    public Boolean getLinkToTextSuccessful() {
        return mLinkToTextSuccessful;
    }

    /** @return The text to be shared in the format it is meant to be shared. */
    @Nullable
    public String getPreviewText() {
        return mPreviewTextFormat == null
                ? mPreviewText
                : String.format(mPreviewTextFormat, mPreviewText);
    }

    /**
     * A helper function returning the image Uri to share if image is passed as image URI, or as a
     * single file.
     */
    @Nullable
    public Uri getImageUriToShare() {
        if (getSingleImageUri() != null) {
            return getSingleImageUri();
        }

        // For cases where multiple images are shared, return the first image.
        if (getFileUris() != null
                && getFileUris().size() > 0
                && getFileContentType() != null
                && getFileContentType().startsWith("image")) {
            return getFileUris().get(0);
        }
        return null;
    }

    /** The builder for {@link ShareParams} objects. */
    public static class Builder {
        private WindowAndroid mWindow;
        private String mTitle;
        private String mText;
        private String mTextFormat;
        private String mUrl;
        private String mFileContentType;
        private ArrayList<Uri> mFileUris;
        private String mImageAltText;
        private Uri mOfflineUri;
        private Uri mSingleImageUri;
        private Uri mPreviewImageUri;
        private TargetChosenCallback mCallback;
        private Boolean mLinkToTextSuccessful;
        private String mPreviewText;
        private String mPreviewTextFormat;
        // TODO(https://crbug/1415082): Remove when DomDistillerUrlUtil is removed from below.
        private boolean mBypassFixingDomDistillerUrl;

        public Builder(@NonNull WindowAndroid window, @NonNull String title, @NonNull String url) {
            mWindow = window;
            mUrl = url;
            mTitle = title;
        }

        /** Sets the text to be shared. */
        public Builder setText(@NonNull String text) {
            mText = text;
            return this;
        }

        /** Sets the text to be shared and its format to be used before sharing it. */
        public Builder setText(@NonNull String text, @NonNull String format) {
            mTextFormat = format;
            return setText(text);
        }

        /** Sets the sharing hub preview text. */
        public Builder setPreviewText(@NonNull String previewText, @NonNull String format) {
            mPreviewTextFormat = format;
            mPreviewText = previewText;
            return this;
        }

        /** Sets the MIME type of the arbitrary files to be shared. */
        public Builder setFileContentType(@NonNull String fileContentType) {
            mFileContentType = fileContentType;
            return this;
        }

        /** Sets the Uri of the arbitrary files to be shared. */
        public Builder setFileUris(@Nullable ArrayList<Uri> fileUris) {
            mFileUris = fileUris;
            return this;
        }

        /** Sets the alt-texts associated with the single image to be shared. */
        public Builder setImageAltText(@Nullable String imageAltText) {
            mImageAltText = imageAltText;
            return this;
        }

        /** Sets the Uri of the offline MHTML file to be shared. */
        public Builder setOfflineUri(@Nullable Uri offlineUri) {
            mOfflineUri = offlineUri;
            return this;
        }

        /**
         * Sets the Uri of a single image to be shared. If multiple image are being shared, use
         * {@link #setFileUris(ArrayList)}.
         */
        public Builder setSingleImageUri(@Nullable Uri singleImageUri) {
            mSingleImageUri = singleImageUri;
            return this;
        }

        /** Sets the Uri of the preview image of the text being shared. */
        public Builder setPreviewImageUri(@Nullable Uri previewImageUri) {
            mPreviewImageUri = previewImageUri;
            return this;
        }

        /** Sets the callback to be called when user makes a choice. */
        public Builder setCallback(@Nullable TargetChosenCallback callback) {
            mCallback = callback;
            return this;
        }

        /** Sets the boolean result of link to text generation. */
        public Builder setLinkToTextSuccessful(@Nullable Boolean linkToTextSuccessful) {
            mLinkToTextSuccessful = linkToTextSuccessful;
            return this;
        }

        /** Sets whether the URL should be fixed to its original URL when it is a dom distiller URL. */
        @VisibleForTesting(otherwise = VisibleForTesting.NONE)
        public Builder setBypassFixingDomDistillerUrl(boolean bypassFixingDomDistillerUrl) {
            mBypassFixingDomDistillerUrl = bypassFixingDomDistillerUrl;
            return this;
        }

        /** @return A fully constructed {@link ShareParams} object. */
        public ShareParams build() {
            if (!TextUtils.isEmpty(mUrl) && !mBypassFixingDomDistillerUrl) {
                mUrl = DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(mUrl);
            }
            return new ShareParams(
                    mWindow,
                    mTitle,
                    mText,
                    mTextFormat,
                    mUrl,
                    mFileContentType,
                    mFileUris,
                    mImageAltText,
                    mOfflineUri,
                    mSingleImageUri,
                    mPreviewImageUri,
                    mCallback,
                    mLinkToTextSuccessful,
                    mPreviewText,
                    mPreviewTextFormat);
        }
    }

    /** Callback interface for when a target is chosen. */
    public static interface TargetChosenCallback {
        /**
         * Called when the user chooses a target in the share dialog. When this is called when a
         * custom action is selected on the system share sheet (e.g. Copy, Edit), the
         * |chosenComponent| can be null.
         *
         * Note that if the user cancels the share dialog, this callback is never called.
         */
        public void onTargetChosen(@Nullable ComponentName chosenComponent);

        /**
         * Called when the user cancels the share dialog.
         *
         * Guaranteed that either this, or onTargetChosen (but not both) will be called, eventually.
         */
        public void onCancel();
    }
}