Bug 1241810 - Bug 1247788 - Add "Notifications" in Settings. r?mcomella draft
authorSebastian Kaspari <s.kaspari@gmail.com>
Thu, 25 Feb 2016 16:16:57 -0800
changeset 335184 eec101d5d4d2172f81e71e1d23b936a928fae3ec
parent 335183 7defe5ecb9fd261a00709e3cc903e8214f173a5b
child 335185 7b4ca1b673522735b428ed8b539935f0bbe1be86
push id11746
push users.kaspari@gmail.com
push dateSat, 27 Feb 2016 23:17:50 +0000
reviewersmcomella
bugs1241810, 1247788
milestone47.0a1
Bug 1241810 - Bug 1247788 - Add "Notifications" in Settings. r?mcomella MozReview-Commit-ID: girmjH2J7Q
mobile/android/base/java/org/mozilla/gecko/feeds/FeedService.java
mobile/android/base/java/org/mozilla/gecko/feeds/action/BaseAction.java
mobile/android/base/java/org/mozilla/gecko/feeds/action/CheckAction.java
mobile/android/base/java/org/mozilla/gecko/feeds/action/EnrollAction.java
mobile/android/base/java/org/mozilla/gecko/feeds/action/SetupAction.java
mobile/android/base/java/org/mozilla/gecko/feeds/action/SubscribeAction.java
mobile/android/base/java/org/mozilla/gecko/feeds/action/WithdrawAction.java
mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java
mobile/android/base/locales/en-US/android_strings.dtd
mobile/android/base/resources/xml-v11/preference_headers.xml
mobile/android/base/resources/xml-v11/preferences.xml
mobile/android/base/resources/xml/preference_headers.xml
mobile/android/base/resources/xml/preferences.xml
mobile/android/base/resources/xml/preferences_notifications.xml
mobile/android/base/strings.xml.in
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/FeedService.java
+++ b/mobile/android/base/java/org/mozilla/gecko/feeds/FeedService.java
@@ -11,23 +11,25 @@ import android.content.Intent;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.support.v4.net.ConnectivityManagerCompat;
 import android.util.Log;
 
 import com.keepsafe.switchboard.SwitchBoard;
 
 import org.mozilla.gecko.AppConstants;
+import org.mozilla.gecko.GeckoSharedPrefs;
 import org.mozilla.gecko.feeds.action.BaseAction;
 import org.mozilla.gecko.feeds.action.CheckAction;
 import org.mozilla.gecko.feeds.action.EnrollAction;
 import org.mozilla.gecko.feeds.action.SetupAction;
 import org.mozilla.gecko.feeds.action.SubscribeAction;
 import org.mozilla.gecko.feeds.action.WithdrawAction;
 import org.mozilla.gecko.feeds.subscriptions.SubscriptionStorage;
+import org.mozilla.gecko.preferences.GeckoPreferences;
 import org.mozilla.gecko.util.Experiments;
 
 /**
  * Background service for subscribing to and checking website feeds to notify the user about updates.
  */
 public class FeedService extends IntentService {
     private static final String LOGTAG = "GeckoFeedService";
 
@@ -69,16 +71,21 @@ public class FeedService extends IntentS
         try {
             if (!SwitchBoard.isInExperiment(this, Experiments.CONTENT_NOTIFICATIONS)) {
                 Log.d(LOGTAG, "Not in content notifications experiment. Skipping.");
                 return;
             }
 
             BaseAction action = createActionForIntent(intent);
 
+            if (action.requiresPreferenceEnabled() && !isPreferenceEnabled()) {
+                Log.d(LOGTAG, "Preference is disabled. Skipping.");
+                return;
+            }
+
             if (action.requiresNetwork() && !isConnectedToUnmeteredNetwork()) {
                 // For now just skip if we are not connected or the network is metered. We do not want
                 // to use precious mobile traffic.
                 Log.d(LOGTAG, "Not connected to a network or network is metered. Skipping.");
                 return;
             }
 
             action.perform(intent);
@@ -120,9 +127,13 @@ public class FeedService extends IntentS
         ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
         NetworkInfo networkInfo = manager.getActiveNetworkInfo();
         if (networkInfo == null || !networkInfo.isConnected()) {
             return false;
         }
 
         return !ConnectivityManagerCompat.isActiveNetworkMetered(manager);
     }
+
+    private boolean isPreferenceEnabled() {
+        return GeckoSharedPrefs.forApp(this).getBoolean(GeckoPreferences.PREFS_NOTIFICATIONS_CONTENT, true);
+    }
 }
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/action/BaseAction.java
+++ b/mobile/android/base/java/org/mozilla/gecko/feeds/action/BaseAction.java
@@ -6,9 +6,10 @@
 package org.mozilla.gecko.feeds.action;
 
 import android.content.Intent;
 
 public interface BaseAction {
     void perform(Intent intent);
 
     boolean requiresNetwork();
+    boolean requiresPreferenceEnabled();
 }
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/action/CheckAction.java
+++ b/mobile/android/base/java/org/mozilla/gecko/feeds/action/CheckAction.java
@@ -145,9 +145,14 @@ public class CheckAction implements Base
                 subscription.getLastModified()
         );
     }
 
     @Override
     public boolean requiresNetwork() {
         return true;
     }
+
+    @Override
+    public boolean requiresPreferenceEnabled() {
+        return true;
+    }
 }
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/action/EnrollAction.java
+++ b/mobile/android/base/java/org/mozilla/gecko/feeds/action/EnrollAction.java
@@ -46,16 +46,21 @@ public class EnrollAction implements Bas
         }
     }
 
     @Override
     public boolean requiresNetwork() {
         return false;
     }
 
+    @Override
+    public boolean requiresPreferenceEnabled() {
+        return true;
+    }
+
     private void searchFor(BrowserDB db, KnownSite knownSite) {
         Cursor cursor = db.getBookmarksForPartialUrl(context.getContentResolver(), "://" + knownSite.getSearchDomain() + "/");
         if (cursor == null) {
             Log.d(LOGTAG, "Nothing found");
             return;
         }
 
         try {
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/action/SetupAction.java
+++ b/mobile/android/base/java/org/mozilla/gecko/feeds/action/SetupAction.java
@@ -35,16 +35,21 @@ public class SetupAction implements Base
         scheduleAlarms(alarmManager);
     }
 
     @Override
     public boolean requiresNetwork() {
         return false;
     }
 
+    @Override
+    public boolean requiresPreferenceEnabled() {
+        return false;
+    }
+
     private void cancelPreviousAlarms(AlarmManager alarmManager) {
         final PendingIntent withdrawIntent = withdrawPendingIntent();
         alarmManager.cancel(withdrawIntent);
 
         final PendingIntent enrollIntent = enrollPendingIntent();
         alarmManager.cancel(enrollIntent);
 
         final PendingIntent checkIntent = checkPendingIntent();
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/action/SubscribeAction.java
+++ b/mobile/android/base/java/org/mozilla/gecko/feeds/action/SubscribeAction.java
@@ -48,16 +48,21 @@ public class SubscribeAction implements 
         subscribe(guid, feedUrl);
     }
 
     @Override
     public boolean requiresNetwork() {
         return true;
     }
 
+    @Override
+    public boolean requiresPreferenceEnabled() {
+        return true;
+    }
+
     private void subscribe(String guid, String feedUrl) {
         FeedFetcher.FeedResponse response = FeedFetcher.fetchAndParseFeed(feedUrl);
         if (response == null) {
             Log.w(LOGTAG, String.format("Could not fetch feed (%s). Not subscribing for now.", feedUrl));
             return;
         }
 
         Log.d(LOGTAG, "Subscribing to feed: " + response.feed.getTitle());
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/action/WithdrawAction.java
+++ b/mobile/android/base/java/org/mozilla/gecko/feeds/action/WithdrawAction.java
@@ -45,14 +45,19 @@ public class WithdrawAction implements B
         }
     }
 
     @Override
     public boolean requiresNetwork() {
         return false;
     }
 
+    @Override
+    public boolean requiresPreferenceEnabled() {
+        return true;
+    }
+
     private void unsubscribe(FeedSubscription subscription) {
         Log.d(LOGTAG, "Unsubscribing from: (" + subscription.getBookmarkGUID() + ") " + subscription.getFeedUrl());
 
         storage.removeSubscription(subscription);
     }
 }
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java
+++ b/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java
@@ -26,23 +26,25 @@ import org.mozilla.gecko.PrefsHelper;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.Restrictions;
 import org.mozilla.gecko.SnackbarHelper;
 import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.gecko.TelemetryContract.Method;
 import org.mozilla.gecko.background.common.GlobalConstants;
 import org.mozilla.gecko.db.BrowserContract.SuggestedSites;
+import org.mozilla.gecko.feeds.FeedService;
 import org.mozilla.gecko.permissions.Permissions;
 import org.mozilla.gecko.restrictions.Restrictable;
 import org.mozilla.gecko.tabqueue.TabQueueHelper;
 import org.mozilla.gecko.tabqueue.TabQueuePrompt;
 import org.mozilla.gecko.updater.UpdateService;
 import org.mozilla.gecko.updater.UpdateServiceHelper;
 import org.mozilla.gecko.util.EventCallback;
+import org.mozilla.gecko.util.Experiments;
 import org.mozilla.gecko.util.GeckoEventListener;
 import org.mozilla.gecko.util.HardwareUtils;
 import org.mozilla.gecko.util.InputOptionsUtils;
 import org.mozilla.gecko.util.NativeEventListener;
 import org.mozilla.gecko.util.NativeJSObject;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import android.annotation.TargetApi;
@@ -82,16 +84,18 @@ import android.util.Log;
 import android.view.MenuItem;
 import android.view.View;
 import android.widget.AdapterView;
 import android.widget.EditText;
 import android.widget.LinearLayout;
 import android.widget.ListAdapter;
 import android.widget.ListView;
 
+import com.keepsafe.switchboard.SwitchBoard;
+
 import org.json.JSONObject;
 
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -147,16 +151,17 @@ OnSharedPreferenceChangeListener
     private static final String PREFS_TRACKING_PROTECTION_LEARN_MORE = NON_PREF_PREFIX + "trackingprotection.learn_more";
     private static final String PREFS_CLEAR_PRIVATE_DATA = NON_PREF_PREFIX + "privacy.clear";
     private static final String PREFS_CLEAR_PRIVATE_DATA_EXIT = NON_PREF_PREFIX + "history.clear_on_exit";
     private static final String PREFS_SCREEN_ADVANCED = NON_PREF_PREFIX + "advanced_screen";
     public static final String PREFS_HOMEPAGE = NON_PREF_PREFIX + "homepage";
     public static final String PREFS_HISTORY_SAVED_SEARCH = NON_PREF_PREFIX + "search.search_history.enabled";
     private static final String PREFS_FAQ_LINK = NON_PREF_PREFIX + "faq.link";
     private static final String PREFS_FEEDBACK_LINK = NON_PREF_PREFIX + "feedback.link";
+    public static final String PREFS_NOTIFICATIONS_CONTENT = NON_PREF_PREFIX + "notifications.content";
 
     private static final String ACTION_STUMBLER_UPLOAD_PREF = AppConstants.ANDROID_PACKAGE_NAME + ".STUMBLER_PREF";
 
 
     // This isn't a Gecko pref, even if it looks like one.
     private static final String PREFS_BROWSER_LOCALE = "locale";
 
     public static final String PREFS_RESTORE_SESSION = NON_PREF_PREFIX + "restoreSession3";
@@ -907,16 +912,22 @@ OnSharedPreferenceChangeListener
                         }
                     });
                 } else if (PREFS_DYNAMIC_TOOLBAR.equals(key)) {
                     if (DynamicToolbar.isForceDisabled()) {
                         preferences.removePreference(pref);
                         i--;
                         continue;
                     }
+                } else if (PREFS_NOTIFICATIONS_CONTENT.equals(key)) {
+                    if (!SwitchBoard.isInExperiment(this, Experiments.CONTENT_NOTIFICATIONS)) {
+                        preferences.removePreference(pref);
+                        i--;
+                        continue;
+                    }
                 }
 
                 // Some Preference UI elements are not actually preferences,
                 // but they require a key to work correctly. For example,
                 // "Clear private data" requires a key for its state to be
                 // saved when the orientation changes. It uses the
                 // "android.not_a_preference.privacy.clear" key - which doesn't
                 // exist in Gecko - to satisfy this requirement.
@@ -1256,16 +1267,18 @@ OnSharedPreferenceChangeListener
                 return true;
             }
         } else if (PREFS_TAB_QUEUE.equals(prefName)) {
             if ((Boolean) newValue && !TabQueueHelper.canDrawOverlays(this)) {
                 Intent promptIntent = new Intent(this, TabQueuePrompt.class);
                 startActivityForResult(promptIntent, REQUEST_CODE_TAB_QUEUE);
                 return false;
             }
+        } else if (PREFS_NOTIFICATIONS_CONTENT.equals(prefName)) {
+            FeedService.setup(this);
         } else if (handlers.containsKey(prefName)) {
             PrefHandler handler = handlers.get(prefName);
             handler.onChange(this, preference, newValue);
         }
 
         // Send Gecko-side pref changes to Gecko
         if (isGeckoPref(prefName)) {
             PrefsHelper.setPref(prefName, newValue, true /* flush */);
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -166,16 +166,19 @@
 <!-- Localization note (pref_search_hint) : "TIP" as in "hint", "clue" etc. Displayed as an
      advisory message on the customise search providers settings page explaining how to add new
      search providers.
      The &formatI; in the string will be replaced by a small image of the icon described, and can be moved to wherever
      it is applicable. -->
 <!ENTITY pref_search_hint "TIP: Add any website to your list of search providers by long-pressing on its search field and then tapping the &formatI; icon.">
 <!ENTITY pref_category_advanced "Advanced">
 <!ENTITY pref_category_advanced_summary2 "Restore tabs, plugins, developer tools">
+<!ENTITY pref_category_notifications "Notifications">
+<!ENTITY pref_content_notifications "Website updates">
+<!ENTITY pref_content_notifications_summary "Allow notifications for supported sites">
 <!ENTITY pref_developer_remotedebugging "Remote debugging">
 <!ENTITY pref_developer_remotedebugging_usb "Remote debugging via USB">
 <!ENTITY pref_developer_remotedebugging_wifi "Remote debugging via Wi-Fi">
 <!ENTITY pref_developer_remotedebugging_wifi_disabled_summary "Wi-Fi debugging requires your device to have a QR code reader app installed.">
 <!ENTITY pref_remember_signons2 "Remember logins">
 <!ENTITY pref_manage_logins "Manage logins">
 
 <!ENTITY pref_category_home "Home">
@@ -211,16 +214,17 @@
      text field. -->
 <!ENTITY home_homepage_hint_user_address "Enter address or search term">
 
 <!-- Localization note: These are shown in the left sidebar on tablets -->
 <!ENTITY pref_header_general "General">
 <!ENTITY pref_header_search "Search">
 <!ENTITY pref_header_privacy_short "Privacy">
 <!ENTITY pref_header_accessibility "Accessibility">
+<!ENTITY pref_header_notifications "Notifications">
 <!ENTITY pref_header_advanced "Advanced">
 <!ENTITY pref_header_help "Help">
 <!ENTITY pref_header_vendor "&vendorShortName;">
 
 <!ENTITY pref_cookies_menu "Cookies">
 <!ENTITY pref_cookies_accept_all "Enabled">
 <!ENTITY pref_cookies_not_accept_foreign "Enabled, excluding 3rd party">
 <!ENTITY pref_cookies_disabled "Disabled">
--- a/mobile/android/base/resources/xml-v11/preference_headers.xml
+++ b/mobile/android/base/resources/xml-v11/preference_headers.xml
@@ -33,16 +33,23 @@
     <header android:fragment="org.mozilla.gecko.preferences.GeckoPreferenceFragment"
             android:title="@string/pref_header_accessibility"
             android:id="@+id/pref_header_accessibility">
         <extra android:name="resource"
                android:value="preferences_accessibility"/>
     </header>
 
     <header android:fragment="org.mozilla.gecko.preferences.GeckoPreferenceFragment"
+        android:title="@string/pref_header_notifications"
+        android:id="@+id/pref_header_notifications">
+        <extra android:name="resource"
+            android:value="preferences_notifications"/>
+    </header>
+
+    <header android:fragment="org.mozilla.gecko.preferences.GeckoPreferenceFragment"
             android:title="@string/pref_header_advanced"
             android:id="@+id/pref_header_advanced">
         <extra android:name="resource"
                android:value="preferences_advanced"/>
     </header>
 
     <header android:fragment="org.mozilla.gecko.preferences.GeckoPreferenceFragment"
         android:title="@string/pref_clear_private_data_now"
--- a/mobile/android/base/resources/xml-v11/preferences.xml
+++ b/mobile/android/base/resources/xml-v11/preferences.xml
@@ -42,16 +42,22 @@
 
     <PreferenceScreen android:title="@string/pref_category_accessibility"
                       android:summary="@string/pref_category_accessibility_summary"
                       android:fragment="org.mozilla.gecko.preferences.GeckoPreferenceFragment" >
         <extra android:name="resource"
                android:value="preferences_accessibility" />
     </PreferenceScreen>
 
+    <PreferenceScreen android:title="@string/pref_category_notifications"
+        android:fragment="org.mozilla.gecko.preferences.GeckoPreferenceFragment">
+        <extra android:name="resource"
+            android:value="preferences_notifications"/>
+    </PreferenceScreen>
+
     <PreferenceScreen android:title="@string/pref_category_advanced"
                       android:summary="@string/pref_category_advanced_summary"
                       android:fragment="org.mozilla.gecko.preferences.GeckoPreferenceFragment"
                       android:key="android.not_a_preference.advanced_screen" >
         <extra android:name="resource"
                android:value="preferences_advanced"/>
     </PreferenceScreen>
 
--- a/mobile/android/base/resources/xml/preference_headers.xml
+++ b/mobile/android/base/resources/xml/preference_headers.xml
@@ -6,16 +6,19 @@
 <!-- This file is a stub to allow IDs to be used in code
      even for a version-limited build. -->
 
 <preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
     <header android:fragment="org.mozilla.gecko.preferences.GeckoPreferenceFragment"
             android:id="@+id/pref_header_search">
     </header>
     <header android:fragment="org.mozilla.gecko.preferences.GeckoPreferenceFragment"
+            android:id="@+id/pref_header_notifications">
+    </header>
+    <header android:fragment="org.mozilla.gecko.preferences.GeckoPreferenceFragment"
             android:id="@+id/pref_header_advanced">
     </header>
     <header android:fragment="org.mozilla.gecko.preferences.GeckoPreferenceFragment"
             android:id="@+id/pref_header_accessibility">
     </header>
     <header android:fragment="org.mozilla.gecko.preferences.GeckoPreferenceFragment"
             android:id="@+id/pref_header_clear_private_data">
     </header>
--- a/mobile/android/base/resources/xml/preferences.xml
+++ b/mobile/android/base/resources/xml/preferences.xml
@@ -58,16 +58,26 @@
                 android:targetPackage="@string/android_package_name"
                 android:targetClass="org.mozilla.gecko.preferences.GeckoPreferences" >
             <extra
                     android:name="resource"
                     android:value="preferences_accessibility" />
         </intent>
     </PreferenceScreen>
 
+    <PreferenceScreen android:title="@string/pref_category_notifications">
+        <intent android:action="android.intent.action.VIEW"
+            android:targetPackage="@string/android_package_name"
+            android:targetClass="org.mozilla.gecko.preferences.GeckoPreferences" >
+            <extra
+                android:name="resource"
+                android:value="preferences_notifications" />
+        </intent>
+    </PreferenceScreen>
+
     <PreferenceScreen android:title="@string/pref_category_advanced"
                       android:summary="@string/pref_category_advanced_summary"
                       android:key="android.not_a_preference.advanced.enabled" >
         <intent android:action="android.intent.action.VIEW"
                 android:targetPackage="@string/android_package_name"
                 android:targetClass="org.mozilla.gecko.preferences.GeckoPreferences" >
             <extra
                     android:name="resource"
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/xml/preferences_notifications.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+    <CheckBoxPreference android:key="android.not_a_preference.notifications.content"
+        android:title="@string/pref_content_notifications"
+        android:summary="@string/pref_content_notifications_summary"
+        android:defaultValue="true" />
+</PreferenceScreen>
\ No newline at end of file
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -168,16 +168,20 @@
 
   <string name="pref_category_advanced">&pref_category_advanced;</string>
   <string name="pref_category_advanced_summary">&pref_category_advanced_summary2;</string>
   <string name="pref_developer_remotedebugging">&pref_developer_remotedebugging;</string>
   <string name="pref_developer_remotedebugging_usb">&pref_developer_remotedebugging_usb;</string>
   <string name="pref_developer_remotedebugging_wifi">&pref_developer_remotedebugging_wifi;</string>
   <string name="pref_developer_remotedebugging_wifi_disabled_summary">&pref_developer_remotedebugging_wifi_disabled_summary;</string>
 
+  <string name="pref_category_notifications">&pref_category_notifications;</string>
+  <string name="pref_content_notifications">&pref_content_notifications;</string>
+  <string name="pref_content_notifications_summary">&pref_content_notifications_summary;</string>
+
   <string name="pref_category_home">&pref_category_home;</string>
   <string name="pref_category_home_summary">&pref_category_home_summary;</string>
   <string name="pref_category_home_panels">&pref_category_home_panels;</string>
   <string name="home_add_panel_title">&home_add_panel_title;</string>
   <string name="home_add_panel_empty">&home_add_panel_empty;</string>
   <string name="home_add_panel_installed">&home_add_panel_installed;</string>
   <string name="pref_category_home_content_settings">&pref_category_home_content_settings;</string>
   <string name="pref_home_updates">&pref_home_updates;</string>
@@ -190,16 +194,17 @@
   <string name="home_homepage_radio_default">&home_homepage_radio_default;</string>
   <string name="home_homepage_radio_user_address">&home_homepage_radio_user_address;</string>
   <string name="home_homepage_hint_user_address">&home_homepage_hint_user_address;</string>
 
   <string name="pref_header_general">&pref_header_general;</string>
   <string name="pref_header_search">&pref_header_search;</string>
   <string name="pref_header_accessibility">&pref_header_accessibility;</string>
   <string name="pref_header_privacy_short">&pref_header_privacy_short;</string>
+  <string name="pref_header_notifications">&pref_header_notifications;</string>
   <string name="pref_header_advanced">&pref_header_advanced;</string>
   <string name="pref_header_vendor">&pref_header_vendor;</string>
 
   <string name="pref_learn_more">&pref_learn_more;</string>
 
   <string name="pref_remember_signons">&pref_remember_signons2;</string>
 
   <string name="pref_manage_logins">&pref_manage_logins;</string>