Bug 1045085 - Remove main Product Announcements code. r=mcomella, a=lmandel
💩💩 backed out by 70930f30da0e 💩 💩
authorRichard Newman <rnewman@mozilla.com>
Thu, 31 Jul 2014 11:24:02 -0700
changeset 216675 776ddfd41f21
parent 216674 880228a5208a
child 216676 70930f30da0e
push id3871
push userryanvm@gmail.com
push date2014-09-08 18:01 +0000
treeherdermozilla-beta@776ddfd41f21 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmcomella, lmandel
bugs1045085
milestone33.0
Bug 1045085 - Remove main Product Announcements code. r=mcomella, a=lmandel
mobile/android/base/android-services.mozbuild
mobile/android/base/background/announcements/Announcement.java
mobile/android/base/background/announcements/AnnouncementPresenter.java
mobile/android/base/background/announcements/AnnouncementsBroadcastReceiver.java
mobile/android/base/background/announcements/AnnouncementsBroadcastService.java
mobile/android/base/background/announcements/AnnouncementsConstants.java.in
mobile/android/base/background/announcements/AnnouncementsFetchDelegate.java
mobile/android/base/background/announcements/AnnouncementsFetchResourceDelegate.java
mobile/android/base/background/announcements/AnnouncementsFetcher.java
mobile/android/base/background/announcements/AnnouncementsService.java
mobile/android/base/background/common/GlobalConstants.java.in
mobile/android/services/manifests/AnnouncementsAndroidManifest_activities.xml.in
mobile/android/services/manifests/AnnouncementsAndroidManifest_permissions.xml.in
mobile/android/services/manifests/AnnouncementsAndroidManifest_services.xml.in
mobile/android/tests/background/junit3/background_junit3_sources.mozbuild
mobile/android/tests/background/junit3/src/announcements/TestAnnouncementsBroadcastService.java
--- a/mobile/android/base/android-services.mozbuild
+++ b/mobile/android/base/android-services.mozbuild
@@ -467,24 +467,16 @@ sync_thirdparty_java_files = [
     'org/mozilla/apache/commons/codec/net/URLCodec.java',
     'org/mozilla/apache/commons/codec/net/Utils.java',
     'org/mozilla/apache/commons/codec/StringDecoder.java',
     'org/mozilla/apache/commons/codec/StringEncoder.java',
     'org/mozilla/apache/commons/codec/StringEncoderComparator.java',
 ]
 
 sync_java_files = [
-    'background/announcements/Announcement.java',
-    'background/announcements/AnnouncementPresenter.java',
-    'background/announcements/AnnouncementsBroadcastReceiver.java',
-    'background/announcements/AnnouncementsBroadcastService.java',
-    'background/announcements/AnnouncementsFetchDelegate.java',
-    'background/announcements/AnnouncementsFetcher.java',
-    'background/announcements/AnnouncementsFetchResourceDelegate.java',
-    'background/announcements/AnnouncementsService.java',
     'background/BackgroundService.java',
     'background/bagheera/BagheeraClient.java',
     'background/bagheera/BagheeraRequestDelegate.java',
     'background/bagheera/BoundedByteArrayEntity.java',
     'background/bagheera/DeflateHelper.java',
     'background/common/DateUtils.java',
     'background/common/log/Logger.java',
     'background/common/log/writers/AndroidLevelCachingLogWriter.java',
@@ -848,14 +840,13 @@ sync_java_files = [
     'sync/Utils.java',
     'tokenserver/TokenServerClient.java',
     'tokenserver/TokenServerClientDelegate.java',
     'tokenserver/TokenServerException.java',
     'tokenserver/TokenServerToken.java',
 ]
 
 sync_generated_java_files = [
-    'org/mozilla/gecko/background/announcements/AnnouncementsConstants.java',
     'org/mozilla/gecko/background/common/GlobalConstants.java',
     'org/mozilla/gecko/background/healthreport/HealthReportConstants.java',
     'org/mozilla/gecko/fxa/FxAccountConstants.java',
     'org/mozilla/gecko/sync/SyncConstants.java',
 ]
deleted file mode 100644
--- a/mobile/android/base/background/announcements/Announcement.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/* 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.background.announcements;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-
-import org.mozilla.gecko.background.common.log.Logger;
-import org.mozilla.gecko.sync.ExtendedJSONObject;
-
-/**
- * Represents a retrieved product announcement.
- *
- * Instances of this class are immutable.
- */
-public class Announcement {
-  private static final String LOG_TAG   = "Announcement";
-
-  private static final String KEY_ID    = "id";
-  private static final String KEY_TITLE = "title";
-  private static final String KEY_URL   = "url";
-  private static final String KEY_TEXT  = "text";
-
-  private final int id;
-  private final String title;
-  private final URI uri;
-  private final String text;
-
-  public Announcement(int id, String title, String text, URI uri) {
-    this.id    = id;
-    this.title = title;
-    this.uri   = uri;
-    this.text  = text;
-  }
-
-  public static Announcement parseAnnouncement(ExtendedJSONObject body) throws URISyntaxException, IllegalArgumentException {
-    final Integer id = body.getIntegerSafely(KEY_ID);
-    if (id == null) {
-      throw new IllegalArgumentException("No id provided in JSON.");
-    }
-    final String title = body.getString(KEY_TITLE);
-    if (title == null || title.trim().length() == 0) {
-      throw new IllegalArgumentException("Missing or empty announcement title.");
-    }
-    final String uri = body.getString(KEY_URL);
-    if (uri == null) {
-      // Empty or otherwise unhappy URI will throw a URISyntaxException.
-      throw new IllegalArgumentException("Missing announcement URI.");
-    }
-
-    final String text = body.getString(KEY_TEXT);
-    if (text == null) {
-      throw new IllegalArgumentException("Missing announcement body.");
-    }
-
-    return new Announcement(id, title, text, new URI(uri));
-  }
-
-  public int getId() {
-    return id;
-  }
-
-  public String getTitle() {
-    return title;
-  }
-
-  public String getText() {
-    return text;
-  }
-
-  public URI getUri() {
-    return uri;
-  }
-
-  public ExtendedJSONObject asJSON() {
-    ExtendedJSONObject out = new ExtendedJSONObject();
-    out.put(KEY_ID,    id);
-    out.put(KEY_TITLE, title);
-    out.put(KEY_URL,   uri.toASCIIString());
-    out.put(KEY_TEXT,  text);
-    return out;
-  }
-
-  /**
-   * Return false if the provided Announcement is in some way invalid,
-   * regardless of being well-formed.
-   */
-  public static boolean isValidAnnouncement(final Announcement an) {
-    final URI uri = an.getUri();
-    if (uri == null) {
-      Logger.warn(LOG_TAG, "No URI: announcement not valid.");
-      return false;
-    }
-
-    final String scheme = uri.getScheme();
-    if (scheme == null) {
-      Logger.warn(LOG_TAG, "Null scheme: announcement not valid.");
-      return false;
-    }
-
-    // Only allow HTTP and HTTPS URLs.
-    if (!scheme.equalsIgnoreCase("http") && !scheme.equalsIgnoreCase("https")) {
-      Logger.warn(LOG_TAG, "Scheme '" + scheme + "' forbidden: announcement not valid.");
-      return false;
-    }
-
-    return true;
-  }
-}
deleted file mode 100644
--- a/mobile/android/base/background/announcements/AnnouncementPresenter.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/* 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.background.announcements;
-
-import java.net.URI;
-
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.background.common.GlobalConstants;
-
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-
-/**
- * Handle requests to display a fetched announcement.
- */
-public class AnnouncementPresenter {
-
-  /**
-   * Display the provided snippet.
-   * @param context
-   *        The context instance to use when obtaining the NotificationManager.
-   * @param notificationID
-   *        A unique ID for this notification.
-   * @param title
-   *        The *already localized* String title. Must not be null.
-   * @param body
-   *        The *already localized* String body. Must not be null.
-   * @param uri
-   *        The URL to open when the notification is tapped.
-   */
-  @SuppressWarnings("deprecation")
-  public static void displayAnnouncement(final Context context,
-                                         final int notificationID,
-                                         final String title,
-                                         final String body,
-                                         final URI uri) {
-    final String ns = Context.NOTIFICATION_SERVICE;
-    final NotificationManager notificationManager = (NotificationManager) context.getSystemService(ns);
-
-    // Set pending intent associated with the notification.
-    Uri u = Uri.parse(uri.toASCIIString());
-    Intent intent = new Intent(Intent.ACTION_VIEW, u);
-
-    // Always open the link with Fennec.
-    intent.setClassName(GlobalConstants.BROWSER_INTENT_PACKAGE, GlobalConstants.BROWSER_INTENT_CLASS);
-    PendingIntent contentIntent = PendingIntent.getActivity(context, 0, intent, 0);
-
-    final int icon = R.drawable.ic_status_logo;
-
-    // Deprecated approach to building a notification.
-    final long when = System.currentTimeMillis();
-    Notification notification = new Notification(icon, title, when);
-    notification.flags = Notification.FLAG_AUTO_CANCEL;
-    notification.setLatestEventInfo(context, title, body, contentIntent);
-
-    // Notification.Builder since API 11.
-    /*
-    Notification notification = new Notification.Builder(context)
-        .setContentTitle(title)
-        .setContentText(body)
-        .setAutoCancel(true)
-        .setContentIntent(contentIntent).getNotification();
-     */
-
-    // Send notification.
-    notificationManager.notify(notificationID, notification);
-  }
-
-  public static void displayAnnouncement(final Context context,
-                                         final Announcement snippet) {
-    final int notificationID = snippet.getId();
-    final String title = snippet.getTitle();
-    final String body = snippet.getText();
-    final URI uri = snippet.getUri();
-    AnnouncementPresenter.displayAnnouncement(context, notificationID, title, body, uri);
-  }
-}
deleted file mode 100644
--- a/mobile/android/base/background/announcements/AnnouncementsBroadcastReceiver.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/* 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.background.announcements;
-
-import org.mozilla.gecko.background.BackgroundService;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-
-/**
- * Watch for notifications to start the announcements service.
- *
- * Some observations:
- *
- * "Also note that as of Android 3.0 the user needs to have started the
- *  application at least once before your application can receive
- *  android.intent.action.BOOT_COMPLETED events."
- */
-public class AnnouncementsBroadcastReceiver extends BroadcastReceiver {
-
-  /**
-   * Forward the intent to an IntentService to do background processing.
-   */
-  @Override
-  public void onReceive(Context context, Intent intent) {
-    if (AnnouncementsConstants.DISABLED) {
-      return;
-    }
-
-    BackgroundService.runIntentInService(context, intent, AnnouncementsBroadcastService.class);
-  }
-}
deleted file mode 100644
--- a/mobile/android/base/background/announcements/AnnouncementsBroadcastService.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/* 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.background.announcements;
-
-import org.mozilla.gecko.background.BackgroundService;
-import org.mozilla.gecko.background.common.GlobalConstants;
-import org.mozilla.gecko.background.common.log.Logger;
-
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
-
-/**
- * A service which listens to broadcast intents from the system and from the
- * browser, registering or unregistering the main
- * {@link AnnouncementsService} with the {@link AlarmManager}.
- */
-public class AnnouncementsBroadcastService extends BackgroundService {
-  private static final String WORKER_THREAD_NAME = "AnnouncementsBroadcastServiceWorker";
-  private static final String LOG_TAG = "AnnounceBrSvc";
-
-  public AnnouncementsBroadcastService() {
-    super(WORKER_THREAD_NAME);
-  }
-
-  protected static SharedPreferences getSharedPreferences(Context context) {
-    return context.getSharedPreferences(AnnouncementsConstants.PREFS_BRANCH,
-        GlobalConstants.SHARED_PREFERENCES_MODE);
-  }
-
-  protected SharedPreferences getSharedPreferences() {
-    return this.getSharedPreferences(AnnouncementsConstants.PREFS_BRANCH,
-        GlobalConstants.SHARED_PREFERENCES_MODE);
-  }
-
-  private void toggleAlarm(final Context context, boolean enabled) {
-    final Class<?> serviceClass = AnnouncementsService.class;
-    Logger.info(LOG_TAG, (enabled ? "R" : "Unr") + "egistering " + serviceClass.getSimpleName() +
-        ".");
-
-    final Intent service = new Intent(context, serviceClass);
-    final PendingIntent pending =  PendingIntent.getService(context, 0, service,
-        PendingIntent.FLAG_CANCEL_CURRENT);
-
-    if (!enabled) {
-      cancelAlarm(pending);
-      return;
-    }
-
-    final long pollInterval = getPollInterval(context);
-    scheduleAlarm(pollInterval, pending);
-  }
-
-  /**
-   * Record the last launch time of our version of Fennec.
-   *
-   * @param context
-   *          the <code>Context</code> to use to gain access to
-   *          <code>SharedPreferences</code>.
-   */
-  public static void recordLastLaunch(final Context context) {
-    final long now = System.currentTimeMillis();
-    final SharedPreferences preferences = getSharedPreferences(context);
-
-    // One of several things might be true, according to our logs:
-    //
-    // * The new current time is older than the last
-    // * … or way in the future
-    // * … or way in the distant past
-    // * … or it's reasonable.
-    //
-    // Furthermore, when we come to calculate idle we might find that the clock
-    // is dramatically different — that the current time is thirteen years older
-    // than our saved timestamp (system clock resets to 2000 on battery change),
-    // or it's thirty years in the future (previous timestamp was saved as 0).
-    //
-    // We should try to do something vaguely sane in these situations.
-    long previous = preferences.getLong(AnnouncementsConstants.PREF_LAST_LAUNCH, -1);
-    if (previous == -1) {
-      Logger.debug(LOG_TAG, "No previous launch recorded.");
-    }
-
-    if (now < GlobalConstants.BUILD_TIMESTAMP_MSEC) {
-      Logger.warn(LOG_TAG, "Current time " + now + " is older than build date " +
-                           GlobalConstants.BUILD_TIMESTAMP_MSEC + ". Ignoring until clock is corrected.");
-      return;
-    }
-
-    if (now > AnnouncementsConstants.LATEST_ACCEPTED_LAUNCH_TIMESTAMP_MSEC) {
-      Logger.warn(LOG_TAG, "Launch time " + now + " is later than max sane launch timestamp " +
-                           AnnouncementsConstants.LATEST_ACCEPTED_LAUNCH_TIMESTAMP_MSEC +
-                           ". Ignoring until clock is corrected.");
-      return;
-    }
-
-    if (previous > now) {
-      Logger.debug(LOG_TAG, "Previous launch " + previous + " later than current time " +
-                            now + ", but new time is sane. Accepting new time.");
-    }
-
-    preferences.edit().putLong(AnnouncementsConstants.PREF_LAST_LAUNCH, now).commit();
-  }
-
-  public static long getPollInterval(final Context context) {
-    final SharedPreferences preferences = getSharedPreferences(context);
-    return preferences.getLong(AnnouncementsConstants.PREF_ANNOUNCE_FETCH_INTERVAL_MSEC, AnnouncementsConstants.DEFAULT_ANNOUNCE_FETCH_INTERVAL_MSEC);
-  }
-
-  public static void setPollInterval(final Context context, long interval) {
-    final SharedPreferences preferences = getSharedPreferences(context);
-    preferences.edit().putLong(AnnouncementsConstants.PREF_ANNOUNCE_FETCH_INTERVAL_MSEC, interval).commit();
-  }
-
-  @Override
-  protected void onHandleIntent(Intent intent) {
-    Logger.setThreadLogTag(AnnouncementsConstants.GLOBAL_LOG_TAG);
-
-    // Intent can be null. Bug 1025937.
-    if (intent == null) {
-      Logger.debug(LOG_TAG, "Short-circuiting on null intent.");
-      return;
-    }
-
-    final String action = intent.getAction();
-    Logger.debug(LOG_TAG, "Broadcast onReceive. Intent is " + action);
-
-    if (AnnouncementsConstants.ACTION_ANNOUNCEMENTS_PREF.equals(action)) {
-      handlePrefIntent(intent);
-      return;
-    }
-
-    if (Intent.ACTION_BOOT_COMPLETED.equals(action) ||
-        Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
-      BackgroundService.reflectContextToFennec(this,
-          GlobalConstants.GECKO_PREFERENCES_CLASS,
-          GlobalConstants.GECKO_BROADCAST_ANNOUNCEMENTS_PREF_METHOD);
-      return;
-    }
-
-    // Failure case.
-    Logger.warn(LOG_TAG, "Unknown intent " + action);
-  }
-
-  /**
-   * Handle the intent sent by the browser when it wishes to notify us
-   * of the value of the user preference. Look at the value and toggle the
-   * alarm service accordingly.
-   *
-   * @param intent must be non-null.
-   */
-  private void handlePrefIntent(Intent intent) {
-    if (!intent.hasExtra("enabled")) {
-      Logger.warn(LOG_TAG, "Got ANNOUNCEMENTS_PREF intent without enabled. Ignoring.");
-      return;
-    }
-
-    final boolean enabled = intent.getBooleanExtra("enabled", true);
-    Logger.debug(LOG_TAG, intent.getStringExtra("branch") + "/" +
-                          intent.getStringExtra("pref")   + " = " +
-                          (intent.hasExtra("enabled") ? enabled : ""));
-
-    toggleAlarm(this, enabled);
-
-    // Primarily intended for debugging and testing, but this doesn't do any harm.
-    if (!enabled) {
-      Logger.info(LOG_TAG, "!enabled: clearing last fetch.");
-      final SharedPreferences sharedPreferences = getSharedPreferences();
-      final Editor editor = sharedPreferences.edit();
-      editor.remove(AnnouncementsConstants.PREF_LAST_FETCH_LOCAL_TIME);
-      editor.remove(AnnouncementsConstants.PREF_EARLIEST_NEXT_ANNOUNCE_FETCH);
-      editor.commit();
-    }
-  }
-}
deleted file mode 100644
--- a/mobile/android/base/background/announcements/AnnouncementsConstants.java.in
+++ /dev/null
@@ -1,50 +0,0 @@
-#filter substitution
-/* 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.background.announcements;
-
-import org.mozilla.gecko.background.common.GlobalConstants;
-
-import android.app.AlarmManager;
-
-public class AnnouncementsConstants {
-  // Not `final` so we have the option to turn this on at runtime with a magic addon.
-  public static boolean DISABLED = false;
-
-  public static final long MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
-
-  public static final String GLOBAL_LOG_TAG = "GeckoAnnounce";
-  public static final String ACTION_ANNOUNCEMENTS_PREF = "@ANDROID_PACKAGE_NAME@.ANNOUNCEMENTS_PREF";
-
-  static final String PREFS_BRANCH = "background";
-  static final String PREF_LAST_FETCH_LOCAL_TIME  = "last_fetch";
-  static final String PREF_LAST_FETCH_SERVER_DATE = "last_announce_date";
-  static final String PREF_LAST_LAUNCH = "last_firefox_launch";
-  static final String PREF_ANNOUNCE_SERVER_BASE_URL  = "announce_server_base_url";
-  static final String PREF_EARLIEST_NEXT_ANNOUNCE_FETCH = "earliest_next_announce_fetch";
-  static final String PREF_ANNOUNCE_FETCH_INTERVAL_MSEC = "announce_fetch_interval_msec";
-
-  public static String DEFAULT_ANNOUNCE_SERVER_BASE_URL = "https://campaigns.services.mozilla.com/announce/";
-
-  public static final String ANNOUNCE_PROTOCOL_VERSION = "1";
-  public static final String ANNOUNCE_APPLICATION = "android";
-  public static String ANNOUNCE_PATH_SUFFIX = AnnouncementsConstants.ANNOUNCE_PROTOCOL_VERSION + "/" +
-                                              AnnouncementsConstants.ANNOUNCE_APPLICATION + "/";
-
-  public static long DEFAULT_ANNOUNCE_FETCH_INTERVAL_MSEC = AlarmManager.INTERVAL_HALF_DAY;
-  public static long DEFAULT_BACKOFF_MSEC = 2 * 24 * 60 * 60 * 1000;   // Two days. Used if no Retry-After header.
-  public static long MINIMUM_FETCH_INTERVAL_MSEC = 60 * 60 * 1000;     // 1 hour.
-
-  // Stop reporting idle counts once they hit one year.
-  public static long MAX_SANE_IDLE_DAYS = 365;
-
-  // Don't track last launch if the timestamp is ridiculously out of range:
-  // four years after build.
-  public static long LATEST_ACCEPTED_LAUNCH_TIMESTAMP_MSEC = GlobalConstants.BUILD_TIMESTAMP_MSEC +
-                                                             4 * 365 * MILLISECONDS_PER_DAY;
-
-  public static String USER_AGENT = "Firefox Announcements " + GlobalConstants.MOZ_APP_VERSION;
-  public static String ANNOUNCE_CHANNEL = GlobalConstants.MOZ_UPDATE_CHANNEL.replace("default", GlobalConstants.MOZ_OFFICIAL_BRANDING ? "release" : "dev");
-}
deleted file mode 100644
--- a/mobile/android/base/background/announcements/AnnouncementsFetchDelegate.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/* 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.background.announcements;
-
-import java.util.List;
-import java.util.Locale;
-
-public interface AnnouncementsFetchDelegate {
-  /**
-   * @return the timestamp of the last fetch in milliseconds.
-   */
-  public long getLastFetch();
-
-  /**
-   * @return the Date header string of the last response, or null if not present.
-   */
-  public String getLastDate();
-
-  /**
-   * @return the current system locale (e.g., en_us).
-   */
-  public Locale getLocale();
-
-  /**
-   * @return the User-Agent header to use for the request.
-   */
-  public String getUserAgent();
-
-  /**
-   * @return the server URL to interrogate, including path.
-   */
-  public String getServiceURL();
-
-  /*
-   * Callback methods.
-   * Note that we provide both a local fetch time and a server date here.
-   * This is so we can track how long we've waited (local), and supply the
-   * date back to the server for If-Modified-Since.
-   */
-  public void onNoNewAnnouncements(long localFetchTime, String serverDate);
-  public void onNewAnnouncements(List<Announcement> snippets, long localFetchTime, String serverDate);
-  public void onLocalError(Exception e);
-  public void onRemoteError(Exception e);
-  public void onRemoteFailure(int status);
-  public void onBackoff(int retryAfterInSeconds);
-}
\ No newline at end of file
deleted file mode 100644
--- a/mobile/android/base/background/announcements/AnnouncementsFetchResourceDelegate.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/* 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.background.announcements;
-
-import java.io.IOException;
-import java.security.GeneralSecurityException;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-import org.json.simple.JSONArray;
-import org.json.simple.JSONObject;
-import org.mozilla.gecko.background.common.log.Logger;
-import org.mozilla.gecko.sync.ExtendedJSONObject;
-import org.mozilla.gecko.sync.NonArrayJSONException;
-import org.mozilla.gecko.sync.net.AuthHeaderProvider;
-import org.mozilla.gecko.sync.net.BaseResource;
-import org.mozilla.gecko.sync.net.BaseResourceDelegate;
-import org.mozilla.gecko.sync.net.Resource;
-import org.mozilla.gecko.sync.net.SyncResponse;
-
-import ch.boye.httpclientandroidlib.Header;
-import ch.boye.httpclientandroidlib.HttpResponse;
-import ch.boye.httpclientandroidlib.client.ClientProtocolException;
-import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase;
-import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient;
-import ch.boye.httpclientandroidlib.impl.cookie.DateUtils;
-import ch.boye.httpclientandroidlib.protocol.HTTP;
-
-/**
- * Converts HTTP resource callbacks into AnnouncementsFetchDelegate callbacks.
- */
-public class AnnouncementsFetchResourceDelegate extends BaseResourceDelegate {
-  private static final String ACCEPT_HEADER = "application/json;charset=utf-8";
-
-  private static final String LOG_TAG = "AnnounceFetchRD";
-
-  protected final long startTime;
-  protected AnnouncementsFetchDelegate delegate;
-
-  public AnnouncementsFetchResourceDelegate(Resource resource, AnnouncementsFetchDelegate delegate) {
-    super(resource);
-    this.startTime = System.currentTimeMillis();
-    this.delegate  = delegate;
-  }
-
-  @Override
-  public String getUserAgent() {
-    return delegate.getUserAgent();
-  }
-
-  @Override
-  public void addHeaders(HttpRequestBase request, DefaultHttpClient client) {
-    super.addHeaders(request, client);
-
-    // The basics.
-    request.addHeader("Accept-Language", delegate.getLocale().toString());
-    request.addHeader("Accept",          ACCEPT_HEADER);
-
-    // We never want to keep connections alive.
-    request.addHeader("Connection", "close");
-
-    // Set If-Modified-Since to avoid re-fetching content.
-    final String ifModifiedSince = delegate.getLastDate();
-    if (ifModifiedSince != null) {
-      Logger.info(LOG_TAG, "If-Modified-Since: " + ifModifiedSince);
-      request.addHeader("If-Modified-Since", ifModifiedSince);
-    }
-
-    // Just in case.
-    request.removeHeaders("Cookie");
-  }
-
-  private List<Announcement> parseBody(ExtendedJSONObject body) throws NonArrayJSONException {
-    List<Announcement> out = new ArrayList<Announcement>(1);
-    JSONArray snippets = body.getArray("announcements");
-    if (snippets == null) {
-      Logger.warn(LOG_TAG, "Missing announcements body. Returning empty.");
-      return out;
-    }
-
-    for (Object s : snippets) {
-      try {
-        out.add(Announcement.parseAnnouncement(new ExtendedJSONObject((JSONObject) s)));
-      } catch (Exception e) {
-        Logger.warn(LOG_TAG, "Malformed announcement or display failed. Skipping.", e);
-      }
-    }
-    return out;
-  }
-
-  @Override
-  public void handleHttpResponse(HttpResponse response) {
-    final Header dateHeader = response.getFirstHeader(HTTP.DATE_HEADER);
-    String date = null;
-    if (dateHeader != null) {
-      // Note that we are deliberately not validating the server time here.
-      // We pass it directly back to the server; we don't care about the
-      // contents, and if we reject a value we essentially re-initialize
-      // the client, which will cause stale announcements to be re-fetched.
-      date = dateHeader.getValue();
-    }
-    if (date == null) {
-      // Use local clock, because skipping is better than re-fetching.
-      date = DateUtils.formatDate(new Date());
-      Logger.warn(LOG_TAG, "No fetch date; using local time " + date);
-    }
-
-    final SyncResponse r = new SyncResponse(response);    // For convenience.
-    try {
-      final int statusCode = r.getStatusCode();
-      Logger.debug(LOG_TAG, "Got announcements response: " + statusCode);
-
-      if (statusCode == 204 || statusCode == 304) {
-        BaseResource.consumeEntity(response);
-        delegate.onNoNewAnnouncements(startTime, date);
-        return;
-      }
-
-      if (statusCode == 200) {
-        final List<Announcement> snippets;
-        try {
-          snippets = parseBody(r.jsonObjectBody());
-        } catch (Exception e) {
-          delegate.onRemoteError(e);
-          return;
-        }
-        delegate.onNewAnnouncements(snippets, startTime, date);
-        return;
-      }
-
-      if (statusCode == 400 || statusCode == 405) {
-        // We did something wrong.
-        Logger.warn(LOG_TAG, "We did something wrong. Oh dear.");
-        // Fall through.
-      }
-
-      if (statusCode == 503 || statusCode == 500) {
-        Logger.warn(LOG_TAG, "Server issue: " + r.body());
-        delegate.onBackoff(r.retryAfterInSeconds());
-        return;
-      }
-
-      // Otherwise, clean up.
-      delegate.onRemoteFailure(statusCode);
-
-    } catch (Exception e) {
-      Logger.warn(LOG_TAG, "Failed to extract body.", e);
-      delegate.onRemoteError(e);
-    }
-  }
-
-  @Override
-  public void handleHttpProtocolException(ClientProtocolException e) {
-    Logger.warn(LOG_TAG, "Protocol exception.", e);
-    delegate.onLocalError(e);
-  }
-
-  @Override
-  public void handleHttpIOException(IOException e) {
-    Logger.warn(LOG_TAG, "IO exception.", e);
-    delegate.onLocalError(e);
-  }
-
-  @Override
-  public void handleTransportException(GeneralSecurityException e) {
-    Logger.warn(LOG_TAG, "Transport exception.", e);
-    // Class this as a remote error, because it's probably something odd
-    // with SSL negotiation.
-    delegate.onRemoteError(e);
-  }
-
-  /**
-   * Be very thorough in case the superclass implementation changes.
-   * We never want this to be an authenticated request.
-   */
-  @Override
-  public AuthHeaderProvider getAuthHeaderProvider() {
-    return null;
-  }
-}
deleted file mode 100644
--- a/mobile/android/base/background/announcements/AnnouncementsFetcher.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/* 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.background.announcements;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URLEncoder;
-
-import org.mozilla.gecko.background.common.GlobalConstants;
-import org.mozilla.gecko.background.common.log.Logger;
-import org.mozilla.gecko.sync.net.BaseResource;
-
-public class AnnouncementsFetcher {
-  private static final String LOG_TAG = "AnnounceFetch";
-  private static final long MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
-
-  public static URI getSnippetURI(String base, String channel,
-                                  String version, String platform,
-                                  int idleDays)
-    throws URISyntaxException {
-    try {
-      final String c = URLEncoder.encode(channel, "UTF-8");
-      final String v = URLEncoder.encode(version, "UTF-8");
-      final String p = URLEncoder.encode(platform, "UTF-8");
-      final String s = base + c + "/" + v + "/" + p + ((idleDays == -1) ? "" : ("?idle=" + idleDays));
-      return new URI(s);
-    } catch (UnsupportedEncodingException e) {
-      // Nonsense.
-      return null;
-    }
-  }
-
-  public static URI getAnnounceURI(final String baseURL, final long lastLaunch) throws URISyntaxException {
-    final String channel = getChannel();
-    final String version = getVersion();
-    final String platform = getPlatform();
-    final int idleDays = getIdleDays(lastLaunch);
-
-    Logger.debug(LOG_TAG, "Fetch URI: idle for " + idleDays + " days.");
-    return getSnippetURI(baseURL, channel, version, platform, idleDays);
-  }
-
-  protected static String getChannel() {
-    return AnnouncementsConstants.ANNOUNCE_CHANNEL;
-  }
-
-  protected static String getVersion() {
-    return GlobalConstants.MOZ_APP_VERSION;
-  }
-
-  protected static String getPlatform() {
-    return GlobalConstants.ANDROID_CPU_ARCH;
-  }
-
-  /**
-   * Return the number of days that we've been idle, assuming that we have a
-   * sane last launch time and the current time is within range. If no sane idle
-   * time can be returned, we return -1.
-   *
-   * @param lastLaunch
-   *          Time at which the browser was last launched, in milliseconds since epoch.
-   * @param now
-   *          Milliseconds since epoch for which idle time should be calculated.
-   * @return number of idle days, or -1 if out of range.
-   */
-  protected static int getIdleDays(final long lastLaunch, final long now) {
-    if (lastLaunch <= 0) {
-      return -1;
-    }
-
-    if (now < GlobalConstants.BUILD_TIMESTAMP_MSEC) {
-      Logger.warn(LOG_TAG, "Current time " + now + " earlier than build date. Not calculating idle.");
-      return -1;
-    }
-
-    if (now < lastLaunch) {
-      Logger.warn(LOG_TAG, "Current time " + now + " earlier than last launch! Not calculating idle.");
-      return -1;
-    }
-
-    final long idleMillis = now - lastLaunch;
-    final int idleDays = (int) (idleMillis / MILLISECONDS_PER_DAY);
-
-    if (idleDays > AnnouncementsConstants.MAX_SANE_IDLE_DAYS) {
-      Logger.warn(LOG_TAG, "Idle from " + lastLaunch + " until " + now +
-                           ", which is insane. Not calculating idle.");
-      return -1;
-    }
-
-    return idleDays;
-  }
-
-  /**
-   * Return the number of days that we've been idle, assuming that we have a
-   * sane last launch time and the current time is within range. If no sane idle
-   * time can be returned, we return -1.
-   * The current time will be calculated from {@link System#currentTimeMillis()}.
-   *
-   * @param lastLaunch
-   *          Unix timestamp at which the browser was last launched.
-   * @return number of idle days, or -1 if out of range.
-   */
-  protected static int getIdleDays(final long lastLaunch) {
-    final long now = System.currentTimeMillis();
-    return getIdleDays(lastLaunch, now);
-  }
-
-  public static void fetchAnnouncements(URI uri, AnnouncementsFetchDelegate delegate) {
-    BaseResource r = new BaseResource(uri);
-    r.delegate = new AnnouncementsFetchResourceDelegate(r, delegate);
-    r.getBlocking();
-  }
-
-  /**
-   * Synchronous.
-   */
-  public static void fetchAndProcessAnnouncements(long lastLaunch,
-                                                  AnnouncementsFetchDelegate delegate) {
-    final long now = System.currentTimeMillis();
-    Logger.debug(LOG_TAG, "Fetching announcements. Last launch: " + lastLaunch + "; now: " + now);
-    try {
-      final String base = delegate.getServiceURL();
-      final URI uri = getAnnounceURI(base, lastLaunch);
-      Logger.info(LOG_TAG, "Fetching announcements from " + uri.toASCIIString());
-      fetchAnnouncements(uri, delegate);
-    } catch (URISyntaxException e) {
-      Logger.warn(LOG_TAG, "Couldn't create URL.", e);
-      return;
-    }
-  }
-}
deleted file mode 100644
--- a/mobile/android/base/background/announcements/AnnouncementsService.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/* 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.background.announcements;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.net.URI;
-import java.util.List;
-import java.util.Locale;
-
-import org.mozilla.gecko.BrowserLocaleManager;
-import org.mozilla.gecko.background.BackgroundService;
-import org.mozilla.gecko.background.common.GlobalConstants;
-import org.mozilla.gecko.background.common.log.Logger;
-
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.os.IBinder;
-
-/**
- * A Service to periodically check for new published announcements,
- * presenting them to the user if local conditions permit.
- *
- * We extend IntentService, rather than just Service, because this gives us
- * a worker thread to avoid main-thread networking.
- *
- * Yes, even though we're in an alarm-triggered service, it still counts
- * as main-thread.
- *
- * The operation of this service is as follows:
- *
- * 0. Decide if a request should be made.
- * 1. Compute the arguments to the request. This includes enough
- *    pertinent details to allow the server to pre-filter a message
- *    set, recording enough tracking details to compute statistics.
- * 2. Issue the request. If this succeeds with a 200 or 204, great;
- *    track that timestamp for the next run through Step 0.
- * 3. Process any received messages.
- *
- * Message processing is as follows:
- *
- * 0. Decide if message display should occur. This might involve
- *    user preference or other kinds of environmental factors.
- * 1. Use the AnnouncementPresenter to open the announcement.
- *
- * Future:
- * * Persisting of multiple announcements.
- * * Prioritization.
- */
-public class AnnouncementsService extends BackgroundService implements AnnouncementsFetchDelegate {
-  private static final String WORKER_THREAD_NAME = "AnnouncementsServiceWorker";
-  private static final String LOG_TAG = "AnnounceService";
-
-  public AnnouncementsService() {
-    super(WORKER_THREAD_NAME);
-    Logger.setThreadLogTag(AnnouncementsConstants.GLOBAL_LOG_TAG);
-    Logger.debug(LOG_TAG, "Creating AnnouncementsService.");
-  }
-
-  public boolean shouldFetchAnnouncements() {
-    final long now = System.currentTimeMillis();
-
-    if (!backgroundDataIsEnabled()) {
-      Logger.debug(LOG_TAG, "Background data not possible. Skipping.");
-      return false;
-    }
-
-    // Don't fetch if we were told to back off.
-    if (getEarliestNextFetch() > now) {
-      return false;
-    }
-
-    // Don't do anything if we haven't waited long enough.
-    final long lastFetch = getLastFetch();
-
-    // Just in case the alarm manager schedules us more frequently, or something
-    // goes awry with relaunches.
-    if ((now - lastFetch) < AnnouncementsConstants.MINIMUM_FETCH_INTERVAL_MSEC) {
-      Logger.debug(LOG_TAG, "Returning: minimum fetch interval of " + AnnouncementsConstants.MINIMUM_FETCH_INTERVAL_MSEC + "ms not met.");
-      return false;
-    }
-
-    return true;
-  }
-
-  /**
-   * Display the first valid announcement in the list.
-   */
-  protected void processAnnouncements(final List<Announcement> announcements) {
-    if (announcements == null) {
-      Logger.warn(LOG_TAG, "No announcements to present.");
-      return;
-    }
-
-    boolean presented = false;
-    for (Announcement an : announcements) {
-      // Do this so we at least log, rather than just returning.
-      if (presented) {
-        Logger.warn(LOG_TAG, "Skipping announcement \"" + an.getTitle() + "\": one already shown.");
-        continue;
-      }
-      if (Announcement.isValidAnnouncement(an)) {
-        presented = true;
-        AnnouncementPresenter.displayAnnouncement(this, an);
-      }
-    }
-  }
-
-  /**
-   * If it's time to do a fetch -- we've waited long enough,
-   * we're allowed to use background data, etc. -- then issue
-   * a fetch. The subsequent background check is handled implicitly
-   * by the AlarmManager.
-   */
-  @Override
-  public void onHandleIntent(Intent intent) {
-    Logger.setThreadLogTag(AnnouncementsConstants.GLOBAL_LOG_TAG);
-
-    // Intent can be null. Bug 1025937.
-    if (intent == null) {
-      Logger.debug(LOG_TAG, "Short-circuiting on null intent.");
-      return;
-    }
-
-    Logger.debug(LOG_TAG, "Running AnnouncementsService.");
-
-    if (AnnouncementsConstants.DISABLED) {
-      Logger.debug(LOG_TAG, "Announcements disabled. Returning from AnnouncementsService.");
-      return;
-    }
-
-    if (!shouldFetchAnnouncements()) {
-      Logger.debug(LOG_TAG, "Not fetching.");
-      return;
-    }
-
-    // Ensure that our locale is up to date, so that the fetcher's
-    // Accept-Language header is, too.
-    BrowserLocaleManager.getInstance().getAndApplyPersistedLocale(getApplicationContext());
-
-    // Otherwise, grab our announcements URL and process the contents.
-    AnnouncementsFetcher.fetchAndProcessAnnouncements(getLastLaunch(), this);
-  }
-
-  @Override
-  public IBinder onBind(Intent intent) {
-    return null;
-  }
-
-  protected long getLastLaunch() {
-    return getSharedPreferences().getLong(AnnouncementsConstants.PREF_LAST_LAUNCH, 0);
-  }
-
-  protected SharedPreferences getSharedPreferences() {
-    return this.getSharedPreferences(AnnouncementsConstants.PREFS_BRANCH, GlobalConstants.SHARED_PREFERENCES_MODE);
-  }
-
-  @Override
-  protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
-    super.dump(fd, writer, args);
-
-    final long lastFetch = getLastFetch();
-    final long lastLaunch = getLastLaunch();
-    writer.write("AnnouncementsService: last fetch " + lastFetch +
-                 ", last Firefox activity: " + lastLaunch + "\n");
-  }
-
-  protected void setEarliestNextFetch(final long earliestInMsec) {
-    this.getSharedPreferences().edit().putLong(AnnouncementsConstants.PREF_EARLIEST_NEXT_ANNOUNCE_FETCH, earliestInMsec).commit();
-  }
-
-  protected long getEarliestNextFetch() {
-    return this.getSharedPreferences().getLong(AnnouncementsConstants.PREF_EARLIEST_NEXT_ANNOUNCE_FETCH, 0L);
-  }
-
-  protected void setLastFetch(final long fetch) {
-    this.getSharedPreferences().edit().putLong(AnnouncementsConstants.PREF_LAST_FETCH_LOCAL_TIME, fetch).commit();
-  }
-
-  @Override
-  public long getLastFetch() {
-    return this.getSharedPreferences().getLong(AnnouncementsConstants.PREF_LAST_FETCH_LOCAL_TIME, 0L);
-  }
-
-  protected String setLastDate(final String fetch) {
-    if (fetch == null) {
-      this.getSharedPreferences().edit().remove(AnnouncementsConstants.PREF_LAST_FETCH_SERVER_DATE).commit();
-      return null;
-    }
-    this.getSharedPreferences().edit().putString(AnnouncementsConstants.PREF_LAST_FETCH_SERVER_DATE, fetch).commit();
-    return fetch;
-  }
-
-  @Override
-  public String getLastDate() {
-    return this.getSharedPreferences().getString(AnnouncementsConstants.PREF_LAST_FETCH_SERVER_DATE, null);
-  }
-
-  /**
-   * Use this to write the persisted server URL, overriding
-   * the default value.
-   * @param url a URI identifying the full request path, e.g.,
-   *            "http://foo.com:1234/announce/"
-   */
-  public void setAnnouncementsServerBaseURL(final URI url) {
-    if (url == null) {
-      throw new IllegalArgumentException("url cannot be null.");
-    }
-    final String scheme = url.getScheme();
-    if (scheme == null) {
-      throw new IllegalArgumentException("url must have a scheme.");
-    }
-    if (!scheme.equalsIgnoreCase("http") && !scheme.equalsIgnoreCase("https")) {
-      throw new IllegalArgumentException("url must be http or https.");
-    }
-    SharedPreferences p = this.getSharedPreferences();
-    p.edit().putString(AnnouncementsConstants.PREF_ANNOUNCE_SERVER_BASE_URL, url.toASCIIString()).commit();
-  }
-
-  /**
-   * Return the service URL, including protocol version and application identifier. E.g.,
-   *
-   *   "https://campaigns.services.mozilla.com/announce/1/android/"
-   */
-  @Override
-  public String getServiceURL() {
-    SharedPreferences p = this.getSharedPreferences();
-    String base = p.getString(AnnouncementsConstants.PREF_ANNOUNCE_SERVER_BASE_URL, AnnouncementsConstants.DEFAULT_ANNOUNCE_SERVER_BASE_URL);
-    return base + AnnouncementsConstants.ANNOUNCE_PATH_SUFFIX;
-  }
-
-  @Override
-  public Locale getLocale() {
-    return Locale.getDefault();
-  }
-
-  @Override
-  public String getUserAgent() {
-    return AnnouncementsConstants.USER_AGENT;
-  }
-
-  protected void persistTimes(long fetched, String date) {
-    setLastFetch(fetched);
-    if (date != null) {
-      setLastDate(date);
-    }
-  }
-
-  @Override
-  public void onNoNewAnnouncements(long fetched, String date) {
-    Logger.info(LOG_TAG, "No new announcements to display.");
-    persistTimes(fetched, date);
-  }
-
-  @Override
-  public void onNewAnnouncements(List<Announcement> announcements, long fetched, String date) {
-    Logger.info(LOG_TAG, "Processing announcements: " + announcements.size());
-    persistTimes(fetched, date);
-    processAnnouncements(announcements);
-  }
-
-  @Override
-  public void onRemoteFailure(int status) {
-    // Bump our fetch timestamp.
-    Logger.warn(LOG_TAG, "Got remote fetch status " + status + "; bumping fetch time.");
-    setLastFetch(System.currentTimeMillis());
-  }
-
-  @Override
-  public void onRemoteError(Exception e) {
-    // Bump our fetch timestamp.
-    Logger.warn(LOG_TAG, "Error processing response.", e);
-    setLastFetch(System.currentTimeMillis());
-  }
-
-  @Override
-  public void onLocalError(Exception e) {
-    Logger.error(LOG_TAG, "Got exception in fetch.", e);
-    // Do nothing yet, so we'll retry.
-  }
-
-  @Override
-  public void onBackoff(int retryAfterInSeconds) {
-    Logger.info(LOG_TAG, "Got retry after: " + retryAfterInSeconds);
-    final long delayInMsec = Math.max(retryAfterInSeconds * 1000, AnnouncementsConstants.DEFAULT_BACKOFF_MSEC);
-    final long fuzzedBackoffInMsec = delayInMsec + Math.round(((double) delayInMsec * 0.25d * Math.random()));
-    Logger.debug(LOG_TAG, "Fuzzed backoff: " + fuzzedBackoffInMsec + "ms.");
-    setEarliestNextFetch(fuzzedBackoffInMsec + System.currentTimeMillis());
-  }
-}
--- a/mobile/android/base/background/common/GlobalConstants.java.in
+++ b/mobile/android/base/background/common/GlobalConstants.java.in
@@ -40,16 +40,15 @@ public class GlobalConstants {
   public static final int SHARED_PREFERENCES_MODE = 0;
 
   // These are used to ask Fennec (via reflection) to send
   // us a pref notification. This avoids us having to guess
   // Fennec's prefs branch and pref name.
   // Eventually Fennec might listen to startup notifications and
   // do this automatically, but this will do for now. See Bug 800244.
   public static String GECKO_PREFERENCES_CLASS = "org.mozilla.gecko.preferences.GeckoPreferences";
-  public static String GECKO_BROADCAST_ANNOUNCEMENTS_PREF_METHOD  = "broadcastAnnouncementsPref";
   public static String GECKO_BROADCAST_HEALTHREPORT_UPLOAD_PREF_METHOD  = "broadcastHealthReportUploadPref";
   public static String GECKO_BROADCAST_HEALTHREPORT_PRUNE_METHOD = "broadcastHealthReportPrune";
 
   // Common time values.
   public static final long MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
   public static final long MILLISECONDS_PER_SIX_MONTHS = 180 * MILLISECONDS_PER_DAY;
 }
deleted file mode 100644
--- a/mobile/android/services/manifests/AnnouncementsAndroidManifest_activities.xml.in
+++ /dev/null
@@ -1,17 +0,0 @@
-        <!--
-             As well as these system actions, we also listen for pref notifications
-             sent by Fennec: @ANDROID_PACKAGE_NAME@.ANNOUNCEMENTS_PREF.
-          -->
-        <receiver android:name="org.mozilla.gecko.background.announcements.AnnouncementsBroadcastReceiver" >
-            <intent-filter>
-                <!-- Startup. -->
-                <action android:name="android.intent.action.BOOT_COMPLETED" />
-            </intent-filter>
-            <intent-filter>
-                <!-- SD card remounted. -->
-                <action android:name="android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE" />
-            </intent-filter>
-            <intent-filter >
-              <action android:name="@ANDROID_PACKAGE_NAME@.ANNOUNCEMENTS_PREF" />
-            </intent-filter>
-        </receiver>
deleted file mode 100644
--- a/mobile/android/services/manifests/AnnouncementsAndroidManifest_permissions.xml.in
+++ /dev/null
@@ -1,5 +0,0 @@
-    <!-- So we can start our service. -->
-    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
-
-    <!-- So we can receive messages from Fennec. -->
-    <uses-permission android:name="@ANDROID_PACKAGE_NAME@.permission.PER_ANDROID_PACKAGE" />
deleted file mode 100644
--- a/mobile/android/services/manifests/AnnouncementsAndroidManifest_services.xml.in
+++ /dev/null
@@ -1,8 +0,0 @@
-        <service
-            android:exported="false"
-            android:name="org.mozilla.gecko.background.announcements.AnnouncementsService" >
-        </service>
-        <service
-            android:exported="false"
-            android:name="org.mozilla.gecko.background.announcements.AnnouncementsBroadcastService" >
-        </service>
--- a/mobile/android/tests/background/junit3/background_junit3_sources.mozbuild
+++ b/mobile/android/tests/background/junit3/background_junit3_sources.mozbuild
@@ -1,16 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 background_junit3_sources = [
-    'src/announcements/TestAnnouncementsBroadcastService.java',
     'src/common/TestAndroidLogWriters.java',
     'src/common/TestBrowserContractHelpers.java',
     'src/common/TestDateUtils.java',
     'src/common/TestUtils.java',
     'src/common/TestWaitHelper.java',
     'src/db/AndroidBrowserRepositoryTestCase.java',
     'src/db/TestAndroidBrowserBookmarksRepository.java',
     'src/db/TestAndroidBrowserHistoryDataExtender.java',
deleted file mode 100644
--- a/mobile/android/tests/background/junit3/src/announcements/TestAnnouncementsBroadcastService.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-package org.mozilla.gecko.background.announcements;
-
-import java.util.concurrent.BrokenBarrierException;
-
-import org.mozilla.gecko.background.common.GlobalConstants;
-import org.mozilla.gecko.background.helpers.BackgroundServiceTestCase;
-
-import android.content.Intent;
-import android.content.SharedPreferences;
-
-public class TestAnnouncementsBroadcastService
-    extends BackgroundServiceTestCase<TestAnnouncementsBroadcastService.MockAnnouncementsBroadcastService> {
-  public static class MockAnnouncementsBroadcastService extends AnnouncementsBroadcastService {
-    @Override
-    protected SharedPreferences getSharedPreferences() {
-      return this.getSharedPreferences(sharedPrefsName,
-          GlobalConstants.SHARED_PREFERENCES_MODE);
-    }
-
-    @Override
-    protected void onHandleIntent(Intent intent) {
-      super.onHandleIntent(intent);
-      try {
-        barrier.await();
-      } catch (InterruptedException e) {
-        fail("Awaiting thread should not be interrupted.");
-      } catch (BrokenBarrierException e) {
-        // This will happen on timeout - do nothing.
-      }
-    }
-  }
-
-  public TestAnnouncementsBroadcastService() {
-    super(MockAnnouncementsBroadcastService.class);
-  }
-
-  @Override
-  public void setUp() throws Exception {
-    super.setUp();
-    // We can't mock AlarmManager since it has a package-private constructor, so instead we reset
-    // the alarm by hand.
-    cancelAlarm(getServiceIntent());
-  }
-
-  @Override
-  public void tearDown() throws Exception {
-    cancelAlarm(getServiceIntent());
-    AnnouncementsConstants.DISABLED = false;
-    super.tearDown();
-  }
-
-  protected Intent getServiceIntent() {
-    final Intent intent = new Intent(getContext(), AnnouncementsService.class);
-    return intent;
-  }
-
-  public void testIgnoredServicePrefIntents() throws Exception {
-    // Intent without "enabled" extra is ignored.
-    intent.setAction(AnnouncementsConstants.ACTION_ANNOUNCEMENTS_PREF);
-    startService(intent);
-    await();
-
-    assertFalse(isServiceAlarmSet(getServiceIntent()));
-  }
-
-  public void testServicePrefIntentDisabled() throws Exception {
-    intent.setAction(AnnouncementsConstants.ACTION_ANNOUNCEMENTS_PREF)
-        .putExtra("enabled", false);
-    startService(intent);
-    await();
-    assertFalse(isServiceAlarmSet(getServiceIntent()));
-  }
-
-  public void testServicePrefIntentEnabled() throws Exception {
-    intent.setAction(AnnouncementsConstants.ACTION_ANNOUNCEMENTS_PREF)
-        .putExtra("enabled", true);
-    startService(intent);
-    await();
-    assertTrue(isServiceAlarmSet(getServiceIntent()));
-  }
-
-  public void testServicePrefCancelled() throws Exception {
-    intent.setAction(AnnouncementsConstants.ACTION_ANNOUNCEMENTS_PREF)
-        .putExtra("enabled", true);
-    startService(intent);
-    await();
-
-    assertTrue(isServiceAlarmSet(getServiceIntent()));
-    barrier.reset();
-
-    intent.putExtra("enabled", false);
-    startService(intent);
-    await();
-    assertFalse(isServiceAlarmSet(getServiceIntent()));
-  }
-}