Index: chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsService.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsService.java b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsService.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..74ca5cabbcf3211ecfe00d43a64d8584f192ff85 |
--- /dev/null |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsService.java |
@@ -0,0 +1,183 @@ |
+// Copyright 2017 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.browseractions; |
+ |
+import android.app.NotificationManager; |
+import android.app.PendingIntent; |
+import android.app.Service; |
+import android.content.Context; |
+import android.content.Intent; |
+import android.os.IBinder; |
+import android.text.TextUtils; |
+ |
+import org.chromium.base.ContextUtils; |
+import org.chromium.base.VisibleForTesting; |
+import org.chromium.chrome.R; |
+import org.chromium.chrome.browser.document.ChromeLauncherActivity; |
+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.NotificationUmaTracker; |
+import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions; |
+import org.chromium.chrome.browser.tab.Tab; |
+import org.chromium.chrome.browser.util.IntentUtils; |
+ |
+/** |
+ * Service responsible for creating background tabs and notifications for Browser Actions. |
+ */ |
+public class BrowserActionsService extends Service { |
+ public static final String ACTION_TAB_CREATION_START = |
+ "org.chromium.chrome.browser.browseractions.ACTION_TAB_CREATION_START"; |
+ public static final String ACTION_TAB_CREATION_UPDATE = |
+ "org.chromium.chrome.browser.browseractions.ACTION_TAB_CREATION_UPDATE"; |
+ public static final String ACTION_TAB_CREATION_FINISH = |
+ "org.chromium.chrome.browser.browseractions.ACTION_TAB_CREATION_FINISH"; |
+ public static final String EXTRA_TAB_ID = "org.chromium.chrome.browser.browseractions.TAB_ID"; |
+ |
+ /** |
+ * Action to request open ChromeTabbedActivity in tab switcher mode. |
+ */ |
+ public static final String ACTION_BROWSER_ACTIONS_OPEN_IN_BACKGROUND = |
+ "org.chromium.chrome.browser.browseractions.browser_action_open_in_background"; |
+ |
+ public static final String PREF_HAS_BROWSER_ACTIONS_NOTIFICATION = |
+ "org.chromium.chrome.browser.browseractions.HAS_BROWSER_ACTIONS_NOTIFICATION"; |
+ |
+ /** |
+ * Extra that indicates whether to show a Tab for single url or the tab switcher for |
+ * multiple urls. |
+ */ |
+ public static final String EXTRA_IS_SINGLE_URL = |
+ "org.chromium.chrome.browser.browseractions.is_single_url"; |
+ |
+ private static Intent sNotificationIntent; |
+ |
+ private int mTitleResId = R.string.browser_actions_single_link_open_notification_title; |
+ |
+ @Override |
+ public IBinder onBind(Intent intent) { |
+ return null; |
+ } |
+ |
+ @VisibleForTesting |
+ static Intent getNotificationIntent() { |
+ return sNotificationIntent; |
+ } |
+ |
+ @Override |
+ public int onStartCommand(Intent intent, int flags, int startId) { |
+ if (TextUtils.equals(intent.getAction(), ACTION_TAB_CREATION_START)) { |
+ sendBrowserActionsNotification(Tab.INVALID_TAB_ID); |
+ ContextUtils.getAppSharedPreferences() |
+ .edit() |
+ .putBoolean(PREF_HAS_BROWSER_ACTIONS_NOTIFICATION, true) |
+ .apply(); |
+ NotificationUmaTracker.getInstance().onNotificationShown( |
+ NotificationUmaTracker.BROWSER_ACTIONS, ChannelDefinitions.CHANNEL_ID_BROWSER); |
+ } else if (TextUtils.equals(intent.getAction(), ACTION_TAB_CREATION_UPDATE)) { |
+ int tabId = IntentUtils.safeGetIntExtra(intent, EXTRA_TAB_ID, Tab.INVALID_TAB_ID); |
+ sendBrowserActionsNotification(tabId); |
+ } else if (TextUtils.equals(intent.getAction(), ACTION_TAB_CREATION_FINISH)) { |
+ stopForeground(false); |
+ } |
+ // The service will not be restarted if Chrome get killed. |
+ return START_NOT_STICKY; |
+ } |
+ |
+ private void sendBrowserActionsNotification(int tabId) { |
+ ChromeNotificationBuilder builder = createNotificationBuilder(tabId); |
+ startForeground(NotificationConstants.NOTIFICATION_ID_BROWSER_ACTIONS, builder.build()); |
+ } |
+ |
+ private ChromeNotificationBuilder createNotificationBuilder(int tabId) { |
+ ChromeNotificationBuilder builder = |
+ NotificationBuilderFactory |
+ .createChromeNotificationBuilder( |
+ true /* preferCompat */, ChannelDefinitions.CHANNEL_ID_BROWSER) |
+ .setSmallIcon(R.drawable.infobar_chrome) |
+ .setLocalOnly(true) |
+ .setAutoCancel(true) |
+ .setContentText(this.getString(R.string.browser_actions_notification_text)); |
+ if (tabId == Tab.INVALID_TAB_ID) { |
+ mTitleResId = hasBrowserActionsNotification() |
+ ? R.string.browser_actions_multi_links_open_notification_title |
+ : R.string.browser_actions_single_link_open_notification_title; |
+ } |
+ builder.setContentTitle(this.getString(mTitleResId)); |
+ sNotificationIntent = buildNotificationIntent(tabId); |
+ PendingIntent notifyPendingIntent = PendingIntent.getActivity( |
+ this, 0, sNotificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); |
+ builder.setContentIntent(notifyPendingIntent); |
+ return builder; |
+ } |
+ |
+ private Intent buildNotificationIntent(int tabId) { |
+ boolean multipleUrls = hasBrowserActionsNotification(); |
+ if (!multipleUrls && tabId != Tab.INVALID_TAB_ID) { |
+ return Tab.createBringTabToFrontIntent(tabId); |
+ } |
+ Intent intent = new Intent(this, ChromeLauncherActivity.class); |
+ intent.setAction(ACTION_BROWSER_ACTIONS_OPEN_IN_BACKGROUND); |
+ intent.putExtra(EXTRA_IS_SINGLE_URL, !multipleUrls); |
+ return intent; |
+ } |
+ |
+ @VisibleForTesting |
+ static boolean hasBrowserActionsNotification() { |
+ return ContextUtils.getAppSharedPreferences().getBoolean( |
+ PREF_HAS_BROWSER_ACTIONS_NOTIFICATION, false); |
+ } |
+ |
+ /** |
+ * Cancel Browser Actions notification. |
+ */ |
+ public static void cancelBrowserActionsNotification() { |
+ NotificationManager notificationManager = |
+ (NotificationManager) ContextUtils.getApplicationContext().getSystemService( |
+ Context.NOTIFICATION_SERVICE); |
+ notificationManager.cancel(NotificationConstants.NOTIFICATION_ID_BROWSER_ACTIONS); |
+ ContextUtils.getAppSharedPreferences() |
+ .edit() |
+ .putBoolean(PREF_HAS_BROWSER_ACTIONS_NOTIFICATION, false) |
+ .apply(); |
+ } |
+ |
+ /** |
+ * Checks whether Chrome should display tab switcher via Browser Actions Intent. |
+ * @param intent The intent to open the Chrome. |
+ * @param isOverviewVisible Whether tab switcher is shown. |
+ */ |
+ public static boolean shouldToggleOverview(Intent intent, boolean isOverviewVisible) { |
+ boolean fromBrowserActions = isStartedByBrowserActions(intent); |
+ boolean isSingleUrl = IntentUtils.safeGetBooleanExtra(intent, EXTRA_IS_SINGLE_URL, false); |
+ if (fromBrowserActions) { |
+ return isSingleUrl == isOverviewVisible; |
+ } |
+ return false; |
+ } |
+ |
+ private static boolean isStartedByBrowserActions(Intent intent) { |
+ if (ACTION_BROWSER_ACTIONS_OPEN_IN_BACKGROUND.equals(intent.getAction())) { |
+ return true; |
+ } |
+ return false; |
+ } |
+ |
+ /** |
+ * Sends a {@link Intent} to update the notification and the status of the {@link |
+ * BrowserActionsService}. |
+ * @param action The actions of the Intent. |
+ * @param tabId The id of the created Tab. |
+ */ |
+ public static void sendIntent(String action, int tabId) { |
+ Context context = ContextUtils.getApplicationContext(); |
+ Intent intent = new Intent(context, BrowserActionsService.class); |
+ intent.setAction(action); |
+ if (tabId != Tab.INVALID_TAB_ID) { |
+ intent.putExtra(EXTRA_TAB_ID, tabId); |
+ } |
+ context.startService(intent); |
+ } |
+} |