Verified Commit 927d61a7 authored by Makoto Kato's avatar Makoto Kato Committed by ma1
Browse files

Bug 1776646 - Support EXTRA_IS_SENSITIVE for clipboard. r=geckoview-reviewers,owlish

When nsITransferable.isPrivateData is true, such as coping password or
private mode, we should set EXTRA_IS_SENSITIVE to ClipData.

AndroidJunit test runner doesn't often get `ClipDescription.extras`
from clipboard service in test runner. So we cannot write a unit test
using AndroidJUnit test runner.

Differential Revision: https://phabricator.services.mozilla.com/D225326
parent 776b61f5
Loading
Loading
Loading
Loading
+17 −6
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ import android.content.ClipboardManager.OnPrimaryClipChangedListener;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.os.Build;
import android.os.PersistableBundle;
import android.text.TextUtils;
import android.util.Log;
import java.io.ByteArrayOutputStream;
@@ -133,8 +134,9 @@ public final class Clipboard {
   * @return true if copy is successful.
   */
  @WrapForJNI(calledFrom = "gecko")
  public static boolean setText(final Context context, final CharSequence text) {
    return setData(context, ClipData.newPlainText("text", text));
  public static boolean setText(
      final Context context, final CharSequence text, final boolean isPrivateData) {
    return setData(context, ClipData.newPlainText("text", text), isPrivateData);
  }

  /**
@@ -147,8 +149,11 @@ public final class Clipboard {
   */
  @WrapForJNI(calledFrom = "gecko")
  private static boolean setHTML(
      final Context context, final CharSequence text, final String htmlText) {
    return setData(context, ClipData.newHtmlText("html", text, htmlText));
      final Context context,
      final CharSequence text,
      final String htmlText,
      final boolean isPrivateData) {
    return setData(context, ClipData.newHtmlText("html", text, htmlText), isPrivateData);
  }

  /**
@@ -158,11 +163,17 @@ public final class Clipboard {
   * @param clipData a {@link android.content.ClipData} to set to clipboard
   * @return true if copy is successful.
   */
  private static boolean setData(final Context context, final ClipData clipData) {
  private static boolean setData(
      final Context context, final ClipData clipData, final boolean isPrivateData) {
    // In API Level 11 and above, CLIPBOARD_SERVICE returns android.content.ClipboardManager,
    // which is a subclass of android.text.ClipboardManager.
    final ClipboardManager cm =
        (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
    if (isPrivateData && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
      final PersistableBundle extras = new PersistableBundle();
      extras.putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true);
      clipData.getDescription().setExtras(extras);
    }
    try {
      cm.setPrimaryClip(clipData);
    } catch (final NullPointerException e) {
@@ -228,7 +239,7 @@ public final class Clipboard {
  @WrapForJNI(calledFrom = "gecko")
  private static void clear(final Context context) {
    if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
      setText(context, null);
      setText(context, null, false);
      return;
    }
    // Although we don't know more details of https://crbug.com/1203377, Blink doesn't use
+8 −3
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ import org.mozilla.gecko.util.ThreadUtils;
  private ExtractedTextRequest mUpdateRequest;
  private final InputConnection mKeyInputConnection;
  private CursorAnchorInfo.Builder mCursorAnchorInfoBuilder;
  private boolean mIsPrivateBrowsing;

  public static SessionTextInput.InputConnectionClient create(
      final GeckoSession session,
@@ -208,12 +209,13 @@ import org.mozilla.gecko.util.ThreadUtils;
        // If selection is empty, we'll select everything
        if (selStart == selEnd) {
          // Fill the clipboard
          Clipboard.setText(view.getContext(), editable);
          Clipboard.setText(view.getContext(), editable, mIsPrivateBrowsing);
          editable.clear();
        } else {
          Clipboard.setText(
              view.getContext(),
              editable.subSequence(Math.min(selStart, selEnd), Math.max(selStart, selEnd)));
              editable.subSequence(Math.min(selStart, selEnd), Math.max(selStart, selEnd)),
              mIsPrivateBrowsing);
          editable.delete(selStart, selEnd);
        }
        break;
@@ -231,7 +233,7 @@ import org.mozilla.gecko.util.ThreadUtils;
                : editable
                    .toString()
                    .substring(Math.min(selStart, selEnd), Math.max(selStart, selEnd));
        Clipboard.setText(view.getContext(), copiedText);
        Clipboard.setText(view.getContext(), copiedText, mIsPrivateBrowsing);
        break;
    }
    return true;
@@ -603,6 +605,9 @@ import org.mozilla.gecko.util.ThreadUtils;
      outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_FLAG_NO_FULLSCREEN;
    }

    mIsPrivateBrowsing =
        ((outAttrs.imeOptions & InputMethods.IME_FLAG_NO_PERSONALIZED_LEARNING) != 0);

    if (DEBUG) {
      Log.d(
          LOGTAG,
+4 −2
Original line number Diff line number Diff line
@@ -92,14 +92,16 @@ nsClipboard::SetNativeClipboardData(nsITransferable* aTransferable,
    return rv;
  }

  bool isPrivate = aTransferable->GetIsPrivateData();

  if (!html.IsEmpty() &&
      java::Clipboard::SetHTML(java::GeckoAppShell::GetApplicationContext(),
                               text, html)) {
                               text, html, isPrivate)) {
    return NS_OK;
  }
  if (!text.IsEmpty() &&
      java::Clipboard::SetText(java::GeckoAppShell::GetApplicationContext(),
                               text)) {
                               text, isPrivate)) {
    return NS_OK;
  }