Bug 1396604 - Remove content notifications code. r?nechen,janh draft
authorSebastian Kaspari <s.kaspari@gmail.com>
Mon, 04 Sep 2017 16:51:07 +0200
changeset 660621 1b19edefd42787f9bdf5ebfe8b28c2200e3101a9
parent 658578 632e42dca494ec3d90b70325d9c359f80cb3f38a
child 730309 782bdf0bb80662127487086843119f87e5f14cd0
push id78479
push users.kaspari@gmail.com
push dateThu, 07 Sep 2017 08:57:00 +0000
reviewersnechen, janh
bugs1396604
milestone57.0a1
Bug 1396604 - Remove content notifications code. r?nechen,janh MozReview-Commit-ID: 5H45Vjnzt5Z
mobile/android/app/src/main/res/values/ids.xml
mobile/android/app/src/main/res/xml/preferences_notifications.xml
mobile/android/base/AndroidManifest.xml.in
mobile/android/base/java/org/mozilla/gecko/BootReceiver.java
mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
mobile/android/base/java/org/mozilla/gecko/Experiments.java
mobile/android/base/java/org/mozilla/gecko/db/LocalUrlAnnotations.java
mobile/android/base/java/org/mozilla/gecko/db/UrlAnnotations.java
mobile/android/base/java/org/mozilla/gecko/feeds/ContentNotificationsDelegate.java
mobile/android/base/java/org/mozilla/gecko/feeds/FeedAlarmReceiver.java
mobile/android/base/java/org/mozilla/gecko/feeds/FeedFetcher.java
mobile/android/base/java/org/mozilla/gecko/feeds/FeedService.java
mobile/android/base/java/org/mozilla/gecko/feeds/action/CheckForUpdatesAction.java
mobile/android/base/java/org/mozilla/gecko/feeds/action/EnrollSubscriptionsAction.java
mobile/android/base/java/org/mozilla/gecko/feeds/action/FeedAction.java
mobile/android/base/java/org/mozilla/gecko/feeds/action/SetupAlarmsAction.java
mobile/android/base/java/org/mozilla/gecko/feeds/action/SubscribeToFeedAction.java
mobile/android/base/java/org/mozilla/gecko/feeds/action/WithdrawSubscriptionsAction.java
mobile/android/base/java/org/mozilla/gecko/feeds/knownsites/KnownSite.java
mobile/android/base/java/org/mozilla/gecko/feeds/knownsites/KnownSiteBlogger.java
mobile/android/base/java/org/mozilla/gecko/feeds/knownsites/KnownSiteMedium.java
mobile/android/base/java/org/mozilla/gecko/feeds/knownsites/KnownSiteTumblr.java
mobile/android/base/java/org/mozilla/gecko/feeds/knownsites/KnownSiteWordpress.java
mobile/android/base/java/org/mozilla/gecko/feeds/parser/Feed.java
mobile/android/base/java/org/mozilla/gecko/feeds/parser/Item.java
mobile/android/base/java/org/mozilla/gecko/feeds/parser/SimpleFeedParser.java
mobile/android/base/java/org/mozilla/gecko/feeds/subscriptions/FeedSubscription.java
mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferenceFragment.java
mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java
mobile/android/base/locales/en-US/android_strings.dtd
mobile/android/base/moz.build
mobile/android/base/strings.xml.in
mobile/android/tests/background/junit4/src/org/mozilla/gecko/feeds/knownsites/TestKnownSiteBlogger.java
mobile/android/tests/background/junit4/src/org/mozilla/gecko/feeds/knownsites/TestKnownSiteMedium.java
mobile/android/tests/background/junit4/src/org/mozilla/gecko/feeds/knownsites/TestKnownSiteTumblr.java
mobile/android/tests/background/junit4/src/org/mozilla/gecko/feeds/parser/TestSimpleFeedParser.java
--- a/mobile/android/app/src/main/res/values/ids.xml
+++ b/mobile/android/app/src/main/res/values/ids.xml
@@ -12,15 +12,14 @@
     <item type="id" name="menu_items"/>
     <item type="id" name="menu_margin"/>
     <item type="id" name="recycler_view_click_support" />
     <item type="id" name="range_list"/>
     <item type="id" name="pref_header_general"/>
     <item type="id" name="pref_header_privacy"/>
     <item type="id" name="pref_header_search"/>
     <item type="id" name="updateServicePermissionNotification" />
-    <item type="id" name="websiteContentNotification" />
     <item type="id" name="foregroundNotification" />
     <item type="id" name="actionbar"/>
     <item type="id" name="action_button"/>
     <item type="id" name="page_progress"/>
     <item type="id" name="mediaControlNotification"/>
 </resources>
--- a/mobile/android/app/src/main/res/xml/preferences_notifications.xml
+++ b/mobile/android/app/src/main/res/xml/preferences_notifications.xml
@@ -1,16 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
-    <SwitchPreference android:key="android.not_a_preference.notifications.content"
-        android:title="@string/pref_content_notifications"
-        android:summary="@string/pref_content_notifications_summary"
-        android:defaultValue="true" />
-    <org.mozilla.gecko.preferences.AlignRightLinkPreference
-        android:key="android.not_a_preference.notifications.content.learn_more"
-        android:title="@string/pref_learn_more"
-        android:persistent="false"
-        url="https://support.mozilla.org/kb/notifications-firefox-android?utm_source=inproduct&amp;utm_medium=notifications&amp;utm_campaign=mobileandroid" />
     <SwitchPreference android:key="android.not_a_preference.notifications.whats_new"
         android:title="@string/pref_whats_new_notification"
         android:summary="@string/pref_whats_new_notification_summary"
         android:defaultValue="true" />
 </PreferenceScreen>
\ No newline at end of file
--- a/mobile/android/base/AndroidManifest.xml.in
+++ b/mobile/android/base/AndroidManifest.xml.in
@@ -381,40 +381,27 @@
             android:name="org.mozilla.gecko.notifications.NotificationService">
         </service>
 
         <service
             android:exported="false"
             android:name="org.mozilla.gecko.dlc.DownloadContentService">
         </service>
 
-        <service
-            android:exported="false"
-            android:name="org.mozilla.gecko.feeds.FeedService">
-        </service>
-
         <!-- DON'T EXPORT THIS, please! An attacker could delete arbitrary files. -->
         <service
             android:exported="false"
             android:name="org.mozilla.gecko.cleanup.FileCleanupService">
         </service>
 
         <receiver
             android:name="org.mozilla.gecko.feeds.FeedAlarmReceiver"
             android:exported="false" />
 
         <receiver
-            android:name="org.mozilla.gecko.BootReceiver"
-            android:exported="false">
-            <intent-filter>
-                <action android:name="android.intent.action.BOOT_COMPLETED"></action>
-            </intent-filter>
-        </receiver>
-
-        <receiver
             android:name="org.mozilla.gecko.PackageReplacedReceiver"
             android:exported="false">
             <intent-filter>
                 <action android:name="android.intent.action.MY_PACKAGE_REPLACED"></action>
             </intent-filter>
         </receiver>
 
         <service
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/BootReceiver.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-
-import org.mozilla.gecko.feeds.FeedService;
-
-/**
- * This broadcast receiver receives ACTION_BOOT_COMPLETED broadcasts and starts components that should
- * run after the device has booted.
- */
-public class BootReceiver extends BroadcastReceiver {
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        if (intent == null || !intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
-            return; // This is not the broadcast you are looking for.
-        }
-
-        FeedService.setup(context);
-    }
-}
--- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
@@ -2,128 +2,23 @@
  * 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;
 
 import android.Manifest;
 import android.annotation.TargetApi;
-import android.app.DownloadManager;
-import android.content.ContentProviderClient;
-import android.os.Environment;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.annotation.UiThread;
-
-import org.mozilla.gecko.activitystream.ActivityStream;
-import org.mozilla.gecko.adjust.AdjustBrowserAppDelegate;
-import org.mozilla.gecko.annotation.RobocopTarget;
-import org.mozilla.gecko.AppConstants.Versions;
-import org.mozilla.gecko.DynamicToolbar.VisibilityTransition;
-import org.mozilla.gecko.Tabs.TabEvents;
-import org.mozilla.gecko.animation.PropertyAnimator;
-import org.mozilla.gecko.bookmarks.BookmarkEditFragment;
-import org.mozilla.gecko.bookmarks.BookmarkUtils;
-import org.mozilla.gecko.bookmarks.EditBookmarkTask;
-import org.mozilla.gecko.cleanup.FileCleanupController;
-import org.mozilla.gecko.dawn.DawnHelper;
-import org.mozilla.gecko.db.BrowserContract;
-import org.mozilla.gecko.db.BrowserDB;
-import org.mozilla.gecko.db.SuggestedSites;
-import org.mozilla.gecko.delegates.BrowserAppDelegate;
-import org.mozilla.gecko.delegates.OfflineTabStatusDelegate;
-import org.mozilla.gecko.delegates.ScreenshotDelegate;
-import org.mozilla.gecko.distribution.Distribution;
-import org.mozilla.gecko.distribution.DistributionStoreCallback;
-import org.mozilla.gecko.dlc.DownloadContentService;
-import org.mozilla.gecko.icons.IconsHelper;
-import org.mozilla.gecko.icons.decoders.IconDirectoryEntry;
-import org.mozilla.gecko.icons.decoders.FaviconDecoder;
-import org.mozilla.gecko.icons.decoders.LoadFaviconResult;
-import org.mozilla.gecko.feeds.ContentNotificationsDelegate;
-import org.mozilla.gecko.feeds.FeedService;
-import org.mozilla.gecko.firstrun.FirstrunAnimationContainer;
-import org.mozilla.gecko.gfx.DynamicToolbarAnimator;
-import org.mozilla.gecko.gfx.DynamicToolbarAnimator.PinReason;
-import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
-import org.mozilla.gecko.home.BrowserSearch;
-import org.mozilla.gecko.home.HomeBanner;
-import org.mozilla.gecko.home.HomeConfig;
-import org.mozilla.gecko.home.HomeConfig.PanelType;
-import org.mozilla.gecko.home.HomeConfigPrefsBackend;
-import org.mozilla.gecko.home.HomeFragment;
-import org.mozilla.gecko.home.HomePager.OnUrlOpenInBackgroundListener;
-import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
-import org.mozilla.gecko.home.HomePanelsManager;
-import org.mozilla.gecko.home.HomeScreen;
-import org.mozilla.gecko.home.SearchEngine;
-import org.mozilla.gecko.icons.Icons;
-import org.mozilla.gecko.media.VideoPlayer;
-import org.mozilla.gecko.menu.GeckoMenu;
-import org.mozilla.gecko.menu.GeckoMenuItem;
-import org.mozilla.gecko.mma.MmaDelegate;
-import org.mozilla.gecko.mozglue.GeckoLoader;
-import org.mozilla.gecko.mozglue.SafeIntent;
-import org.mozilla.gecko.notifications.NotificationHelper;
-import org.mozilla.gecko.overlays.ui.ShareDialog;
-import org.mozilla.gecko.permissions.Permissions;
-import org.mozilla.gecko.preferences.ClearOnShutdownPref;
-import org.mozilla.gecko.preferences.GeckoPreferences;
-import org.mozilla.gecko.promotion.AddToHomeScreenPromotion;
-import org.mozilla.gecko.delegates.BookmarkStateChangeDelegate;
-import org.mozilla.gecko.promotion.ReaderViewBookmarkPromotion;
-import org.mozilla.gecko.prompts.Prompt;
-import org.mozilla.gecko.reader.SavedReaderViewHelper;
-import org.mozilla.gecko.reader.ReaderModeUtils;
-import org.mozilla.gecko.reader.ReadingListHelper;
-import org.mozilla.gecko.restrictions.Restrictable;
-import org.mozilla.gecko.restrictions.Restrictions;
-import org.mozilla.gecko.search.SearchEngineManager;
-import org.mozilla.gecko.sync.repositories.android.FennecTabsRepository;
-import org.mozilla.gecko.tabqueue.TabQueueHelper;
-import org.mozilla.gecko.tabqueue.TabQueuePrompt;
-import org.mozilla.gecko.tabs.TabHistoryController;
-import org.mozilla.gecko.tabs.TabHistoryController.OnShowTabHistory;
-import org.mozilla.gecko.tabs.TabHistoryFragment;
-import org.mozilla.gecko.tabs.TabHistoryPage;
-import org.mozilla.gecko.tabs.TabsPanel;
-import org.mozilla.gecko.telemetry.TelemetryUploadService;
-import org.mozilla.gecko.telemetry.TelemetryCorePingDelegate;
-import org.mozilla.gecko.telemetry.measurements.SearchCountMeasurements;
-import org.mozilla.gecko.toolbar.AutocompleteHandler;
-import org.mozilla.gecko.toolbar.BrowserToolbar;
-import org.mozilla.gecko.toolbar.BrowserToolbar.TabEditingState;
-import org.mozilla.gecko.trackingprotection.TrackingProtectionPrompt;
-import org.mozilla.gecko.updater.PostUpdateHandler;
-import org.mozilla.gecko.updater.UpdateServiceHelper;
-import org.mozilla.gecko.util.ActivityUtils;
-import org.mozilla.gecko.util.Clipboard;
-import org.mozilla.gecko.util.ContextUtils;
-import org.mozilla.gecko.util.DrawableUtil;
-import org.mozilla.gecko.util.EventCallback;
-import org.mozilla.gecko.util.GamepadUtils;
-import org.mozilla.gecko.util.GeckoBundle;
-import org.mozilla.gecko.util.HardwareUtils;
-import org.mozilla.gecko.util.IntentUtils;
-import org.mozilla.gecko.util.MenuUtils;
-import org.mozilla.gecko.util.PrefUtils;
-import org.mozilla.gecko.util.StringUtils;
-import org.mozilla.gecko.util.ThreadUtils;
-import org.mozilla.gecko.util.WindowUtil;
-import org.mozilla.gecko.widget.ActionModePresenter;
-import org.mozilla.gecko.widget.AnchoredPopup;
-import org.mozilla.gecko.widget.AnimatedProgressBar;
-import org.mozilla.gecko.widget.GeckoActionProvider;
-
 import android.app.Activity;
 import android.app.AlertDialog;
+import android.app.DownloadManager;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
+import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
@@ -134,17 +29,21 @@ import android.graphics.drawable.BitmapD
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.nfc.NdefMessage;
 import android.nfc.NdefRecord;
 import android.nfc.NfcAdapter;
 import android.nfc.NfcEvent;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.Environment;
 import android.os.StrictMode;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.UiThread;
 import android.support.design.widget.Snackbar;
 import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentManager;
 import android.support.v4.app.NotificationCompat;
 import android.support.v4.content.res.ResourcesCompat;
 import android.support.v4.view.MenuItemCompat;
 import android.text.TextUtils;
 import android.util.AttributeSet;
@@ -162,27 +61,125 @@ import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.ViewStub;
 import android.view.ViewTreeObserver;
 import android.view.Window;
 import android.view.animation.Interpolator;
 import android.widget.Button;
 import android.widget.ListView;
 import android.widget.ViewFlipper;
+
+import org.mozilla.gecko.AppConstants.Versions;
+import org.mozilla.gecko.DynamicToolbar.VisibilityTransition;
+import org.mozilla.gecko.Tabs.TabEvents;
+import org.mozilla.gecko.activitystream.ActivityStream;
+import org.mozilla.gecko.adjust.AdjustBrowserAppDelegate;
+import org.mozilla.gecko.animation.PropertyAnimator;
+import org.mozilla.gecko.annotation.RobocopTarget;
+import org.mozilla.gecko.bookmarks.BookmarkEditFragment;
+import org.mozilla.gecko.bookmarks.BookmarkUtils;
+import org.mozilla.gecko.bookmarks.EditBookmarkTask;
+import org.mozilla.gecko.cleanup.FileCleanupController;
+import org.mozilla.gecko.dawn.DawnHelper;
+import org.mozilla.gecko.db.BrowserContract;
+import org.mozilla.gecko.db.BrowserDB;
+import org.mozilla.gecko.db.SuggestedSites;
+import org.mozilla.gecko.delegates.BookmarkStateChangeDelegate;
+import org.mozilla.gecko.delegates.BrowserAppDelegate;
+import org.mozilla.gecko.delegates.OfflineTabStatusDelegate;
+import org.mozilla.gecko.delegates.ScreenshotDelegate;
+import org.mozilla.gecko.distribution.Distribution;
+import org.mozilla.gecko.distribution.DistributionStoreCallback;
+import org.mozilla.gecko.dlc.DownloadContentService;
+import org.mozilla.gecko.firstrun.FirstrunAnimationContainer;
+import org.mozilla.gecko.gfx.DynamicToolbarAnimator;
+import org.mozilla.gecko.gfx.DynamicToolbarAnimator.PinReason;
+import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
+import org.mozilla.gecko.home.BrowserSearch;
+import org.mozilla.gecko.home.HomeBanner;
+import org.mozilla.gecko.home.HomeConfig;
+import org.mozilla.gecko.home.HomeConfig.PanelType;
+import org.mozilla.gecko.home.HomeConfigPrefsBackend;
+import org.mozilla.gecko.home.HomeFragment;
+import org.mozilla.gecko.home.HomePager.OnUrlOpenInBackgroundListener;
+import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
+import org.mozilla.gecko.home.HomePanelsManager;
+import org.mozilla.gecko.home.HomeScreen;
+import org.mozilla.gecko.home.SearchEngine;
+import org.mozilla.gecko.icons.Icons;
+import org.mozilla.gecko.icons.IconsHelper;
+import org.mozilla.gecko.icons.decoders.FaviconDecoder;
+import org.mozilla.gecko.icons.decoders.IconDirectoryEntry;
+import org.mozilla.gecko.icons.decoders.LoadFaviconResult;
+import org.mozilla.gecko.media.VideoPlayer;
+import org.mozilla.gecko.menu.GeckoMenu;
+import org.mozilla.gecko.menu.GeckoMenuItem;
+import org.mozilla.gecko.mma.MmaDelegate;
+import org.mozilla.gecko.mozglue.GeckoLoader;
+import org.mozilla.gecko.mozglue.SafeIntent;
+import org.mozilla.gecko.notifications.NotificationHelper;
+import org.mozilla.gecko.overlays.ui.ShareDialog;
+import org.mozilla.gecko.permissions.Permissions;
+import org.mozilla.gecko.preferences.ClearOnShutdownPref;
+import org.mozilla.gecko.preferences.GeckoPreferences;
+import org.mozilla.gecko.promotion.AddToHomeScreenPromotion;
+import org.mozilla.gecko.promotion.ReaderViewBookmarkPromotion;
+import org.mozilla.gecko.prompts.Prompt;
+import org.mozilla.gecko.reader.ReaderModeUtils;
+import org.mozilla.gecko.reader.ReadingListHelper;
+import org.mozilla.gecko.reader.SavedReaderViewHelper;
+import org.mozilla.gecko.restrictions.Restrictable;
+import org.mozilla.gecko.restrictions.Restrictions;
+import org.mozilla.gecko.search.SearchEngineManager;
 import org.mozilla.gecko.switchboard.AsyncConfigLoader;
 import org.mozilla.gecko.switchboard.SwitchBoard;
+import org.mozilla.gecko.sync.repositories.android.FennecTabsRepository;
+import org.mozilla.gecko.tabqueue.TabQueueHelper;
+import org.mozilla.gecko.tabqueue.TabQueuePrompt;
+import org.mozilla.gecko.tabs.TabHistoryController;
+import org.mozilla.gecko.tabs.TabHistoryController.OnShowTabHistory;
+import org.mozilla.gecko.tabs.TabHistoryFragment;
+import org.mozilla.gecko.tabs.TabHistoryPage;
+import org.mozilla.gecko.tabs.TabsPanel;
+import org.mozilla.gecko.telemetry.TelemetryCorePingDelegate;
+import org.mozilla.gecko.telemetry.TelemetryUploadService;
+import org.mozilla.gecko.telemetry.measurements.SearchCountMeasurements;
+import org.mozilla.gecko.toolbar.AutocompleteHandler;
+import org.mozilla.gecko.toolbar.BrowserToolbar;
+import org.mozilla.gecko.toolbar.BrowserToolbar.TabEditingState;
+import org.mozilla.gecko.trackingprotection.TrackingProtectionPrompt;
+import org.mozilla.gecko.updater.PostUpdateHandler;
+import org.mozilla.gecko.updater.UpdateServiceHelper;
+import org.mozilla.gecko.util.ActivityUtils;
+import org.mozilla.gecko.util.Clipboard;
+import org.mozilla.gecko.util.ContextUtils;
+import org.mozilla.gecko.util.DrawableUtil;
+import org.mozilla.gecko.util.EventCallback;
+import org.mozilla.gecko.util.GamepadUtils;
+import org.mozilla.gecko.util.GeckoBundle;
+import org.mozilla.gecko.util.HardwareUtils;
+import org.mozilla.gecko.util.IntentUtils;
+import org.mozilla.gecko.util.MenuUtils;
+import org.mozilla.gecko.util.PrefUtils;
+import org.mozilla.gecko.util.StringUtils;
+import org.mozilla.gecko.util.ThreadUtils;
+import org.mozilla.gecko.util.WindowUtil;
+import org.mozilla.gecko.widget.ActionModePresenter;
+import org.mozilla.gecko.widget.AnchoredPopup;
+import org.mozilla.gecko.widget.AnimatedProgressBar;
+import org.mozilla.gecko.widget.GeckoActionProvider;
 import org.mozilla.gecko.widget.SplashScreen;
 
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.lang.reflect.Method;
 import java.net.URLEncoder;
+import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.regex.Pattern;
 
 import static org.mozilla.gecko.mma.MmaDelegate.NEW_TAB;
@@ -333,17 +330,16 @@ public class BrowserApp extends GeckoApp
 
     private final TelemetryCorePingDelegate mTelemetryCorePingDelegate = new TelemetryCorePingDelegate();
 
     private final List<BrowserAppDelegate> delegates = Collections.unmodifiableList(Arrays.asList(
             new AddToHomeScreenPromotion(),
             new ScreenshotDelegate(),
             new BookmarkStateChangeDelegate(),
             new ReaderViewBookmarkPromotion(),
-            new ContentNotificationsDelegate(),
             new PostUpdateHandler(),
             mTelemetryCorePingDelegate,
             new OfflineTabStatusDelegate(),
             new AdjustBrowserAppDelegate(mTelemetryCorePingDelegate)
     ));
 
     @NonNull
     private SearchEngineManager mSearchEngineManager; // Contains reference to Context - DO NOT LEAK!
@@ -1814,17 +1810,16 @@ public class BrowserApp extends GeckoApp
 
                 if (AppConstants.MOZ_ANDROID_DOWNLOAD_CONTENT_SERVICE &&
                         !IntentUtils.getIsInAutomationFromEnvironment(new SafeIntent(getIntent()))) {
                     // TODO: Better scheduling of DLC actions (Bug 1257492)
                     DownloadContentService.startSync(this);
                     DownloadContentService.startVerification(this);
                 }
 
-                FeedService.setup(this);
                 break;
 
             case "Accessibility:Enabled":
                 mDynamicToolbar.setAccessibilityEnabled(message.getBoolean("enabled"));
                 break;
 
             case "Menu:Open":
                 if (mBrowserToolbar.isEditing()) {
--- a/mobile/android/base/java/org/mozilla/gecko/Experiments.java
+++ b/mobile/android/base/java/org/mozilla/gecko/Experiments.java
@@ -20,21 +20,16 @@ import java.util.List;
  * https://github.com/mozilla-services/switchboard-experiments
  */
 public class Experiments {
     private static final String LOGTAG = "GeckoExperiments";
 
     // Show a system notification linking to a "What's New" page on app update.
     public static final String WHATSNEW_NOTIFICATION = "whatsnew-notification";
 
-    // Subscribe to known, bookmarked sites and show a notification if new content is available.
-    public static final String CONTENT_NOTIFICATIONS_12HRS = "content-notifications-12hrs";
-    public static final String CONTENT_NOTIFICATIONS_8AM = "content-notifications-8am";
-    public static final String CONTENT_NOTIFICATIONS_5PM = "content-notifications-5pm";
-
     // Onboarding: "Features and Story". These experiments are determined
     // on the client, they are not part of the server config.
     public static final String ONBOARDING3_A = "onboarding3-a"; // Control: No first run
     public static final String ONBOARDING3_B = "onboarding3-b"; // 4 static Feature + 1 dynamic slides
     public static final String ONBOARDING3_C = "onboarding3-c"; // Differentiating features slides
 
     // Synchronizing the catalog of downloadable content from Kinto
     public static final String DOWNLOAD_CONTENT_CATALOG_SYNC = "download-content-catalog-sync";
--- a/mobile/android/base/java/org/mozilla/gecko/db/LocalUrlAnnotations.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/LocalUrlAnnotations.java
@@ -5,22 +5,19 @@
 package org.mozilla.gecko.db;
 
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.net.Uri;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import android.util.Log;
 
-import org.json.JSONException;
 import org.mozilla.gecko.annotation.RobocopTarget;
 import org.mozilla.gecko.db.BrowserContract.UrlAnnotations.Key;
-import org.mozilla.gecko.feeds.subscriptions.FeedSubscription;
 
 public class LocalUrlAnnotations implements UrlAnnotations {
     private static final String LOGTAG = "LocalUrlAnnotations";
 
     private Uri urlAnnotationsTableWithProfile;
 
     public LocalUrlAnnotations(final String profile) {
         urlAnnotationsTableWithProfile = DBUtils.appendProfile(profile, BrowserContract.UrlAnnotations.CONTENT_URI);
@@ -92,75 +89,22 @@ public class LocalUrlAnnotations impleme
     public Cursor getWebsitesWithFeedUrl(ContentResolver cr) {
         return cr.query(urlAnnotationsTableWithProfile,
                 new String[] { BrowserContract.UrlAnnotations.URL },
                 BrowserContract.UrlAnnotations.KEY + " = ?",
                 new String[] { Key.FEED.getDbValue() },
                 null);
     }
 
-    /**
-     * Returns true if there's a subscription for this feed URL. False otherwise.
-     */
-    @Override
-    public boolean hasFeedSubscription(ContentResolver cr, String feedUrl) {
-        return hasResultsForSelection(cr,
-                BrowserContract.UrlAnnotations.URL + " = ? AND " + BrowserContract.UrlAnnotations.KEY + " = ?",
-                new String[]{feedUrl, Key.FEED_SUBSCRIPTION.getDbValue()});
-    }
-
-    /**
-     * Insert the given feed subscription (Mapping from feed URL to the subscription object).
-     */
-    @Override
-    public void insertFeedSubscription(ContentResolver cr, FeedSubscription subscription) {
-        try {
-            insertAnnotation(cr, subscription.getFeedUrl(), Key.FEED_SUBSCRIPTION, subscription.toJSON().toString());
-        } catch (JSONException e) {
-            Log.w(LOGTAG, "Could not serialize subscription");
-        }
-    }
-
-    /**
-     * Update the feed subscription with new values.
-     */
-    @Override
-    public void updateFeedSubscription(ContentResolver cr, FeedSubscription subscription) {
-        try {
-            updateAnnotation(cr, subscription.getFeedUrl(), Key.FEED_SUBSCRIPTION, subscription.toJSON().toString());
-        } catch (JSONException e) {
-            Log.w(LOGTAG, "Could not serialize subscription");
-        }
-    }
-
-    /**
-     * Delete the subscription for the feed URL.
-     */
-    @Override
-    public void deleteFeedSubscription(ContentResolver cr, FeedSubscription subscription) {
-        deleteAnnotation(cr, subscription.getFeedUrl(), Key.FEED_SUBSCRIPTION);
-    }
-
     private int deleteAnnotation(final ContentResolver cr, final String url, final Key key) {
         return cr.delete(urlAnnotationsTableWithProfile,
                 BrowserContract.UrlAnnotations.KEY + " = ? AND " + BrowserContract.UrlAnnotations.URL + " = ?",
                 new String[] { key.getDbValue(), url  });
     }
 
-    private int updateAnnotation(final ContentResolver cr, final String url, final Key key, final String value) {
-        ContentValues values = new ContentValues();
-        values.put(BrowserContract.UrlAnnotations.VALUE, value);
-        values.put(BrowserContract.UrlAnnotations.DATE_MODIFIED, System.currentTimeMillis());
-
-        return cr.update(urlAnnotationsTableWithProfile,
-                values,
-                BrowserContract.UrlAnnotations.KEY + " = ? AND " + BrowserContract.UrlAnnotations.URL + " = ?",
-                new String[]{key.getDbValue(), url});
-    }
-
     private void insertAnnotation(final ContentResolver cr, final String url, final Key key, final String value) {
         insertAnnotation(cr, url, key.getDbValue(), value);
     }
 
     @RobocopTarget
     @Override
     public void insertAnnotation(final ContentResolver cr, final String url, final String key, final String value) {
         final long creationTime = System.currentTimeMillis();
--- a/mobile/android/base/java/org/mozilla/gecko/db/UrlAnnotations.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/UrlAnnotations.java
@@ -1,33 +1,29 @@
 /* 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.db;
 
 import android.content.ContentResolver;
 import android.database.Cursor;
+
 import org.mozilla.gecko.annotation.RobocopTarget;
-import org.mozilla.gecko.feeds.subscriptions.FeedSubscription;
 
 public interface UrlAnnotations {
     @RobocopTarget void insertAnnotation(ContentResolver cr, String url, String key, String value);
 
     Cursor getScreenshots(ContentResolver cr);
     void insertScreenshot(ContentResolver cr, String pageUrl, String screenshotPath);
 
     Cursor getFeedSubscriptions(ContentResolver cr);
     Cursor getWebsitesWithFeedUrl(ContentResolver cr);
     void deleteFeedUrl(ContentResolver cr, String websiteUrl);
     boolean hasWebsiteForFeedUrl(ContentResolver cr, String feedUrl);
-    void deleteFeedSubscription(ContentResolver cr, FeedSubscription subscription);
-    void updateFeedSubscription(ContentResolver cr, FeedSubscription subscription);
-    boolean hasFeedSubscription(ContentResolver cr, String feedUrl);
-    void insertFeedSubscription(ContentResolver cr, FeedSubscription subscription);
     boolean hasFeedUrlForWebsite(ContentResolver cr, String websiteUrl);
     void insertFeedUrl(ContentResolver cr, String originUrl, String feedUrl);
 
     void insertReaderViewUrl(ContentResolver cr, String pageURL);
     void deleteReaderViewUrl(ContentResolver cr, String pageURL);
 
     /**
      * Did the user ever interact with this URL in regards to home screen shortcuts?
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/ContentNotificationsDelegate.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.feeds;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v4.app.NotificationManagerCompat;
-
-import org.mozilla.gecko.AppConstants;
-import org.mozilla.gecko.BrowserApp;
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.Telemetry;
-import org.mozilla.gecko.TelemetryContract;
-import org.mozilla.gecko.delegates.BrowserAppDelegate;
-import org.mozilla.gecko.mozglue.SafeIntent;
-
-import java.util.List;
-
-/**
- * BrowserAppDelegate implementation that takes care of handling intents from content notifications.
- */
-public class ContentNotificationsDelegate extends BrowserAppDelegate {
-    // The application is opened from a content notification
-    public static final String ACTION_CONTENT_NOTIFICATION = AppConstants.ANDROID_PACKAGE_NAME + ".action.CONTENT_NOTIFICATION";
-
-    public static final String EXTRA_READ_BUTTON = "read_button";
-    public static final String EXTRA_URLS = "urls";
-
-    private static final String TELEMETRY_EXTRA_CONTENT_UPDATE = "content_update";
-    private static final String TELEMETRY_EXTRA_READ_NOW_BUTTON = TELEMETRY_EXTRA_CONTENT_UPDATE + "_read_now";
-
-    @Override
-    public void onCreate(BrowserApp browserApp, Bundle savedInstanceState) {
-        if (savedInstanceState != null) {
-            // This activity is getting restored: We do not want to handle the URLs in the Intent again. The browser
-            // will take care of restoring the tabs we already created.
-            return;
-        }
-
-
-        final Intent unsafeIntent = browserApp.getIntent();
-
-        // Nothing to do.
-        if (unsafeIntent == null) {
-            return;
-        }
-
-        final SafeIntent intent = new SafeIntent(unsafeIntent);
-
-        if (ACTION_CONTENT_NOTIFICATION.equals(intent.getAction())) {
-            openURLsFromIntent(browserApp, intent);
-        }
-    }
-
-    @Override
-    public void onNewIntent(BrowserApp browserApp, @NonNull final SafeIntent intent) {
-        if (ACTION_CONTENT_NOTIFICATION.equals(intent.getAction())) {
-            openURLsFromIntent(browserApp, intent);
-        }
-    }
-
-    private void openURLsFromIntent(BrowserApp browserApp, @NonNull final SafeIntent intent) {
-        final List<String> urls = intent.getStringArrayListExtra(EXTRA_URLS);
-        if (urls != null) {
-            browserApp.openUrls(urls);
-        }
-
-        Telemetry.startUISession(TelemetryContract.Session.EXPERIMENT, FeedService.getEnabledExperiment(browserApp));
-
-        Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.INTENT, TELEMETRY_EXTRA_CONTENT_UPDATE);
-
-        if (intent.getBooleanExtra(EXTRA_READ_BUTTON, false)) {
-            // "READ NOW" button in notification was clicked
-            Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, TelemetryContract.Method.NOTIFICATION, TELEMETRY_EXTRA_READ_NOW_BUTTON);
-
-            // Android's "auto cancel" won't remove the notification when an action button is pressed. So we do it ourselves here.
-            NotificationManagerCompat.from(browserApp).cancel(R.id.websiteContentNotification);
-        } else {
-            // Notification was clicked
-            Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, TelemetryContract.Method.NOTIFICATION, TELEMETRY_EXTRA_CONTENT_UPDATE);
-        }
-
-        Telemetry.stopUISession(TelemetryContract.Session.EXPERIMENT, FeedService.getEnabledExperiment(browserApp));
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/FeedAlarmReceiver.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.feeds;
-
-import android.content.Context;
-import android.content.Intent;
-import android.support.v4.content.WakefulBroadcastReceiver;
-import android.util.Log;
-
-/**
- * Broadcast receiver that will receive broadcasts from the AlarmManager and start the FeedService
- * with the given action.
- */
-public class FeedAlarmReceiver extends WakefulBroadcastReceiver {
-    private static final String LOGTAG = "FeedCheckAction";
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        final String action = intent.getAction();
-
-        Log.d(LOGTAG, "Received alarm with action: " + action);
-
-        final Intent serviceIntent = new Intent(context, FeedService.class);
-        serviceIntent.setAction(action);
-
-        startWakefulService(context, serviceIntent);
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/FeedFetcher.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.feeds;
-
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-
-import org.mozilla.gecko.feeds.parser.Feed;
-import org.mozilla.gecko.feeds.parser.SimpleFeedParser;
-import org.mozilla.gecko.util.IOUtils;
-import org.mozilla.gecko.util.ProxySelector;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.net.URI;
-import java.net.URISyntaxException;
-
-import ch.boye.httpclientandroidlib.util.TextUtils;
-
-/**
- * Helper class for fetching and parsing a feed.
- */
-public class FeedFetcher {
-    private static final int CONNECT_TIMEOUT = 15000;
-    private static final int READ_TIMEOUT = 15000;
-
-    public static class FeedResponse {
-        public final Feed feed;
-        public final String etag;
-        public final String lastModified;
-
-        public FeedResponse(Feed feed, String etag, String lastModified) {
-            this.feed = feed;
-            this.etag = etag;
-            this.lastModified = lastModified;
-        }
-    }
-
-    /**
-     * Fetch and parse a feed from the given URL. Will return null if fetching or parsing failed.
-     */
-    public static FeedResponse fetchAndParseFeed(String url) {
-        return fetchAndParseFeedIfModified(url, null, null);
-    }
-
-    /**
-     * Fetch and parse a feed from the given URL using the given ETag and "Last modified" value.
-     *
-     * Will return null if fetching or parsing failed. Will also return null if the feed has not
-     * changed (ETag / Last-Modified-Since).
-     *
-     * @param eTag The ETag from the last fetch or null if no ETag is available (will always fetch feed)
-     * @param lastModified The "Last modified" header from the last time the feed has been fetch or
-     *                     null if no value is available (will always fetch feed)
-     * @return A FeedResponse or null if no feed could be fetched (error or no new version available)
-     */
-    @Nullable
-    public static FeedResponse fetchAndParseFeedIfModified(@NonNull String url, @Nullable String eTag, @Nullable String lastModified) {
-        HttpURLConnection connection = null;
-        InputStream stream = null;
-
-        try {
-            connection = (HttpURLConnection) ProxySelector.openConnectionWithProxy(new URI(url));
-            connection.setInstanceFollowRedirects(true);
-            connection.setConnectTimeout(CONNECT_TIMEOUT);
-            connection.setReadTimeout(READ_TIMEOUT);
-
-            if (!TextUtils.isEmpty(eTag)) {
-                connection.setRequestProperty("If-None-Match", eTag);
-            }
-
-            if (!TextUtils.isEmpty(lastModified)) {
-                connection.setRequestProperty("If-Modified-Since", lastModified);
-            }
-
-            final int statusCode = connection.getResponseCode();
-
-            if (statusCode != HttpURLConnection.HTTP_OK) {
-                return null;
-            }
-
-            String responseEtag = connection.getHeaderField("ETag");
-            if (!TextUtils.isEmpty(responseEtag) && responseEtag.startsWith("W/")) {
-                // Weak ETag, get actual ETag value
-                responseEtag = responseEtag.substring(2);
-            }
-
-            final String updatedLastModified = connection.getHeaderField("Last-Modified");
-
-            stream = new BufferedInputStream(connection.getInputStream());
-
-            final SimpleFeedParser parser = new SimpleFeedParser();
-            final Feed feed = parser.parse(stream);
-
-            return new FeedResponse(feed, responseEtag, updatedLastModified);
-        } catch (IOException e) {
-            return null;
-        } catch (SimpleFeedParser.ParserException e) {
-            return null;
-        } catch (URISyntaxException e) {
-            return null;
-        } finally {
-            if (connection != null) {
-                connection.disconnect();
-            }
-            IOUtils.safeStreamClose(stream);
-        }
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/FeedService.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.feeds;
-
-import android.app.IntentService;
-import android.content.Context;
-import android.content.Intent;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.support.annotation.Nullable;
-import android.support.v4.net.ConnectivityManagerCompat;
-import android.util.Log;
-
-import org.mozilla.gecko.switchboard.SwitchBoard;
-
-import org.mozilla.gecko.AppConstants;
-import org.mozilla.gecko.GeckoSharedPrefs;
-import org.mozilla.gecko.db.BrowserDB;
-import org.mozilla.gecko.feeds.action.FeedAction;
-import org.mozilla.gecko.feeds.action.CheckForUpdatesAction;
-import org.mozilla.gecko.feeds.action.EnrollSubscriptionsAction;
-import org.mozilla.gecko.feeds.action.SetupAlarmsAction;
-import org.mozilla.gecko.feeds.action.SubscribeToFeedAction;
-import org.mozilla.gecko.feeds.action.WithdrawSubscriptionsAction;
-import org.mozilla.gecko.preferences.GeckoPreferences;
-import org.mozilla.gecko.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";
-
-    public static final String ACTION_SETUP = AppConstants.ANDROID_PACKAGE_NAME + ".FEEDS.SETUP";
-    public static final String ACTION_SUBSCRIBE = AppConstants.ANDROID_PACKAGE_NAME + ".FEEDS.SUBSCRIBE";
-    public static final String ACTION_CHECK = AppConstants.ANDROID_PACKAGE_NAME + ".FEEDS.CHECK";
-    public static final String ACTION_ENROLL = AppConstants.ANDROID_PACKAGE_NAME + ".FEEDS.ENROLL";
-    public static final String ACTION_WITHDRAW = AppConstants.ANDROID_PACKAGE_NAME + ".FEEDS.WITHDRAW";
-
-    public static void setup(Context context) {
-        Intent intent = new Intent(context, FeedService.class);
-        intent.setAction(ACTION_SETUP);
-        context.startService(intent);
-    }
-
-    public static void subscribe(Context context, String feedUrl) {
-        Intent intent = new Intent(context, FeedService.class);
-        intent.setAction(ACTION_SUBSCRIBE);
-        intent.putExtra(SubscribeToFeedAction.EXTRA_FEED_URL, feedUrl);
-        context.startService(intent);
-    }
-
-    public FeedService() {
-        super(LOGTAG);
-    }
-
-    private BrowserDB browserDB;
-
-    @Override
-    public void onCreate() {
-        super.onCreate();
-
-        browserDB = BrowserDB.from(this);
-    }
-
-    @Override
-    protected void onHandleIntent(Intent intent) {
-        try {
-            if (intent == null) {
-                return;
-            }
-
-            Log.d(LOGTAG, "Service started with action: " + intent.getAction());
-
-            if (!isInExperiment(this)) {
-                Log.d(LOGTAG, "Not in content notifications experiment. Skipping.");
-                return;
-            }
-
-            FeedAction action = createActionForIntent(intent);
-            if (action == null) {
-                Log.d(LOGTAG, "No action to process");
-                return;
-            }
-
-            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(browserDB, intent);
-        } finally {
-            FeedAlarmReceiver.completeWakefulIntent(intent);
-        }
-
-        Log.d(LOGTAG, "Done.");
-    }
-
-    @Nullable
-    private FeedAction createActionForIntent(Intent intent) {
-        final Context context = getApplicationContext();
-
-        switch (intent.getAction()) {
-            case ACTION_SETUP:
-                return new SetupAlarmsAction(context);
-
-            case ACTION_SUBSCRIBE:
-                return new SubscribeToFeedAction(context);
-
-            case ACTION_CHECK:
-                return new CheckForUpdatesAction(context);
-
-            case ACTION_ENROLL:
-                return new EnrollSubscriptionsAction(context);
-
-            case ACTION_WITHDRAW:
-                return new WithdrawSubscriptionsAction(context);
-
-            default:
-                throw new AssertionError("Unknown action: " + intent.getAction());
-        }
-    }
-
-    private boolean isConnectedToUnmeteredNetwork() {
-        ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
-        NetworkInfo networkInfo = manager.getActiveNetworkInfo();
-        if (networkInfo == null || !networkInfo.isConnected()) {
-            return false;
-        }
-
-        return !ConnectivityManagerCompat.isActiveNetworkMetered(manager);
-    }
-
-    public static boolean isInExperiment(Context context) {
-        return SwitchBoard.isInExperiment(context, Experiments.CONTENT_NOTIFICATIONS_12HRS) ||
-               SwitchBoard.isInExperiment(context, Experiments.CONTENT_NOTIFICATIONS_5PM) ||
-               SwitchBoard.isInExperiment(context, Experiments.CONTENT_NOTIFICATIONS_8AM);
-    }
-
-    public static String getEnabledExperiment(Context context) {
-        String experiment = null;
-
-        if (SwitchBoard.isInExperiment(context, Experiments.CONTENT_NOTIFICATIONS_12HRS)) {
-            experiment = Experiments.CONTENT_NOTIFICATIONS_12HRS;
-        } else if (SwitchBoard.isInExperiment(context, Experiments.CONTENT_NOTIFICATIONS_8AM)) {
-            experiment = Experiments.CONTENT_NOTIFICATIONS_8AM;
-        } else if (SwitchBoard.isInExperiment(context, Experiments.CONTENT_NOTIFICATIONS_5PM)) {
-            experiment = Experiments.CONTENT_NOTIFICATIONS_5PM;
-        }
-
-        return experiment;
-    }
-
-    private boolean isPreferenceEnabled() {
-        return GeckoSharedPrefs.forApp(this).getBoolean(GeckoPreferences.PREFS_NOTIFICATIONS_CONTENT, true);
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/action/CheckForUpdatesAction.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.feeds.action;
-
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.support.v4.app.NotificationCompat;
-import android.support.v4.app.NotificationManagerCompat;
-import android.support.v4.content.ContextCompat;
-import android.text.format.DateFormat;
-
-import org.json.JSONException;
-import org.mozilla.gecko.AppConstants;
-import org.mozilla.gecko.BrowserApp;
-import org.mozilla.gecko.GeckoApp;
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.Telemetry;
-import org.mozilla.gecko.TelemetryContract;
-import org.mozilla.gecko.db.BrowserContract;
-import org.mozilla.gecko.db.BrowserDB;
-import org.mozilla.gecko.db.UrlAnnotations;
-import org.mozilla.gecko.feeds.ContentNotificationsDelegate;
-import org.mozilla.gecko.feeds.FeedFetcher;
-import org.mozilla.gecko.feeds.FeedService;
-import org.mozilla.gecko.feeds.parser.Feed;
-import org.mozilla.gecko.feeds.subscriptions.FeedSubscription;
-import org.mozilla.gecko.preferences.GeckoPreferences;
-import org.mozilla.gecko.util.StringUtils;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-/**
- * CheckForUpdatesAction: Check if feeds we subscribed to have new content available.
- */
-public class CheckForUpdatesAction extends FeedAction {
-    /**
-     * This extra will be added to Intents fired by the notification.
-     */
-    public static final String EXTRA_CONTENT_NOTIFICATION = "content-notification";
-
-    private final Context context;
-
-    public CheckForUpdatesAction(Context context) {
-        this.context = context;
-    }
-
-    @Override
-    public void perform(BrowserDB browserDB, Intent intent) {
-        final UrlAnnotations urlAnnotations = browserDB.getUrlAnnotations();
-        final ContentResolver resolver = context.getContentResolver();
-        final List<Feed> updatedFeeds = new ArrayList<>();
-
-        log("Checking feeds for updates..");
-
-        Cursor cursor = urlAnnotations.getFeedSubscriptions(resolver);
-        if (cursor == null) {
-            return;
-        }
-
-        try {
-            while (cursor.moveToNext()) {
-                FeedSubscription subscription = FeedSubscription.fromCursor(cursor);
-
-                FeedFetcher.FeedResponse response = checkFeedForUpdates(subscription);
-                if (response != null) {
-                    final Feed feed = response.feed;
-
-                    if (!hasBeenVisited(browserDB, feed.getLastItem().getURL())) {
-                        // Only notify about this update if the last item hasn't been visited yet.
-                        updatedFeeds.add(feed);
-                    } else {
-                        Telemetry.startUISession(TelemetryContract.Session.EXPERIMENT, FeedService.getEnabledExperiment(context));
-                        Telemetry.sendUIEvent(TelemetryContract.Event.CANCEL,
-                                TelemetryContract.Method.SERVICE,
-                                "content_update");
-                        Telemetry.stopUISession(TelemetryContract.Session.EXPERIMENT, FeedService.getEnabledExperiment(context));
-                    }
-
-                    urlAnnotations.updateFeedSubscription(resolver, subscription);
-                }
-            }
-        } catch (JSONException e) {
-            log("Could not deserialize subscription", e);
-        } finally {
-            cursor.close();
-        }
-
-        showNotification(updatedFeeds);
-    }
-
-    private FeedFetcher.FeedResponse checkFeedForUpdates(FeedSubscription subscription) {
-        log("Checking feed: " + subscription.getFeedTitle());
-
-        FeedFetcher.FeedResponse response = fetchFeed(subscription);
-        if (response == null) {
-            return null;
-        }
-
-        if (subscription.hasBeenUpdated(response)) {
-            log("* Feed has changed. New item: " + response.feed.getLastItem().getTitle());
-
-            subscription.update(response);
-
-            return response;
-
-        }
-
-        return null;
-    }
-
-    /**
-     * Returns true if this URL has been visited before.
-     *
-     * We do an exact match. So this can fail if the feed uses a different URL and redirects to
-     * content. But it's better than no checks at all.
-     */
-    private boolean hasBeenVisited(final BrowserDB browserDB, final String url) {
-        final Cursor cursor = browserDB.getHistoryForURL(context.getContentResolver(), url);
-        if (cursor == null) {
-            return false;
-        }
-
-        try {
-            if (cursor.moveToFirst()) {
-                return cursor.getInt(cursor.getColumnIndex(BrowserContract.History.VISITS)) > 0;
-            }
-        } finally {
-            cursor.close();
-        }
-
-        return false;
-    }
-
-    private void showNotification(List<Feed> updatedFeeds) {
-        final int feedCount = updatedFeeds.size();
-        if (feedCount == 0) {
-            return;
-        }
-
-        if (feedCount == 1) {
-            showNotificationForSingleUpdate(updatedFeeds.get(0));
-        } else {
-            showNotificationForMultipleUpdates(updatedFeeds);
-        }
-
-        Telemetry.startUISession(TelemetryContract.Session.EXPERIMENT, FeedService.getEnabledExperiment(context));
-        Telemetry.sendUIEvent(TelemetryContract.Event.SHOW, TelemetryContract.Method.NOTIFICATION, "content_update");
-        Telemetry.stopUISession(TelemetryContract.Session.EXPERIMENT, FeedService.getEnabledExperiment(context));
-    }
-
-    private void showNotificationForSingleUpdate(Feed feed) {
-        final String date = DateFormat.getMediumDateFormat(context).format(new Date(feed.getLastItem().getTimestamp()));
-
-        final NotificationCompat.BigTextStyle style = new NotificationCompat.BigTextStyle()
-                .bigText(feed.getLastItem().getTitle())
-                .setBigContentTitle(feed.getTitle())
-                .setSummaryText(context.getString(R.string.content_notification_updated_on, date));
-
-        final PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, createOpenIntent(feed), PendingIntent.FLAG_UPDATE_CURRENT);
-
-        final Notification notification = new NotificationCompat.Builder(context)
-                .setSmallIcon(R.drawable.ic_status_logo)
-                .setContentTitle(feed.getTitle())
-                .setContentText(feed.getLastItem().getTitle())
-                .setStyle(style)
-                .setColor(ContextCompat.getColor(context, R.color.fennec_ui_accent))
-                .setContentIntent(pendingIntent)
-                .setAutoCancel(true)
-                .addAction(createOpenAction(feed))
-                .addAction(createNotificationSettingsAction())
-                .build();
-
-        NotificationManagerCompat.from(context).notify(R.id.websiteContentNotification, notification);
-    }
-
-    private void showNotificationForMultipleUpdates(List<Feed> feeds) {
-        final NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
-        for (Feed feed : feeds) {
-            inboxStyle.addLine(StringUtils.stripScheme(feed.getLastItem().getURL(), StringUtils.UrlFlags.STRIP_HTTPS));
-        }
-        inboxStyle.setSummaryText(context.getString(R.string.content_notification_summary));
-
-        final PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, createOpenIntent(feeds), PendingIntent.FLAG_UPDATE_CURRENT);
-
-        Notification notification = new NotificationCompat.Builder(context)
-                .setSmallIcon(R.drawable.ic_status_logo)
-                .setContentTitle(context.getString(R.string.content_notification_title_plural, feeds.size()))
-                .setContentText(context.getString(R.string.content_notification_summary))
-                .setStyle(inboxStyle)
-                .setColor(ContextCompat.getColor(context, R.color.fennec_ui_accent))
-                .setContentIntent(pendingIntent)
-                .setAutoCancel(true)
-                .addAction(createOpenAction(feeds))
-                .setNumber(feeds.size())
-                .addAction(createNotificationSettingsAction())
-                .build();
-
-        NotificationManagerCompat.from(context).notify(R.id.websiteContentNotification, notification);
-    }
-
-    private Intent createOpenIntent(Feed feed) {
-        final List<Feed> feeds = new ArrayList<>();
-        feeds.add(feed);
-
-        return createOpenIntent(feeds);
-    }
-
-    private Intent createOpenIntent(List<Feed> feeds) {
-        final ArrayList<String> urls = new ArrayList<>();
-        for (Feed feed : feeds) {
-            urls.add(feed.getLastItem().getURL());
-        }
-
-        final Intent intent = new Intent(context, BrowserApp.class);
-        intent.setAction(ContentNotificationsDelegate.ACTION_CONTENT_NOTIFICATION);
-        intent.putStringArrayListExtra(ContentNotificationsDelegate.EXTRA_URLS, urls);
-
-        return intent;
-    }
-
-    private NotificationCompat.Action createOpenAction(Feed feed) {
-        final List<Feed> feeds = new ArrayList<>();
-        feeds.add(feed);
-
-        return createOpenAction(feeds);
-    }
-
-    private NotificationCompat.Action createOpenAction(List<Feed> feeds) {
-        Intent intent = createOpenIntent(feeds);
-        intent.putExtra(ContentNotificationsDelegate.EXTRA_READ_BUTTON, true);
-
-        PendingIntent pendingIntent = PendingIntent.getActivity(context, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
-
-        return new NotificationCompat.Action(
-                R.drawable.open_in_browser,
-                context.getString(R.string.content_notification_action_read_now),
-                pendingIntent);
-    }
-
-    private NotificationCompat.Action createNotificationSettingsAction() {
-        final Intent intent = new Intent(GeckoApp.ACTION_LAUNCH_SETTINGS);
-        intent.setClassName(AppConstants.ANDROID_PACKAGE_NAME, AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
-        intent.putExtra(EXTRA_CONTENT_NOTIFICATION, true);
-
-        GeckoPreferences.setResourceToOpen(intent, "preferences_notifications");
-
-        PendingIntent settingsIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
-
-        return new NotificationCompat.Action(
-                R.drawable.settings_notifications,
-                context.getString(R.string.content_notification_action_settings),
-                settingsIntent);
-    }
-
-    private FeedFetcher.FeedResponse fetchFeed(FeedSubscription subscription) {
-        return FeedFetcher.fetchAndParseFeedIfModified(
-                subscription.getFeedUrl(),
-                subscription.getETag(),
-                subscription.getLastModified()
-        );
-    }
-
-    @Override
-    public boolean requiresNetwork() {
-        return true;
-    }
-
-    @Override
-    public boolean requiresPreferenceEnabled() {
-        return true;
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/action/EnrollSubscriptionsAction.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.feeds.action;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.text.TextUtils;
-
-import org.mozilla.gecko.db.BrowserContract;
-import org.mozilla.gecko.db.BrowserDB;
-import org.mozilla.gecko.db.UrlAnnotations;
-import org.mozilla.gecko.feeds.FeedService;
-import org.mozilla.gecko.feeds.knownsites.KnownSiteBlogger;
-import org.mozilla.gecko.feeds.knownsites.KnownSite;
-import org.mozilla.gecko.feeds.knownsites.KnownSiteMedium;
-import org.mozilla.gecko.feeds.knownsites.KnownSiteTumblr;
-import org.mozilla.gecko.feeds.knownsites.KnownSiteWordpress;
-
-/**
- * EnrollSubscriptionsAction: Search for bookmarks of known sites we can subscribe to.
- */
-public class EnrollSubscriptionsAction extends FeedAction {
-    private static final String LOGTAG = "FeedEnrollAction";
-
-    private static final KnownSite[] knownSites = {
-        new KnownSiteMedium(),
-        new KnownSiteBlogger(),
-        new KnownSiteWordpress(),
-        new KnownSiteTumblr(),
-    };
-
-    private Context context;
-
-    public EnrollSubscriptionsAction(Context context) {
-        this.context = context;
-    }
-
-    @Override
-    public void perform(BrowserDB db, Intent intent) {
-        log("Searching for bookmarks to enroll in updates");
-
-        final ContentResolver contentResolver = context.getContentResolver();
-
-        for (KnownSite knownSite : knownSites) {
-            searchFor(db, contentResolver, knownSite);
-        }
-    }
-
-    @Override
-    public boolean requiresNetwork() {
-        return false;
-    }
-
-    @Override
-    public boolean requiresPreferenceEnabled() {
-        return true;
-    }
-
-    private void searchFor(BrowserDB db, ContentResolver contentResolver, KnownSite knownSite) {
-        final UrlAnnotations urlAnnotations = db.getUrlAnnotations();
-
-        final Cursor cursor = db.getBookmarksForPartialUrl(contentResolver, knownSite.getURLSearchString());
-        if (cursor == null) {
-            log("Nothing found (" + knownSite.getClass().getSimpleName() + ")");
-            return;
-        }
-
-        try {
-            log("Found " + cursor.getCount() + " websites");
-
-            while (cursor.moveToNext()) {
-
-                final String url = cursor.getString(cursor.getColumnIndex(BrowserContract.Bookmarks.URL));
-
-                log(" URL: " + url);
-
-                String feedUrl = knownSite.getFeedFromURL(url);
-                if (TextUtils.isEmpty(feedUrl)) {
-                    log("Could not determine feed for URL: " + url);
-                    return;
-                }
-
-                if (!urlAnnotations.hasFeedUrlForWebsite(contentResolver, url)) {
-                    urlAnnotations.insertFeedUrl(contentResolver, url, feedUrl);
-                }
-
-                if (!urlAnnotations.hasFeedSubscription(contentResolver, feedUrl)) {
-                    FeedService.subscribe(context, feedUrl);
-                }
-            }
-        } finally {
-            cursor.close();
-        }
-    }
-
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/action/FeedAction.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.feeds.action;
-
-import android.content.Intent;
-import android.util.Log;
-
-import org.mozilla.gecko.db.BrowserDB;
-
-/**
- * Interface for actions run by FeedService.
- */
-public abstract class FeedAction {
-    public static final boolean DEBUG_LOG = false;
-
-    /**
-     * Perform this action.
-     *
-     * @param browserDB database instance to perform the action.
-     * @param intent used to start the service.
-     */
-    public abstract void perform(BrowserDB browserDB, Intent intent);
-
-    /**
-     * Does this action require an active network connection?
-     */
-    public abstract boolean requiresNetwork();
-
-    /**
-     * Should this action only run if the preference is enabled?
-     */
-    public abstract boolean requiresPreferenceEnabled();
-
-    /**
-     * This method will swallow all log messages to avoid logging potential personal information.
-     *
-     * For debugging purposes set {@code DEBUG_LOG} to true.
-     */
-    public void log(String message) {
-        if (DEBUG_LOG) {
-            Log.d("Gecko" + getClass().getSimpleName(), message);
-        }
-    }
-
-    /**
-     * This method will swallow all log messages to avoid logging potential personal information.
-     *
-     * For debugging purposes set {@code DEBUG_LOG} to true.
-     */
-    public void log(String message, Throwable throwable) {
-        if (DEBUG_LOG) {
-            Log.d("Gecko" + getClass().getSimpleName(), message, throwable);
-        }
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/action/SetupAlarmsAction.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.feeds.action;
-
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.os.SystemClock;
-
-import org.mozilla.gecko.switchboard.SwitchBoard;
-
-import org.mozilla.gecko.db.BrowserDB;
-import org.mozilla.gecko.feeds.FeedAlarmReceiver;
-import org.mozilla.gecko.feeds.FeedService;
-import org.mozilla.gecko.Experiments;
-
-import java.text.DateFormat;
-import java.util.Calendar;
-
-/**
- * SetupAlarmsAction: Set up alarms to run various actions every now and then.
- */
-public class SetupAlarmsAction extends FeedAction {
-    private static final String LOGTAG = "FeedSetupAction";
-
-    private Context context;
-
-    public SetupAlarmsAction(Context context) {
-        this.context = context;
-    }
-
-    @Override
-    public void perform(BrowserDB browserDB, Intent intent) {
-        final AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
-
-        cancelPreviousAlarms(alarmManager);
-        scheduleAlarms(alarmManager);
-    }
-
-    @Override
-    public boolean requiresNetwork() {
-        return false;
-    }
-
-    @Override
-    public boolean requiresPreferenceEnabled() {
-        return false;
-    }
-
-    private void cancelPreviousAlarms(AlarmManager alarmManager) {
-        final PendingIntent withdrawIntent = getWithdrawPendingIntent();
-        alarmManager.cancel(withdrawIntent);
-
-        final PendingIntent enrollIntent = getEnrollPendingIntent();
-        alarmManager.cancel(enrollIntent);
-
-        final PendingIntent checkIntent = getCheckPendingIntent();
-        alarmManager.cancel(checkIntent);
-
-        log("Cancelled previous alarms");
-    }
-
-    private void scheduleAlarms(AlarmManager alarmManager) {
-        alarmManager.setInexactRepeating(
-                AlarmManager.ELAPSED_REALTIME,
-                SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_FIFTEEN_MINUTES,
-                AlarmManager.INTERVAL_DAY,
-                getWithdrawPendingIntent());
-
-        alarmManager.setInexactRepeating(
-                AlarmManager.ELAPSED_REALTIME,
-                SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR,
-                AlarmManager.INTERVAL_DAY,
-                getEnrollPendingIntent()
-        );
-
-        if (SwitchBoard.isInExperiment(context, Experiments.CONTENT_NOTIFICATIONS_12HRS)) {
-            scheduleUpdateCheckEvery12Hours(alarmManager);
-        }
-
-        if (SwitchBoard.isInExperiment(context, Experiments.CONTENT_NOTIFICATIONS_8AM)) {
-            scheduleUpdateAtFullHour(alarmManager, 8);
-        }
-
-        if (SwitchBoard.isInExperiment(context, Experiments.CONTENT_NOTIFICATIONS_5PM)) {
-            scheduleUpdateAtFullHour(alarmManager, 17);
-        }
-
-
-        log("Scheduled alarms");
-    }
-
-    private void scheduleUpdateCheckEvery12Hours(AlarmManager alarmManager) {
-        alarmManager.setInexactRepeating(
-                AlarmManager.ELAPSED_REALTIME,
-                SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HOUR,
-                AlarmManager.INTERVAL_HALF_DAY,
-                getCheckPendingIntent()
-        );
-    }
-
-    private void scheduleUpdateAtFullHour(AlarmManager alarmManager, int hourOfDay) {
-        final Calendar calendar = Calendar.getInstance();
-
-        if (calendar.get(Calendar.HOUR_OF_DAY) >= hourOfDay) {
-            // This time has already passed today. Try again tomorrow.
-            calendar.add(Calendar.DAY_OF_MONTH, 1);
-        }
-
-        calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
-        calendar.set(Calendar.MINUTE, 0);
-        calendar.set(Calendar.SECOND, 0);
-        calendar.set(Calendar.MILLISECOND, 0);
-
-        alarmManager.setInexactRepeating(
-                AlarmManager.RTC,
-                calendar.getTimeInMillis(),
-                AlarmManager.INTERVAL_DAY,
-                getCheckPendingIntent()
-        );
-
-        log("Scheduled update alarm at " + DateFormat.getDateTimeInstance().format(calendar.getTime()));
-    }
-
-    private PendingIntent getWithdrawPendingIntent() {
-        Intent intent = new Intent(context, FeedAlarmReceiver.class);
-        intent.setAction(FeedService.ACTION_WITHDRAW);
-        return PendingIntent.getBroadcast(context, 0, intent, 0);
-    }
-
-    private PendingIntent getEnrollPendingIntent() {
-        Intent intent = new Intent(context, FeedAlarmReceiver.class);
-        intent.setAction(FeedService.ACTION_ENROLL);
-        return PendingIntent.getBroadcast(context, 0, intent, 0);
-    }
-
-    private PendingIntent getCheckPendingIntent() {
-        Intent intent = new Intent(context, FeedAlarmReceiver.class);
-        intent.setAction(FeedService.ACTION_CHECK);
-        return PendingIntent.getBroadcast(context, 0, intent, 0);
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/action/SubscribeToFeedAction.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.feeds.action;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-
-import org.mozilla.gecko.Telemetry;
-import org.mozilla.gecko.TelemetryContract;
-import org.mozilla.gecko.db.BrowserDB;
-import org.mozilla.gecko.db.UrlAnnotations;
-import org.mozilla.gecko.feeds.FeedFetcher;
-import org.mozilla.gecko.feeds.FeedService;
-import org.mozilla.gecko.feeds.subscriptions.FeedSubscription;
-
-/**
- * SubscribeToFeedAction: Try to fetch a feed and create a subscription if successful.
- */
-public class SubscribeToFeedAction extends FeedAction {
-    private static final String LOGTAG = "FeedSubscribeAction";
-
-    public static final String EXTRA_FEED_URL = "feed_url";
-
-    private Context context;
-
-    public SubscribeToFeedAction(Context context) {
-        this.context = context;
-    }
-
-    @Override
-    public void perform(BrowserDB browserDB, Intent intent) {
-        final UrlAnnotations urlAnnotations = browserDB.getUrlAnnotations();
-
-        final Bundle extras = intent.getExtras();
-        final String feedUrl = extras.getString(EXTRA_FEED_URL);
-
-        if (urlAnnotations.hasFeedSubscription(context.getContentResolver(), feedUrl)) {
-            log("Already subscribed to " + feedUrl + ". Skipping.");
-            return;
-        }
-
-        log("Subscribing to feed: " + feedUrl);
-
-        subscribe(urlAnnotations, feedUrl);
-    }
-
-    @Override
-    public boolean requiresNetwork() {
-        return true;
-    }
-
-    @Override
-    public boolean requiresPreferenceEnabled() {
-        return true;
-    }
-
-    private void subscribe(UrlAnnotations urlAnnotations, String feedUrl) {
-        FeedFetcher.FeedResponse response = FeedFetcher.fetchAndParseFeed(feedUrl);
-        if (response == null) {
-            log(String.format("Could not fetch feed (%s). Not subscribing for now.", feedUrl));
-            return;
-        }
-
-        log("Subscribing to feed: " + response.feed.getTitle());
-        log("          Last item: " + response.feed.getLastItem().getTitle());
-
-        final FeedSubscription subscription = FeedSubscription.create(feedUrl, response);
-
-        urlAnnotations.insertFeedSubscription(context.getContentResolver(), subscription);
-
-        Telemetry.startUISession(TelemetryContract.Session.EXPERIMENT, FeedService.getEnabledExperiment(context));
-        Telemetry.sendUIEvent(TelemetryContract.Event.SAVE, TelemetryContract.Method.SERVICE, "content_update");
-        Telemetry.stopUISession(TelemetryContract.Session.EXPERIMENT, FeedService.getEnabledExperiment(context));
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/action/WithdrawSubscriptionsAction.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.feeds.action;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-
-import org.json.JSONException;
-import org.mozilla.gecko.Telemetry;
-import org.mozilla.gecko.TelemetryContract;
-import org.mozilla.gecko.db.BrowserContract;
-import org.mozilla.gecko.db.BrowserDB;
-import org.mozilla.gecko.db.UrlAnnotations;
-import org.mozilla.gecko.feeds.FeedService;
-import org.mozilla.gecko.feeds.subscriptions.FeedSubscription;
-
-/**
- * WithdrawSubscriptionsAction: Look for feeds to unsubscribe from.
- */
-public class WithdrawSubscriptionsAction extends FeedAction {
-    private static final String LOGTAG = "FeedWithdrawAction";
-
-    private Context context;
-
-    public WithdrawSubscriptionsAction(Context context) {
-        this.context = context;
-    }
-
-    @Override
-    public void perform(BrowserDB browserDB, Intent intent) {
-        log("Searching for subscriptions to remove..");
-
-        final UrlAnnotations urlAnnotations = browserDB.getUrlAnnotations();
-        final ContentResolver resolver = context.getContentResolver();
-
-        removeFeedsOfUnknownUrls(browserDB, urlAnnotations, resolver);
-        removeSubscriptionsOfRemovedFeeds(urlAnnotations, resolver);
-    }
-
-    /**
-     * Search for website URLs with a feed assigned. Remove entry if website URL is not known anymore:
-     * For now this means the website is not bookmarked.
-     */
-    private void removeFeedsOfUnknownUrls(BrowserDB browserDB, UrlAnnotations urlAnnotations, ContentResolver resolver) {
-        Cursor cursor = urlAnnotations.getWebsitesWithFeedUrl(resolver);
-        if (cursor == null) {
-            return;
-        }
-
-        try {
-            while (cursor.moveToNext()) {
-                final String url = cursor.getString(cursor.getColumnIndex(BrowserContract.UrlAnnotations.URL));
-
-                if (!browserDB.isBookmark(resolver, url)) {
-                    log("Removing feed for unknown URL: " + url);
-
-                    urlAnnotations.deleteFeedUrl(resolver, url);
-                }
-            }
-        } finally {
-            cursor.close();
-        }
-    }
-
-    /**
-     * Remove subscriptions of feed URLs that are not assigned to a website URL (anymore).
-     */
-    private void removeSubscriptionsOfRemovedFeeds(UrlAnnotations urlAnnotations, ContentResolver resolver) {
-        Cursor cursor = urlAnnotations.getFeedSubscriptions(resolver);
-        if (cursor == null) {
-            return;
-        }
-
-        try {
-            while (cursor.moveToNext()) {
-                final FeedSubscription subscription = FeedSubscription.fromCursor(cursor);
-
-                if (!urlAnnotations.hasWebsiteForFeedUrl(resolver, subscription.getFeedUrl())) {
-                    log("Removing subscription for feed: " + subscription.getFeedUrl());
-
-                    urlAnnotations.deleteFeedSubscription(resolver, subscription);
-
-                    Telemetry.startUISession(TelemetryContract.Session.EXPERIMENT, FeedService.getEnabledExperiment(context));
-                    Telemetry.sendUIEvent(TelemetryContract.Event.UNSAVE, TelemetryContract.Method.SERVICE, "content_update");
-                    Telemetry.stopUISession(TelemetryContract.Session.EXPERIMENT, FeedService.getEnabledExperiment(context));
-                }
-            }
-        } catch (JSONException e) {
-            log("Could not deserialize subscription", e);
-        } finally {
-            cursor.close();
-        }
-    }
-
-    @Override
-    public boolean requiresNetwork() {
-        return false;
-    }
-
-    @Override
-    public boolean requiresPreferenceEnabled() {
-        return true;
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/knownsites/KnownSite.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.feeds.knownsites;
-
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-
-/**
- * A site we know and for which we can guess the feed URL from an arbitrary URL.
- */
-public interface KnownSite {
-    /**
-     * Get a search string to find URLs of this site in our database. This search string is usually
-     * a partial domain / URL.
-     *
-     * For example we could return "medium.com" to find all URLs that contain this string. This could
-     * obviously find URLs that are not actually medium.com sites. This is acceptable as long as
-     * getFeedFromURL() can handle these inputs and either returns a feed for valid URLs or null for
-     * other matches that are not related to this site.
-     */
-    @NonNull String getURLSearchString();
-
-    /**
-     * Get the Feed URL for this URL. For a known site we can "guess" the feed URL from an URL
-     * pointing to any page. The input URL will be a result from the database found with the value
-     * returned by getURLSearchString().
-     *
-     * Example:
-     * - Input:  https://medium.com/@antlam/ux-thoughts-for-2016-1fc1d6e515e8
-     * - Output: https://medium.com/feed/@antlam
-     *
-     * @return the url representing a feed, or null if a feed could not be determined.
-     */
-    @Nullable String getFeedFromURL(String url);
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/knownsites/KnownSiteBlogger.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.feeds.knownsites;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Blogger.com
- */
-public class KnownSiteBlogger implements KnownSite {
-    @Override
-    public String getURLSearchString() {
-        return ".blogspot.com";
-    }
-
-    @Override
-    public String getFeedFromURL(String url) {
-        Pattern pattern = Pattern.compile("https?://(www\\.)?(.*?)\\.blogspot\\.com(/.*)?");
-        Matcher matcher = pattern.matcher(url);
-        if (matcher.matches()) {
-            return String.format("https://%s.blogspot.com/feeds/posts/default", matcher.group(2));
-        }
-        return null;
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/knownsites/KnownSiteMedium.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.feeds.knownsites;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Medium.com
- */
-public class KnownSiteMedium implements KnownSite {
-    @Override
-    public String getURLSearchString() {
-        return "://medium.com/";
-    }
-
-    @Override
-    public String getFeedFromURL(String url) {
-        Pattern pattern = Pattern.compile("https?://medium.com/([^/]+)(/.*)?");
-        Matcher matcher = pattern.matcher(url);
-        if (matcher.matches()) {
-            return String.format("https://medium.com/feed/%s", matcher.group(1));
-        }
-        return null;
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/knownsites/KnownSiteTumblr.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.feeds.knownsites;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Tumblr.com
- */
-public class KnownSiteTumblr implements KnownSite {
-    @Override
-    public String getURLSearchString() {
-        return ".tumblr.com";
-    }
-
-    @Override
-    public String getFeedFromURL(String url) {
-        final Pattern pattern = Pattern.compile("https?://(.*?).tumblr.com(/.*)?");
-        final Matcher matcher = pattern.matcher(url);
-        if (matcher.matches()) {
-            final String username = matcher.group(1);
-            if (username.equals("www")) {
-                return null;
-            }
-            return "http://" + username + ".tumblr.com/rss";
-        }
-        return null;
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/knownsites/KnownSiteWordpress.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.mozilla.gecko.feeds.knownsites;
-
-import android.support.annotation.NonNull;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Wordpress.com
- */
-public class KnownSiteWordpress implements KnownSite {
-    @Override
-    public String getURLSearchString() {
-        return ".wordpress.com";
-    }
-
-    @Override
-    public String getFeedFromURL(String url) {
-        Pattern pattern = Pattern.compile("https?://(.*?).wordpress.com(/.*)?");
-        Matcher matcher = pattern.matcher(url);
-        if (matcher.matches()) {
-            return "https://" + matcher.group(1) + ".wordpress.com/feed/";
-        }
-        return null;
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/parser/Feed.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.feeds.parser;
-
-import ch.boye.httpclientandroidlib.util.TextUtils;
-
-public class Feed {
-    private String title;
-    private String websiteURL;
-    private String feedURL;
-    private Item lastItem;
-
-    public static Feed create(String title, String websiteURL, String feedURL, Item lastItem) {
-        Feed feed = new Feed();
-
-        feed.setTitle(title);
-        feed.setWebsiteURL(websiteURL);
-        feed.setFeedURL(feedURL);
-        feed.setLastItem(lastItem);
-
-        return feed;
-    }
-
-    /* package-private */ Feed() {}
-
-    /* package-private */ void setTitle(String title) {
-        this.title = title;
-    }
-
-    /* package-private */ void setWebsiteURL(String websiteURL) {
-        this.websiteURL = websiteURL;
-    }
-
-    /* package-private */ void setFeedURL(String feedURL) {
-        this.feedURL = feedURL;
-    }
-
-    /* package-private */ void setLastItem(Item lastItem) {
-        this.lastItem = lastItem;
-    }
-
-    /**
-     * Is this feed object sufficiently complete so that we can use it?
-     */
-    /* package-private */ boolean isSufficientlyComplete() {
-        return !TextUtils.isEmpty(title) &&
-                lastItem != null &&
-                !TextUtils.isEmpty(lastItem.getURL()) &&
-                !TextUtils.isEmpty(lastItem.getTitle());
-    }
-
-    public String getTitle() {
-        return title;
-    }
-
-    public String getWebsiteURL() {
-        return websiteURL;
-    }
-
-    public String getFeedURL() {
-        return feedURL;
-    }
-
-    public Item getLastItem() {
-        return lastItem;
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/parser/Item.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.feeds.parser;
-
-public class Item {
-    private String title;
-    private String url;
-    private long timestamp;
-
-    public static Item create(String title, String url, long timestamp) {
-        Item item = new Item();
-
-        item.setTitle(title);
-        item.setURL(url);
-        item.setTimestamp(timestamp);
-
-        return item;
-    }
-
-    /* package-private */ void setTitle(String title) {
-        this.title = title;
-    }
-
-    /* package-private */ void setURL(String url) {
-        this.url = url;
-    }
-
-    /* package-private */ void setTimestamp(long timestamp) {
-        this.timestamp = timestamp;
-    }
-
-    public String getTitle() {
-        return title;
-    }
-
-    public String getURL() {
-        return url;
-    }
-
-    /**
-     * @return the number of milliseconds since Jan. 1, 1970, midnight GMT.
-     */
-    public long getTimestamp() {
-        return timestamp;
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/parser/SimpleFeedParser.java
+++ /dev/null
@@ -1,367 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.feeds.parser;
-
-import android.util.Log;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-
-import ch.boye.httpclientandroidlib.util.TextUtils;
-
-/**
- * A super simple feed parser written for implementing "content notifications". This XML Pull Parser
- * can read ATOM and RSS feeds and returns an object describing the feed and the latest entry.
- */
-public class SimpleFeedParser {
-    /**
-     * Generic exception that's thrown by the parser whenever a stream cannot be parsed.
-     */
-    public static class ParserException extends Exception {
-        private static final long serialVersionUID = -6119538440219805603L;
-
-        public ParserException(Throwable cause) {
-            super(cause);
-        }
-
-        public ParserException(String message) {
-            super(message);
-        }
-    }
-
-    private static final String LOGTAG = "Gecko/FeedParser";
-
-    private static final String TAG_RSS = "rss";
-    private static final String TAG_FEED = "feed";
-    private static final String TAG_RDF = "RDF";
-    private static final String TAG_TITLE = "title";
-    private static final String TAG_ITEM = "item";
-    private static final String TAG_LINK = "link";
-    private static final String TAG_ENTRY = "entry";
-    private static final String TAG_PUBDATE = "pubDate";
-    private static final String TAG_UPDATED = "updated";
-    private static final String TAG_DATE = "date";
-    private static final String TAG_SOURCE = "source";
-    private static final String TAG_IMAGE = "image";
-    private static final String TAG_CONTENT = "content";
-
-    private class ParserState {
-        public Feed feed;
-        public Item currentItem;
-        public boolean isRSS;
-        public boolean isATOM;
-        public boolean inSource;
-        public boolean inImage;
-        public boolean inContent;
-    }
-
-    public Feed parse(InputStream in) throws ParserException, IOException {
-        final ParserState state = new ParserState();
-
-        try {
-            final XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
-            factory.setNamespaceAware(true);
-
-            XmlPullParser parser = factory.newPullParser();
-            parser.setInput(in, null);
-
-            int eventType = parser.getEventType();
-
-            while (eventType != XmlPullParser.END_DOCUMENT) {
-                switch (eventType) {
-                    case XmlPullParser.START_DOCUMENT:
-                        handleStartDocument(state);
-                        break;
-
-                    case XmlPullParser.START_TAG:
-                        handleStartTag(parser, state);
-                        break;
-
-                    case XmlPullParser.END_TAG:
-                        handleEndTag(parser, state);
-                        break;
-                }
-
-                eventType = parser.next();
-            }
-        } catch (XmlPullParserException e) {
-            throw new ParserException(e);
-        }
-
-        if (!state.feed.isSufficientlyComplete()) {
-            throw new ParserException("Feed is not sufficiently complete");
-        }
-
-        return state.feed;
-    }
-
-    private void handleStartDocument(ParserState state) {
-        state.feed = new Feed();
-    }
-
-    private void handleStartTag(XmlPullParser parser, ParserState state) throws IOException, XmlPullParserException {
-        switch (parser.getName()) {
-            case TAG_RSS:
-                state.isRSS = true;
-                break;
-
-            case TAG_FEED:
-                state.isATOM = true;
-                break;
-
-            case TAG_RDF:
-                // This is a RSS 1.0 feed
-                state.isRSS = true;
-                break;
-
-            case TAG_ITEM:
-            case TAG_ENTRY:
-                state.currentItem = new Item();
-                break;
-
-            case TAG_TITLE:
-                handleTitleStartTag(parser, state);
-                break;
-
-            case TAG_LINK:
-                handleLinkStartTag(parser, state);
-                break;
-
-            case TAG_PUBDATE:
-                handlePubDateStartTag(parser, state);
-                break;
-
-            case TAG_UPDATED:
-                handleUpdatedStartTag(parser, state);
-                break;
-
-            case TAG_DATE:
-                handleDateStartTag(parser, state);
-                break;
-
-            case TAG_SOURCE:
-                state.inSource = true;
-                break;
-
-            case TAG_IMAGE:
-                state.inImage = true;
-                break;
-
-            case TAG_CONTENT:
-                state.inContent = true;
-                break;
-        }
-    }
-
-    private void handleEndTag(XmlPullParser parser, ParserState state) {
-        switch (parser.getName()) {
-            case TAG_ITEM:
-            case TAG_ENTRY:
-                handleItemOrEntryREndTag(state);
-                break;
-
-            case TAG_SOURCE:
-                state.inSource = false;
-                break;
-
-            case TAG_IMAGE:
-                state.inImage = false;
-                break;
-
-            case TAG_CONTENT:
-                state.inContent = false;
-                break;
-        }
-    }
-
-    private void handleTitleStartTag(XmlPullParser parser, ParserState state) throws IOException, XmlPullParserException {
-        if (state.inSource || state.inImage || state.inContent) {
-            // We do not care about titles in <source>, <image> or <media> tags.
-            return;
-        }
-
-        String title = getTextUntilEndTag(parser, TAG_TITLE);
-
-        title = title.replaceAll("[\r\n]", " ");
-        title = title.replaceAll("  +", " ");
-
-        if (state.currentItem != null) {
-            state.currentItem.setTitle(title);
-        } else {
-            state.feed.setTitle(title);
-        }
-    }
-
-    private void handleLinkStartTag(XmlPullParser parser, ParserState state) throws IOException, XmlPullParserException {
-        if (state.inSource || state.inImage) {
-            // We do not care about links in <source> or <image> tags.
-            return;
-        }
-
-        Map<String, String> attributes = fetchAttributes(parser);
-
-        if (attributes.size() > 0) {
-            String rel = attributes.get("rel");
-
-            if (state.currentItem == null && "self".equals(rel)) {
-                state.feed.setFeedURL(attributes.get("href"));
-                return;
-            }
-
-            if (rel == null || "alternate".equals(rel)) {
-                String type = attributes.get("type");
-                if (type == null || type.equals("text/html")) {
-                    String link = attributes.get("href");
-                    if (TextUtils.isEmpty(link)) {
-                        return;
-                    }
-
-                    if (state.currentItem != null) {
-                        state.currentItem.setURL(link);
-                    } else {
-                        state.feed.setWebsiteURL(link);
-                    }
-
-                    return;
-                }
-            }
-        }
-
-        if (state.isRSS) {
-            String link = getTextUntilEndTag(parser, TAG_LINK);
-            if (TextUtils.isEmpty(link)) {
-                return;
-            }
-
-            if (state.currentItem != null) {
-                state.currentItem.setURL(link);
-            } else {
-                state.feed.setWebsiteURL(link);
-            }
-        }
-    }
-
-    private void handleItemOrEntryREndTag(ParserState state) {
-        if (state.feed.getLastItem() == null || state.feed.getLastItem().getTimestamp() < state.currentItem.getTimestamp()) {
-            // Only set this item as "last item" if we do not have an item yet or this item is newer.
-            state.feed.setLastItem(state.currentItem);
-        }
-
-        state.currentItem = null;
-    }
-
-    private void handlePubDateStartTag(XmlPullParser parser, ParserState state) throws IOException, XmlPullParserException {
-        if (state.currentItem == null) {
-            return;
-        }
-
-        String pubDate = getTextUntilEndTag(parser, TAG_PUBDATE);
-        if (TextUtils.isEmpty(pubDate)) {
-            return;
-        }
-
-        // RFC-822
-        SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
-
-        updateCurrentItemTimestamp(state, pubDate, format);
-    }
-
-    private void handleUpdatedStartTag(XmlPullParser parser, ParserState state) throws IOException, XmlPullParserException {
-        if (state.inSource) {
-            // We do not care about stuff in <source> tags.
-            return;
-        }
-
-        if (state.currentItem == null) {
-            // We are only interested in <updated> values of feed items.
-            return;
-        }
-
-        String updated = getTextUntilEndTag(parser, TAG_UPDATED);
-        if (TextUtils.isEmpty(updated)) {
-            return;
-        }
-
-        SimpleDateFormat[] formats = new SimpleDateFormat[] {
-            new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US),
-            new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US)
-        };
-
-        // Fix timezones SimpleDateFormat can't parse:
-        // 2016-01-26T18:56:54Z -> 2016-01-26T18:56:54+0000 (Timezone: Z -> +0000)
-        updated = updated.replaceFirst("Z$", "+0000");
-        // 2016-01-26T18:56:54+01:00 -> 2016-01-26T18:56:54+0100 (Timezone: +01:00 -> +0100)
-        updated = updated.replaceFirst("([0-9]{2})([\\+\\-])([0-9]{2}):([0-9]{2})$", "$1$2$3$4");
-
-        updateCurrentItemTimestamp(state, updated, formats);
-    }
-
-    private void handleDateStartTag(XmlPullParser parser, ParserState state) throws IOException, XmlPullParserException {
-        if (state.currentItem == null) {
-            // We are only interested in <updated> values of feed items.
-            return;
-        }
-
-        String text = getTextUntilEndTag(parser, TAG_DATE);
-        if (TextUtils.isEmpty(text)) {
-            return;
-        }
-
-        // Fix timezones SimpleDateFormat can't parse:
-        // 2016-01-26T18:56:54+00:00 -> 2016-01-26T18:56:54+0000
-        text = text.replaceFirst("([0-9]{2})([\\+\\-])([0-9]{2}):([0-9]{2})$", "$1$2$3$4");
-
-        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US);
-
-        updateCurrentItemTimestamp(state, text, format);
-    }
-
-    private void updateCurrentItemTimestamp(ParserState state, String text, SimpleDateFormat... formats) {
-        for (SimpleDateFormat format : formats) {
-            try {
-                Date date = format.parse(text);
-                state.currentItem.setTimestamp(date.getTime());
-                return;
-            } catch (ParseException e) {
-                Log.w(LOGTAG, "Could not parse 'updated': " + text);
-            }
-        }
-    }
-
-    private Map<String, String> fetchAttributes(XmlPullParser parser) {
-        Map<String, String> attributes = new HashMap<>();
-
-        for (int i = 0; i < parser.getAttributeCount(); i++) {
-            attributes.put(parser.getAttributeName(i), parser.getAttributeValue(i));
-        }
-
-        return attributes;
-    }
-
-    private String getTextUntilEndTag(XmlPullParser parser, String tag) throws IOException, XmlPullParserException {
-        StringBuilder builder = new StringBuilder();
-
-        while (parser.next() != XmlPullParser.END_DOCUMENT) {
-            if (parser.getEventType() == XmlPullParser.TEXT) {
-                builder.append(parser.getText());
-            } else if (parser.getEventType() == XmlPullParser.END_TAG && tag.equals(parser.getName())) {
-                break;
-            }
-        }
-
-        return builder.toString().trim();
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/subscriptions/FeedSubscription.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.feeds.subscriptions;
-
-import android.database.Cursor;
-import android.text.TextUtils;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.mozilla.gecko.db.BrowserContract;
-import org.mozilla.gecko.feeds.FeedFetcher;
-import org.mozilla.gecko.feeds.parser.Item;
-
-/**
- * An object describing a subscription and containing some meta data about the last time we fetched
- * the feed.
- */
-public class FeedSubscription {
-    private static final String JSON_KEY_FEED_TITLE = "feed_title";
-    private static final String JSON_KEY_LAST_ITEM_TITLE = "last_item_title";
-    private static final String JSON_KEY_LAST_ITEM_URL = "last_item_url";
-    private static final String JSON_KEY_LAST_ITEM_TIMESTAMP = "last_item_timestamp";
-    private static final String JSON_KEY_ETAG = "etag";
-    private static final String JSON_KEY_LAST_MODIFIED = "last_modified";
-
-    private String feedUrl;
-    private String feedTitle;
-    private String lastItemTitle;
-    private String lastItemUrl;
-    private long lastItemTimestamp;
-    private String etag;
-    private String lastModified;
-
-    public static FeedSubscription create(String feedUrl, FeedFetcher.FeedResponse response) {
-        FeedSubscription subscription = new FeedSubscription();
-        subscription.feedUrl = feedUrl;
-
-        subscription.update(response);
-
-        return subscription;
-    }
-
-    public static FeedSubscription fromCursor(Cursor cursor) throws JSONException {
-        final FeedSubscription subscription = new FeedSubscription();
-        subscription.feedUrl = cursor.getString(cursor.getColumnIndex(BrowserContract.UrlAnnotations.URL));
-
-        final String value = cursor.getString(cursor.getColumnIndex(BrowserContract.UrlAnnotations.VALUE));
-        subscription.fromJSON(new JSONObject(value));
-
-        return subscription;
-    }
-
-    private void fromJSON(JSONObject object) throws JSONException {
-        feedTitle = object.getString(JSON_KEY_FEED_TITLE);
-        lastItemTitle = object.getString(JSON_KEY_LAST_ITEM_TITLE);
-        lastItemUrl = object.getString(JSON_KEY_LAST_ITEM_URL);
-        lastItemTimestamp = object.getLong(JSON_KEY_LAST_ITEM_TIMESTAMP);
-        etag = object.optString(JSON_KEY_ETAG);
-        lastModified = object.optString(JSON_KEY_LAST_MODIFIED);
-    }
-
-    public void update(FeedFetcher.FeedResponse response) {
-        feedTitle = response.feed.getTitle();
-        lastItemTitle = response.feed.getLastItem().getTitle();
-        lastItemUrl = response.feed.getLastItem().getURL();
-        lastItemTimestamp = response.feed.getLastItem().getTimestamp();
-        etag = response.etag;
-        lastModified = response.lastModified;
-    }
-
-    /**
-     * Guesstimate if this response is a newer representation of the feed.
-     */
-    public boolean hasBeenUpdated(FeedFetcher.FeedResponse response) {
-        final Item responseItem = response.feed.getLastItem();
-
-        if (responseItem.getTimestamp() > lastItemTimestamp) {
-            // The timestamp is from a newer date so we expect that this item is a new item. But this
-            // could also mean that the timestamp of an already existing item has been updated. We
-            // accept that and assume that the content will have changed too in this case.
-            return true;
-        }
-
-        if (responseItem.getTimestamp() == lastItemTimestamp && responseItem.getTimestamp() != 0) {
-            // We have a timestamp that is not zero and this item has still the timestamp: It's very
-            // likely that we are looking at the same item. We assume this is not new content.
-            return false;
-        }
-
-        if (!responseItem.getURL().equals(lastItemUrl)) {
-            // The URL changed: It is very likely that this is a new item. At least it has been updated
-            // in a way that we just treat it as new content here.
-            return true;
-        }
-
-        return false;
-    }
-
-    public String getFeedUrl() {
-        return feedUrl;
-    }
-
-    public String getFeedTitle() {
-        return feedTitle;
-    }
-
-    public String getETag() {
-        return etag;
-    }
-
-    public String getLastModified() {
-        return lastModified;
-    }
-
-    public JSONObject toJSON() throws JSONException {
-        JSONObject object = new JSONObject();
-
-        object.put(JSON_KEY_FEED_TITLE, feedTitle);
-        object.put(JSON_KEY_LAST_ITEM_TITLE, lastItemTitle);
-        object.put(JSON_KEY_LAST_ITEM_URL, lastItemUrl);
-        object.put(JSON_KEY_LAST_ITEM_TIMESTAMP, lastItemTimestamp);
-        object.put(JSON_KEY_ETAG, etag);
-        object.put(JSON_KEY_LAST_MODIFIED, lastModified);
-
-        return object;
-    }
-}
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferenceFragment.java
+++ b/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferenceFragment.java
@@ -121,17 +121,16 @@ public class GeckoPreferenceFragment ext
             return getString(R.string.pref_category_privacy_short);
         }
 
         // We can launch this category from the the magnifying glass in the quick search bar.
         if (res == R.xml.preferences_search) {
             return getString(R.string.pref_category_search);
         }
 
-        // Launched as action from content notifications.
         if (res == R.xml.preferences_notifications) {
             return getString(R.string.pref_category_notifications);
         }
 
         return null;
     }
 
     /**
@@ -153,17 +152,16 @@ public class GeckoPreferenceFragment ext
             return R.id.pref_header_privacy;
         }
 
         // We can launch this category from the the magnifying glass in the quick search bar.
         if (res == R.xml.preferences_search) {
             return R.id.pref_header_search;
         }
 
-        // Launched as action from content notifications.
         if (res == R.xml.preferences_notifications) {
             return R.id.pref_header_notifications;
         }
 
         return -1;
     }
 
     private void updateTitle() {
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java
+++ b/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java
@@ -1,72 +1,29 @@
 /* -*- 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.preferences;
 
-import org.json.JSONArray;
-import org.mozilla.gecko.AboutPages;
-import org.mozilla.gecko.AdjustConstants;
-import org.mozilla.gecko.AppConstants;
-import org.mozilla.gecko.BrowserApp;
-import org.mozilla.gecko.BrowserLocaleManager;
-import org.mozilla.gecko.DataReportingNotification;
-import org.mozilla.gecko.DynamicToolbar;
-import org.mozilla.gecko.EventDispatcher;
-import org.mozilla.gecko.Experiments;
-import org.mozilla.gecko.GeckoApplication;
-import org.mozilla.gecko.GeckoProfile;
-import org.mozilla.gecko.GeckoSharedPrefs;
-import org.mozilla.gecko.LocaleManager;
-import org.mozilla.gecko.Locales;
-import org.mozilla.gecko.PrefsHelper;
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.SnackbarBuilder;
-import org.mozilla.gecko.Telemetry;
-import org.mozilla.gecko.TelemetryContract;
-import org.mozilla.gecko.TelemetryContract.Method;
-import org.mozilla.gecko.activitystream.ActivityStream;
-import org.mozilla.gecko.db.BrowserContract.SuggestedSites;
-import org.mozilla.gecko.feeds.FeedService;
-import org.mozilla.gecko.feeds.action.CheckForUpdatesAction;
-import org.mozilla.gecko.mma.MmaDelegate;
-import org.mozilla.gecko.permissions.Permissions;
-import org.mozilla.gecko.restrictions.Restrictable;
-import org.mozilla.gecko.restrictions.Restrictions;
-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.BundleEventListener;
-import org.mozilla.gecko.util.ContextUtils;
-import org.mozilla.gecko.util.EventCallback;
-import org.mozilla.gecko.util.GeckoBundle;
-import org.mozilla.gecko.util.HardwareUtils;
-import org.mozilla.gecko.util.InputOptionsUtils;
-import org.mozilla.gecko.util.ThreadUtils;
-import org.mozilla.gecko.util.ViewUtil;
-
+import android.Manifest;
 import android.annotation.TargetApi;
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.Fragment;
 import android.app.FragmentManager;
 import android.app.NotificationManager;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
 import android.content.res.Configuration;
-import android.Manifest;
-import android.os.Build;
 import android.os.Bundle;
 import android.preference.CheckBoxPreference;
 import android.preference.EditTextPreference;
 import android.preference.ListPreference;
 import android.preference.Preference;
 import android.preference.Preference.OnPreferenceChangeListener;
 import android.preference.Preference.OnPreferenceClickListener;
 import android.preference.PreferenceActivity;
@@ -85,17 +42,53 @@ 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 org.mozilla.gecko.switchboard.SwitchBoard;
+import org.json.JSONArray;
+import org.mozilla.gecko.AboutPages;
+import org.mozilla.gecko.AdjustConstants;
+import org.mozilla.gecko.AppConstants;
+import org.mozilla.gecko.BrowserApp;
+import org.mozilla.gecko.BrowserLocaleManager;
+import org.mozilla.gecko.DataReportingNotification;
+import org.mozilla.gecko.DynamicToolbar;
+import org.mozilla.gecko.EventDispatcher;
+import org.mozilla.gecko.GeckoApplication;
+import org.mozilla.gecko.GeckoProfile;
+import org.mozilla.gecko.GeckoSharedPrefs;
+import org.mozilla.gecko.LocaleManager;
+import org.mozilla.gecko.Locales;
+import org.mozilla.gecko.PrefsHelper;
+import org.mozilla.gecko.R;
+import org.mozilla.gecko.SnackbarBuilder;
+import org.mozilla.gecko.Telemetry;
+import org.mozilla.gecko.TelemetryContract;
+import org.mozilla.gecko.TelemetryContract.Method;
+import org.mozilla.gecko.db.BrowserContract.SuggestedSites;
+import org.mozilla.gecko.mma.MmaDelegate;
+import org.mozilla.gecko.permissions.Permissions;
+import org.mozilla.gecko.restrictions.Restrictable;
+import org.mozilla.gecko.restrictions.Restrictions;
+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.BundleEventListener;
+import org.mozilla.gecko.util.ContextUtils;
+import org.mozilla.gecko.util.EventCallback;
+import org.mozilla.gecko.util.GeckoBundle;
+import org.mozilla.gecko.util.HardwareUtils;
+import org.mozilla.gecko.util.InputOptionsUtils;
+import org.mozilla.gecko.util.ThreadUtils;
+import org.mozilla.gecko.util.ViewUtil;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -150,18 +143,16 @@ public class GeckoPreferences
     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_HOMEPAGE_FOR_EVERY_NEW_TAB = NON_PREF_PREFIX + "newtab.load_homepage";
     public static final String PREFS_HOMEPAGE_PARTNER_COPY = GeckoPreferences.PREFS_HOMEPAGE + ".partner";
     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";
-    public static final String PREFS_NOTIFICATIONS_CONTENT_LEARN_MORE = NON_PREF_PREFIX + "notifications.content.learn_more";
     public static final String PREFS_NOTIFICATIONS_WHATS_NEW = NON_PREF_PREFIX + "notifications.whats_new";
     public static final String PREFS_APP_UPDATE_LAST_BUILD_ID = "app.update.last_build_id";
     public static final String PREFS_READ_PARTNER_CUSTOMIZATIONS_PROVIDER = NON_PREF_PREFIX + "distribution.read_partner_customizations_provider";
     public static final String PREFS_READ_PARTNER_BOOKMARKS_PROVIDER = NON_PREF_PREFIX + "distribution.read_partner_bookmarks_provider";
     public static final String PREFS_CUSTOM_TABS = NON_PREF_PREFIX + "customtabs";
     public static final String PREFS_PWA = NON_PREF_PREFIX + "pwa";
     public static final String PREFS_CATEGORY_EXPERIMENTAL_FEATURES = NON_PREF_PREFIX + "category_experimental";
     public static final String PREFS_COMPACT_TABS = NON_PREF_PREFIX + "compact_tabs";
@@ -410,23 +401,16 @@ public class GeckoPreferences
         // capture EXTRA_SHOW_FRAGMENT_TITLE from the intent and store the title ID.
 
         // If launched from notification, explicitly cancel the notification.
         if (intentExtras != null && intentExtras.containsKey(DataReportingNotification.ALERT_NAME_DATAREPORTING_NOTIFICATION)) {
             Telemetry.sendUIEvent(TelemetryContract.Event.LAUNCH, Method.NOTIFICATION, "settings-data-choices");
             NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
             notificationManager.cancel(DataReportingNotification.ALERT_NAME_DATAREPORTING_NOTIFICATION.hashCode());
         }
-
-        // Launched from "Notifications settings" action button in a notification.
-        if (intentExtras != null && intentExtras.containsKey(CheckForUpdatesAction.EXTRA_CONTENT_NOTIFICATION)) {
-            Telemetry.startUISession(TelemetryContract.Session.EXPERIMENT, FeedService.getEnabledExperiment(this));
-            Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, Method.BUTTON, "notification-settings");
-            Telemetry.stopUISession(TelemetryContract.Session.EXPERIMENT, FeedService.getEnabledExperiment(this));
-        }
     }
 
     /**
      * Set intent to display top-level settings fragment,
      * and show the correct title.
      */
     private void setupTopLevelFragmentIntent() {
         Intent intent = getIntent();
@@ -844,23 +828,16 @@ public class GeckoPreferences
                     final String url = getResources().getString(R.string.feedback_link, AppConstants.MOZ_APP_VERSION, AppConstants.MOZ_UPDATE_CHANNEL);
                     ((LinkPreference) pref).setUrl(url);
                 } else if (PREFS_DYNAMIC_TOOLBAR.equals(key)) {
                     if (DynamicToolbar.isForceDisabled()) {
                         preferences.removePreference(pref);
                         i--;
                         continue;
                     }
-                } else if (PREFS_NOTIFICATIONS_CONTENT.equals(key) ||
-                        PREFS_NOTIFICATIONS_CONTENT_LEARN_MORE.equals(key)) {
-                    if (!FeedService.isInExperiment(this)) {
-                        preferences.removePreference(pref);
-                        i--;
-                        continue;
-                    }
                 } else if (PREFS_CUSTOM_TABS.equals(key) && !AppConstants.MOZ_ANDROID_CUSTOM_TABS) {
                     preferences.removePreference(pref);
                     i--;
                     continue;
                 } else if (PREFS_PWA.equals(key) && !AppConstants.MOZ_ANDROID_PWA) {
                     preferences.removePreference(pref);
                     i--;
                     continue;
@@ -1174,18 +1151,16 @@ public class GeckoPreferences
                 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);
         } else if (PREFS_SEARCH_SUGGESTIONS_ENABLED.equals(prefName)) {
             // Tell Gecko to transmit the current search engine data again, so
             // BrowserSearch is notified immediately about the new enabled state.
             EventDispatcher.getInstance().dispatch("SearchEngines:GetVisible", null);
         }
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -201,18 +201,16 @@
 <!ENTITY pref_search_hint2 "TIP: Add any website to your list of search providers by long-pressing on its search field and then touching the &formatI; icon.">
 <!ENTITY pref_category_advanced "Advanced">
 <!-- Localization note (pref_category_advanced_summary3): “data saver” in this
      context means consuming less data, e.g. by not loading images, not
      “storing data”. -->
 <!ENTITY pref_category_advanced_summary3 "Restore tabs, data saver, developer tools">
 <!ENTITY pref_category_notifications "Notifications">
 <!ENTITY pref_category_notifications_summary "New features, website updates">
-<!ENTITY pref_content_notifications "Website updates">
-<!ENTITY pref_content_notifications_summary2 "Discover new content from supported sites">
 <!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">
 <!ENTITY pref_category_home_summary "Customize your homepage">
@@ -330,33 +328,16 @@
 <!-- Localization note (tab_queue_notification_text_singular2) : This is the
      text of a notification; we expect only one tab queued. -->
 <!ENTITY tab_queue_notification_text_singular2 "1 tab waiting">
 
 <!-- Localization note (tab_queue_notification_settings): This notification text is shown if a tab
      has been queued but we are missing the system permission to show an overlay. -->
 <!ENTITY tab_queue_notification_settings "To \&quot;Open multiple links\&quot;, please enable the \'Draw over other apps\' permission for &brandShortName;">
 
-<!ENTITY content_notification_summary "&brandShortName;">
-<!-- Localization note (content_notification_title_plural): &formatD; will be replaced with the number of websites that
-     have been updated (new content is available). The number of websites is always more than one (>= 2). For a single
-     update the website title is used instead of this string.
-     We can't use Android plural forms, sadly. See Bug #753859. -->
-<!ENTITY content_notification_title_plural "&formatD; websites updated">
-<!-- Localization note (content_notification_action_settings2): This label will be shown as an action in a content notification.
-     Clicking the action will jump to the notification settings of the app. -->
-<!ENTITY content_notification_action_settings2 "Settings">
-<!-- Localization note(content_notification_action_read_now): This label will be shown as an action in a content notification.
-     Clicking the action will open all new content in the browser. -->
-<!ENTITY content_notification_action_read_now "Read now">
-<!-- Localization note (content_notification_updated_on): &formatS; will be replaced with a medium sized version of the
-     date, depending on locale. For en_US this is for example: Feb 24, 2016. For more details see the Android developer
-     documentation for DateFormat.getMediumDateFormat(). -->
-<!ENTITY content_notification_updated_on "Updated on &formatS;">
-
 <!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 private data">
 <!-- Localization note (pref_clear_private_data_now_tablet): This action to clear private data is only shown on tablets.
      The action is shown below a header saying "Clear private data"; See pref_clear_private_data -->
 <!ENTITY pref_clear_private_data_now_tablet "Clear now">
 <!ENTITY pref_clear_on_exit_title3 "Clear private data on exit">
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -548,17 +548,16 @@ gbjar.sources += ['java/org/mozilla/geck
     'ANRReporter.java',
     'bookmarks/BookmarkEditFragment.java',
     'bookmarks/BookmarkUtils.java',
     'bookmarks/CreateFolderCallback.java',
     'bookmarks/CreateFolderFragment.java',
     'bookmarks/EditBookmarkTask.java',
     'bookmarks/SelectFolderCallback.java',
     'bookmarks/SelectFolderFragment.java',
-    'BootReceiver.java',
     'BrowserApp.java',
     'BrowserLocaleManager.java',
     'cleanup/FileCleanupController.java',
     'cleanup/FileCleanupService.java',
     'CustomEditText.java',
     'customtabs/ActionBarPresenter.java',
     'customtabs/CustomTabsActivity.java',
     'customtabs/CustomTabsSecurityPopup.java',
@@ -624,35 +623,16 @@ gbjar.sources += ['java/org/mozilla/geck
     'dlc/VerifyAction.java',
     'DoorHangerPopup.java',
     'DownloadsIntegration.java',
     'drawable/DrawableWrapper.java',
     'drawable/ShiftDrawable.java',
     'DynamicToolbar.java',
     'EditBookmarkDialog.java',
     'Experiments.java',
-    'feeds/action/CheckForUpdatesAction.java',
-    'feeds/action/EnrollSubscriptionsAction.java',
-    'feeds/action/FeedAction.java',
-    'feeds/action/SetupAlarmsAction.java',
-    'feeds/action/SubscribeToFeedAction.java',
-    'feeds/action/WithdrawSubscriptionsAction.java',
-    'feeds/ContentNotificationsDelegate.java',
-    'feeds/FeedAlarmReceiver.java',
-    'feeds/FeedFetcher.java',
-    'feeds/FeedService.java',
-    'feeds/knownsites/KnownSite.java',
-    'feeds/knownsites/KnownSiteBlogger.java',
-    'feeds/knownsites/KnownSiteMedium.java',
-    'feeds/knownsites/KnownSiteTumblr.java',
-    'feeds/knownsites/KnownSiteWordpress.java',
-    'feeds/parser/Feed.java',
-    'feeds/parser/Item.java',
-    'feeds/parser/SimpleFeedParser.java',
-    'feeds/subscriptions/FeedSubscription.java',
     'FilePicker.java',
     'FilePickerResultHandler.java',
     'FindInPageBar.java',
     'firstrun/DataPanel.java',
     'firstrun/FirstrunAnimationContainer.java',
     'firstrun/FirstrunPager.java',
     'firstrun/FirstrunPagerConfig.java',
     'firstrun/FirstrunPanel.java',
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -164,18 +164,16 @@
   <string name="pref_category_advanced">&pref_category_advanced;</string>
   <string name="pref_category_advanced_summary">&pref_category_advanced_summary3;</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_category_notifications_summary">&pref_category_notifications_summary;</string>
-  <string name="pref_content_notifications">&pref_content_notifications;</string>
-  <string name="pref_content_notifications_summary">&pref_content_notifications_summary2;</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="pref_home_updates_wifi">&pref_home_updates_wifi;</string>
   <string name="pref_category_home_add_ons">&pref_category_home_add_ons;</string>
   <string name="pref_home_updates">&pref_home_updates2;</string>
   <string name="pref_home_updates_enabled">&pref_home_updates_enabled;</string>
@@ -299,22 +297,16 @@
   <string name="tab_queue_prompt_settings_button">&tab_queue_prompt_settings_button;</string>
   <string name="tab_queue_toast_message">&tab_queue_toast_message3;</string>
   <string name="tab_queue_toast_action">&tab_queue_toast_action;</string>
   <string name="tab_queue_notification_text_singular">&tab_queue_notification_text_singular2;</string>
   <string name="tab_queue_notification_text_plural">&tab_queue_notification_text_plural2;</string>
   <string name="tab_queue_notification_title">&tab_queue_notification_title;</string>
   <string name="tab_queue_notification_settings">&tab_queue_notification_settings;</string>
 
-  <string name="content_notification_summary">&content_notification_summary;</string>
-  <string name="content_notification_title_plural">&content_notification_title_plural;</string>
-  <string name="content_notification_action_settings">&content_notification_action_settings2;</string>
-  <string name="content_notification_action_read_now">&content_notification_action_read_now;</string>
-  <string name="content_notification_updated_on">&content_notification_updated_on;</string>
-
   <string name="pref_default_browser">&pref_default_browser;</string>
   <string name="pref_default_browser_mozilla_support_tablet">&pref_default_browser_mozilla_support_tablet;</string>
 
   <string name="pref_about_firefox">&pref_about_firefox;</string>
 
   <string name="pref_vendor_faqs">&pref_vendor_faqs;</string>
   <!-- https://support.mozilla.org/1/mobile/%VERSION%/%OS%/%LOCALE%/faq -->
   <string name="faq_link">https://support.mozilla.org/1/mobile/&formatS1;/&formatS2;/&formatS3;/faq</string>
deleted file mode 100644
--- a/mobile/android/tests/background/junit4/src/org/mozilla/gecko/feeds/knownsites/TestKnownSiteBlogger.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.feeds.knownsites;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mozilla.gecko.background.testhelpers.TestRunner;
-import org.mozilla.gecko.helpers.AssertUtil;
-
-@RunWith(TestRunner.class)
-public class TestKnownSiteBlogger {
-    /**
-     * Test that the search string is a substring of some known URLs.
-     */
-    @Test
-    public void testURLSearchString() {
-        final KnownSite blogger = new KnownSiteBlogger();
-        final String searchString = blogger.getURLSearchString();
-
-        AssertUtil.assertContains(
-                "http://mykzilla.blogspot.com/",
-                searchString);
-
-        AssertUtil.assertContains(
-                "http://example.blogspot.com",
-                searchString);
-
-        AssertUtil.assertContains(
-                "https://mykzilla.blogspot.com/2015/06/introducing-pluotsorbet.html",
-                searchString);
-
-        AssertUtil.assertContains(
-                "http://android-developers.blogspot.com/2016/02/android-support-library-232.html",
-                searchString);
-
-        AssertUtil.assertContainsNot(
-                "http://www.mozilla.org",
-                searchString);
-    }
-
-    /**
-     * Test that we get a feed URL for valid Blogger URLs.
-     */
-    @Test
-    public void testGettingFeedFromURL() {
-        final KnownSite blogger = new KnownSiteBlogger();
-
-        Assert.assertEquals(
-                "https://mykzilla.blogspot.com/feeds/posts/default",
-                blogger.getFeedFromURL("http://mykzilla.blogspot.com/"));
-
-        Assert.assertEquals(
-                "https://example.blogspot.com/feeds/posts/default",
-                blogger.getFeedFromURL("http://example.blogspot.com"));
-
-        Assert.assertEquals(
-                "https://mykzilla.blogspot.com/feeds/posts/default",
-                blogger.getFeedFromURL("https://mykzilla.blogspot.com/2015/06/introducing-pluotsorbet.html"));
-
-        Assert.assertEquals(
-                "https://android-developers.blogspot.com/feeds/posts/default",
-                blogger.getFeedFromURL("http://android-developers.blogspot.com/2016/02/android-support-library-232.html"));
-
-        Assert.assertEquals(
-                "https://example.blogspot.com/feeds/posts/default",
-                blogger.getFeedFromURL("http://example.blogspot.com/2016/03/i-moved-to-example.blogspot.com"));
-
-        Assert.assertNull(blogger.getFeedFromURL("http://www.mozilla.org"));
-    }
-}
deleted file mode 100644
--- a/mobile/android/tests/background/junit4/src/org/mozilla/gecko/feeds/knownsites/TestKnownSiteMedium.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.feeds.knownsites;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mozilla.gecko.background.testhelpers.TestRunner;
-import org.mozilla.gecko.helpers.AssertUtil;
-
-@RunWith(TestRunner.class)
-public class TestKnownSiteMedium {
-    /**
-     * Test that the search string is a substring of some known URLs.
-     */
-    @Test
-    public void testURLSearchString() {
-        final KnownSite medium = new KnownSiteMedium();
-        final String searchString = medium.getURLSearchString();
-
-        AssertUtil.assertContains(
-                "https://medium.com/@Antlam/",
-                searchString);
-
-        AssertUtil.assertContains(
-                "https://medium.com/google-developers",
-                searchString);
-
-        AssertUtil.assertContains(
-                "http://medium.com/@brandonshin/how-slackbot-forced-us-to-workout-7b4741a2de73",
-                searchString
-        );
-
-        AssertUtil.assertContainsNot(
-                "http://www.mozilla.org",
-                searchString);
-    }
-
-    /**
-     * Test that we get a feed URL for valid Medium URLs.
-     */
-    @Test
-    public void testGettingFeedFromURL() {
-        final KnownSite medium = new KnownSiteMedium();
-
-        Assert.assertEquals(
-                "https://medium.com/feed/@Antlam",
-                medium.getFeedFromURL("https://medium.com/@Antlam/")
-        );
-
-        Assert.assertEquals(
-                "https://medium.com/feed/google-developers",
-                medium.getFeedFromURL("https://medium.com/google-developers")
-        );
-
-        Assert.assertEquals(
-                "https://medium.com/feed/@brandonshin",
-                medium.getFeedFromURL("http://medium.com/@brandonshin/how-slackbot-forced-us-to-workout-7b4741a2de73")
-        );
-
-        Assert.assertNull(medium.getFeedFromURL("http://www.mozilla.org"));
-    }
-}
deleted file mode 100644
--- a/mobile/android/tests/background/junit4/src/org/mozilla/gecko/feeds/knownsites/TestKnownSiteTumblr.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.feeds.knownsites;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mozilla.gecko.background.testhelpers.TestRunner;
-import org.mozilla.gecko.helpers.AssertUtil;
-
-@RunWith(TestRunner.class)
-public class TestKnownSiteTumblr {
-    /**
-     * Test that the search string is a substring of some known URLs.
-     */
-    @Test
-    public void testURLSearchString() {
-        final KnownSite tumblr = new KnownSiteTumblr();
-        final String searchString = tumblr.getURLSearchString();
-
-        AssertUtil.assertContains(
-                "http://contentnotifications.tumblr.com/",
-                searchString);
-
-        AssertUtil.assertContains(
-                "https://contentnotifications.tumblr.com",
-                searchString);
-
-        AssertUtil.assertContains(
-                "http://contentnotifications.tumblr.com/post/142684202402/content-notification-firefox-for-android-480",
-                searchString);
-
-        AssertUtil.assertContainsNot(
-                "http://www.mozilla.org",
-                searchString);
-    }
-
-    /**
-     * Test that we get a feed URL for valid Medium URLs.
-     */
-    @Test
-    public void testGettingFeedFromURL() {
-        final KnownSite tumblr = new KnownSiteTumblr();
-
-        Assert.assertEquals(
-                "http://contentnotifications.tumblr.com/rss",
-                tumblr.getFeedFromURL("http://contentnotifications.tumblr.com/")
-        );
-
-        Assert.assertEquals(
-                "http://staff.tumblr.com/rss",
-                tumblr.getFeedFromURL("https://staff.tumblr.com/post/141928246566/replies-are-back-and-the-sun-is-shining-on-the")
-        );
-
-        Assert.assertNull(tumblr.getFeedFromURL("https://www.tumblr.com"));
-
-        Assert.assertNull(tumblr.getFeedFromURL("http://www.mozilla.org"));
-    }
-}
deleted file mode 100644
--- a/mobile/android/tests/background/junit4/src/org/mozilla/gecko/feeds/parser/TestSimpleFeedParser.java
+++ /dev/null
@@ -1,323 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.feeds.parser;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mozilla.gecko.background.testhelpers.TestRunner;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedReader;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.UnsupportedEncodingException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.text.SimpleDateFormat;
-import java.util.Locale;
-
-@RunWith(TestRunner.class)
-public class TestSimpleFeedParser {
-    /**
-     * Parse and verify the RSS example from Wikipedia:
-     * https://en.wikipedia.org/wiki/RSS#Example
-     */
-    @Test
-    public void testRSSExample() throws Exception {
-        InputStream stream = openFeed("feed_rss_wikipedia.xml");
-
-        SimpleFeedParser parser = new SimpleFeedParser();
-        Feed feed = parser.parse(stream);
-
-        Assert.assertNotNull(feed);
-        Assert.assertEquals("RSS Title", feed.getTitle());
-        Assert.assertEquals("http://www.example.com/main.html", feed.getWebsiteURL());
-        Assert.assertNull(feed.getFeedURL());
-        Assert.assertTrue(feed.isSufficientlyComplete());
-
-        Item item = feed.getLastItem();
-
-        Assert.assertNotNull(item);
-        Assert.assertEquals("Example entry", item.getTitle());
-        Assert.assertEquals("http://www.example.com/blog/post/1", item.getURL());
-        Assert.assertEquals(1252254000000L, item.getTimestamp());
-    }
-
-    /**
-     * Parse and verify the ATOM example from Wikipedia:
-     * https://en.wikipedia.org/wiki/Atom_%28standard%29#Example_of_an_Atom_1.0_feed
-     */
-    @Test
-    public void testATOMExample() throws Exception {
-        InputStream stream = openFeed("feed_atom_wikipedia.xml");
-
-        SimpleFeedParser parser = new SimpleFeedParser();
-        Feed feed = parser.parse(stream);
-
-        Assert.assertNotNull(feed);
-        Assert.assertEquals("Example Feed", feed.getTitle());
-        Assert.assertEquals("http://example.org/", feed.getWebsiteURL());
-        Assert.assertEquals("http://example.org/feed/", feed.getFeedURL());
-        Assert.assertTrue(feed.isSufficientlyComplete());
-
-        Item item = feed.getLastItem();
-
-        Assert.assertNotNull(item);
-        Assert.assertEquals("Atom-Powered Robots Run Amok", item.getTitle());
-        Assert.assertEquals("http://example.org/2003/12/13/atom03.html", item.getURL());
-        Assert.assertEquals(1071340202000L, item.getTimestamp());
-    }
-
-    /**
-     * Parse and verify a snapshot of a Medium feed.
-     */
-    @Test
-    public void testMediumFeed() throws Exception {
-        InputStream stream = openFeed("feed_rss_medium.xml");
-
-        SimpleFeedParser parser = new SimpleFeedParser();
-        Feed feed = parser.parse(stream);
-
-        Assert.assertNotNull(feed);
-        Assert.assertEquals("Anthony Lam on Medium", feed.getTitle());
-        Assert.assertEquals("https://medium.com/@antlam?source=rss-59f49b9e4b19------2", feed.getWebsiteURL());
-        Assert.assertEquals("https://medium.com/feed/@antlam", feed.getFeedURL());
-        Assert.assertTrue(feed.isSufficientlyComplete());
-
-        Item item = feed.getLastItem();
-
-        Assert.assertNotNull(item);
-        Assert.assertEquals("UX thoughts for 2016", item.getTitle());
-        Assert.assertEquals("https://medium.com/@antlam/ux-thoughts-for-2016-1fc1d6e515e8?source=rss-59f49b9e4b19------2", item.getURL());
-        Assert.assertEquals(1452537838000L, item.getTimestamp());
-    }
-
-    /**
-     * Parse and verify a snapshot of planet.mozilla.org ATOM feed.
-     */
-    @Test
-    public void testPlanetMozillaATOMFeed() throws Exception {
-        InputStream stream = openFeed("feed_atom_planetmozilla.xml");
-
-        SimpleFeedParser parser = new SimpleFeedParser();
-        Feed feed = parser.parse(stream);
-
-        Assert.assertNotNull(feed);
-        Assert.assertEquals("Planet Mozilla", feed.getTitle());
-        Assert.assertEquals("http://planet.mozilla.org/", feed.getWebsiteURL());
-        Assert.assertEquals("http://planet.mozilla.org/atom.xml", feed.getFeedURL());
-        Assert.assertTrue(feed.isSufficientlyComplete());
-
-        Item item = feed.getLastItem();
-
-        Assert.assertNotNull(item);
-        Assert.assertEquals("Firefox 45.0 Beta 3 Testday, February 5th", item.getTitle());
-        Assert.assertEquals("https://quality.mozilla.org/2016/01/firefox-45-0-beta-3-testday-february-5th/", item.getURL());
-        Assert.assertEquals(1453819255000L, item.getTimestamp());
-    }
-
-    /**
-     * Parse and verify a snapshot of planet.mozilla.org RSS 2.0 feed.
-     */
-    @Test
-    public void testPlanetMozillaRSS20Feed() throws Exception {
-        InputStream stream = openFeed("feed_rss20_planetmozilla.xml");
-
-        SimpleFeedParser parser = new SimpleFeedParser();
-        Feed feed = parser.parse(stream);
-
-        Assert.assertNotNull(feed);
-        Assert.assertEquals("Planet Mozilla", feed.getTitle());
-        Assert.assertEquals("http://planet.mozilla.org/", feed.getWebsiteURL());
-        Assert.assertEquals("http://planet.mozilla.org/rss20.xml", feed.getFeedURL());
-        Assert.assertTrue(feed.isSufficientlyComplete());
-
-        Item item = feed.getLastItem();
-
-        Assert.assertNotNull(item);
-        Assert.assertEquals("Aaron Klotz: Announcing Mozdbgext", item.getTitle());
-        Assert.assertEquals("http://dblohm7.ca/blog/2016/01/26/announcing-mozdbgext/", item.getURL());
-        Assert.assertEquals(1453837500000L, item.getTimestamp());
-    }
-
-    /**
-     * Parse and verify a snapshot of planet.mozilla.org RSS 1.0 feed.
-     */
-    @Test
-    public void testPlanetMozillaRSS10Feed() throws Exception {
-        InputStream stream = openFeed("feed_rss10_planetmozilla.xml");
-
-        SimpleFeedParser parser = new SimpleFeedParser();
-        Feed feed = parser.parse(stream);
-
-        Assert.assertNotNull(feed);
-        Assert.assertEquals("Planet Mozilla", feed.getTitle());
-        Assert.assertEquals("http://planet.mozilla.org/", feed.getWebsiteURL());
-        Assert.assertEquals("http://planet.mozilla.org/rss10.xml", feed.getFeedURL());
-        Assert.assertTrue(feed.isSufficientlyComplete());
-
-        Item item = feed.getLastItem();
-
-        Assert.assertNotNull(item);
-        Assert.assertEquals("Aaron Klotz: Announcing Mozdbgext", item.getTitle());
-        Assert.assertEquals("http://dblohm7.ca/blog/2016/01/26/announcing-mozdbgext/", item.getURL());
-        Assert.assertEquals(1453837500000L, item.getTimestamp());
-    }
-
-    /**
-     * Parse an verify a snapshot of a feedburner ATOM feed.
-     */
-    @Test
-    public void testFeedburnerAtomFeed() throws Exception {
-        InputStream stream = openFeed("feed_atom_feedburner.xml");
-
-        SimpleFeedParser parser = new SimpleFeedParser();
-        Feed feed = parser.parse(stream);
-
-        Assert.assertNotNull(feed);
-        Assert.assertEquals("Android Zeitgeist", feed.getTitle());
-        Assert.assertEquals("http://www.androidzeitgeist.com/", feed.getWebsiteURL());
-        Assert.assertEquals("http://feeds.feedburner.com/AndroidZeitgeist", feed.getFeedURL());
-        Assert.assertTrue(feed.isSufficientlyComplete());
-
-        Item item = feed.getLastItem();
-
-        Assert.assertNotNull(item);
-        Assert.assertEquals("Support for restricted profiles in Firefox 42", item.getTitle());
-        Assert.assertEquals("http://feedproxy.google.com/~r/AndroidZeitgeist/~3/xaSicfGuwOU/support-restricted-profiles-firefox.html", item.getURL());
-        Assert.assertEquals(1442511968239L, item.getTimestamp());
-    }
-
-    /**
-     * Parse and verify a snapshot of a Tumblr RSS feed.
-     */
-    @Test
-    public void testTumblrRssFeed() throws Exception {
-        InputStream stream = openFeed("feed_rss_tumblr.xml");
-
-        SimpleFeedParser parser = new SimpleFeedParser();
-        Feed feed = parser.parse(stream);
-
-        Assert.assertNotNull(feed);
-        Assert.assertEquals("Tumblr Staff", feed.getTitle());
-        Assert.assertEquals("http://staff.tumblr.com/", feed.getWebsiteURL());
-        Assert.assertNull(feed.getFeedURL());
-        Assert.assertTrue(feed.isSufficientlyComplete());
-
-        Item item = feed.getLastItem();
-
-        Assert.assertNotNull(item);
-        Assert.assertEquals("hardyboyscovers: Can Nancy Drew see things through and solve...", item.getTitle());
-        Assert.assertEquals("http://staff.tumblr.com/post/138124026275", item.getURL());
-        Assert.assertEquals(1453861812000L, item.getTimestamp());
-    }
-
-    /**
-     * Parse and verify a snapshot of a Spiegel (German news magazine) RSS feed.
-     */
-    @Test
-    public void testSpiegelRssFeed() throws Exception {
-        InputStream stream = openFeed("feed_rss_spon.xml");
-
-        SimpleFeedParser parser = new SimpleFeedParser();
-        Feed feed = parser.parse(stream);
-
-        Assert.assertNotNull(feed);
-        Assert.assertEquals("SPIEGEL ONLINE - Schlagzeilen", feed.getTitle());
-        Assert.assertEquals("http://www.spiegel.de", feed.getWebsiteURL());
-        Assert.assertNull(feed.getFeedURL());
-        Assert.assertTrue(feed.isSufficientlyComplete());
-
-        Item item = feed.getLastItem();
-
-        Assert.assertNotNull(item);
-        Assert.assertEquals("Angebliche Vergewaltigung einer 13-Jährigen: Steinmeier kanzelt russischen Minister Lawrow ab", item.getTitle());
-        Assert.assertEquals("http://www.spiegel.de/politik/ausland/steinmeier-kanzelt-lawrow-ab-aerger-um-angebliche-vergewaltigung-a-1074292.html#ref=rss", item.getURL());
-        Assert.assertEquals(1453914976000L, item.getTimestamp());
-    }
-
-    /**
-     * Parse and verify a snapshot of a Heise (German tech news) RSS feed.
-     */
-    @Test
-    public void testHeiseRssFeed() throws Exception {
-        InputStream stream = openFeed("feed_rss_heise.xml");
-
-        SimpleFeedParser parser = new SimpleFeedParser();
-        Feed feed = parser.parse(stream);
-
-        Assert.assertNotNull(feed);
-        Assert.assertEquals("heise online News", feed.getTitle());
-        Assert.assertEquals("http://www.heise.de/newsticker/", feed.getWebsiteURL());
-        Assert.assertNull(feed.getFeedURL());
-        Assert.assertTrue(feed.isSufficientlyComplete());
-
-        Item item = feed.getLastItem();
-
-        Assert.assertNotNull(item);
-        Assert.assertEquals("Google: “Dramatische Verbesserungen” für Chrome in iOS", item.getTitle());
-        Assert.assertEquals("http://www.heise.de/newsticker/meldung/Google-Dramatische-Verbesserungen-fuer-Chrome-in-iOS-3085808.html?wt_mc=rss.ho.beitrag.atom", item.getURL());
-        Assert.assertEquals(1453915920000L, item.getTimestamp());
-    }
-
-    @Test
-    public void testWordpressFeed() throws Exception {
-        InputStream stream = openFeed("feed_rss_wordpress.xml");
-
-        SimpleFeedParser parser = new SimpleFeedParser();
-        Feed feed = parser.parse(stream);
-
-        Assert.assertNotNull(feed);
-        Assert.assertEquals("justasimpletest2016", feed.getTitle());
-        Assert.assertEquals("https://justasimpletest2016.wordpress.com", feed.getWebsiteURL());
-        Assert.assertEquals("https://justasimpletest2016.wordpress.com/feed/", feed.getFeedURL());
-        Assert.assertTrue(feed.isSufficientlyComplete());
-
-        Item item = feed.getLastItem();
-
-        Assert.assertNotNull(item);
-        Assert.assertEquals("Hello World!", item.getTitle());
-        Assert.assertEquals("https://justasimpletest2016.wordpress.com/2016/02/26/hello-world/", item.getURL());
-        Assert.assertEquals(1456524466000L, item.getTimestamp());
-    }
-
-    /**
-     * Parse and test a snapshot of mykzilla.blogspot.com
-     */
-    @Test
-    public void testBloggerFeed() throws Exception {
-        InputStream stream = openFeed("feed_atom_blogger.xml");
-
-        SimpleFeedParser parser = new SimpleFeedParser();
-        Feed feed = parser.parse(stream);
-
-        Assert.assertNotNull(feed);
-        Assert.assertEquals("mykzilla", feed.getTitle());
-        Assert.assertEquals("http://mykzilla.blogspot.com/", feed.getWebsiteURL());
-        Assert.assertEquals("http://www.blogger.com/feeds/18929277/posts/default", feed.getFeedURL());
-        Assert.assertTrue(feed.isSufficientlyComplete());
-
-        Item item = feed.getLastItem();
-
-        Assert.assertNotNull(item);
-        Assert.assertEquals("URL Has Been Changed", item.getTitle());
-        Assert.assertEquals("http://mykzilla.blogspot.com/2016/01/url-has-been-changed.html", item.getURL());
-        Assert.assertEquals(1452531451366L, item.getTimestamp());
-    }
-
-    private InputStream openFeed(String fileName) throws URISyntaxException, FileNotFoundException, UnsupportedEncodingException {
-        URL url = getClass().getResource("/" + fileName);
-        if (url == null) {
-            throw new FileNotFoundException(fileName);
-        }
-
-        return new BufferedInputStream(new FileInputStream(url.getPath()));
-    }
-}