Bug 1129433 - Show "# tabs opened in background" notification in system tray (r=mcomella)
authorMartyn Haigh <martyn.haigh@gmail.com>
Fri, 20 Mar 2015 13:42:09 +0000
changeset 263453 4e033cac2931ca8425706701424afccbe09e4aad
parent 263452 62b25fdb0b790d4631a1c434463340590befcf52
child 263454 e807296e0ae23c53f2600ae497b12df02a571edd
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmcomella
bugs1129433
milestone39.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1129433 - Show &quot;# tabs opened in background&quot; notification in system tray (r=mcomella)
mobile/android/base/locales/en-US/android_strings.dtd
mobile/android/base/resources/values/ids.xml
mobile/android/base/strings.xml.in
mobile/android/base/tabqueue/TabQueueHelper.java
mobile/android/base/tabqueue/TabQueueService.java
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -181,16 +181,30 @@
 
 <!ENTITY pref_tracking_protection_title "Tracking protection">
 <!ENTITY pref_tracking_protection_summary "&brandShortName; will prevent sites from tracking you">
 <!ENTITY pref_donottrack_title "Do not track">
 <!ENTITY pref_donottrack_summary "&brandShortName; will tell sites that you do not want to be tracked">
 
 <!ENTITY tab_queue_toast_message "Open later">
 <!ENTITY tab_queue_toast_action "Open now">
+<!-- Localization note (tab_queue_notification_text_plural) : The
+     formatD is replaced with the number of tabs queued.  The
+     number of tabs queued is always more than one.  We can't use
+     Android plural forms, sadly. See Bug #753859. -->
+<!ENTITY tab_queue_notification_text_plural "&formatD; tabs queued">
+<!-- Localization note (tab_queue_notification_title_plural) : This is the
+     title of a notification; we expect more than one tab queued. -->
+<!ENTITY tab_queue_notification_title_plural "Tabs Queued">
+<!-- Localization note (tab_queue_notification_title_singular) : This is the
+     title of a notification; we expect only one tab queued. -->
+<!ENTITY tab_queue_notification_title_singular "Tab Queued">
+<!-- Localization note (tab_queue_notification_text_singular) : This is the
+     text of a notification; we expect only one tab queued. -->
+<!ENTITY tab_queue_notification_text_singular "1 tab queued">
 
 <!ENTITY pref_char_encoding "Character encoding">
 <!ENTITY pref_char_encoding_on "Show menu">
 <!ENTITY pref_char_encoding_off "Don\'t show menu">
 <!ENTITY pref_clear_private_data2 "Clear now">
 <!ENTITY pref_clear_private_data_category "Clear private data">
 <!ENTITY pref_clear_on_exit_title2 "Clear on exit">
 <!ENTITY pref_clear_on_exit_summary2 "&brandShortName; will automatically clear your data whenever you select \u0022Quit\u0022 from the main menu">
--- a/mobile/android/base/resources/values/ids.xml
+++ b/mobile/android/base/resources/values/ids.xml
@@ -1,12 +1,13 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 <resources>
 
+    <item type="id" name="tabQueueNotification"/>
     <item type="id" name="guestNotification"/>
     <item type="id" name="original_height"/>
     <item type="id" name="menu_items"/>
 
 </resources>
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -236,16 +236,20 @@
   <string name="pref_update_autodownload_disabled">&pref_update_autodownload_never;</string>
   <string name="pref_update_autodownload_enabled">&pref_update_autodownload_always;</string>
 
   <string name="pref_tab_queue_title">&pref_tab_queue_title;</string>
   <string name="pref_tab_queue_summary">&pref_tab_queue_summary;</string>
 
   <string name="tab_queue_toast_message">&tab_queue_toast_message;</string>
   <string name="tab_queue_toast_action">&tab_queue_toast_action;</string>
+  <string name="tab_queue_notification_text_singular">&tab_queue_notification_text_singular;</string>
+  <string name="tab_queue_notification_text_plural">&tab_queue_notification_text_plural;</string>
+  <string name="tab_queue_notification_title_singular">&tab_queue_notification_title_singular;</string>
+  <string name="tab_queue_notification_title_plural">&tab_queue_notification_title_plural;</string>
 
   <string name="pref_about_firefox">&pref_about_firefox;</string>
   <string name="pref_vendor_faqs">&pref_vendor_faqs;</string>
   <string name="pref_vendor_feedback">&pref_vendor_feedback;</string>
 
   <string name="pref_dialog_set_default">&pref_dialog_set_default;</string>
   <string name="pref_default">&pref_dialog_default;</string>
   <string name="pref_dialog_remove">&pref_dialog_remove;</string>
--- a/mobile/android/base/tabqueue/TabQueueHelper.java
+++ b/mobile/android/base/tabqueue/TabQueueHelper.java
@@ -1,40 +1,80 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.tabqueue;
 
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.support.v4.app.NotificationCompat;
+import org.json.JSONArray;
+import org.mozilla.gecko.BrowserApp;
 import org.mozilla.gecko.GeckoProfile;
+import org.mozilla.gecko.R;
 import org.mozilla.gecko.util.ThreadUtils;
 
-import android.text.TextUtils;
-import android.util.Log;
-import org.json.JSONArray;
-import org.json.JSONException;
-
-import java.io.IOException;
-
 public class TabQueueHelper {
     private static final String LOGTAG = "Gecko" + TabQueueHelper.class.getSimpleName();
 
     public static final String FILE_NAME = "tab_queue_url_list.json";
+    public static final String LOAD_URLS_ACTION = "TAB_QUEUE_LOAD_URLS_ACTION";
+    public static final int TAB_QUEUE_NOTIFICATION_ID = R.id.tabQueueNotification;
 
     /**
      * Reads file and converts any content to JSON, adds passed in URL to the data and writes back to the file,
      * creating the file if it doesn't already exist.  This should not be run on the UI thread.
      *
      * @param profile
      * @param url      URL to add
      * @param filename filename to add URL to
+     * @return the number of tabs currently queued
      */
-    public static void queueURL(final GeckoProfile profile, final String url, final String filename) {
+    public static int queueURL(final GeckoProfile profile, final String url, final String filename) {
         ThreadUtils.assertNotOnUiThread();
 
         JSONArray jsonArray = profile.readJSONArrayFromFile(filename);
 
         jsonArray.put(url);
 
         profile.writeFile(filename, jsonArray.toString());
+
+        return jsonArray.length();
+    }
+
+    /**
+     * Displays a notification showing the total number of tabs queue.  If there is already a notification displayed, it
+     * will be replaced.
+     *
+     * @param context
+     * @param tabsQueued
+     */
+    static public void showNotification(Context context, int tabsQueued) {
+        Intent resultIntent = new Intent(context, BrowserApp.class);
+        resultIntent.setAction(TabQueueHelper.LOAD_URLS_ACTION);
+
+        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, resultIntent, PendingIntent.FLAG_CANCEL_CURRENT);
+
+        String title, text;
+        final Resources resources = context.getResources();
+        if(tabsQueued == 1) {
+            title = resources.getString(R.string.tab_queue_notification_title_singular);
+            text = resources.getString(R.string.tab_queue_notification_text_singular);
+        } else {
+            title = resources.getString(R.string.tab_queue_notification_title_plural);
+            text = resources.getString(R.string.tab_queue_notification_text_plural, tabsQueued);
+        }
+
+        NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
+                                                                   .setSmallIcon(R.drawable.ic_status_logo)
+                                                                   .setContentTitle(title)
+                                                                   .setContentText(text)
+                                                                   .setContentIntent(pendingIntent);
+
+        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+        notificationManager.notify(TabQueueHelper.TAB_QUEUE_NOTIFICATION_ID, builder.build());
     }
 }
\ No newline at end of file
--- a/mobile/android/base/tabqueue/TabQueueService.java
+++ b/mobile/android/base/tabqueue/TabQueueService.java
@@ -1,16 +1,17 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.tabqueue;
 
 import android.app.Service;
+import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
 import android.graphics.PixelFormat;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
 import android.util.Log;
 import android.view.Gravity;
@@ -155,18 +156,20 @@ public class TabQueueService extends Ser
         }
         final ContextUtils.SafeIntent safeIntent = new ContextUtils.SafeIntent(intent);
         final String intentData = safeIntent.getDataString();
 
         // As we're doing disk IO, let's run this stuff in a separate thread.
         executorService.submit(new Runnable() {
             @Override
             public void run() {
-                final GeckoProfile profile = GeckoProfile.get(getApplicationContext());
-                TabQueueHelper.queueURL(profile, intentData, filename);
+                Context applicationContext = getApplicationContext();
+                final GeckoProfile profile = GeckoProfile.get(applicationContext);
+                int tabsQueued = TabQueueHelper.queueURL(profile, intentData, filename);
+                TabQueueHelper.showNotification(applicationContext, tabsQueued);
             }
         });
     }
 
     @Override
     public void onDestroy() {
         super.onDestroy();
         tabQueueHandler = null;