Bug 1396604 - Remove content notifications code. r=JanH,nechen
authorSebastian Kaspari <s.kaspari@gmail.com>
Mon, 04 Sep 2017 16:51:07 +0200
changeset 379314 ebc53301e8df237714c6aac6955078177c4e5ea8
parent 379313 3f4f3fa121615e0ba5f54bef8eb6437daf493d40
child 379315 6c13864a1bee068297569066afb4f234d77ed9c7
push id50638
push users.kaspari@gmail.com
push dateThu, 07 Sep 2017 08:59:18 +0000
treeherderautoland@ebc53301e8df [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersJanH, nechen
bugs1396604
milestone57.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1396604 - Remove content notifications code. r=JanH,nechen 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()));
-    }
-}