Skip to content

Commit

Permalink
Handle incoming Shared Clipboard messages on Android.
Browse files Browse the repository at this point in the history
Bug: 992345
Change-Id: I825496fc0a0da3084f741c420a8abcea84e5daf6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1745473
Commit-Queue: Michael van Ouwerkerk <mvanouwerkerk@chromium.org>
Reviewed-by: Michael van Ouwerkerk <mvanouwerkerk@chromium.org>
Reviewed-by: Peter Beverloo <peter@chromium.org>
Reviewed-by: Theresa  <twellington@chromium.org>
Reviewed-by: Alexei Svitkine <asvitkine@chromium.org>
Reviewed-by: Richard Knoll <knollr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#686382}
  • Loading branch information
mvano authored and Commit Bot committed Aug 13, 2019
1 parent 3711362 commit e47e934
Show file tree
Hide file tree
Showing 20 changed files with 256 additions and 41 deletions.
1 change: 1 addition & 0 deletions chrome/android/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -2617,6 +2617,7 @@ generate_jni("chrome_jni_headers") {
"java/src/org/chromium/chrome/browser/sessions/SessionTabHelper.java",
"java/src/org/chromium/chrome/browser/sharing/SharingJNIBridge.java",
"java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallMessageHandler.java",
"java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardMessageHandler.java",
"java/src/org/chromium/chrome/browser/signin/IdentityServicesProvider.java",
"java/src/org/chromium/chrome/browser/signin/ProfileDownloader.java",
"java/src/org/chromium/chrome/browser/signin/SigninInvestigator.java",
Expand Down
2 changes: 2 additions & 0 deletions chrome/android/chrome_java_sources.gni
Original file line number Diff line number Diff line change
Expand Up @@ -1413,7 +1413,9 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/share/ShareHelper.java",
"java/src/org/chromium/chrome/browser/share/ShareMenuActionHandler.java",
"java/src/org/chromium/chrome/browser/share/ShareParams.java",
"java/src/org/chromium/chrome/browser/sharing/SharingNotificationUtil.java",
"java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallMessageHandler.java",
"java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardMessageHandler.java",
"java/src/org/chromium/chrome/browser/sharing/SharingJNIBridge.java",
"java/src/org/chromium/chrome/browser/signin/AccountPickerDialogFragment.java",
"java/src/org/chromium/chrome/browser/signin/IdentityServicesProvider.java",
Expand Down
2 changes: 2 additions & 0 deletions chrome/android/java/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1239,6 +1239,8 @@ android:value="true" />

<receiver android:name="org.chromium.chrome.browser.sharing.click_to_call.ClickToCallMessageHandler$TapReceiver"
android:exported="false"/>
<receiver android:name="org.chromium.chrome.browser.sharing.shared_clipboard.SharedClipboardMessageHandler$TapReceiver"
android:exported="false"/>

<receiver android:name="org.chromium.chrome.browser.offlinepages.prefetch.PrefetchedPagesNotifier$ClickReceiver"
android:exported="false"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1322,6 +1322,9 @@
<receiver
android:exported="false"
android:name="org.chromium.chrome.browser.sharing.click_to_call.ClickToCallMessageHandler$TapReceiver"/>
<receiver
android:exported="false"
android:name="org.chromium.chrome.browser.sharing.shared_clipboard.SharedClipboardMessageHandler$TapReceiver"/>
<receiver
android:exported="false"
android:name="org.chromium.chrome.browser.upgrade.PackageReplacedBroadcastReceiver">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ public class NotificationConstants {
*/
public static final int NOTIFICATION_ID_CLICK_TO_CALL = 9;

/**
* Unique identifier for Shared Clipboard notifications.
*/
public static final int NOTIFICATION_ID_SHARED_CLIPBOARD = 10;

/**
* Separator used to separate the notification origin from additional data such as the
* developer specified tag. This and the prefix following it need to be the same as the one
Expand All @@ -123,6 +128,7 @@ public class NotificationConstants {
public static final String GROUP_WEBAPK = "WebApk";
public static final String GROUP_SEND_TAB_TO_SELF = "SendTabToSelf";
public static final String GROUP_CLICK_TO_CALL = "ClickToCall";
public static final String GROUP_SHARED_CLIPBOARD = "SharedClipboard";

// Web notification group names are set dynamically as this prefix + notification origin.
// For example, 'Web:chromium.org' for a notification from chromium.org.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class NotificationUmaTracker {
SystemNotificationType.OFFLINE_CONTENT_SUGGESTION,
SystemNotificationType.TRUSTED_WEB_ACTIVITY_SITES, SystemNotificationType.OFFLINE_PAGES,
SystemNotificationType.SEND_TAB_TO_SELF, SystemNotificationType.UPDATES,
SystemNotificationType.CLICK_TO_CALL})
SystemNotificationType.CLICK_TO_CALL, SystemNotificationType.SHARED_CLIPBOARD})
@Retention(RetentionPolicy.SOURCE)
public @interface SystemNotificationType {
int UNKNOWN = -1;
Expand All @@ -71,8 +71,9 @@ public class NotificationUmaTracker {
int SEND_TAB_TO_SELF = 15;
int UPDATES = 16;
int CLICK_TO_CALL = 17;
int SHARED_CLIPBOARD = 18;

int NUM_ENTRIES = 18;
int NUM_ENTRIES = 19;
}

/*
Expand Down Expand Up @@ -176,6 +177,10 @@ public void onNotificationContentClick(@SystemNotificationType int type, long cr
recordNotificationAgeHistogram(
"Mobile.SystemNotification.Content.Click.Age.ClickToCall", createTime);
break;
case SystemNotificationType.SHARED_CLIPBOARD:
recordNotificationAgeHistogram(
"Mobile.SystemNotification.Content.Click.Age.SharedClipboard", createTime);
break;
}
}

Expand Down Expand Up @@ -204,6 +209,10 @@ public void onNotificationDismiss(@SystemNotificationType int type, long createT
recordNotificationAgeHistogram(
"Mobile.SystemNotification.Dismiss.Age.ClickToCall", createTime);
break;
case SystemNotificationType.SHARED_CLIPBOARD:
recordNotificationAgeHistogram(
"Mobile.SystemNotification.Dismiss.Age.SharedClipboard", createTime);
break;
}
}

Expand Down Expand Up @@ -234,6 +243,10 @@ public void onNotificationActionClick(@ActionType int actionType,
recordNotificationAgeHistogram(
"Mobile.SystemNotification.Action.Click.Age.ClickToCall", createTime);
break;
case SystemNotificationType.SHARED_CLIPBOARD:
recordNotificationAgeHistogram(
"Mobile.SystemNotification.Action.Click.Age.SharedClipboard", createTime);
break;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.sharing;

import android.app.Notification;
import android.content.Context;
import android.content.res.Resources;
import android.support.annotation.DrawableRes;
import android.support.v4.app.NotificationCompat;

import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.ContextUtils;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.notifications.ChromeNotification;
import org.chromium.chrome.browser.notifications.ChromeNotificationBuilder;
import org.chromium.chrome.browser.notifications.NotificationBuilderFactory;
import org.chromium.chrome.browser.notifications.NotificationManagerProxyImpl;
import org.chromium.chrome.browser.notifications.NotificationMetadata;
import org.chromium.chrome.browser.notifications.NotificationUmaTracker;
import org.chromium.chrome.browser.notifications.NotificationUmaTracker.SystemNotificationType;
import org.chromium.chrome.browser.notifications.PendingIntentProvider;
import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions;

/**
* Provides common functionality for handling sharing notifications.
*/
public final class SharingNotificationUtil {
/**
* Shows a notification with a configuration common to all sharing notifications.
*
* @param type The type of notification.
* @param group The notification group.
* @param id The notification id.
* @param contentIntent The notification content intent.
* @param contentTitle The notification title text.
* @param contentText The notification content text.
* @param smallIcon The small notification icon.
*/
public static void showNotification(@SystemNotificationType int type, String group, int id,
PendingIntentProvider contentIntent, String contentTitle, String contentText,
@DrawableRes int smallIcon) {
Context context = ContextUtils.getApplicationContext();
Resources resources = context.getResources();
ChromeNotificationBuilder builder =
NotificationBuilderFactory
.createChromeNotificationBuilder(/*preferCompat=*/true,
ChannelDefinitions.ChannelId.SHARING,
/*remoteAppPackageName=*/null,
new NotificationMetadata(type, group, id))
.setContentIntent(contentIntent)
.setContentTitle(contentTitle)
.setContentText(contentText)
.setColor(ApiCompatibilityUtils.getColor(
context.getResources(), R.color.default_icon_color_blue))
.setGroup(group)
.setPriorityBeforeO(NotificationCompat.PRIORITY_HIGH)
.setVibrate(new long[0])
.setSmallIcon(smallIcon)
.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_ALL);
ChromeNotification notification = builder.buildChromeNotification();

new NotificationManagerProxyImpl(context).notify(notification);
NotificationUmaTracker.getInstance().onNotificationShown(
type, notification.getNotification());
}

private SharingNotificationUtil() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,21 @@

package org.chromium.chrome.browser.sharing.click_to_call;

import android.app.Notification;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;
import android.text.TextUtils;

import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.ContextUtils;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.metrics.CachedMetrics;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.notifications.ChromeNotification;
import org.chromium.chrome.browser.notifications.ChromeNotificationBuilder;
import org.chromium.chrome.browser.notifications.NotificationBuilderFactory;
import org.chromium.chrome.browser.notifications.NotificationConstants;
import org.chromium.chrome.browser.notifications.NotificationManagerProxyImpl;
import org.chromium.chrome.browser.notifications.NotificationMetadata;
import org.chromium.chrome.browser.notifications.NotificationUmaTracker;
import org.chromium.chrome.browser.notifications.PendingIntentProvider;
import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions;
import org.chromium.chrome.browser.sharing.SharingNotificationUtil;

/**
* Manages ClickToCall related notifications for Android.
Expand Down Expand Up @@ -68,33 +59,11 @@ private static void showNotification(String phoneNumber) {
/*requestCode=*/0,
new Intent(context, TapReceiver.class).putExtra(EXTRA_PHONE_NUMBER, phoneNumber),
PendingIntent.FLAG_UPDATE_CURRENT);
Resources resources = context.getResources();
String text = resources.getString(R.string.click_to_call_notification_text);
ChromeNotificationBuilder builder =
NotificationBuilderFactory
.createChromeNotificationBuilder(/*preferCompat=*/true,
ChannelDefinitions.ChannelId.SHARING,
/*remoteAppPackageName=*/null,
new NotificationMetadata(
NotificationUmaTracker.SystemNotificationType.CLICK_TO_CALL,
NotificationConstants.GROUP_CLICK_TO_CALL,
NotificationConstants.NOTIFICATION_ID_CLICK_TO_CALL))
.setContentIntent(contentIntent)
.setContentTitle(phoneNumber)
.setContentText(text)
.setColor(ApiCompatibilityUtils.getColor(
context.getResources(), R.color.default_icon_color_blue))
.setGroup(NotificationConstants.GROUP_CLICK_TO_CALL)
.setPriorityBeforeO(NotificationCompat.PRIORITY_HIGH)
.setVibrate(new long[0])
.setSmallIcon(R.drawable.ic_phone_googblue_36dp)
.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_ALL);
ChromeNotification notification = builder.buildChromeNotification();

new NotificationManagerProxyImpl(context).notify(notification);
NotificationUmaTracker.getInstance().onNotificationShown(
SharingNotificationUtil.showNotification(
NotificationUmaTracker.SystemNotificationType.CLICK_TO_CALL,
notification.getNotification());
NotificationConstants.GROUP_CLICK_TO_CALL,
NotificationConstants.NOTIFICATION_ID_CLICK_TO_CALL, contentIntent, phoneNumber,
context.getResources().getString(R.string.click_to_call_notification_text),
R.drawable.ic_phone_googblue_36dp);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.sharing.shared_clipboard;

import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

import org.chromium.base.ContextUtils;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.notifications.NotificationConstants;
import org.chromium.chrome.browser.notifications.NotificationUmaTracker;
import org.chromium.chrome.browser.notifications.PendingIntentProvider;
import org.chromium.chrome.browser.sharing.SharingNotificationUtil;

/**
* Handles Shared Clipboard messages and notifications for Android.
*/
public class SharedClipboardMessageHandler {
/**
* Handles the tapping of a notification.
*/
public static final class TapReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO(mvanouwerkerk): handle this.
}
}

/**
* Displays a notification to tell the user that new clipboard contents have been received and
* written to the clipboard.
*/
@CalledByNative
private static void showNotification() {
// TODO(mvanouwerkerk): Set the correct small icon for the notification.
// TODO(mvanouwerkerk): Parameterize title text with machine name.
Context context = ContextUtils.getApplicationContext();
PendingIntentProvider contentIntent = PendingIntentProvider.getBroadcast(context,
/*requestCode=*/0, new Intent(context, TapReceiver.class),
PendingIntent.FLAG_UPDATE_CURRENT);
SharingNotificationUtil.showNotification(
NotificationUmaTracker.SystemNotificationType.SHARED_CLIPBOARD,
NotificationConstants.GROUP_SHARED_CLIPBOARD,
NotificationConstants.NOTIFICATION_ID_SHARED_CLIPBOARD, contentIntent,
context.getResources().getString(R.string.shared_clipboard_notification_title),
context.getResources().getString(R.string.shared_clipboard_notification_text),
R.drawable.ic_phone_googblue_36dp);
}
}
8 changes: 8 additions & 0 deletions chrome/android/java/strings/android_chrome_strings.grd
Original file line number Diff line number Diff line change
Expand Up @@ -3846,6 +3846,14 @@ The site does NOT gain access to the camera. The camera images are only visible
Tap to make call
</message>

<!-- Shared Clipboard -->
<message name="IDS_SHARED_CLIPBOARD_NOTIFICATION_TITLE" desc="Title text displayed in a shared clipboard notification.">
Text shared from other device
</message>
<message name="IDS_SHARED_CLIPBOARD_NOTIFICATION_TEXT" desc="Content text displayed in a shared clipboard notification.">
Copied to your clipboard
</message>

<!-- Chrome Duet -->
<message name="IDS_IPH_DUET_TITLE" desc="This string appears in an overlay that explains a new UI to users. 'Search' refers to searching the web, and 'explore' refers to Chrome's suggested content.">
Search &amp; explore
Expand Down
2 changes: 2 additions & 0 deletions chrome/browser/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -1564,6 +1564,8 @@ jumbo_split_static_library("browser") {
"sharing/ping_message_handler.h",
"sharing/shared_clipboard/feature_flags.cc",
"sharing/shared_clipboard/feature_flags.h",
"sharing/shared_clipboard/shared_clipboard_message_handler_android.cc",
"sharing/shared_clipboard/shared_clipboard_message_handler_android.h",
"sharing/sharing_constants.cc",
"sharing/sharing_constants.h",
"sharing/sharing_device_info.cc",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/sharing/shared_clipboard/shared_clipboard_message_handler_android.h"

#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/android/chrome_jni_headers/SharedClipboardMessageHandler_jni.h"
#include "chrome/browser/sharing/proto/shared_clipboard_message.pb.h"
#include "chrome/browser/sharing/proto/sharing_message.pb.h"
#include "ui/base/clipboard/clipboard_types.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"

SharedClipboardMessageHandler::SharedClipboardMessageHandler() = default;

SharedClipboardMessageHandler::~SharedClipboardMessageHandler() = default;

void SharedClipboardMessageHandler::OnMessage(
const chrome_browser_sharing::SharingMessage& message) {
DCHECK(message.has_shared_clipboard_message());

ui::ScopedClipboardWriter(ui::ClipboardType::kCopyPaste)
.WriteText(base::UTF8ToUTF16(message.shared_clipboard_message().text()));

JNIEnv* env = base::android::AttachCurrentThread();
Java_SharedClipboardMessageHandler_showNotification(env);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_SHARING_SHARED_CLIPBOARD_SHARED_CLIPBOARD_MESSAGE_HANDLER_ANDROID_H_
#define CHROME_BROWSER_SHARING_SHARED_CLIPBOARD_SHARED_CLIPBOARD_MESSAGE_HANDLER_ANDROID_H_

#include "base/macros.h"
#include "chrome/browser/sharing/sharing_message_handler.h"

// Handles incoming messages for the shared clipboard feature.
class SharedClipboardMessageHandler : public SharingMessageHandler {
public:
SharedClipboardMessageHandler();
~SharedClipboardMessageHandler() override;

// SharingMessageHandler implementation:
void OnMessage(
const chrome_browser_sharing::SharingMessage& message) override;

private:
DISALLOW_COPY_AND_ASSIGN(SharedClipboardMessageHandler);
};

#endif // CHROME_BROWSER_SHARING_SHARED_CLIPBOARD_SHARED_CLIPBOARD_MESSAGE_HANDLER_ANDROID_H_

0 comments on commit e47e934

Please sign in to comment.