Bug 1235869 - Remove web runtime from android. r=myk
authorBrendan Dahl <bdahl@mozilla.com>
Mon, 29 Feb 2016 10:31:00 +0100
changeset 286224 93156962855dcdc9448fcc87f2cb337483e96f20
parent 286223 b0f74770edc6172dd4eb67a009fcac8b914197a8
child 286225 89e36be196d9dfbd5e37bb8a17fe461d825d090e
push id30042
push userkwierso@gmail.com
push dateTue, 01 Mar 2016 22:20:44 +0000
treeherderautoland@d6788a70c97b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmyk
bugs1235869
milestone47.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 1235869 - Remove web runtime from android. r=myk
.eslintignore
layout/reftests/font-face/reftest.list
layout/reftests/writing-mode/reftest.list
mobile/android/.eslintrc
mobile/android/app/mobile.js
mobile/android/base/AndroidManifest.xml.in
mobile/android/base/WebappFragmentRepeater.inc
mobile/android/base/WebappManifestFragment.xml.frag.in
mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
mobile/android/base/java/org/mozilla/gecko/GeckoAppShell.java
mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
mobile/android/base/java/org/mozilla/gecko/GeckoProfile.java
mobile/android/base/java/org/mozilla/gecko/Webapp.java
mobile/android/base/java/org/mozilla/gecko/webapp/Allocator.java
mobile/android/base/java/org/mozilla/gecko/webapp/ApkResources.java
mobile/android/base/java/org/mozilla/gecko/webapp/Dispatcher.java
mobile/android/base/java/org/mozilla/gecko/webapp/EventListener.java
mobile/android/base/java/org/mozilla/gecko/webapp/InstallHelper.java
mobile/android/base/java/org/mozilla/gecko/webapp/InstallListener.java
mobile/android/base/java/org/mozilla/gecko/webapp/TaskKiller.java
mobile/android/base/java/org/mozilla/gecko/webapp/UninstallListener.java
mobile/android/base/java/org/mozilla/gecko/webapp/WebappImpl.java
mobile/android/base/java/org/mozilla/gecko/webapp/Webapps.java
mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedEditText.java
mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedFrameLayout.java
mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedImageButton.java
mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedImageView.java
mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedLinearLayout.java
mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedRelativeLayout.java
mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedTextSwitcher.java
mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedTextView.java
mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedView.java
mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedView.java.frag
mobile/android/base/locales/en-US/android_strings.dtd
mobile/android/base/moz.build
mobile/android/base/resources/layout/shared_ui_components.xml
mobile/android/base/resources/layout/web_app.xml
mobile/android/base/strings.xml.in
mobile/android/chrome/content/WebappRT.js
mobile/android/chrome/content/browser.js
mobile/android/chrome/jar.mn
mobile/android/components/MobileComponents.manifest
mobile/android/components/WebappsUpdateTimer.js
mobile/android/components/moz.build
mobile/android/installer/package-manifest.in
mobile/android/locales/en-US/chrome/webapp.properties
mobile/android/locales/jar.mn
mobile/android/modules/WebappManager.jsm
mobile/android/modules/WebappManagerWorker.js
mobile/android/modules/moz.build
--- a/.eslintignore
+++ b/.eslintignore
@@ -146,20 +146,16 @@ mobile/android/chrome/content/about.js
 
 # Not much JS to lint and non-standard at that
 mobile/android/installer/
 mobile/android/locales/
 
 # Pretty sure we're disabling this one anyway
 mobile/android/modules/ContactService.jsm
 
-# es7 proposed: array comprehensions
-#   https://github.com/eslint/espree/issues/125
-mobile/android/modules/WebappManager.jsm
-
 # Non-standard `(catch ex if ...)`
 mobile/android/components/Snippets.js
 
 # Bug 1178739: Ignore this file as a quick fix for "Illegal yield expression"
 mobile/android/modules/HomeProvider.jsm
 
 # services/ exclusions
 
--- a/layout/reftests/font-face/reftest.list
+++ b/layout/reftests/font-face/reftest.list
@@ -137,18 +137,18 @@ fails-if(cocoaWidget) fails-if(winWidget
 
 HTTP(..) != 534352-1-extra-cmap-sentinel.html 534352-1-extra-cmap-sentinel-ref.html
 HTTP(..) == bug533251.html bug533251-ref.html
 
 # Bug 875287
 HTTP(..) == font-familiy-whitespace-1.html font-familiy-whitespace-1-ref.html
 HTTP(..) != font-familiy-whitespace-1.html font-familiy-whitespace-1-notref.html
 
-skip-if(B2G||Mulet) HTTP(..) == ivs-1.html ivs-1-ref.html # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) HTTP(..) == cjkcisvs-1.html cjkcisvs-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
+skip-if(B2G||Mulet||Android) HTTP(..) == ivs-1.html ivs-1-ref.html # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop # Android bug 1250229
+skip-if(B2G||Mulet||Android) HTTP(..) == cjkcisvs-1.html cjkcisvs-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop # Android bug 1250229
 
 skip-if(B2G||Mulet) HTTP(..) == missing-names.html missing-names-ref.html # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
 
 # Tests for bug 670900 - handling of 404 (not found) error in @font-face URL
 # (using Chunkfive font data returned from a .sjs file)
 HTTP(..) == font-error-404-1.html font-error-404-1-ref.html # HTTP status 404, don't load
 skip-if(B2G||Mulet) HTTP(..) == font-error-404-2.html font-error-404-2-ref.html # HTTP status 200, load # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
 HTTP(..) != font-error-404-1.html font-error-404-2.html # sanity-check that the results differ
--- a/layout/reftests/writing-mode/reftest.list
+++ b/layout/reftests/writing-mode/reftest.list
@@ -164,16 +164,16 @@ fuzzy-if(gtkWidget||B2G,255,6) fuzzy-if(
 == 1196887-1-computed-display-inline-block.html 1196887-1-computed-display-inline-block-ref.html
 == 1205787-legacy-svg-values-1.html 1205787-legacy-svg-values-1-ref.html
 
 == 1216747-1.html 1216747-1-ref.html
 != 1216747-1.html 1216747-1-notref.html
 
 == 1243125-1-floats-overflowing.html 1243125-1-floats-overflowing-ref.html
 
-HTTP(..) == 1248248-1-orientation-break-glyphrun.html 1248248-1-orientation-break-glyphrun-ref.html
+skip-if(Android) HTTP(..) == 1248248-1-orientation-break-glyphrun.html 1248248-1-orientation-break-glyphrun-ref.html # Android bug 1250229
 
 # Suite of tests from Gérard Talbot in bug 1079151
 # Frequent Windows 7 load failed: timed out waiting for test to complete (waiting for onload scripts to complete), bug 1167155 and friends
 skip-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) include abspos/reftest.list
 
 # Tests for tables with vertical writing modes
 include tables/reftest.list
--- a/mobile/android/.eslintrc
+++ b/mobile/android/.eslintrc
@@ -22,17 +22,16 @@ globals:
     Services: false
     SharedPreferences: false
     strings: false
     Strings: false
     Task: false
     TelemetryStopwatch: false
     UITelemetry: false
     UserAgentOverrides: 0
-    WebappManager: false
     XPCOMUtils: false
     ctypes: false
     dump: false
     exports: false
     importScripts: false
     module: false
     require: false
     uuidgen: false
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -860,40 +860,16 @@ pref("browser.snippets.geoUrl", "https:/
 // URL used to ping metrics with stats about which snippets have been shown
 pref("browser.snippets.statsUrl", "https://snippets-stats.mozilla.org/mobile");
 
 // These prefs require a restart to take effect.
 pref("browser.snippets.enabled", true);
 pref("browser.snippets.syncPromo.enabled", true);
 pref("browser.snippets.firstrunHomepage.enabled", true);
 
-// The URL of the APK factory from which we obtain APKs for webapps.
-pref("browser.webapps.apkFactoryUrl", "https://controller.apk.firefox.com/application.apk");
-
-// How frequently to check for webapp updates, in seconds (86400 is daily).
-pref("browser.webapps.updateInterval", 86400);
-
-// Whether or not to check for updates.  Enabled by default, but the runtime
-// disables it for webapp profiles on firstrun, so only the main Fennec process
-// checks for updates (to avoid duplicate update notifications).
-//
-// In the future, we might want to make each webapp process check for updates
-// for its own webapp, in which case we'll need to have a third state for this
-// preference.  Thus it's an integer rather than a boolean.
-//
-// Possible values:
-//   0: don't check for updates
-//   1: do check for updates
-pref("browser.webapps.checkForUpdates", 1);
-
-// The URL of the service that checks for updates.
-// To test updates, set this to http://apk-update-checker.paas.allizom.org,
-// which is a test server that always reports all apps as having updates.
-pref("browser.webapps.updateCheckUrl", "https://controller.apk.firefox.com/app_updates");
-
 // The mode of home provider syncing.
 // 0: Sync always
 // 1: Sync only when on wifi
 pref("home.sync.updateMode", 0);
 
 // How frequently to check if we should sync home provider data.
 pref("home.sync.checkIntervalSecs", 3600);
 
--- a/mobile/android/base/AndroidManifest.xml.in
+++ b/mobile/android/base/AndroidManifest.xml.in
@@ -179,54 +179,22 @@
                 <data android:scheme="http" />
                 <data android:scheme="https" />
                 <data android:mimeType="text/html"/>
                 <data android:mimeType="text/plain"/>
                 <data android:mimeType="application/xhtml+xml"/>
             </intent-filter>
         </activity>
 
-        <activity android:name="org.mozilla.gecko.webapp.Dispatcher"
-            android:noHistory="true" >
-            <intent-filter>
-                <!-- catch links from synthetic apks -->
-                <action android:name="android.intent.action.VIEW" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:mimeType="application/webapp" />
-            </intent-filter>
-        </activity>
-
-        <receiver android:name="org.mozilla.gecko.webapp.UninstallListener" >
-          <intent-filter>
-             <action android:name="android.intent.action.PACKAGE_REMOVED" />
-             <data android:scheme="package" />
-          </intent-filter>
-        </receiver>
-
-        <receiver android:name="org.mozilla.gecko.webapp.TaskKiller">
-          <intent-filter>
-             <action android:name="org.mozilla.webapp.TASK_REMOVED" />
-             <category android:name="android.intent.category.DEFAULT" />
-          </intent-filter>
-        </receiver>
-
         <receiver android:name="org.mozilla.gecko.restrictions.RestrictionProvider">
           <intent-filter>
             <action android:name="android.intent.action.GET_RESTRICTION_ENTRIES" />
           </intent-filter>
         </receiver>
 
-        <!-- Declare a predefined number of Webapp<num> activities. These are
-             used so that each web app can launch in its own process. Keep
-             this number in sync with the total number of web apps handled in
-             WebappAllocator. -->
-
-#define FRAGMENT WebappManifestFragment.xml.frag.in
-#include WebappFragmentRepeater.inc
-
         <!-- Masquerade as the Resolver so that we can be opened from the Marketplace. -->
         <activity-alias
             android:name="com.android.internal.app.ResolverActivity"
             android:targetActivity="@MOZ_ANDROID_BROWSER_INTENT_CLASS@"
             android:exported="true" />
 
         <receiver android:name="org.mozilla.gecko.GeckoUpdateReceiver">
             <intent-filter>
deleted file mode 100644
--- a/mobile/android/base/WebappFragmentRepeater.inc
+++ /dev/null
@@ -1,301 +0,0 @@
-#define APPNUM 0
-#include @FRAGMENT@
-
-#define APPNUM 1
-#include @FRAGMENT@
-
-#define APPNUM 2
-#include @FRAGMENT@
-
-#define APPNUM 3
-#include @FRAGMENT@
-
-#define APPNUM 4
-#include @FRAGMENT@
-
-#define APPNUM 5
-#include @FRAGMENT@
-
-#define APPNUM 6
-#include @FRAGMENT@
-
-#define APPNUM 7
-#include @FRAGMENT@
-
-#define APPNUM 8
-#include @FRAGMENT@
-
-#define APPNUM 9
-#include @FRAGMENT@
-
-#define APPNUM 10
-#include @FRAGMENT@
-
-#define APPNUM 11
-#include @FRAGMENT@
-
-#define APPNUM 12
-#include @FRAGMENT@
-
-#define APPNUM 13
-#include @FRAGMENT@
-
-#define APPNUM 14
-#include @FRAGMENT@
-
-#define APPNUM 15
-#include @FRAGMENT@
-
-#define APPNUM 16
-#include @FRAGMENT@
-
-#define APPNUM 17
-#include @FRAGMENT@
-
-#define APPNUM 18
-#include @FRAGMENT@
-
-#define APPNUM 19
-#include @FRAGMENT@
-
-#define APPNUM 20
-#include @FRAGMENT@
-
-#define APPNUM 21
-#include @FRAGMENT@
-
-#define APPNUM 22
-#include @FRAGMENT@
-
-#define APPNUM 23
-#include @FRAGMENT@
-
-#define APPNUM 24
-#include @FRAGMENT@
-
-#define APPNUM 25
-#include @FRAGMENT@
-
-#define APPNUM 26
-#include @FRAGMENT@
-
-#define APPNUM 27
-#include @FRAGMENT@
-
-#define APPNUM 28
-#include @FRAGMENT@
-
-#define APPNUM 29
-#include @FRAGMENT@
-
-#define APPNUM 30
-#include @FRAGMENT@
-
-#define APPNUM 31
-#include @FRAGMENT@
-
-#define APPNUM 32
-#include @FRAGMENT@
-
-#define APPNUM 33
-#include @FRAGMENT@
-
-#define APPNUM 34
-#include @FRAGMENT@
-
-#define APPNUM 35
-#include @FRAGMENT@
-
-#define APPNUM 36
-#include @FRAGMENT@
-
-#define APPNUM 37
-#include @FRAGMENT@
-
-#define APPNUM 38
-#include @FRAGMENT@
-
-#define APPNUM 39
-#include @FRAGMENT@
-
-#define APPNUM 40
-#include @FRAGMENT@
-
-#define APPNUM 41
-#include @FRAGMENT@
-
-#define APPNUM 42
-#include @FRAGMENT@
-
-#define APPNUM 43
-#include @FRAGMENT@
-
-#define APPNUM 44
-#include @FRAGMENT@
-
-#define APPNUM 45
-#include @FRAGMENT@
-
-#define APPNUM 46
-#include @FRAGMENT@
-
-#define APPNUM 47
-#include @FRAGMENT@
-
-#define APPNUM 48
-#include @FRAGMENT@
-
-#define APPNUM 49
-#include @FRAGMENT@
-
-#define APPNUM 50
-#include @FRAGMENT@
-
-#define APPNUM 51
-#include @FRAGMENT@
-
-#define APPNUM 52
-#include @FRAGMENT@
-
-#define APPNUM 53
-#include @FRAGMENT@
-
-#define APPNUM 54
-#include @FRAGMENT@
-
-#define APPNUM 55
-#include @FRAGMENT@
-
-#define APPNUM 56
-#include @FRAGMENT@
-
-#define APPNUM 57
-#include @FRAGMENT@
-
-#define APPNUM 58
-#include @FRAGMENT@
-
-#define APPNUM 59
-#include @FRAGMENT@
-
-#define APPNUM 60
-#include @FRAGMENT@
-
-#define APPNUM 61
-#include @FRAGMENT@
-
-#define APPNUM 62
-#include @FRAGMENT@
-
-#define APPNUM 63
-#include @FRAGMENT@
-
-#define APPNUM 64
-#include @FRAGMENT@
-
-#define APPNUM 65
-#include @FRAGMENT@
-
-#define APPNUM 66
-#include @FRAGMENT@
-
-#define APPNUM 67
-#include @FRAGMENT@
-
-#define APPNUM 68
-#include @FRAGMENT@
-
-#define APPNUM 69
-#include @FRAGMENT@
-
-#define APPNUM 70
-#include @FRAGMENT@
-
-#define APPNUM 71
-#include @FRAGMENT@
-
-#define APPNUM 72
-#include @FRAGMENT@
-
-#define APPNUM 73
-#include @FRAGMENT@
-
-#define APPNUM 74
-#include @FRAGMENT@
-
-#define APPNUM 75
-#include @FRAGMENT@
-
-#define APPNUM 76
-#include @FRAGMENT@
-
-#define APPNUM 77
-#include @FRAGMENT@
-
-#define APPNUM 78
-#include @FRAGMENT@
-
-#define APPNUM 79
-#include @FRAGMENT@
-
-#define APPNUM 80
-#include @FRAGMENT@
-
-#define APPNUM 81
-#include @FRAGMENT@
-
-#define APPNUM 82
-#include @FRAGMENT@
-
-#define APPNUM 83
-#include @FRAGMENT@
-
-#define APPNUM 84
-#include @FRAGMENT@
-
-#define APPNUM 85
-#include @FRAGMENT@
-
-#define APPNUM 86
-#include @FRAGMENT@
-
-#define APPNUM 87
-#include @FRAGMENT@
-
-#define APPNUM 88
-#include @FRAGMENT@
-
-#define APPNUM 89
-#include @FRAGMENT@
-
-#define APPNUM 90
-#include @FRAGMENT@
-
-#define APPNUM 91
-#include @FRAGMENT@
-
-#define APPNUM 92
-#include @FRAGMENT@
-
-#define APPNUM 93
-#include @FRAGMENT@
-
-#define APPNUM 94
-#include @FRAGMENT@
-
-#define APPNUM 95
-#include @FRAGMENT@
-
-#define APPNUM 96
-#include @FRAGMENT@
-
-#define APPNUM 97
-#include @FRAGMENT@
-
-#define APPNUM 98
-#include @FRAGMENT@
-
-#define APPNUM 99
-#include @FRAGMENT@
-#undef APPNUM
-#undef FRAGMENT
deleted file mode 100644
--- a/mobile/android/base/WebappManifestFragment.xml.frag.in
+++ /dev/null
@@ -1,9 +0,0 @@
-        <activity android:name="org.mozilla.gecko.webapp.Webapps$Webapp@APPNUM@"
-                  android:label="@string/webapp_generic_name"
-                  android:configChanges="keyboard|keyboardHidden|mcc|mnc|orientation|screenSize"
-                  android:windowSoftInputMode="stateUnspecified|adjustResize"
-                  android:process=":@ANDROID_PACKAGE_NAME@.Webapp@APPNUM@"
-                  android:theme="@style/Gecko.App"
-                  android:launchMode="singleTop"
-                  android:exported="true"
-        />
--- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
@@ -674,16 +674,17 @@ public class BrowserApp extends GeckoApp
         }
 
         setBrowserToolbarListeners();
 
         mFindInPageBar = (FindInPageBar) findViewById(R.id.find_in_page);
         mMediaCastingBar = (MediaCastingBar) findViewById(R.id.media_casting);
 
         EventDispatcher.getInstance().registerGeckoThreadListener((GeckoEventListener)this,
+            "Gecko:DelayedStartup",
             "Menu:Open",
             "Menu:Update",
             "LightweightTheme:Update",
             "Search:Keyword",
             "Prompt:ShowTop");
 
         EventDispatcher.getInstance().registerGeckoThreadListener((NativeEventListener)this,
             "CharEncoding:Data",
@@ -1385,16 +1386,17 @@ public class BrowserApp extends GeckoApp
             mAccountsHelper = null;
         }
 
         if (mZoomedView != null) {
             mZoomedView.destroy();
         }
 
         EventDispatcher.getInstance().unregisterGeckoThreadListener((GeckoEventListener) this,
+            "Gecko:DelayedStartup",
             "Menu:Open",
             "Menu:Update",
             "LightweightTheme:Update",
             "Search:Keyword",
             "Prompt:ShowTop");
 
         EventDispatcher.getInstance().unregisterGeckoThreadListener((NativeEventListener) this,
             "CharEncoding:Data",
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
@@ -38,18 +38,16 @@ import org.mozilla.gecko.util.EventCallb
 import org.mozilla.gecko.util.FileUtils;
 import org.mozilla.gecko.util.GeckoEventListener;
 import org.mozilla.gecko.util.GeckoRequest;
 import org.mozilla.gecko.util.HardwareUtils;
 import org.mozilla.gecko.util.NativeEventListener;
 import org.mozilla.gecko.util.NativeJSObject;
 import org.mozilla.gecko.util.PrefUtils;
 import org.mozilla.gecko.util.ThreadUtils;
-import org.mozilla.gecko.webapp.EventListener;
-import org.mozilla.gecko.webapp.UninstallListener;
 import org.mozilla.gecko.widget.ButtonToast;
 
 import android.annotation.SuppressLint;
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
@@ -139,17 +137,16 @@ public abstract class GeckoApp
 
     private static final String LOGTAG = "GeckoApp";
     private static final int ONE_DAY_MS = 1000*60*60*24;
 
     public enum StartupAction {
         NORMAL,     /* normal application start */
         URL,        /* launched with a passed URL */
         PREFETCH,   /* launched with a passed URL that we prefetch */
-        WEBAPP,     /* launched as a webapp runtime */
         GUEST,      /* launched in guest browsing */
         RESTRICTED, /* launched with restricted profile */
         SHORTCUT    /* launched from a homescreen shortcut */
     }
 
     public static final String ACTION_ALERT_CALLBACK       = "org.mozilla.gecko.ACTION_ALERT_CALLBACK";
     public static final String ACTION_HOMESCREEN_SHORTCUT  = "org.mozilla.gecko.BOOKMARK";
     public static final String ACTION_DEBUG                = "org.mozilla.gecko.DEBUG";
@@ -209,18 +206,16 @@ public abstract class GeckoApp
     private Telemetry.Timer mJavaUiStartupTimer;
     private Telemetry.Timer mGeckoReadyStartupTimer;
 
     private String mPrivateBrowsingSession;
 
     private volatile HealthRecorder mHealthRecorder;
     private volatile Locale mLastLocale;
 
-    private EventListener mWebappEventListener;
-
     private Intent mRestartIntent;
 
     abstract public int getLayout();
 
     abstract protected String getDefaultProfileName() throws NoMozillaDirectoryException;
 
     protected void processTabQueue() {};
 
@@ -686,19 +681,17 @@ public abstract class GeckoApp
                            }
                        });
         }
     }
 
     @Override
     public void handleMessage(String event, JSONObject message) {
         try {
-            if (event.equals("Gecko:DelayedStartup")) {
-                ThreadUtils.postToBackgroundThread(new UninstallListener.DelayedStartupTask(this));
-            } else if (event.equals("Gecko:Ready")) {
+            if (event.equals("Gecko:Ready")) {
                 mGeckoReadyStartupTimer.stop();
                 geckoConnected();
 
                 // This method is already running on the background thread, so we
                 // know that mHealthRecorder will exist. That doesn't stop us being
                 // paranoid.
                 // This method is cheap, so don't spawn a new runnable.
                 final HealthRecorder rec = mHealthRecorder;
@@ -706,20 +699,16 @@ public abstract class GeckoApp
                   rec.recordGeckoStartupTime(mGeckoReadyStartupTimer.getElapsed());
                 }
 
             } else if (event.equals("Gecko:Exited")) {
                 // Gecko thread exited first; let GeckoApp die too.
                 doShutdown();
                 return;
 
-            } else if ("NativeApp:IsDebuggable".equals(event)) {
-                JSONObject ret = new JSONObject();
-                ret.put("isDebuggable", getIsDebuggable());
-                EventDispatcher.sendResponse(message, ret);
             } else if (event.equals("Accessibility:Event")) {
                 GeckoAccessibility.sendAccessibilityEvent(message);
             }
         } catch (Exception e) {
             Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
         }
     }
 
@@ -1263,20 +1252,18 @@ public abstract class GeckoApp
             }
         }
 
         // GeckoThread has to register for "Gecko:Ready" first, so GeckoApp registers
         // for events after initializing GeckoThread but before launching it.
 
         EventDispatcher.getInstance().registerGeckoThreadListener((GeckoEventListener)this,
             "Gecko:Ready",
-            "Gecko:DelayedStartup",
             "Gecko:Exited",
-            "Accessibility:Event",
-            "NativeApp:IsDebuggable");
+            "Accessibility:Event");
 
         EventDispatcher.getInstance().registerGeckoThreadListener((NativeEventListener)this,
             "Accessibility:Ready",
             "Bookmark:Insert",
             "Contact:Add",
             "DevToolsAuth:Scan",
             "DOMFullScreen:Start",
             "DOMFullScreen:Stop",
@@ -1294,21 +1281,16 @@ public abstract class GeckoApp
             "ToggleChrome:Show",
             "Update:Check",
             "Update:Download",
             "Update:Install");
 
         EventDispatcher.getInstance().registerBackgroundThreadListener((BundleEventListener) this,
                 "History:GetPrePathLastVisitedTimeMilliseconds");
 
-        if (mWebappEventListener == null) {
-            mWebappEventListener = new EventListener();
-            mWebappEventListener.registerEvents();
-        }
-
         GeckoThread.launch();
 
         Bundle stateBundle = ContextUtils.getBundleExtra(getIntent(), EXTRA_STATE_BUNDLE);
         if (stateBundle != null) {
             // Use the state bundle if it was given as an intent extra. This is
             // only intended to be used internally via Robocop, so a boolean
             // is read from a private shared pref to prevent other apps from
             // injecting states.
@@ -2098,20 +2080,18 @@ public abstract class GeckoApp
             // This build does not support the Android version of the device:
             // We did not initialize anything, so skip cleaning up.
             super.onDestroy();
             return;
         }
 
         EventDispatcher.getInstance().unregisterGeckoThreadListener((GeckoEventListener)this,
             "Gecko:Ready",
-            "Gecko:DelayedStartup",
             "Gecko:Exited",
-            "Accessibility:Event",
-            "NativeApp:IsDebuggable");
+            "Accessibility:Event");
 
         EventDispatcher.getInstance().unregisterGeckoThreadListener((NativeEventListener)this,
             "Accessibility:Ready",
             "Bookmark:Insert",
             "Contact:Add",
             "DOMFullScreen:Start",
             "DOMFullScreen:Stop",
             "Image:SetAs",
@@ -2128,21 +2108,16 @@ public abstract class GeckoApp
             "ToggleChrome:Show",
             "Update:Check",
             "Update:Download",
             "Update:Install");
 
         EventDispatcher.getInstance().unregisterBackgroundThreadListener((BundleEventListener) this,
                 "History:GetPrePathLastVisitedTimeMilliseconds");
 
-        if (mWebappEventListener != null) {
-            mWebappEventListener.unregisterEvents();
-            mWebappEventListener = null;
-        }
-
         deleteTempFiles();
 
         if (mDoorHangerPopup != null)
             mDoorHangerPopup.destroy();
         if (mFormAssistPopup != null)
             mFormAssistPopup.destroy();
         if (mContactService != null)
             mContactService.destroy();
@@ -2668,33 +2643,16 @@ public abstract class GeckoApp
         try {
             versionCode = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode;
         } catch (NameNotFoundException e) {
             Log.wtf(LOGTAG, getPackageName() + " not found", e);
         }
         return versionCode;
     }
 
-    protected boolean getIsDebuggable() {
-        // Return false so Fennec doesn't appear to be debuggable.  WebappImpl
-        // then overrides this and returns the value of android:debuggable for
-        // the webapp APK, so webapps get the behavior supported by this method
-        // (i.e. automatic configuration and enabling of the remote debugger).
-        return false;
-
-        // If we ever want to expose this for Fennec, here's how we would do it:
-        // int flags = 0;
-        // try {
-        //     flags = getPackageManager().getPackageInfo(getPackageName(), 0).applicationInfo.flags;
-        // } catch (NameNotFoundException e) {
-        //     Log.wtf(LOGTAG, getPackageName() + " not found", e);
-        // }
-        // return (flags & android.content.pm.ApplicationInfo.FLAG_DEBUGGABLE) != 0;
-    }
-
     // FHR reason code for a session end prior to a restart for a
     // locale change.
     private static final String SESSION_END_LOCALE_CHANGED = "L";
 
     /**
      * This exists so that a locale can be applied in two places: when saved
      * in a nested activity, and then again when we get back up to GeckoApp.
      *
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoAppShell.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoAppShell.java
@@ -2830,14 +2830,9 @@ public class GeckoAppShell
 
     @WrapForJNI
     static Rect getScreenSize() {
         final WindowManager wm = (WindowManager)
                 getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
         final Display disp = wm.getDefaultDisplay();
         return new Rect(0, 0, disp.getWidth(), disp.getHeight());
     }
-
-    @JNITarget
-    static boolean isWebAppProcess() {
-        return GeckoProfile.get(getApplicationContext()).isWebAppProfile();
-    }
 }
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
@@ -140,17 +140,16 @@ public class GeckoApplication extends Ap
 
         // This getInstance call will force initialization of the NotificationHelper, but does nothing with the result
         NotificationHelper.getInstance(context).init();
 
         MulticastDNSManager.getInstance(context).init();
 
         // Make sure that all browser-ish applications default to the real LocalBrowserDB.
         // GeckoView consumers use their own Application class, so this doesn't affect them.
-        // WebappImpl overrides this on creation.
         //
         // We need to do this before any access to the profile; it controls
         // which database class is used.
         //
         // As such, this needs to occur before the GeckoView in GeckoApp is inflated -- i.e., in the
         // GeckoApp constructor or earlier -- because GeckoView implicitly accesses the profile. This is earlier!
         GeckoProfile.setBrowserDBFactory(new BrowserDB.Factory() {
             @Override
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoProfile.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoProfile.java
@@ -78,17 +78,16 @@ public final class GeckoProfile {
     private static File sGuestDir;
     private static GeckoProfile sGuestProfile;
     private static boolean sShouldCheckForGuestProfile = true;
 
     public static boolean sIsUsingCustomProfile;
 
     private final String mName;
     private final File mMozillaDir;
-    private final boolean mIsWebAppProfile;
     private final Context mApplicationContext;
 
     private final BrowserDB mDB;
 
     /**
      * Access to this member should be synchronized to avoid
      * races during creation -- particularly between getDir and GeckoView#init.
      *
@@ -301,16 +300,18 @@ public final class GeckoProfile {
                 profile.setDir(profileDir);
                 return profile;
             }
 
             throw new IllegalStateException("Refusing to reuse profile with a different directory.");
         }
     }
 
+    // Currently unused outside of testing.
+    @RobocopTarget
     public static boolean removeProfile(Context context, String profileName) {
         if (profileName == null) {
             Log.w(LOGTAG, "Unable to remove profile: null profile name.");
             return false;
         }
 
         final GeckoProfile profile = get(context, profileName);
         if (profile == null) {
@@ -452,35 +453,31 @@ public final class GeckoProfile {
 
     private GeckoProfile(Context context, String profileName, File profileDir, BrowserDB.Factory dbFactory) throws NoMozillaDirectoryException {
         if (TextUtils.isEmpty(profileName)) {
             throw new IllegalArgumentException("Unable to create GeckoProfile for empty profile name.");
         }
 
         mApplicationContext = context.getApplicationContext();
         mName = profileName;
-        mIsWebAppProfile = profileName.startsWith("webapp");
         mMozillaDir = GeckoProfileDirectories.getMozillaDirectory(context);
 
         // This apes the behavior of setDir.
         if (profileDir != null && profileDir.exists() && profileDir.isDirectory()) {
             mProfileDir = profileDir;
         }
 
         // N.B., mProfileDir can be null at this point.
         mDB = dbFactory.get(profileName, mProfileDir);
     }
 
     public BrowserDB getDB() {
         return mDB;
     }
 
-    public boolean isWebAppProfile() {
-        return mIsWebAppProfile;
-    }
 
     // Warning, Changing the lock file state from outside apis will cause this to become out of sync
     public boolean locked() {
         if (mLocked != LockState.UNDEFINED) {
             return mLocked == LockState.LOCKED;
         }
 
         boolean profileExists;
@@ -999,54 +996,48 @@ public final class GeckoProfile {
         profileSection.setProperty("Path", saltedName);
 
         if (parser.getSection("General") == null) {
             INISection generalSection = new INISection("General");
             generalSection.setProperty("StartWithLastProfile", 1);
             parser.addSection(generalSection);
         }
 
-        if (!isDefaultSet && !mIsWebAppProfile) {
-            // only set as default if this is the first non-webapp
-            // profile we're creating
+        if (!isDefaultSet) {
+            // only set as default if this is the first profile we're creating
             profileSection.setProperty("Default", 1);
 
             // We have no intention of stopping this session. The FIRSTRUN session
             // ends when the browsing session/activity has ended. All events
             // during firstrun will be tagged as FIRSTRUN.
             Telemetry.startUISession(TelemetryContract.Session.FIRSTRUN);
         }
 
         parser.addSection(profileSection);
         parser.write();
 
-        // Trigger init for non-webapp profiles.
-        if (!mIsWebAppProfile) {
-            enqueueInitialization(profileDir);
-        }
+        enqueueInitialization(profileDir);
 
         // Write out profile creation time, mirroring the logic in nsToolkitProfileService.
         try {
             FileOutputStream stream = new FileOutputStream(profileDir.getAbsolutePath() + File.separator + "times.json");
             OutputStreamWriter writer = new OutputStreamWriter(stream, Charset.forName("UTF-8"));
             try {
                 writer.append("{\"created\": " + System.currentTimeMillis() + "}\n");
             } finally {
                 writer.close();
             }
         } catch (Exception e) {
             // Best-effort.
             Log.w(LOGTAG, "Couldn't write times.json.", e);
         }
 
-        // Initialize pref flag for displaying the start pane for a new non-webapp profile.
-        if (!mIsWebAppProfile) {
-            final SharedPreferences prefs = GeckoSharedPrefs.forProfile(mApplicationContext);
-            prefs.edit().putBoolean(FirstrunAnimationContainer.PREF_FIRSTRUN_ENABLED, true).apply();
-        }
+        // Initialize pref flag for displaying the start pane for a new profile.
+        final SharedPreferences prefs = GeckoSharedPrefs.forProfile(mApplicationContext);
+        prefs.edit().putBoolean(FirstrunAnimationContainer.PREF_FIRSTRUN_ENABLED, true).apply();
 
         return profileDir;
     }
 
     /**
      * This method is called once, immediately before creation of the profile
      * directory completes.
      *
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/Webapp.java
+++ /dev/null
@@ -1,13 +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 org.mozilla.gecko.webapp.WebappImpl;
-
-/**
- * This class serves only as a namespace wrapper for WebappImpl.
- */
-public class Webapp extends WebappImpl {}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/webapp/Allocator.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/* -*- 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.webapp;
-
-import java.util.ArrayList;
-
-import org.mozilla.gecko.GeckoAppShell;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.util.Log;
-
-public class Allocator {
-
-    private final String LOGTAG = "GeckoWebappAllocator";
-
-    private static final String PREFIX_ORIGIN = "webapp-origin-";
-    private static final String PREFIX_PACKAGE_NAME = "webapp-package-name-";
-
-    // These prefixes are for prefs used by the old shortcut-based runtime.
-    // We define them here so maybeMigrateOldPrefs can migrate them to their
-    // new equivalents if this app was originally installed as a shortcut.
-    // Maybe we can remove this code in the future!
-    private static final String PREFIX_OLD_APP = "app";
-    private static final String PREFIX_OLD_ICON = "icon";
-
-    // The number of Webapp# and WEBAPP# activities/apps/intents
-    private final static int MAX_WEB_APPS = 100;
-
-    protected static Allocator sInstance;
-    public static Allocator getInstance() {
-        return getInstance(GeckoAppShell.getContext());
-    }
-
-    public static synchronized Allocator getInstance(Context cx) {
-        if (sInstance == null) {
-            sInstance = new Allocator(cx);
-        }
-
-        return sInstance;
-    }
-
-    SharedPreferences mPrefs;
-
-    @SuppressWarnings("deprecation") // Suppressing deprecation notification for Context.MODE_MULTI_PROCESS until we
-                                     // reach a timeline for removal of the whole feature. (Bug 1171213)
-    protected Allocator(Context context) {
-        mPrefs = context.getSharedPreferences("webapps", Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS);
-    }
-
-    private static String appKey(int index) {
-        return PREFIX_PACKAGE_NAME + index;
-    }
-
-    public static String iconKey(int index) {
-        return "web-app-color-" + index;
-    }
-
-    public static String originKey(int i) {
-        return PREFIX_ORIGIN + i;
-    }
-
-    private static String oldAppKey(int index) {
-        return PREFIX_OLD_APP + index;
-    }
-
-    private static String oldIconKey(int index) {
-        return PREFIX_OLD_ICON + index;
-    }
-
-    public ArrayList<String> getInstalledPackageNames() {
-        ArrayList<String> installedPackages = new ArrayList<String>();
-
-        for (int i = 0; i < MAX_WEB_APPS; ++i) {
-            if (mPrefs.contains(appKey(i))) {
-                installedPackages.add(mPrefs.getString(appKey(i), ""));
-            }
-        }
-        return installedPackages;
-    }
-
-    public synchronized int findOrAllocatePackage(final String packageName) {
-        int index = getIndexForApp(packageName);
-        if (index != -1)
-            return index;
-
-        for (int i = 0; i < MAX_WEB_APPS; ++i) {
-            if (!mPrefs.contains(appKey(i))) {
-                // found unused index i
-                putPackageName(i, packageName);
-                return i;
-            }
-        }
-
-        // no more apps!
-        return -1;
-    }
-
-    public synchronized void putPackageName(final int index, final String packageName) {
-        mPrefs.edit().putString(appKey(index), packageName).apply();
-    }
-
-    public void updateColor(int index, int color) {
-        mPrefs.edit().putInt(iconKey(index), color).apply();
-    }
-
-    public synchronized int getIndexForApp(String packageName) {
-        return findSlotForPrefix(PREFIX_PACKAGE_NAME, packageName);
-    }
-
-    protected int findSlotForPrefix(String prefix, String value) {
-        for (int i = 0; i < MAX_WEB_APPS; ++i) {
-            if (mPrefs.getString(prefix + i, "").equals(value)) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-    public synchronized String getAppForIndex(int index) {
-        return mPrefs.getString(appKey(index), null);
-    }
-
-    public synchronized int releaseIndexForApp(String app) {
-        int index = getIndexForApp(app);
-        if (index == -1)
-            return -1;
-
-        releaseIndex(index);
-        return index;
-    }
-
-    public synchronized void releaseIndex(final int index) {
-        mPrefs.edit().remove(appKey(index)).remove(iconKey(index)).remove(originKey(index)).apply();
-    }
-
-    public void putOrigin(int index, String origin) {
-        mPrefs.edit().putString(originKey(index), origin).apply();
-    }
-
-    public String getOrigin(int index) {
-        return mPrefs.getString(originKey(index), null);
-    }
-
-    public int getColor(int index) {
-        return mPrefs.getInt(iconKey(index), -1);
-    }
-
-    /**
-     * Migrate old prefs to their new equivalents if this app was originally
-     * installed by the shortcut-based implementation.
-     */
-    public void maybeMigrateOldPrefs(int index) {
-        if (!mPrefs.contains(oldAppKey(index))) {
-            return;
-        }
-
-        Log.i(LOGTAG, "migrating old prefs");
-
-        // The old appKey pref stored the origin, while the new appKey pref
-        // stores the packageName, so we migrate oldAppKey to the origin pref.
-        putOrigin(index, mPrefs.getString(oldAppKey(index), null));
-
-        // The old iconKey pref actually stored the splash screen background
-        // color, so we migrate oldIconKey to the color pref.
-        updateColor(index, mPrefs.getInt(oldIconKey(index), -1));
-
-        // Remove the old prefs so we don't migrate them the next time around.
-        mPrefs.edit().remove(oldAppKey(index)).remove(oldIconKey(index)).apply();
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/webapp/ApkResources.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/* -*- 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.webapp;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Environment;
-import android.util.Log;
-
-public class ApkResources {
-    private static final String LOGTAG = "GeckoWebappApkResources";
-    private final String mPackageName;
-    private final ApplicationInfo mInfo;
-    private final Context mContext;
-
-    public ApkResources(Context context, String packageName) throws NameNotFoundException {
-        mPackageName = packageName;
-        mInfo = context.getPackageManager().getApplicationInfo(
-                    mPackageName, PackageManager.GET_META_DATA);
-        mContext = context;
-    }
-
-    private ApplicationInfo info() {
-        return mInfo;
-    }
-
-    public String getPackageName() {
-        return mPackageName;
-    }
-
-    private Bundle metadata() {
-        return mInfo.metaData;
-    }
-
-    public String getManifest(Context context) {
-        return readResource(context, "manifest");
-    }
-
-    public String getMiniManifest(Context context) {
-        return readResource(context, "mini");
-    }
-
-    public String getManifestUrl() {
-        return metadata().getString("manifestUrl");
-    }
-
-    public boolean isPackaged() {
-        return "packaged".equals(getWebappType());
-    }
-
-    public boolean isDebuggable() {
-        return (mInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
-    }
-
-    private String readResource(Context context, String resourceName) {
-        Uri resourceUri = Uri.parse("android.resource://" + mPackageName
-                + "/raw/" + resourceName);
-        StringBuilder fileContent = new StringBuilder();
-        try {
-            final BufferedReader r = new BufferedReader(new InputStreamReader(context
-                    .getContentResolver().openInputStream(resourceUri)));
-            try {
-                String line;
-
-                while ((line = r.readLine()) != null) {
-                    fileContent.append(line);
-                }
-            } finally {
-                r.close();
-            }
-        } catch (FileNotFoundException e) {
-            Log.e(LOGTAG, String.format("File not found: \"%s\"", resourceName));
-        } catch (IOException e) {
-            Log.e(LOGTAG, String.format("Couldn't read file: \"%s\"", resourceName));
-        }
-
-        return fileContent.toString();
-    }
-
-    public Uri getAppIconUri() {
-        return Uri.parse("android.resource://" + mPackageName + "/" + info().icon);
-    }
-
-    public Drawable getAppIcon() {
-        return info().loadIcon(mContext.getPackageManager());
-    }
-
-    public String getWebappType() {
-        return metadata().getString("webapp");
-    }
-
-    public String getAppName() {
-        return info().name;
-    }
-
-    /**
-     * Which APK installer installed this APK.
-     *
-     * For OEM backed marketplaces, this will be non-<code>null</code>. Otherwise, <code>null</code>.
-     *
-     * TODO check that the G+ package installer gives us non-null results.
-     *
-     * @return the package name of the APK that installed this.
-     */
-    public String getPackageInstallerName() {
-        return mContext.getPackageManager().getInstallerPackageName(mPackageName);
-    }
-
-    public Uri getZipFileUri() {
-        return Uri.parse("android.resource://" + mPackageName + "/raw/application");
-    }
-
-    public File getFileDirectory() {
-        File dir = mContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
-        String path = dir.getAbsolutePath().replace(mContext.getPackageName(), mPackageName);
-
-        dir = new File(path);
-
-        if (!dir.exists()) {
-            dir.mkdirs();
-        }
-
-        return dir;
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/webapp/Dispatcher.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/* -*- 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.webapp;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.util.Log;
-
-public class Dispatcher extends Activity {
-    private static final String LOGTAG = "GeckoWebappDispatcher";
-
-    @Override
-    protected void onCreate(Bundle bundle) {
-        super.onCreate(bundle);
-
-        Allocator allocator = Allocator.getInstance(getApplicationContext());
-
-        if (bundle == null) {
-            bundle = getIntent().getExtras();
-        }
-
-        if (bundle == null) {
-            Log.e(LOGTAG, "Passed intent data missing.");
-            return;
-        }
-
-        String packageName = bundle.getString("packageName");
-
-        if (packageName == null) {
-            Log.e(LOGTAG, "Package name data missing.");
-            return;
-        }
-
-        int index = allocator.getIndexForApp(packageName);
-        boolean isInstalled = index >= 0;
-        if (!isInstalled) {
-            index = allocator.findOrAllocatePackage(packageName);
-        }
-
-        // Copy the intent, without interfering with it.
-        Intent intent = new Intent(getIntent());
-
-        // Only change its destination.
-        intent.setClassName(getApplicationContext(), "org.mozilla.gecko.webapp.Webapps$Webapp" + index);
-
-        // If and only if we haven't seen this before.
-        intent.putExtra("isInstalled", isInstalled);
-
-        startActivity(intent);
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/webapp/EventListener.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/* -*- 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.webapp;
-
-import java.io.File;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.mozilla.gecko.ActivityHandlerHelper;
-import org.mozilla.gecko.AppConstants.Versions;
-import org.mozilla.gecko.EventDispatcher;
-import org.mozilla.gecko.GeckoAppShell;
-import org.mozilla.gecko.GeckoProfile;
-import org.mozilla.gecko.util.ActivityResultHandler;
-import org.mozilla.gecko.util.EventCallback;
-import org.mozilla.gecko.util.NativeEventListener;
-import org.mozilla.gecko.util.NativeJSObject;
-import org.mozilla.gecko.util.ThreadUtils;
-
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.net.Uri;
-import android.util.Log;
-
-public class EventListener implements NativeEventListener  {
-
-    private static final String LOGTAG = "GeckoWebappEventListener";
-
-    public void registerEvents() {
-        EventDispatcher.getInstance().registerGeckoThreadListener(this,
-            "Webapps:Preinstall",
-            "Webapps:InstallApk",
-            "Webapps:UninstallApk",
-            "Webapps:Postinstall",
-            "Webapps:Launch",
-            "Webapps:Uninstall",
-            "Webapps:GetApkVersions");
-    }
-
-    public void unregisterEvents() {
-        EventDispatcher.getInstance().unregisterGeckoThreadListener(this,
-            "Webapps:Preinstall",
-            "Webapps:InstallApk",
-            "Webapps:UninstallApk",
-            "Webapps:Postinstall",
-            "Webapps:Launch",
-            "Webapps:Uninstall",
-            "Webapps:GetApkVersions");
-    }
-
-    @Override
-    public void handleMessage(String event, NativeJSObject message, EventCallback callback) {
-        try {
-            if (event.equals("Webapps:InstallApk")) {
-                installApk(GeckoAppShell.getGeckoInterface().getActivity(), message, callback);
-            } else if (event.equals("Webapps:UninstallApk")) {
-                uninstallApk(GeckoAppShell.getGeckoInterface().getActivity(), message);
-            } else if (event.equals("Webapps:Postinstall")) {
-                postInstallWebapp(message.getString("apkPackageName"), message.getString("origin"));
-            } else if (event.equals("Webapps:Launch")) {
-                launchWebapp(message.getString("packageName"));
-            } else if (event.equals("Webapps:GetApkVersions")) {
-                JSONObject obj = new JSONObject();
-                obj.put("versions", getApkVersions(GeckoAppShell.getGeckoInterface().getActivity(),
-                                                   message.getStringArray("packageNames")));
-                callback.sendSuccess(obj);
-            }
-        } catch (Exception e) {
-            Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
-        }
-    }
-
-    public static void postInstallWebapp(String aPackageName, String aOrigin) {
-        Allocator allocator = Allocator.getInstance(GeckoAppShell.getContext());
-        int index = allocator.findOrAllocatePackage(aPackageName);
-        allocator.putOrigin(index, aOrigin);
-    }
-
-    private void launchWebapp(String aPackageName) {
-        Intent intent = GeckoAppShell.getContext().getPackageManager().getLaunchIntentForPackage(aPackageName);
-        GeckoAppShell.getGeckoInterface().getActivity().startActivity(intent);
-    }
-
-    public static void uninstallWebapp(final String packageName) {
-        // On uninstall, we need to do a couple of things:
-        //   1. nuke the running app process.
-        //   2. nuke the profile that was assigned to that webapp
-        ThreadUtils.postToBackgroundThread(new Runnable() {
-            @Override
-            public void run() {
-                int index = Allocator.getInstance(GeckoAppShell.getContext()).releaseIndexForApp(packageName);
-
-                // if -1, nothing to do; we didn't think it was installed anyway
-                if (index == -1)
-                    return;
-
-                killWebappSlot(GeckoAppShell.getContext(), index);
-
-                // then nuke the profile
-                GeckoProfile.removeProfile(GeckoAppShell.getContext(), "webapp" + index);
-            }
-        });
-    }
-
-    /**
-     * Used in both uninstall and swiping away from the recent task list.
-     *
-     * @param context
-     * @param slot
-     */
-    public static void killWebappSlot(Context context, int slot) {
-        // kill the app if it's running
-        String targetProcessName = context.getPackageName();
-        targetProcessName = targetProcessName + ":" + targetProcessName + ".Webapp" + slot;
-
-        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
-        List<ActivityManager.RunningAppProcessInfo> procs = am.getRunningAppProcesses();
-        if (procs != null) {
-            for (ActivityManager.RunningAppProcessInfo proc : procs) {
-                if (proc.processName.equals(targetProcessName)) {
-                    android.os.Process.killProcess(proc.pid);
-                    break;
-                }
-            }
-        }
-    }
-
-    public static void installApk(final Activity context, NativeJSObject message, final EventCallback callback) {
-        final JSONObject messageData;
-
-        // We get the manifest url out of javascript here so we can use it as a checksum
-        // in InstallListener when a package has been installed.
-        String manifestUrl;
-        String filePath;
-
-        try {
-            filePath = message.getString("filePath");
-            messageData = new JSONObject(message.getObject("data").toString());
-            manifestUrl = messageData.getJSONObject("app").getString("manifestURL");
-        } catch (JSONException e) {
-            Log.wtf(LOGTAG, "Error getting file path and data", e);
-            callback.sendError("Error getting file path and data: " + e.toString());
-            return;
-        }
-
-        final File file = new File(filePath);
-
-        if (!file.exists()) {
-            Log.wtf(LOGTAG, "APK file doesn't exist at path " + filePath);
-            callback.sendError("APK file doesn't exist at path " + filePath);
-            return;
-        }
-
-        // We will check the manifestUrl from the one in the APK.
-        // Thus, we can have a one-to-one mapping of apk to receiver.
-        final InstallListener receiver = new InstallListener(manifestUrl, messageData, file);
-
-        // Listen for packages being installed.
-        IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
-        filter.addDataScheme("package");
-
-        // As of API 19 we can do something like this to only trigger this receiver
-        // for a specific package name:
-        // int currentApiVersion = android.os.Build.VERSION.SDK_INT;
-        // if (currentApiVersion >= android.os.Build.VERSION_CODES.KITKAT){ // KITKAT == 19
-        //    filter.addDataSchemeSpecificPart("com.example.someapp", PatternMatcher.PATTERN_LITERAL);
-        // }
-        // TODO: Implement package name filtering to IntentFilter.
-
-        context.registerReceiver(receiver, filter);
-
-        Intent intent = new Intent(Intent.ACTION_VIEW);
-        intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
-
-        // Now call the package installer.
-        ActivityHandlerHelper.startIntentForActivity(context, intent, new ActivityResultHandler() {
-            // Invoked if the user cancels installation or presses the 'Done'
-            // button once the app has been successfully installed. It may also
-            // be called when the user presses Open and then returns to Fennec.
-            @Override
-            public void onActivityResult(int resultCode, Intent data) {
-                if (!receiver.isReceived()) {
-                    callback.sendError("APK installation cancelled by user");
-                    context.unregisterReceiver(receiver);
-                }
-                if (file.delete()) {
-                    Log.i(LOGTAG, "Downloaded APK file deleted");
-                }
-            }
-        });
-    }
-
-    public static void uninstallApk(final Activity context, NativeJSObject message) {
-        final String packageName = message.getString("apkPackageName");
-        final Uri packageUri = Uri.parse("package:" + packageName);
-
-        final Intent intent;
-        if (Versions.preICS) {
-            intent = new Intent(Intent.ACTION_DELETE, packageUri);
-        } else {
-            intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageUri);
-        }
-
-        context.startActivity(intent);
-    }
-
-    private static final int DEFAULT_VERSION_CODE = -1;
-
-    public static JSONObject getApkVersions(Activity context, String[] packageNames) {
-        Set<String> packageNameSet = new HashSet<String>();
-        packageNameSet.addAll(Arrays.asList(packageNames));
-
-        final PackageManager pm = context.getPackageManager();
-        List<ApplicationInfo> apps = pm.getInstalledApplications(0);
-
-        JSONObject jsonMessage = new JSONObject();
-
-        for (ApplicationInfo app : apps) {
-            if (packageNameSet.contains(app.packageName)) {
-                int versionCode = DEFAULT_VERSION_CODE;
-                try {
-                    versionCode = pm.getPackageInfo(app.packageName, 0).versionCode;
-                } catch (PackageManager.NameNotFoundException e) {
-                    Log.e(LOGTAG, "couldn't get version for app " + app.packageName, e);
-                }
-                try {
-                    jsonMessage.put(app.packageName, versionCode);
-                } catch (JSONException e) {
-                    Log.e(LOGTAG, "unable to store version code field for app " + app.packageName, e);
-                }
-            }
-        }
-
-        return jsonMessage;
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/webapp/InstallHelper.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/* -*- 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.webapp;
-
-import java.io.Closeable;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.mozilla.gecko.EventDispatcher;
-import org.mozilla.gecko.GeckoAppShell;
-import org.mozilla.gecko.GeckoEvent;
-import org.mozilla.gecko.GeckoProfile;
-import org.mozilla.gecko.gfx.BitmapUtils;
-import org.mozilla.gecko.util.EventCallback;
-import org.mozilla.gecko.util.NativeEventListener;
-import org.mozilla.gecko.util.NativeJSObject;
-import org.mozilla.gecko.util.ThreadUtils;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.util.Log;
-
-public class InstallHelper implements NativeEventListener {
-    private static final String LOGTAG = "GeckoWebappInstallHelper";
-    private static final String[] INSTALL_EVENT_NAMES = new String[] {"Webapps:Postinstall"};
-    private final Context mContext;
-    private final InstallCallback mCallback;
-    private final ApkResources mApkResources;
-
-    public static interface InstallCallback {
-        // on the GeckoThread
-        void installCompleted(InstallHelper installHelper, String event, NativeJSObject message);
-
-        // on the GeckoBackgroundThread
-        void installErrored(InstallHelper installHelper, Exception exception);
-    }
-
-    public InstallHelper(Context context, ApkResources apkResources, InstallCallback cb) {
-        mContext = context;
-        mCallback = cb;
-        mApkResources = apkResources;
-    }
-
-    public void startInstall(String profileName) throws IOException {
-        startInstall(profileName, null);
-    }
-
-    public void startInstall(final String profileName, final JSONObject message) throws IOException {
-        ThreadUtils.postToBackgroundThread(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    install(profileName, message);
-                } catch (IOException e) {
-                    handleException(e);
-                }
-            }
-        });
-    }
-
-    protected void handleException(Exception e) {
-        if (mCallback != null) {
-            mCallback.installErrored(this, e);
-        } else {
-            Log.e(LOGTAG, "mozApps.install failed", e);
-        }
-    }
-
-    void install(String profileName, JSONObject message) throws IOException {
-        if (message == null) {
-            message = new JSONObject();
-        }
-
-        // we can change the profile to be in the app's area here
-        GeckoProfile profile = GeckoProfile.get(mContext, profileName);
-
-        try {
-            message.put("apkPackageName", mApkResources.getPackageName());
-            message.put("manifestURL", mApkResources.getManifestUrl());
-            message.put("title", mApkResources.getAppName());
-            message.put("manifest", new JSONObject(mApkResources.getManifest(mContext)));
-
-            String appType = mApkResources.getWebappType();
-            message.putOpt("type", appType);
-            if ("packaged".equals(appType)) {
-                message.putOpt("updateManifest", new JSONObject(mApkResources.getMiniManifest(mContext)));
-            }
-
-            message.putOpt("profilePath", profile.getDir());
-
-            if (mApkResources.isPackaged()) {
-                File zipFile = copyApplicationZipFile();
-                message.putOpt("zipFilePath", Uri.fromFile(zipFile).toString());
-            }
-        } catch (JSONException e) {
-            handleException(e);
-            return;
-        }
-
-        registerGeckoListener();
-
-        GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Webapps:AutoInstall", message.toString()));
-        calculateColor();
-    }
-
-    public File copyApplicationZipFile() throws IOException {
-        if (!mApkResources.isPackaged()) {
-            return null;
-        }
-
-        Uri uri = mApkResources.getZipFileUri();
-
-        InputStream in = null;
-        OutputStream out = null;
-        File destPath = new File(mApkResources.getFileDirectory(), "application.zip");
-        try {
-            in = mContext.getContentResolver().openInputStream(uri);
-            out = new FileOutputStream(destPath);
-            byte[] buffer = new byte[1024];
-            int read = 0;
-            while ((read = in.read(buffer)) != -1) {
-                out.write(buffer, 0, read);
-            }
-            out.flush();
-        } catch (IOException e) {
-            throw e;
-        } finally {
-            close(in);
-            close(out);
-        }
-        return destPath;
-    }
-
-    private static void close(Closeable close) {
-        if (close == null) {
-            return;
-        }
-        try {
-            close.close();
-        } catch (IOException e) {
-            // NOP
-        }
-    }
-
-    public void registerGeckoListener() {
-        EventDispatcher.getInstance().registerGeckoThreadListener(this, INSTALL_EVENT_NAMES);
-    }
-
-    private void calculateColor() {
-        ThreadUtils.assertOnBackgroundThread();
-        Allocator slots = Allocator.getInstance(mContext);
-        int index = slots.getIndexForApp(mApkResources.getPackageName());
-        Bitmap bitmap = BitmapUtils.getBitmapFromDrawable(mApkResources.getAppIcon());
-        slots.updateColor(index, BitmapUtils.getDominantColor(bitmap));
-    }
-
-    @Override
-    public void handleMessage(String event, NativeJSObject message, EventCallback callback) {
-        EventDispatcher.getInstance().unregisterGeckoThreadListener(this, INSTALL_EVENT_NAMES);
-
-        if (mCallback != null) {
-            mCallback.installCompleted(this, event, message);
-        }
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/webapp/InstallListener.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/* -*- 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.webapp;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.mozilla.gecko.GeckoThread;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.text.TextUtils;
-import android.util.Log;
-
-public class InstallListener extends BroadcastReceiver {
-
-    private static final String LOGTAG = "GeckoWebappInstallListener";
-    private final JSONObject mData;
-    private final String mManifestUrl;
-    private boolean mReceived;
-    private final File mApkFile;
-
-    public InstallListener(String manifestUrl, JSONObject data, File apkFile) {
-        mData = data;
-        mApkFile = apkFile;
-        mManifestUrl = manifestUrl;
-        if (mManifestUrl == null) {
-            throw new IllegalArgumentException("manifestUrl must not be null");
-        }
-        if (mApkFile == null || mApkFile.exists()) {
-            throw new IllegalArgumentException("apkFile must not be null and must exist");
-        }
-    }
-
-    public boolean isReceived() {
-        return mReceived;
-    }
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        String packageName = intent.getData().getSchemeSpecificPart();
-
-        if (TextUtils.isEmpty(packageName)) {
-            Log.i(LOGTAG, "No package name defined in intent");
-            return;
-        }
-
-        ApkResources apkResources = null;
-        try {
-            apkResources = new ApkResources(context, packageName);
-        } catch (NameNotFoundException e) {
-            Log.e(LOGTAG, "Can't find package that's just been installed");
-            return;
-        }
-
-        String manifestUrl = apkResources.getManifestUrl();
-        if (TextUtils.isEmpty(manifestUrl)) {
-            Log.i(LOGTAG, "No manifest URL present in metadata");
-            return;
-        }
-        if (!isCorrectManifest(manifestUrl)) {
-            // This happens when the updater triggers installation of multiple
-            // APK updates simultaneously.  If we're the receiver for another
-            // update, then simply ignore this intent by returning early.
-            Log.i(LOGTAG, "Manifest URL is for a different install; ignoring");
-            return;
-        }
-
-        // If we're here then everything is looking good and installation can continue.
-        mReceived = true;
-        context.unregisterReceiver(this);
-
-        if (mApkFile != null && mApkFile.delete()) {
-            Log.i(LOGTAG, "Downloaded APK file deleted");
-        }
-
-
-        if (GeckoThread.isRunning()) {
-            InstallHelper installHelper = new InstallHelper(context, apkResources, null);
-            try {
-                JSONObject dataObject = new JSONObject();
-                dataObject.put("request", mData);
-
-                Allocator slots = Allocator.getInstance(context);
-                int i = slots.findOrAllocatePackage(packageName);
-                installHelper.startInstall("webapp" + i, dataObject);
-            } catch (JSONException e) {
-                Log.e(LOGTAG, "Couldn't parse data from mozApps.install()", e);
-            } catch (IOException e) {
-                Log.e(LOGTAG, "Couldn't install packaged app", e);
-            }
-        }
-    }
-
-    public boolean isCorrectManifest(String manifestUrl) {
-        // Don't use URL and the sameFile method as this also includes the query which
-        // we want to ignore.
-        try {
-            String registeredUrl = mManifestUrl.split("\\?")[0];
-            String observedUrl = manifestUrl.split("\\?")[0];
-            return registeredUrl.equals(observedUrl);
-        } catch (NullPointerException e) {
-            Log.e(LOGTAG, "One or both of the manifest URLs is null", e);
-        }
-        return false;
-    }
-
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/webapp/TaskKiller.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/* -*- 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.webapp;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.util.Log;
-
-/**
- * This BroadcastReceiver is registered in the AndroidManifest.xml.in file.
- *
- * <p>It listens for intents sent by synthesized APKs when the task has been ended.
- * e.g. when the user has swiped it out of the Recent Apps List.</p>
- *
- */
-public class TaskKiller extends BroadcastReceiver {
-
-    private static final String LOGTAG = "GeckoWebappTaskKiller";
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        String packageName = intent.getStringExtra("packageName");
-        int slot = Allocator.getInstance(context).getIndexForApp(packageName);
-        if (slot >= 0) {
-            EventListener.killWebappSlot(context, slot);
-        } else {
-            Log.w(LOGTAG, "Asked to kill " + packageName + " but this runtime (" + context.getPackageName() + ") doesn't know about it.");
-        }
-    }
-
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/webapp/UninstallListener.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/* -*- 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.webapp;
-
-import org.mozilla.gecko.AppConstants;
-import org.mozilla.gecko.GeckoApp;
-import org.mozilla.gecko.GeckoAppShell;
-import org.mozilla.gecko.GeckoEvent;
-import org.mozilla.gecko.GeckoProfile;
-import org.mozilla.gecko.util.ThreadUtils;
-
-import android.app.ActivityManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.text.TextUtils;
-import android.util.Log;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.json.JSONArray;
-
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Set;
-import java.util.ArrayList;
-
-public class UninstallListener extends BroadcastReceiver {
-
-    private static final String LOGTAG = "GeckoWebappUninstallListener";
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
-            Log.i(LOGTAG, "Package is being replaced; ignoring removal intent");
-            return;
-        }
-
-        String packageName = intent.getData().getSchemeSpecificPart();
-
-        if (TextUtils.isEmpty(packageName)) {
-            Log.i(LOGTAG, "No package name defined in intent");
-            return;
-        }
-
-        Allocator allocator = Allocator.getInstance(context);
-        ArrayList<String> installedPackages = allocator.getInstalledPackageNames();
-
-        if (installedPackages.contains(packageName)) {
-            doUninstall(context, packageName);
-        }
-    }
-
-    private static void doUninstall(Context context, String packageName) {
-        ArrayList<String> uninstalledPackages = new ArrayList<String>();
-        uninstalledPackages.add(packageName);
-        doUninstall(context, uninstalledPackages);
-    }
-
-    private static void doUninstall(Context context, ArrayList<String> packageNames) {
-        Allocator allocator = Allocator.getInstance(context);
-        JSONObject message = new JSONObject();
-        JSONArray jsonPackages = new JSONArray();
-
-        for (String packageName : packageNames) {
-            // Although its unlikely that an app is not allocated, but is installed in Gecko, it
-            // is possible. We always send the packageName to JS to be removed from Gecko's registry.
-            jsonPackages.put(packageName);
-
-            int index = allocator.getIndexForApp(packageName);
-
-            // If -1, nothing more to do; we didn't think it was installed anyway.
-            if (index == -1)
-                continue;
-
-            allocator.releaseIndex(index);
-
-            // kill the app if it's running
-            String targetProcessName = context.getPackageName();
-            targetProcessName = targetProcessName + ":" + targetProcessName + ".Webapp" + index;
-
-            ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
-            List<ActivityManager.RunningAppProcessInfo> procs = am.getRunningAppProcesses();
-            if (procs != null) {
-                for (ActivityManager.RunningAppProcessInfo proc : procs) {
-                    if (proc.processName.equals(targetProcessName)) {
-                        android.os.Process.killProcess(proc.pid);
-                        break;
-                    }
-                }
-            }
-
-            // then nuke the profile
-            GeckoProfile.removeProfile(context, "webapp" + index);
-        }
-
-        try {
-            message.put("apkPackageNames", jsonPackages);
-            GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Webapps:AutoUninstall", message.toString()));
-        } catch (JSONException e) {
-            Log.e(LOGTAG, "Error sending uninstall packages to Gecko", e);
-        }
-    }
-
-    public static void initUninstallPackageScan(Context context) {
-        // get list of packages we think are installed
-        Allocator allocator = Allocator.getInstance(context);
-        ArrayList<String> fennecPackages = allocator.getInstalledPackageNames();
-        ArrayList<String> uninstalledPackages = new ArrayList<String>();
-
-        final PackageManager pm = context.getPackageManager();
-        //get a list of installed apps on device
-        List<ApplicationInfo> packages = pm.getInstalledApplications(PackageManager.GET_META_DATA);
-        Set<String> allInstalledPackages = new HashSet<String>();
-
-        for (ApplicationInfo packageInfo : packages) {
-            allInstalledPackages.add(packageInfo.packageName);
-        }
-
-        for (String packageName : fennecPackages) {
-            if (!allInstalledPackages.contains(packageName)) {
-                uninstalledPackages.add(packageName);
-            }
-        }
-
-        if (uninstalledPackages.size() > 0) {
-            doUninstall(context, uninstalledPackages);
-        }
-    }
-
-    public static class DelayedStartupTask implements Runnable {
-        private final GeckoApp mApp;
-
-        public DelayedStartupTask(GeckoApp app) {
-            mApp = app;
-        }
-
-        @Override
-        public void run() {
-            ThreadUtils.assertOnBackgroundThread();
-
-            // Perform webapp uninstalls as appropriate.
-            UninstallListener.initUninstallPackageScan(mApp.getApplicationContext());
-        }
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/webapp/WebappImpl.java
+++ /dev/null
@@ -1,413 +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.webapp;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URI;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.mozilla.gecko.GeckoApp;
-import org.mozilla.gecko.GeckoAppShell;
-import org.mozilla.gecko.GeckoEvent;
-import org.mozilla.gecko.GeckoProfile;
-import org.mozilla.gecko.GeckoThread;
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.Tab;
-import org.mozilla.gecko.Tabs;
-import org.mozilla.gecko.db.BrowserDB;
-import org.mozilla.gecko.db.StubBrowserDB;
-import org.mozilla.gecko.mozglue.ContextUtils.SafeIntent;
-import org.mozilla.gecko.util.NativeJSObject;
-import org.mozilla.gecko.webapp.InstallHelper.InstallCallback;
-
-import android.content.Intent;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.graphics.Color;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.GradientDrawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.Display;
-import android.view.View;
-import android.view.animation.Animation;
-import android.view.animation.AnimationUtils;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-public class WebappImpl extends GeckoApp implements InstallCallback {
-    private static final String LOGTAG = "GeckoWebappImpl";
-
-    private URI mOrigin;
-    private TextView mTitlebarText;
-    private View mTitlebar;
-
-    // Must only be accessed from the UI thread.
-    View mSplashscreen;
-
-    private boolean mIsApk = true;
-    private ApkResources mApkResources;
-    private String mManifestUrl;
-    private String mAppName;
-
-    protected int getIndex() { return 0; }
-
-    @Override
-    public int getLayout() { return R.layout.web_app; }
-
-    public WebappImpl() {
-        GeckoProfile.setBrowserDBFactory(new BrowserDB.Factory() {
-            @Override
-            public BrowserDB get(String profileName, File profileDir) {
-                return new StubBrowserDB(profileName);
-            }
-        });
-    }
-
-    @Override
-    public void onCreate(Bundle savedInstance) {
-        Bundle extras = getIntent().getExtras();
-        if (extras == null) {
-            extras = savedInstance;
-        }
-
-        if (extras == null) {
-            extras = new Bundle();
-        }
-
-        boolean isInstalled = extras.getBoolean("isInstalled", false);
-        String packageName = extras.getString("packageName");
-
-        if (packageName == null) {
-            Log.w(LOGTAG, "no package name; treating as legacy shortcut");
-
-            mIsApk = false;
-
-            // Shortcut apps are already installed.
-            isInstalled = true;
-
-            Uri data = getIntent().getData();
-            if (data == null) {
-                Log.wtf(LOGTAG, "can't get manifest URL from shortcut data");
-                setResult(RESULT_CANCELED);
-                finish();
-                return;
-            }
-            mManifestUrl = data.toString();
-
-            String shortcutName = extras.getString(Intent.EXTRA_SHORTCUT_NAME);
-            mAppName = shortcutName != null ? shortcutName : "Web App";
-        } else {
-            try {
-                mApkResources = new ApkResources(this, packageName);
-            } catch (NameNotFoundException e) {
-                Log.e(LOGTAG, "Can't find package for webapp " + packageName, e);
-                setResult(RESULT_CANCELED);
-                finish();
-                return;
-            }
-
-            mManifestUrl = mApkResources.getManifestUrl();
-            mAppName = mApkResources.getAppName();
-        }
-
-        // start Gecko.
-        super.onCreate(savedInstance);
-
-        mTitlebarText = (TextView)findViewById(R.id.webapp_title);
-        mTitlebar = findViewById(R.id.webapp_titlebar);
-        mSplashscreen = findViewById(R.id.splashscreen);
-
-        Allocator allocator = Allocator.getInstance(this);
-        int index = getIndex();
-
-        // We have to migrate old prefs before getting the origin because origin
-        // is one of the prefs we might migrate.
-        allocator.maybeMigrateOldPrefs(index);
-
-        String origin = allocator.getOrigin(index);
-        boolean isInstallCompleting = (origin == null);
-
-        if (!GeckoThread.isRunning() || !isInstalled || isInstallCompleting) {
-            // Show the splash screen if we need to start Gecko, or we need to install this.
-            overridePendingTransition(R.anim.grow_fade_in_center, android.R.anim.fade_out);
-            showSplash();
-        } else {
-            mSplashscreen.setVisibility(View.GONE);
-        }
-
-        if (!isInstalled || isInstallCompleting) {
-            InstallHelper installHelper = new InstallHelper(getApplicationContext(), mApkResources, this);
-            if (!isInstalled) {
-                // start the vanilla install.
-                try {
-                    installHelper.startInstall(getDefaultProfileName());
-                } catch (IOException e) {
-                    Log.e(LOGTAG, "Couldn't install packaged app", e);
-                }
-            } else {
-                // an install is already happening, so we should let it complete.
-                Log.i(LOGTAG, "Waiting for existing install to complete");
-                installHelper.registerGeckoListener();
-            }
-            return;
-        }
-
-        launchWebapp(origin);
-
-        setTitle(mAppName);
-    }
-
-    @Override
-    protected String getURIFromIntent(SafeIntent intent) {
-        String uri = super.getURIFromIntent(intent);
-        if (uri != null) {
-            return uri;
-        }
-        // This is where we construct the URL from the Intent from the
-        // the synthesized APK.
-
-        // TODO Translate AndroidIntents into WebActivities here.
-        if (mIsApk) {
-            return mApkResources.getManifestUrl();
-        }
-
-        // If this is a legacy shortcut, then we should have been able to get
-        // the URI from the intent data.  Otherwise, we should have been able
-        // to get it from the APK resources.  So we should never get here.
-        Log.wtf(LOGTAG, "Couldn't get URI from intent nor APK resources");
-        return null;
-    }
-
-    @Override
-    protected void loadStartupTab(final int flags) {
-        loadStartupTab(null, null, flags);
-    }
-
-    // Note: there is no support for loading with intent extras in
-    // Webapps at the moment because I don't have time to debug/test.
-    @Override
-    protected void loadStartupTab(final String uri, final SafeIntent unusedIntent, int flags) {
-        // Load a tab so it's available for any code that assumes a tab
-        // before the app tab itself is loaded in BrowserApp._loadWebapp.
-        flags = Tabs.LOADURL_NEW_TAB | Tabs.LOADURL_USER_ENTERED | Tabs.LOADURL_EXTERNAL;
-        super.loadStartupTab("about:blank", null, flags);
-    }
-
-    private void showSplash() {
-        // get the favicon dominant color, stored when the app was installed
-        int dominantColor = Allocator.getInstance().getColor(getIndex());
-
-        setBackgroundGradient(dominantColor);
-
-        ImageView image = (ImageView)findViewById(R.id.splashscreen_icon);
-        Drawable d = null;
-
-        if (mIsApk) {
-            Uri uri = mApkResources.getAppIconUri();
-            image.setImageURI(uri);
-            d = image.getDrawable();
-        } else {
-            // look for a logo.png in the profile dir and show it. If we can't find a logo show nothing
-            File profile = getProfile().getDir();
-            File logoFile = new File(profile, "logo.png");
-            if (logoFile.exists()) {
-                d = Drawable.createFromPath(logoFile.getPath());
-                image.setImageDrawable(d);
-            }
-        }
-
-        if (d != null) {
-            Animation fadein = AnimationUtils.loadAnimation(this, R.anim.grow_fade_in_center);
-            fadein.setStartOffset(500);
-            fadein.setDuration(1000);
-            image.startAnimation(fadein);
-        }
-    }
-
-    public void setBackgroundGradient(int dominantColor) {
-        int[] colors = new int[2];
-        // now lighten it, to ensure that the icon stands out in the center
-        float[] f = new float[3];
-        Color.colorToHSV(dominantColor, f);
-        f[2] = Math.min(f[2]*2, 1.0f);
-        colors[0] = Color.HSVToColor(255, f);
-
-        // now generate a second, slightly darker version of the same color
-        f[2] *= 0.75;
-        colors[1] = Color.HSVToColor(255, f);
-
-        // Draw the background gradient
-        GradientDrawable gd = new GradientDrawable(GradientDrawable.Orientation.TL_BR, colors);
-        gd.setGradientType(GradientDrawable.RADIAL_GRADIENT);
-        Display display = getWindowManager().getDefaultDisplay();
-        gd.setGradientCenter(0.5f, 0.5f);
-        gd.setGradientRadius(Math.max(display.getWidth()/2, display.getHeight()/2));
-        mSplashscreen.setBackgroundDrawable(gd);
-    }
-
-    /* (non-Javadoc)
-     * @see org.mozilla.gecko.GeckoApp#getDefaultProfileName()
-     */
-    @Override
-    protected String getDefaultProfileName() {
-        return "webapp" + getIndex();
-    }
-
-    @Override
-    protected boolean getSessionRestoreState(Bundle savedInstanceState) {
-        // for now webapps never restore your session
-        return false;
-    }
-
-    @Override
-    public void onTabChanged(Tab tab, Tabs.TabEvents msg, Object data) {
-        switch(msg) {
-            case SELECTED:
-            case LOCATION_CHANGE:
-                if (Tabs.getInstance().isSelectedTab(tab)) {
-                    final String urlString = tab.getURL();
-
-                    // Don't show the titlebar for about:blank, which we load
-                    // into the initial tab we create while waiting for the app
-                    // to load.
-                    if (urlString != null && urlString.equals("about:blank")) {
-                        mTitlebar.setVisibility(View.GONE);
-                        return;
-                    }
-
-                    final URI uri;
-
-                    try {
-                        uri = new URI(urlString);
-                    } catch (java.net.URISyntaxException ex) {
-                        mTitlebarText.setText(urlString);
-
-                        // If we can't parse the url, and its an app protocol hide
-                        // the titlebar and return, otherwise show the titlebar
-                        // and the full url
-                        if (urlString != null && !urlString.startsWith("app://")) {
-                            mTitlebar.setVisibility(View.VISIBLE);
-                        } else {
-                            mTitlebar.setVisibility(View.GONE);
-                        }
-                        return;
-                    }
-
-                    if (mOrigin != null && mOrigin.getHost().equals(uri.getHost())) {
-                        mTitlebar.setVisibility(View.GONE);
-                    } else {
-                        mTitlebarText.setText(uri.getScheme() + "://" + uri.getHost());
-                        mTitlebar.setVisibility(View.VISIBLE);
-                    }
-                }
-                break;
-            case LOADED:
-                hideSplash();
-                break;
-            case START:
-                if (mSplashscreen != null && mSplashscreen.getVisibility() == View.VISIBLE) {
-                    View area = findViewById(R.id.splashscreen_progress);
-                    area.setVisibility(View.VISIBLE);
-                    Animation fadein = AnimationUtils.loadAnimation(this, android.R.anim.fade_in);
-                    fadein.setDuration(1000);
-                    area.startAnimation(fadein);
-                }
-                break;
-        }
-        super.onTabChanged(tab, msg, data);
-    }
-
-    protected void hideSplash() {
-        if (mSplashscreen != null && mSplashscreen.getVisibility() == View.VISIBLE) {
-            Animation fadeout = AnimationUtils.loadAnimation(this, android.R.anim.fade_out);
-            fadeout.setAnimationListener(new Animation.AnimationListener() {
-                @Override
-                public void onAnimationEnd(Animation animation) {
-                  mSplashscreen.setVisibility(View.GONE);
-                }
-                @Override
-                public void onAnimationRepeat(Animation animation) { }
-                @Override
-                public void onAnimationStart(Animation animation) { }
-            });
-            mSplashscreen.startAnimation(fadeout);
-        }
-    }
-
-    @Override
-    public void installCompleted(InstallHelper installHelper, String event, NativeJSObject message) {
-        if (event == null) {
-            return;
-        }
-
-        if (event.equals("Webapps:Postinstall")) {
-            String origin = message.optString("origin", null);
-            launchWebapp(origin);
-        }
-    }
-
-    @Override
-    public void installErrored(InstallHelper installHelper, Exception exception) {
-        Log.e(LOGTAG, "Install errored", exception);
-    }
-
-    private void setOrigin(String origin) {
-        try {
-            mOrigin = new URI(origin);
-        } catch (java.net.URISyntaxException ex) {
-            // If this isn't an app: URL, just settle for not having an origin.
-            if (!origin.startsWith("app://")) {
-                return;
-            }
-
-            // If that failed fall back to the origin stored in the shortcut.
-            if (!mIsApk) {
-                Log.i(LOGTAG, "Origin is app: URL; falling back to intent URL");
-                Uri data = getIntent().getData();
-                if (data != null) {
-                    try {
-                        mOrigin = new URI(data.toString());
-                    } catch (java.net.URISyntaxException ex2) {
-                        Log.e(LOGTAG, "Unable to parse intent URL: ", ex);
-                    }
-                }
-            }
-        }
-    }
-
-    public void launchWebapp(String origin) {
-        setOrigin(origin);
-
-        try {
-            JSONObject launchObject = new JSONObject();
-            launchObject.putOpt("url", mManifestUrl);
-            launchObject.putOpt("name", mAppName);
-            Log.i(LOGTAG, "Trying to launch: " + launchObject);
-            GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Webapps:Load", launchObject.toString()));
-        } catch (JSONException e) {
-            Log.e(LOGTAG, "Error populating launch message", e);
-        }
-    }
-
-    @Override
-    protected boolean getIsDebuggable() {
-        if (mIsApk) {
-            return mApkResources.isDebuggable();
-        }
-
-        // This is a legacy shortcut, which didn't provide a way to determine
-        // that the app is debuggable, so we say the app is not debuggable.
-        return false;
-    }
-
-    @Override
-    protected StartupAction getStartupAction(final String passedURL, final String action) {
-        return StartupAction.WEBAPP;
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/webapp/Webapps.java
+++ /dev/null
@@ -1,513 +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.webapp;
-
-/**
- * Declare a predefined number of Webapp<num> classes to the Webapps class.
- * These are used so that each web app can launch in its own process. Keep this
- * number in sync with the number of web apps defined in the Android manifest.
- */
-public final class Webapps {
-    public static class Webapp0 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 0; }
-    }
-
-    public static class Webapp1 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 1; }
-    }
-
-    public static class Webapp2 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 2; }
-    }
-
-    public static class Webapp3 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 3; }
-    }
-
-    public static class Webapp4 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 4; }
-    }
-
-    public static class Webapp5 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 5; }
-    }
-
-    public static class Webapp6 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 6; }
-    }
-
-    public static class Webapp7 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 7; }
-    }
-
-    public static class Webapp8 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 8; }
-    }
-
-    public static class Webapp9 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 9; }
-    }
-
-    public static class Webapp10 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 10; }
-    }
-
-    public static class Webapp11 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 11; }
-    }
-
-    public static class Webapp12 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 12; }
-    }
-
-    public static class Webapp13 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 13; }
-    }
-
-    public static class Webapp14 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 14; }
-    }
-
-    public static class Webapp15 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 15; }
-    }
-
-    public static class Webapp16 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 16; }
-    }
-
-    public static class Webapp17 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 17; }
-    }
-
-    public static class Webapp18 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 18; }
-    }
-
-    public static class Webapp19 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 19; }
-    }
-
-    public static class Webapp20 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 20; }
-    }
-
-    public static class Webapp21 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 21; }
-    }
-
-    public static class Webapp22 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 22; }
-    }
-
-    public static class Webapp23 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 23; }
-    }
-
-    public static class Webapp24 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 24; }
-    }
-
-    public static class Webapp25 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 25; }
-    }
-
-    public static class Webapp26 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 26; }
-    }
-
-    public static class Webapp27 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 27; }
-    }
-
-    public static class Webapp28 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 28; }
-    }
-
-    public static class Webapp29 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 29; }
-    }
-
-    public static class Webapp30 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 30; }
-    }
-
-    public static class Webapp31 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 31; }
-    }
-
-    public static class Webapp32 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 32; }
-    }
-
-    public static class Webapp33 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 33; }
-    }
-
-    public static class Webapp34 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 34; }
-    }
-
-    public static class Webapp35 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 35; }
-    }
-
-    public static class Webapp36 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 36; }
-    }
-
-    public static class Webapp37 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 37; }
-    }
-
-    public static class Webapp38 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 38; }
-    }
-
-    public static class Webapp39 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 39; }
-    }
-
-    public static class Webapp40 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 40; }
-    }
-
-    public static class Webapp41 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 41; }
-    }
-
-    public static class Webapp42 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 42; }
-    }
-
-    public static class Webapp43 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 43; }
-    }
-
-    public static class Webapp44 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 44; }
-    }
-
-    public static class Webapp45 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 45; }
-    }
-
-    public static class Webapp46 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 46; }
-    }
-
-    public static class Webapp47 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 47; }
-    }
-
-    public static class Webapp48 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 48; }
-    }
-
-    public static class Webapp49 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 49; }
-    }
-
-    public static class Webapp50 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 50; }
-    }
-
-    public static class Webapp51 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 51; }
-    }
-
-    public static class Webapp52 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 52; }
-    }
-
-    public static class Webapp53 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 53; }
-    }
-
-    public static class Webapp54 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 54; }
-    }
-
-    public static class Webapp55 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 55; }
-    }
-
-    public static class Webapp56 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 56; }
-    }
-
-    public static class Webapp57 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 57; }
-    }
-
-    public static class Webapp58 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 58; }
-    }
-
-    public static class Webapp59 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 59; }
-    }
-
-    public static class Webapp60 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 60; }
-    }
-
-    public static class Webapp61 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 61; }
-    }
-
-    public static class Webapp62 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 62; }
-    }
-
-    public static class Webapp63 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 63; }
-    }
-
-    public static class Webapp64 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 64; }
-    }
-
-    public static class Webapp65 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 65; }
-    }
-
-    public static class Webapp66 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 66; }
-    }
-
-    public static class Webapp67 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 67; }
-    }
-
-    public static class Webapp68 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 68; }
-    }
-
-    public static class Webapp69 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 69; }
-    }
-
-    public static class Webapp70 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 70; }
-    }
-
-    public static class Webapp71 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 71; }
-    }
-
-    public static class Webapp72 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 72; }
-    }
-
-    public static class Webapp73 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 73; }
-    }
-
-    public static class Webapp74 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 74; }
-    }
-
-    public static class Webapp75 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 75; }
-    }
-
-    public static class Webapp76 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 76; }
-    }
-
-    public static class Webapp77 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 77; }
-    }
-
-    public static class Webapp78 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 78; }
-    }
-
-    public static class Webapp79 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 79; }
-    }
-
-    public static class Webapp80 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 80; }
-    }
-
-    public static class Webapp81 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 81; }
-    }
-
-    public static class Webapp82 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 82; }
-    }
-
-    public static class Webapp83 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 83; }
-    }
-
-    public static class Webapp84 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 84; }
-    }
-
-    public static class Webapp85 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 85; }
-    }
-
-    public static class Webapp86 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 86; }
-    }
-
-    public static class Webapp87 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 87; }
-    }
-
-    public static class Webapp88 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 88; }
-    }
-
-    public static class Webapp89 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 89; }
-    }
-
-    public static class Webapp90 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 90; }
-    }
-
-    public static class Webapp91 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 91; }
-    }
-
-    public static class Webapp92 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 92; }
-    }
-
-    public static class Webapp93 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 93; }
-    }
-
-    public static class Webapp94 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 94; }
-    }
-
-    public static class Webapp95 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 95; }
-    }
-
-    public static class Webapp96 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 96; }
-    }
-
-    public static class Webapp97 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 97; }
-    }
-
-    public static class Webapp98 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 98; }
-    }
-
-    public static class Webapp99 extends WebappImpl {
-        @Override
-        protected int getIndex() { return 99; }
-    }
-}
--- a/mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedEditText.java
+++ b/mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedEditText.java
@@ -44,18 +44,18 @@ public class ThemedEditText extends andr
     }
 
     public ThemedEditText(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         initialize(context, attrs, defStyle);
     }
 
     private void initialize(final Context context, final AttributeSet attrs, final int defStyle) {
-        // The theme can be null, particularly for webapps: Bug 1089266.  Or we
-        // might be instantiating this View in an IDE, with no ambient GeckoApplication.
+        // The theme can be null, particularly if we might be instantiating this
+        // View in an IDE, with no ambient GeckoApplication.
         final Context applicationContext = context.getApplicationContext();
         if (applicationContext instanceof GeckoApplication) {
             theme = ((GeckoApplication) applicationContext).getLightweightTheme();
         }
 
         final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LightweightTheme);
         autoUpdateTheme = theme != null && a.getBoolean(R.styleable.LightweightTheme_autoUpdateTheme, true);
         a.recycle();
--- a/mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedFrameLayout.java
+++ b/mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedFrameLayout.java
@@ -44,18 +44,18 @@ public class ThemedFrameLayout extends a
     }
 
     public ThemedFrameLayout(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         initialize(context, attrs, defStyle);
     }
 
     private void initialize(final Context context, final AttributeSet attrs, final int defStyle) {
-        // The theme can be null, particularly for webapps: Bug 1089266.  Or we
-        // might be instantiating this View in an IDE, with no ambient GeckoApplication.
+        // The theme can be null, particularly if we might be instantiating this
+        // View in an IDE, with no ambient GeckoApplication.
         final Context applicationContext = context.getApplicationContext();
         if (applicationContext instanceof GeckoApplication) {
             theme = ((GeckoApplication) applicationContext).getLightweightTheme();
         }
 
         final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LightweightTheme);
         autoUpdateTheme = theme != null && a.getBoolean(R.styleable.LightweightTheme_autoUpdateTheme, true);
         a.recycle();
--- a/mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedImageButton.java
+++ b/mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedImageButton.java
@@ -44,18 +44,18 @@ public class ThemedImageButton extends a
     }
 
     public ThemedImageButton(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         initialize(context, attrs, defStyle);
     }
 
     private void initialize(final Context context, final AttributeSet attrs, final int defStyle) {
-        // The theme can be null, particularly for webapps: Bug 1089266.  Or we
-        // might be instantiating this View in an IDE, with no ambient GeckoApplication.
+        // The theme can be null, particularly if we might be instantiating this
+        // View in an IDE, with no ambient GeckoApplication.
         final Context applicationContext = context.getApplicationContext();
         if (applicationContext instanceof GeckoApplication) {
             theme = ((GeckoApplication) applicationContext).getLightweightTheme();
         }
 
         final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LightweightTheme);
         autoUpdateTheme = theme != null && a.getBoolean(R.styleable.LightweightTheme_autoUpdateTheme, true);
         a.recycle();
--- a/mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedImageView.java
+++ b/mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedImageView.java
@@ -44,18 +44,18 @@ public class ThemedImageView extends and
     }
 
     public ThemedImageView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         initialize(context, attrs, defStyle);
     }
 
     private void initialize(final Context context, final AttributeSet attrs, final int defStyle) {
-        // The theme can be null, particularly for webapps: Bug 1089266.  Or we
-        // might be instantiating this View in an IDE, with no ambient GeckoApplication.
+        // The theme can be null, particularly if we might be instantiating this
+        // View in an IDE, with no ambient GeckoApplication.
         final Context applicationContext = context.getApplicationContext();
         if (applicationContext instanceof GeckoApplication) {
             theme = ((GeckoApplication) applicationContext).getLightweightTheme();
         }
 
         final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LightweightTheme);
         autoUpdateTheme = theme != null && a.getBoolean(R.styleable.LightweightTheme_autoUpdateTheme, true);
         a.recycle();
--- a/mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedLinearLayout.java
+++ b/mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedLinearLayout.java
@@ -39,18 +39,18 @@ public class ThemedLinearLayout extends 
     private ColorStateList drawableColors;
 
     public ThemedLinearLayout(Context context, AttributeSet attrs) {
         super(context, attrs);
         initialize(context, attrs, 0);
     }
 
     private void initialize(final Context context, final AttributeSet attrs, final int defStyle) {
-        // The theme can be null, particularly for webapps: Bug 1089266.  Or we
-        // might be instantiating this View in an IDE, with no ambient GeckoApplication.
+        // The theme can be null, particularly if we might be instantiating this
+        // View in an IDE, with no ambient GeckoApplication.
         final Context applicationContext = context.getApplicationContext();
         if (applicationContext instanceof GeckoApplication) {
             theme = ((GeckoApplication) applicationContext).getLightweightTheme();
         }
 
         final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LightweightTheme);
         autoUpdateTheme = theme != null && a.getBoolean(R.styleable.LightweightTheme_autoUpdateTheme, true);
         a.recycle();
--- a/mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedRelativeLayout.java
+++ b/mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedRelativeLayout.java
@@ -44,18 +44,18 @@ public class ThemedRelativeLayout extend
     }
 
     public ThemedRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         initialize(context, attrs, defStyle);
     }
 
     private void initialize(final Context context, final AttributeSet attrs, final int defStyle) {
-        // The theme can be null, particularly for webapps: Bug 1089266.  Or we
-        // might be instantiating this View in an IDE, with no ambient GeckoApplication.
+        // The theme can be null, particularly if we might be instantiating this
+        // View in an IDE, with no ambient GeckoApplication.
         final Context applicationContext = context.getApplicationContext();
         if (applicationContext instanceof GeckoApplication) {
             theme = ((GeckoApplication) applicationContext).getLightweightTheme();
         }
 
         final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LightweightTheme);
         autoUpdateTheme = theme != null && a.getBoolean(R.styleable.LightweightTheme_autoUpdateTheme, true);
         a.recycle();
--- a/mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedTextSwitcher.java
+++ b/mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedTextSwitcher.java
@@ -39,18 +39,18 @@ public class ThemedTextSwitcher extends 
     private ColorStateList drawableColors;
 
     public ThemedTextSwitcher(Context context, AttributeSet attrs) {
         super(context, attrs);
         initialize(context, attrs, 0);
     }
 
     private void initialize(final Context context, final AttributeSet attrs, final int defStyle) {
-        // The theme can be null, particularly for webapps: Bug 1089266.  Or we
-        // might be instantiating this View in an IDE, with no ambient GeckoApplication.
+        // The theme can be null, particularly if we might be instantiating this
+        // View in an IDE, with no ambient GeckoApplication.
         final Context applicationContext = context.getApplicationContext();
         if (applicationContext instanceof GeckoApplication) {
             theme = ((GeckoApplication) applicationContext).getLightweightTheme();
         }
 
         final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LightweightTheme);
         autoUpdateTheme = theme != null && a.getBoolean(R.styleable.LightweightTheme_autoUpdateTheme, true);
         a.recycle();
--- a/mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedTextView.java
+++ b/mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedTextView.java
@@ -44,18 +44,18 @@ public class ThemedTextView extends andr
     }
 
     public ThemedTextView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         initialize(context, attrs, defStyle);
     }
 
     private void initialize(final Context context, final AttributeSet attrs, final int defStyle) {
-        // The theme can be null, particularly for webapps: Bug 1089266.  Or we
-        // might be instantiating this View in an IDE, with no ambient GeckoApplication.
+        // The theme can be null, particularly if we might be instantiating this
+        // View in an IDE, with no ambient GeckoApplication.
         final Context applicationContext = context.getApplicationContext();
         if (applicationContext instanceof GeckoApplication) {
             theme = ((GeckoApplication) applicationContext).getLightweightTheme();
         }
 
         final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LightweightTheme);
         autoUpdateTheme = theme != null && a.getBoolean(R.styleable.LightweightTheme_autoUpdateTheme, true);
         a.recycle();
--- a/mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedView.java
+++ b/mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedView.java
@@ -44,18 +44,18 @@ public class ThemedView extends android.
     }
 
     public ThemedView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         initialize(context, attrs, defStyle);
     }
 
     private void initialize(final Context context, final AttributeSet attrs, final int defStyle) {
-        // The theme can be null, particularly for webapps: Bug 1089266.  Or we
-        // might be instantiating this View in an IDE, with no ambient GeckoApplication.
+        // The theme can be null, particularly if we might be instantiating this
+        // View in an IDE, with no ambient GeckoApplication.
         final Context applicationContext = context.getApplicationContext();
         if (applicationContext instanceof GeckoApplication) {
             theme = ((GeckoApplication) applicationContext).getLightweightTheme();
         }
 
         final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LightweightTheme);
         autoUpdateTheme = theme != null && a.getBoolean(R.styleable.LightweightTheme_autoUpdateTheme, true);
         a.recycle();
--- a/mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedView.java.frag
+++ b/mobile/android/base/java/org/mozilla/gecko/widget/themed/ThemedView.java.frag
@@ -47,18 +47,18 @@ public class Themed@VIEW_NAME_SUFFIX@ ex
 //#ifdef STYLE_CONSTRUCTOR
     public Themed@VIEW_NAME_SUFFIX@(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         initialize(context, attrs, defStyle);
     }
 
 //#endif
     private void initialize(final Context context, final AttributeSet attrs, final int defStyle) {
-        // The theme can be null, particularly for webapps: Bug 1089266.  Or we
-        // might be instantiating this View in an IDE, with no ambient GeckoApplication.
+        // The theme can be null, particularly if we might be instantiating this
+        // View in an IDE, with no ambient GeckoApplication.
         final Context applicationContext = context.getApplicationContext();
         if (applicationContext instanceof GeckoApplication) {
             theme = ((GeckoApplication) applicationContext).getLightweightTheme();
         }
 
         final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LightweightTheme);
         autoUpdateTheme = theme != null && a.getBoolean(R.styleable.LightweightTheme_autoUpdateTheme, true);
         a.recycle();
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -645,18 +645,16 @@ just addresses the organization to follo
       replaced with the name of the currently highlighted icon. -->
 <!ENTITY search_bar_item_desc "Search with &formatS;">
 
 <!-- Localization note (suggestion_for_engine): The placeholder &formatS1; will be
      replaced with the name of the search engine. The placeholder &formatS2; will be
      replaced with the search query. -->
 <!ENTITY suggestion_for_engine "Search &formatS1; for &formatS2;">
 
-<!ENTITY webapp_generic_name "App">
-
 <!ENTITY searchable_description "Bookmarks and history">
 
  <!-- Updater notifications -->
 <!ENTITY updater_start_title2 "Update available for &brandShortName;">
 <!ENTITY updater_start_select2 "Touch to download">
 
 <!ENTITY updater_downloading_title2 "Downloading &brandShortName;">
 <!ENTITY updater_downloading_title_failed2 "Download failed">
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -575,27 +575,16 @@ gbjar.sources += ['java/org/mozilla/geck
     'toolbar/ToolbarEditText.java',
     'toolbar/ToolbarPrefs.java',
     'toolbar/ToolbarProgressView.java',
     'TouchEventInterceptor.java',
     'trackingprotection/TrackingProtectionPrompt.java',
     'updater/UpdateService.java',
     'updater/UpdateServiceHelper.java',
     'util/Experiments.java',
-    'Webapp.java',
-    'webapp/Allocator.java',
-    'webapp/ApkResources.java',
-    'webapp/Dispatcher.java',
-    'webapp/EventListener.java',
-    'webapp/InstallHelper.java',
-    'webapp/InstallListener.java',
-    'webapp/TaskKiller.java',
-    'webapp/UninstallListener.java',
-    'webapp/WebappImpl.java',
-    'webapp/Webapps.java',
     'widget/ActivityChooserModel.java',
     'widget/AllCapsTextView.java',
     'widget/AnchoredPopup.java',
     'widget/AnimatedHeightLayout.java',
     'widget/BasicColorPicker.java',
     'widget/ButtonToast.java',
     'widget/CheckableLinearLayout.java',
     'widget/ClickableWhenDisabledEditText.java',
--- a/mobile/android/base/resources/layout/shared_ui_components.xml
+++ b/mobile/android/base/resources/layout/shared_ui_components.xml
@@ -1,15 +1,15 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 <!-- This file is used to include shared UI components in different gecko app
-     layouts, such as gecko_app.xml and web_app.xml -->
+     layouts, such as gecko_app.xml -->
 
 <merge xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:gecko="http://schemas.android.com/apk/res-auto">
 
     <org.mozilla.gecko.GeckoView android:id="@+id/layer_view"
                                  gecko:doinit="false"
                                  android:layout_width="match_parent"
                                  android:layout_height="match_parent"
deleted file mode 100644
--- a/mobile/android/base/resources/layout/web_app.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:id="@+id/main_layout"
-              android:orientation="vertical"
-              android:layout_width="match_parent"
-              android:layout_height="match_parent">
-
-    <LinearLayout android:id="@+id/webapp_titlebar"
-                  android:visibility="gone"
-                  style="@style/WebView.Titlebar"
-                  android:layout_width="match_parent"
-                  android:layout_height="wrap_content"
-                  android:orientation="horizontal">
-    
-        <TextView android:id="@+id/webapp_title"
-                  style="@style/WebView.Titlebar.Title"
-                  android:layout_width="match_parent"
-                  android:layout_height="wrap_content"
-                  android:singleLine="true"/>
-
-    </LinearLayout>
-
-    <RelativeLayout android:id="@+id/gecko_layout"
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent"
-                    android:layout_below="@+id/webapp_titlebar">
-
-        <include layout="@layout/shared_ui_components"/>
-
-        <RelativeLayout android:id="@+id/splashscreen"
-                        android:layout_width="match_parent"
-                        android:layout_height="match_parent" >
-
-            <ImageView android:id="@+id/splashscreen_icon"
-                      android:minWidth="128dip"
-                      android:minHeight="128dip"
-                      android:layout_width="wrap_content"
-                      android:layout_height="wrap_content"
-                      android:layout_centerHorizontal="true"
-                      android:layout_centerVertical="true"/>
-
-            <ProgressBar android:id="@+id/splashscreen_progress"
-                         android:layout_width="wrap_content"
-                         android:layout_height="wrap_content"
-                         android:gravity="center"
-                         android:layout_centerHorizontal="true"
-                         android:layout_alignParentBottom="true"
-                         android:paddingBottom="30dip"
-                         android:visibility="gone"/>
-
-        </RelativeLayout>
-
-    </RelativeLayout>
-
-    <ViewStub android:id="@+id/toast_stub"
-              android:layout="@layout/button_toast"
-              style="@style/Toast"/>
-
-</RelativeLayout>
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -518,18 +518,16 @@
 
   <!-- Bookmark import/export -->
   <string name="bookmarkhistory_button_import">&bookmarkhistory_button_import;</string>
   <string name="bookmarkhistory_import_both">&bookmarkhistory_import_both;</string>
   <string name="bookmarkhistory_import_bookmarks">&bookmarkhistory_import_bookmarks;</string>
   <string name="bookmarkhistory_import_history">&bookmarkhistory_import_history;</string>
   <string name="bookmarkhistory_import_wait">&bookmarkhistory_import_wait;</string>
 
-  <string name="webapp_generic_name">&webapp_generic_name;</string>
-
   <string name="searchable_description">&searchable_description;</string>
 
   <!-- Updater notifications -->
   <string name="updater_start_title">&updater_start_title2;</string>
   <string name="updater_start_select">&updater_start_select2;</string>
 
   <string name="updater_downloading_title">&updater_downloading_title2;</string>
   <string name="updater_downloading_title_failed">&updater_downloading_title_failed2;</string>
deleted file mode 100644
--- a/mobile/android/chrome/content/WebappRT.js
+++ /dev/null
@@ -1,218 +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/. */
-
-/*globals PermissionsInstaller */
-
-var Cc = Components.classes;
-var Ci = Components.interfaces;
-var Cu = Components.utils;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/FileUtils.jsm");
-Cu.import("resource://gre/modules/NetUtil.jsm");
-Cu.import("resource://gre/modules/PermissionsInstaller.jsm");
-Cu.import("resource://gre/modules/ContactService.jsm");
-Cu.import("resource://gre/modules/AppsUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "Notifications", "resource://gre/modules/Notifications.jsm");
-
-function pref(name, value) {
-  return {
-    name: name,
-    value: value
-  }
-}
-
-var WebappRT = {
-  prefs: [
-    // Disable all add-on locations other than the profile (which can't be disabled this way)
-    pref("extensions.enabledScopes", 1),
-    // Auto-disable any add-ons that are "dropped in" to the profile
-    pref("extensions.autoDisableScopes", 1),
-    // Disable add-on installation via the web-exposed APIs
-    pref("xpinstall.enabled", false),
-    pref("media.useAudioChannelAPI", true),
-    pref("dom.mozTCPSocket.enabled", true),
-
-    // Enabled system messages for web activity support
-    pref("dom.sysmsg.enabled", true),
-  ],
-
-  init: function(aStatus, aUrl, aCallback) {
-    this.deck = document.getElementById("browsers");
-    this.deck.addEventListener("click", this, false, true);
-
-    // on first run, update any prefs
-    if (aStatus == "new") {
-      this.prefs.forEach(this.addPref);
-
-      // update the blocklist url to use a different app id
-      let blocklist = Services.prefs.getCharPref("extensions.blocklist.url");
-      blocklist = blocklist.replace(/%APP_ID%/g, "webapprt-mobile@mozilla.org");
-      Services.prefs.setCharPref("extensions.blocklist.url", blocklist);
-    }
-
-    // On firstrun, set permissions to their default values.
-    // When the webapp runtime is updated, update the permissions.
-    if (aStatus == "new" || aStatus == "upgrade") {
-      this.getManifestFor(aUrl, function (aManifest, aApp) {
-        if (aManifest) {
-          PermissionsInstaller.installPermissions(aApp, true);
-        }
-      });
-    }
-
-    // If the app is in debug mode, configure and enable the remote debugger.
-    Messaging.sendRequestForResult({ type: "NativeApp:IsDebuggable" }).then((response) => {
-      let that = this;
-      let name = this._getAppName(aUrl);
-
-       if (response.isDebuggable) {
-        Notifications.create({
-          title: Strings.browser.formatStringFromName("remoteStartNotificationTitle", [name], 1),
-          message: Strings.browser.GetStringFromName("remoteStartNotificationMessage"),
-          icon: "drawable://warning_doorhanger",
-          onClick: function(aId, aCookie) {
-            that._enableRemoteDebugger(aUrl);
-          },
-        });
-      }
-    });
-
-    this.findManifestUrlFor(aUrl, (function(aLaunchUrl) {
-      if (aStatus == "new") {
-        if (BrowserApp.manifest && BrowserApp.manifest.orientation) {
-          let orientation = BrowserApp.manifest.orientation;
-          if (Array.isArray(orientation)) {
-            orientation = orientation.join(",");
-          }
-          this.addPref(pref("app.orientation.default", orientation));
-        }
-      }
-
-      aCallback(aLaunchUrl);
-    }).bind(this));
-  },
-
-  getManifestFor: function (aUrl, aCallback) {
-    let request = navigator.mozApps.mgmt.getAll();
-    request.onsuccess = function() {
-      let apps = request.result;
-      for (let i = 0; i < apps.length; i++) {
-        let app = apps[i];
-        let manifest = new ManifestHelper(app.manifest, app.origin, app.manifestURL);
-
-        // if this is a path to the manifest, or the launch path, then we have a hit.
-        if (app.manifestURL == aUrl || manifest.fullLaunchPath() == aUrl) {
-          aCallback(manifest, app);
-          return;
-        }
-      }
-
-      // Otherwise, once we loop through all of them, we have a miss.
-      aCallback(undefined);
-    };
-
-    request.onerror = function() {
-      // Treat an error like a miss. We can't find the manifest.
-      aCallback(undefined);
-    };
-  },
-
-  findManifestUrlFor: function(aUrl, aCallback) {
-    this.getManifestFor(aUrl, function(aManifest, aApp) {
-      if (!aManifest) {
-        // we can't find the manifest, so open it like a web page
-        aCallback(aUrl);
-        return;
-      }
-
-      BrowserApp.manifest = aManifest;
-      BrowserApp.manifestUrl = aApp.manifestURL;
-
-      aCallback(aManifest.fullLaunchPath());
-    });
-  },
-
-  addPref: function(aPref) {
-    switch (typeof aPref.value) {
-      case "string":
-        Services.prefs.setCharPref(aPref.name, aPref.value);
-        break;
-      case "boolean":
-        Services.prefs.setBoolPref(aPref.name, aPref.value);
-        break;
-      case "number":
-        Services.prefs.setIntPref(aPref.name, aPref.value);
-        break;
-    }
-  },
-
-  _getAppName: function(aUrl) {
-    let name = Strings.browser.GetStringFromName("remoteNotificationGenericName");
-    let app = DOMApplicationRegistry.getAppByManifestURL(aUrl);
-
-    if (app) {
-      name = app.name;
-    }
-
-    return name;
-  },
-
-
-  _enableRemoteDebugger: function(aUrl) {
-    // Skip the connection prompt in favor of notifying the user below.
-    Services.prefs.setBoolPref("devtools.debugger.prompt-connection", false);
-
-    // Automagically find a free port and configure the debugger to use it.
-    let serv = Cc['@mozilla.org/network/server-socket;1'].createInstance(Ci.nsIServerSocket);
-    serv.init(-1, true, -1);
-    let port = serv.port;
-    serv.close();
-    Services.prefs.setIntPref("devtools.debugger.remote-port", port);
-    // Clear the UNIX domain socket path to ensure a TCP socket will be used
-    // instead.
-    Services.prefs.setCharPref("devtools.debugger.unix-domain-socket", "");
-
-    Services.prefs.setBoolPref("devtools.debugger.remote-enabled", true);
-
-    // Notify the user that we enabled the debugger and which port it's using
-    // so they can use the DevTools Connect… dialog to connect the client to it.
-    DOMApplicationRegistry.registryReady.then(() => {
-      let name = this._getAppName(aUrl);
-
-      Notifications.create({
-        title: Strings.browser.formatStringFromName("remoteNotificationTitle", [name], 1),
-        message: Strings.browser.formatStringFromName("remoteNotificationMessage", [port], 1),
-        icon: "drawable://warning_doorhanger",
-      });
-    });
-  },
-
-  handleEvent: function(event) {
-    let target = event.target;
-
-    // walk up the tree to find the nearest link tag
-    while (target && !(target instanceof HTMLAnchorElement)) {
-      target = target.parentNode;
-    }
-
-    if (!target || target.getAttribute("target") != "_blank") {
-      return;
-    }
-
-    let uri = Services.io.newURI(target.href, target.ownerDocument.characterSet, null);
-
-    // Direct the URL to the browser.
-    Cc["@mozilla.org/uriloader/external-protocol-service;1"].
-      getService(Ci.nsIExternalProtocolService).
-      getProtocolHandlerInfo(uri.scheme).
-      launchWithURI(uri);
-
-    // Prevent the runtime from loading the URL.  We do this after directing it
-    // to the browser to give the runtime a shot at handling the URL if we fail
-    // to direct it to the browser for some reason.
-    event.preventDefault();
-  }
-}
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -88,19 +88,16 @@ XPCOMUtils.defineLazyServiceGetter(this,
 
 XPCOMUtils.defineLazyServiceGetter(this, "Profiler",
                                    "@mozilla.org/tools/profiler;1",
                                    "nsIProfiler");
 
 XPCOMUtils.defineLazyModuleGetter(this, "SimpleServiceDiscovery",
                                   "resource://gre/modules/SimpleServiceDiscovery.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "WebappManager",
-                                  "resource://gre/modules/WebappManager.jsm");
-
 XPCOMUtils.defineLazyModuleGetter(this, "CharsetMenu",
                                   "resource://gre/modules/CharsetMenu.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "NetErrorHelper",
                                   "resource://gre/modules/NetErrorHelper.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "PermissionsUtils",
                                   "resource://gre/modules/PermissionsUtils.jsm");
@@ -438,25 +435,16 @@ var BrowserApp = {
     Services.obs.addObserver(this, "Viewport:Change", false);
     Services.obs.addObserver(this, "Viewport:Flush", false);
     Services.obs.addObserver(this, "Passwords:Init", false);
     Services.obs.addObserver(this, "FormHistory:Init", false);
     Services.obs.addObserver(this, "android-get-pref", false);
     Services.obs.addObserver(this, "android-set-pref", false);
     Services.obs.addObserver(this, "gather-telemetry", false);
     Services.obs.addObserver(this, "keyword-search", false);
-    Services.obs.addObserver(this, "webapps-runtime-install", false);
-    Services.obs.addObserver(this, "webapps-runtime-install-package", false);
-    Services.obs.addObserver(this, "webapps-ask-install", false);
-    Services.obs.addObserver(this, "webapps-ask-uninstall", false);
-    Services.obs.addObserver(this, "webapps-launch", false);
-    Services.obs.addObserver(this, "webapps-runtime-uninstall", false);
-    Services.obs.addObserver(this, "Webapps:AutoInstall", false);
-    Services.obs.addObserver(this, "Webapps:Load", false);
-    Services.obs.addObserver(this, "Webapps:AutoUninstall", false);
     Services.obs.addObserver(this, "sessionstore-state-purge-complete", false);
     Services.obs.addObserver(this, "Fonts:Reload", false);
 
     Messaging.addListener(this.getHistory.bind(this), "Session:GetHistory");
 
     function showFullScreenWarning() {
       Snackbars.show(Strings.browser.GetStringFromName("alertFullScreenToast"), Snackbars.LENGTH_LONG);
     }
@@ -647,23 +635,16 @@ var BrowserApp = {
   /**
    * Pass this a locale string, such as "fr" or "es_ES".
    */
   setLocale: function (locale) {
     console.log("browser.js: requesting locale set: " + locale);
     Messaging.sendRequest({ type: "Locale:Set", locale: locale });
   },
 
-  _initRuntime: function(status, url, callback) {
-    let sandbox = {};
-    Services.scriptloader.loadSubScript("chrome://browser/content/WebappRT.js", sandbox);
-    window.WebappRT = sandbox.WebappRT;
-    WebappRT.init(status, url, callback);
-  },
-
   initContextMenu: function () {
     // We pass a thunk in place of a raw label string. This allows the
     // context menu to automatically accommodate locale changes without
     // having to be rebuilt.
     let stringGetter = name => () => Strings.browser.GetStringFromName(name);
 
     // TODO: These should eventually move into more appropriate classes
     NativeWindow.contextmenus.add(stringGetter("contextmenu.openInNewTab"),
@@ -1278,25 +1259,16 @@ var BrowserApp = {
 
     let message = {
       type: "Tab:Close",
       tabID: aTab.id
     };
     Messaging.sendRequest(message);
   },
 
-  _loadWebapp: function(aMessage) {
-    // Entry point for WebApps. This is the point in which we know
-    // the code is being used as a WebApp runtime.
-    this._initRuntime(this._startupStatus, aMessage.url, aUrl => {
-      this.manifestUrl = aMessage.url;
-      this.addTab(aUrl, { title: aMessage.name });
-    });
-  },
-
   // Calling this will update the state in BrowserApp after a tab has been
   // closed in the Java UI.
   _handleTabClosed: function _handleTabClosed(aTab, aShowUndoSnackbar) {
     if (aTab == this.selectedTab)
       this.selectedTab = null;
 
     let tabIndex = this._tabs.indexOf(aTab);
 
@@ -1933,54 +1905,16 @@ var BrowserApp = {
       case "sessionstore-state-purge-complete":
         Messaging.sendRequest({ type: "Session:StatePurged" });
         break;
 
       case "gather-telemetry":
         Messaging.sendRequest({ type: "Telemetry:Gather" });
         break;
 
-      case "webapps-runtime-install":
-        WebappManager.install(JSON.parse(aData), aSubject);
-        break;
-
-      case "webapps-runtime-install-package":
-        WebappManager.installPackage(JSON.parse(aData), aSubject);
-        break;
-
-      case "webapps-ask-install":
-        WebappManager.askInstall(JSON.parse(aData));
-        break;
-
-      case "webapps-ask-uninstall":
-        WebappManager.askUninstall(JSON.parse(aData));
-        break;
-
-      case "webapps-launch": {
-        WebappManager.launch(JSON.parse(aData));
-        break;
-      }
-
-      case "webapps-runtime-uninstall": {
-        WebappManager.uninstall(JSON.parse(aData), aSubject);
-        break;
-      }
-
-      case "Webapps:AutoInstall":
-        WebappManager.autoInstall(JSON.parse(aData));
-        break;
-
-      case "Webapps:Load":
-        this._loadWebapp(JSON.parse(aData));
-        break;
-
-      case "Webapps:AutoUninstall":
-        WebappManager.autoUninstall(JSON.parse(aData));
-        break;
-
       case "Locale:OS":
         // We know the system locale. We use this for generating Accept-Language headers.
         console.log("Locale:OS: " + aData);
         let currentOSLocale = this.getOSLocalePref();
         if (currentOSLocale == aData) {
           break;
         }
 
--- a/mobile/android/chrome/jar.mn
+++ b/mobile/android/chrome/jar.mn
@@ -29,17 +29,16 @@ chrome.jar:
   content/browser.xul                  (content/browser.xul)
   content/browser.js                   (content/browser.js)
   content/bindings/checkbox.xml        (content/bindings/checkbox.xml)
   content/bindings/settings.xml        (content/bindings/settings.xml)
   content/netError.xhtml               (content/netError.xhtml)
   content/SelectHelper.js              (content/SelectHelper.js)
   content/SelectionHandler.js          (content/SelectionHandler.js)
   content/ActionBarHandler.js          (content/ActionBarHandler.js)
-  content/WebappRT.js                  (content/WebappRT.js)
   content/EmbedRT.js                   (content/EmbedRT.js)
   content/InputWidgetHelper.js         (content/InputWidgetHelper.js)
   content/WebrtcUI.js                  (content/WebrtcUI.js)
   content/MemoryObserver.js            (content/MemoryObserver.js)
   content/ConsoleAPI.js                (content/ConsoleAPI.js)
   content/PluginHelper.js              (content/PluginHelper.js)
   content/PrintHelper.js               (content/PrintHelper.js)
   content/OfflineApps.js               (content/OfflineApps.js)
--- a/mobile/android/components/MobileComponents.manifest
+++ b/mobile/android/components/MobileComponents.manifest
@@ -36,21 +36,16 @@ category agent-style-sheets browser-cont
 component {8c1f07d6-cba3-4226-a315-8bd43d67d032} SessionStore.js
 contract @mozilla.org/browser/sessionstore;1 {8c1f07d6-cba3-4226-a315-8bd43d67d032}
 category app-startup SessionStore service,@mozilla.org/browser/sessionstore;1
 
 # ContentPermissionPrompt.js
 component {C6E8C44D-9F39-4AF7-BCC0-76E38A8310F5} ContentPermissionPrompt.js
 contract @mozilla.org/content-permission/prompt;1 {C6E8C44D-9F39-4AF7-BCC0-76E38A8310F5}
 
-# WebappsUpdateTimer.js
-component {8f7002cb-e959-4f0a-a2e8-563232564385} WebappsUpdateTimer.js
-contract @mozilla.org/webapps-update-timer;1 {8f7002cb-e959-4f0a-a2e8-563232564385}
-category update-timer WebappsUpdateTimer @mozilla.org/webapps-update-timer;1,getService,webapp-background-update-timer,browser.webapps.updateInterval,86400
-
 # PromptService.js
 component {9a61149b-2276-4a0a-b79c-be994ad106cf} PromptService.js
 contract @mozilla.org/prompter;1 {9a61149b-2276-4a0a-b79c-be994ad106cf}
 contract @mozilla.org/embedcomp/prompt-service;1 {9a61149b-2276-4a0a-b79c-be994ad106cf}
 component {80dae1e9-e0d2-4974-915f-f97050fa8068} PromptService.js
 contract @mozilla.org/network/authprompt-adapter-factory;1 {80dae1e9-e0d2-4974-915f-f97050fa8068}
 #endif
 
deleted file mode 100644
--- a/mobile/android/components/WebappsUpdateTimer.js
+++ /dev/null
@@ -1,78 +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/. */
-
-/**
- * This component triggers a periodic webapp update check.
- */
-
-"use strict";
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-
-Cu.import("resource://gre/modules/JNI.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/WebappManager.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-const Log = Cu.import("resource://gre/modules/AndroidLog.jsm", {}).AndroidLog.bind("WebappsUpdateTimer");
-
-function isWebAppProcess() {
-  let jenv = null;
-  try {
-    jenv = JNI.GetForThread();
-
-    let GeckoAppShell = JNI.LoadClass(jenv, "org.mozilla.gecko.GeckoAppShell", {
-      static_methods: [
-        { name: "isWebAppProcess", sig: "()Z" }
-      ],
-    });
-
-    return GeckoAppShell.isWebAppProcess();
-  } finally {
-    if (jenv) {
-      JNI.UnloadClasses(jenv);
-    }
-  }
-}
-
-function WebappsUpdateTimer() {}
-
-WebappsUpdateTimer.prototype = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback,
-                                         Ci.nsISupportsWeakReference]),
-  classID: Components.ID("{8f7002cb-e959-4f0a-a2e8-563232564385}"),
-
-  notify: function(aTimer) {
-    // Ignore the timer if automatic update checks are disabled or if this
-    // is a webapp process (since we only want to bug people about updates
-    // from the browser process).
-    if (Services.prefs.getIntPref("browser.webapps.checkForUpdates") == 0 || !isWebAppProcess()) {
-      return;
-    }
-
-    // If we are offline, wait to be online to start the update check.
-    if (Services.io.offline) {
-      Log.i("network offline for webapp update check; waiting");
-      Services.obs.addObserver(this, "network:offline-status-changed", true);
-      return;
-    }
-
-    Log.i("periodic check for webapp updates");
-    WebappManager.checkForUpdates();
-  },
-
-  observe: function(aSubject, aTopic, aData) {
-    if (aTopic !== "network:offline-status-changed" || aData !== "online") {
-      return;
-    }
-
-    Log.i("network back online for webapp update check; commencing");
-    Services.obs.removeObserver(this, "network:offline-status-changed");
-    WebappManager.checkForUpdates();
-  }
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([WebappsUpdateTimer]);
--- a/mobile/android/components/moz.build
+++ b/mobile/android/components/moz.build
@@ -30,17 +30,16 @@ EXTRA_COMPONENTS += [
 if not CONFIG['MOZ_B2GDROID']:
     EXTRA_COMPONENTS += [
         'ContentPermissionPrompt.js',
         'FilePicker.js',
         'HelperAppDialog.js',
         'PromptService.js',
         'SessionStore.js',
         'SiteSpecificUserAgent.js',
-        'WebappsUpdateTimer.js',
     ]
 
 # Keep it this way if at all possible.  If you need preprocessing,
 # consider adding fields to AppConstants.jsm.
 EXTRA_PP_COMPONENTS += [
     'MobileComponents.manifest',
 ]
 
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -552,16 +552,15 @@
 
 #ifdef ENABLE_MARIONETTE
 @BINPATH@/chrome/marionette@JAREXT@
 @BINPATH@/chrome/marionette.manifest
 @BINPATH@/components/MarionetteComponents.manifest
 @BINPATH@/components/marionettecomponent.js
 #endif
 
-@BINPATH@/components/WebappsUpdateTimer.js
 @BINPATH@/components/DataStore.manifest
 @BINPATH@/components/DataStoreImpl.js
 @BINPATH@/components/dom_datastore.xpt
 
 #ifdef PKG_LOCALE_MANIFEST
 #include @PKG_LOCALE_MANIFEST@
 #endif
deleted file mode 100644
--- a/mobile/android/locales/en-US/chrome/webapp.properties
+++ /dev/null
@@ -1,59 +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/.
-
-checkingForUpdatesTitle=Checking for updates…
-checkingForUpdatesMessage=Checking for updates to your apps
-
-noUpdatesTitle=No updates available
-noUpdatesMessage=There are no updates to your apps
-
-# LOCALIZATION NOTE (retrieveUpdateTitle): Semi-colon list of plural forms.
-# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
-# #1 is the number of updates.
-# example: 3 new updates available
-retrieveUpdateTitle=#1 new update available;#1 new updates available
-
-# LOCALIZATION NOTE (retrieveUpdateMessage): Semi-colon list of plural forms.
-# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
-# %1$S is a comma-separated list of apps for which to retrieve an update.
-# example: Touch to retrieve updates for Foo, Bar, Baz
-retrieveUpdateMessage=Touch to retrieve update for %1$S;Touch to retrieve updates for %1$S
-
-# LOCALIZATION NOTE (retrievingUpdateTitle): Semi-colon list of plural forms.
-# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
-# #1 is the number of updates.
-# example: Retrieving 3 updates…
-retrievingUpdateTitle=Retrieving #1 update…;Retrieving #1 updates…
-
-# LOCALIZATION NOTE (retrievingUpdateMessage): Semi-colon list of plural forms.
-# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
-# %1$S is a comma-separated list of apps for which we're retrieving updates.
-# example: Retrieving updates for Foo, Bar, Baz
-retrievingUpdateMessage=Retrieving update for %1$S; Retrieving updates for %1$S
-
-# LOCALIZATION NOTE (installUpdateTitle): Semi-colon list of plural forms.
-# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
-# #1 is the number of updates.
-# example: 3 updates downloaded
-installUpdateTitle=#1 update downloaded;#1 updates downloaded
-
-# LOCALIZATION NOTE (installUpdateMessage2): Semi-colon list of plural forms.
-# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
-# %1$S is a comma-separated list of apps for which to install an update.
-# example: Touch to install updates for Foo, Bar, Baz
-installUpdateMessage2=Touch to install update for %1$S;Touch to install updates for %1$S
-
-# LOCALIZATION NOTE (retrievalFailedTitle): Semi-colon list of plural forms.
-# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
-# #1 is the number of updates.
-# example: 3 updates failed
-retrievalFailedTitle=#1 update failed;#1 updates failed
-
-# LOCALIZATION NOTE (retrievalFailedMessage): Semi-colon list of plural forms.
-# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
-# %1$S is a comma-separated list of apps for which retrieval failed.
-# example: Failed to retrieve updates for Foo, Bar, Baz
-retrievalFailedMessage=Failed to retrieve update for %1$S;Failed to retrieve updates for %1$S
-
-webappsDisabled=Installing apps is disabled
--- a/mobile/android/locales/jar.mn
+++ b/mobile/android/locales/jar.mn
@@ -32,17 +32,16 @@
   locale/@AB_CD@/browser/notification.dtd         (%chrome/notification.dtd)
   locale/@AB_CD@/browser/pippki.properties        (%chrome/pippki.properties)
   locale/@AB_CD@/browser/sync.dtd                 (%chrome/sync.dtd)
   locale/@AB_CD@/browser/sync.properties          (%chrome/sync.properties)
   locale/@AB_CD@/browser/prompt.dtd               (%chrome/prompt.dtd)
   locale/@AB_CD@/browser/feedback.dtd             (%chrome/feedback.dtd)
   locale/@AB_CD@/browser/phishing.dtd             (%chrome/phishing.dtd)
   locale/@AB_CD@/browser/handling.properties      (%chrome/handling.properties)
-  locale/@AB_CD@/browser/webapp.properties        (%chrome/webapp.properties)
   locale/@AB_CD@/browser/aboutLogins.dtd          (%chrome/aboutLogins.dtd)
   locale/@AB_CD@/browser/aboutLogins.properties  (%chrome/aboutLogins.properties)
 #ifdef NIGHTLY_BUILD
   locale/@AB_CD@/browser/webcompatReporter.properties (%chrome/webcompatReporter.properties)
 #endif
 % resource search-plugins chrome://browser/locale/searchplugins/
 
 # overrides for toolkit l10n, also for en-US
deleted file mode 100644
--- a/mobile/android/modules/WebappManager.jsm
+++ /dev/null
@@ -1,659 +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/. */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = ["WebappManager"];
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-const UPDATE_URL_PREF = "browser.webapps.updateCheckUrl";
-
-Cu.import("resource://gre/modules/AppsUtils.jsm");
-Cu.import("resource://gre/modules/Downloads.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/NetUtil.jsm");
-Cu.import("resource://gre/modules/FileUtils.jsm");
-Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
-Cu.import("resource://gre/modules/Webapps.jsm");
-Cu.import("resource://gre/modules/osfile.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "Notifications", "resource://gre/modules/Notifications.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Messaging", "resource://gre/modules/Messaging.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PluralForm", "resource://gre/modules/PluralForm.jsm");
-
-// Import AppsServiceChild.DOMApplicationRegistry for its getAll method.
-var AppsServiceChild = {};
-XPCOMUtils.defineLazyModuleGetter(AppsServiceChild, "DOMApplicationRegistry",
-                                  "resource://gre/modules/AppsServiceChild.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "Strings", function() {
-  return Services.strings.createBundle("chrome://browser/locale/webapp.properties");
-});
-
-XPCOMUtils.defineLazyServiceGetter(this, "ParentalControls",
-  "@mozilla.org/parental-controls-service;1", "nsIParentalControlsService");
-
-/**
- * Get the formatted plural form of a string.  Escapes semicolons in arguments
- * to provide to the formatter before formatting the string, then unescapes them
- * after getting its plural form, to avoid tripping up the plural form getter
- * with a semicolon in one of the formatter's arguments, since the plural forms
- * of localized strings are delimited by semicolons.
- *
- * Ideally, we'd get the plural form first and then format the string,
- * so we wouldn't have to escape/unescape the semicolons; but that would require
- * changes to nsIStringBundle and PluralForm.jsm.
- *
- * @param stringName {String} the string to get the formatted plural form of
- * @param formatterArgs {Array} of {String} args to provide to the formatter
- * @param pluralNum {Number} the number that determines the plural form
- * @returns {String} the formatted plural form of the string
- */
-function getFormattedPluralForm(stringName, formatterArgs, pluralNum) {
-  // Escape semicolons by replacing them with ESC characters.
-  let escapedArgs = formatterArgs.map((arg) => arg.replace(/;/g, String.fromCharCode(0x1B)));
-  let formattedString = Strings.formatStringFromName(stringName, escapedArgs, escapedArgs.length);
-  let pluralForm = PluralForm.get(pluralNum, formattedString);
-  let unescapedString = pluralForm.replace(String.fromCharCode(0x1B), ";", "g");
-  return unescapedString;
-}
-
-var Log = Cu.import("resource://gre/modules/AndroidLog.jsm", {}).AndroidLog;
-var debug = Log.d.bind(null, "WebappManager");
-
-this.WebappManager = {
-  __proto__: DOMRequestIpcHelper.prototype,
-
-  get _testing() {
-    try {
-      return Services.prefs.getBoolPref("browser.webapps.testing");
-    } catch(ex) {
-      return false;
-    }
-  },
-
-  install: function(aMessage, aMessageManager) {
-    if (this._testing) {
-      // Go directly to DOM.  Do not download/install APK, do not collect $200.
-      DOMApplicationRegistry.doInstall(aMessage, aMessageManager);
-      return;
-    }
-
-    this._installApk(aMessage, aMessageManager);
-  },
-
-  installPackage: function(aMessage, aMessageManager) {
-    if (this._testing) {
-      // Go directly to DOM.  Do not download/install APK, do not collect $200.
-      DOMApplicationRegistry.doInstallPackage(aMessage, aMessageManager);
-      return;
-    }
-
-    this._installApk(aMessage, aMessageManager);
-  },
-
-  _installApk: function(aMessage, aMessageManager) { return Task.spawn((function*() {
-    if (!ParentalControls.isAllowed(ParentalControls.INSTALL_APPS)) {
-      aMessage.error = Strings.GetStringFromName("webappsDisabled"),
-      aMessageManager.sendAsyncMessage("Webapps:Install:Return:KO", aMessage);
-      return;
-    }
-
-    let filePath;
-
-    try {
-      filePath = yield this._downloadApk(aMessage.app.manifestURL);
-    } catch(ex) {
-      aMessage.error = ex;
-      aMessageManager.sendAsyncMessage("Webapps:Install:Return:KO", aMessage);
-      debug("error downloading APK: " + ex);
-      return;
-    }
-
-    Messaging.sendRequestForResult({
-      type: "Webapps:InstallApk",
-      filePath: filePath,
-      data: aMessage,
-    }).catch(function (error) {
-      aMessage.error = error;
-      aMessageManager.sendAsyncMessage("Webapps:Install:Return:KO", aMessage);
-      debug("error downloading APK: " + error);
-    });
-  }).bind(this)); },
-
-  _downloadApk: function(aManifestUrl) {
-    debug("_downloadApk for " + aManifestUrl);
-    let deferred = Promise.defer();
-
-    // Get the endpoint URL and convert it to an nsIURI/nsIURL object.
-    const GENERATOR_URL_PREF = "browser.webapps.apkFactoryUrl";
-    const GENERATOR_URL_BASE = Services.prefs.getCharPref(GENERATOR_URL_PREF);
-    let generatorUrl = NetUtil.newURI(GENERATOR_URL_BASE).QueryInterface(Ci.nsIURL);
-
-    // Populate the query part of the URL with the manifest URL parameter.
-    let params = {
-      manifestUrl: aManifestUrl,
-    };
-    generatorUrl.query =
-      Object.keys(params).map((p) => p + "=" + encodeURIComponent(params[p])).join("&");
-    debug("downloading APK from " + generatorUrl.spec);
-
-    Downloads.getSystemDownloadsDirectory().then(function(downloadsDir) {
-      let file = new FileUtils.File(downloadsDir);
-      file.append(aManifestUrl.replace(/[^a-zA-Z0-9]/gi, "") + ".apk");
-      file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
-      debug("downloading APK to " + file.path);
-
-      let worker = new ChromeWorker("resource://gre/modules/WebappManagerWorker.js");
-      worker.onmessage = function(event) {
-        let { type, message } = event.data;
-
-        worker.terminate();
-
-        if (type == "success") {
-          deferred.resolve(file.path);
-        } else { // type == "failure"
-          debug("error downloading APK: " + message);
-          deferred.reject(message);
-        }
-      }
-
-      // Trigger the download.
-      worker.postMessage({ url: generatorUrl.spec, path: file.path });
-    });
-
-    return deferred.promise;
-  },
-
-  _deleteAppcachePath: function(aManifest) {
-    // We don't yet support pre-installing an appcache because it isn't clear
-    // how to do it without degrading the user experience (since users expect
-    // apps to be available after the system tells them they've been installed,
-    // which has already happened) and because nsCacheService shuts down
-    // when we trigger the native install dialog and doesn't re-init itself
-    // afterward (TODO: file bug about this behavior).
-    if ("appcache_path" in aManifest) {
-      debug("deleting appcache_path from manifest: " + aManifest.appcache_path);
-      delete aManifest.appcache_path;
-    }
-  },
-
-  askInstall: function(aData) {
-    let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
-    file.initWithPath(aData.profilePath);
-
-    this._deleteAppcachePath(aData.app.manifest);
-
-    DOMApplicationRegistry.registryReady.then(() => {
-      DOMApplicationRegistry.confirmInstall(aData, file, (function(aApp, aManifest) {
-        this._postInstall(aData.profilePath, aManifest, aData.app.origin,
-                          aData.app.apkPackageName, aData.app.manifestURL);
-      }).bind(this));
-    });
-  },
-
-  _postInstall: function(aProfilePath, aNewManifest, aOrigin, aApkPackageName, aManifestURL) {
-    // aOrigin may now point to the app: url that hosts this app.
-    Messaging.sendRequest({
-      type: "Webapps:Postinstall",
-      apkPackageName: aApkPackageName,
-      origin: aOrigin,
-    });
-  },
-
-  askUninstall: function(aData) {
-    // Android does not currently support automatic uninstalling of apps.
-    // See bug 1019054.
-    DOMApplicationRegistry.denyUninstall(aData, "NOT_SUPPORTED");
-  },
-
-  launch: function({ apkPackageName }) {
-    debug("launch: " + apkPackageName);
-
-    Messaging.sendRequest({
-      type: "Webapps:Launch",
-      packageName: apkPackageName,
-    });
-  },
-
-  uninstall: Task.async(function*(aData, aMessageManager) {
-    debug("uninstall: " + aData.manifestURL);
-
-    yield DOMApplicationRegistry.registryReady;
-
-    if (this._testing) {
-      // Go directly to DOM.  Do not uninstall APK, do not collect $200.
-      DOMApplicationRegistry.doUninstall(aData, aMessageManager);
-      return;
-    }
-
-    let app = DOMApplicationRegistry.getAppByManifestURL(aData.manifestURL);
-    if (!app) {
-      throw new Error("app not found in registry");
-    }
-
-    // If the APK is installed, then _getAPKVersions will return a version
-    // for it, so we can use that function to determine its install status.
-    if (app.apkPackageName && app.apkPackageName in (yield this._getAPKVersions([ app.apkPackageName ]))) {
-      debug("APK is installed; requesting uninstallation");
-      Messaging.sendRequest({
-        type: "Webapps:UninstallApk",
-        apkPackageName: app.apkPackageName,
-      });
-
-      // We don't need to call DOMApplicationRegistry.doUninstall at this point,
-      // because the APK uninstall listener will call autoUninstall once the APK
-      // is uninstalled; and if the user cancels the APK uninstallation, then we
-      // shouldn't remove the app from the registry anyway.
-
-      // But we should tell the requesting document the result of their request.
-      // TODO: tell the requesting document if uninstallation succeeds or fails
-      // by storing weak references to the message/manager pair here and then
-      // using them in autoUninstall if they're still defined when it's called;
-      // and make EventListener.uninstallApk return an error when APK uninstall
-      // fails (which it should be able to detect reliably on Android 4+),
-      // which we observe here and use to notify the requester of failure.
-    } else {
-      // The APK isn't installed, but remove the app from the registry anyway,
-      // to ensure the user can always remove an app from the registry (and thus
-      // about:apps) even if it's out of sync with installed APKs.
-      debug("APK not installed; proceeding directly to removal from registry");
-      DOMApplicationRegistry.uninstall(aData.manifestURL);
-    }
-
-  }),
-
-  autoInstall: function(aData) {
-    debug("autoInstall " + aData.manifestURL);
-
-    let mm = {
-      sendAsyncMessage: function (aMessageName, aData) {
-        // TODO hook this back to Java to report errors.
-        debug("sendAsyncMessage " + aMessageName + ": " + JSON.stringify(aData));
-      }
-    };
-
-    let origin = Services.io.newURI(aData.manifestURL, null, null).prePath;
-
-    let message = aData.request || {
-      app: {
-        origin: origin,
-        receipts: [],
-      }
-    };
-
-    if (aData.updateManifest) {
-      if (aData.zipFilePath) {
-        aData.updateManifest.package_path = aData.zipFilePath;
-      }
-      message.app.updateManifest = aData.updateManifest;
-    }
-
-    // The manifest url may be subtly different between the
-    // time the APK was built and the APK being installed.
-    // Thus, we should take the APK as the source of truth.
-    message.app.manifestURL = aData.manifestURL;
-    message.app.manifest = aData.manifest;
-    message.app.apkPackageName = aData.apkPackageName;
-    message.profilePath = aData.profilePath;
-    message.mm = mm;
-    message.apkInstall = true;
-
-    DOMApplicationRegistry.registryReady.then(() => {
-      // If the app is already installed, update the existing installation.
-      // We should be able to use DOMApplicationRegistry.getAppByManifestURL,
-      // but it returns a mozIApplication, while _autoUpdate needs the original
-      // object from DOMApplicationRegistry.webapps in order to modify it.
-      for (let [ , app] in Iterator(DOMApplicationRegistry.webapps)) {
-        if (app.manifestURL == aData.manifestURL) {
-          return this._autoUpdate(aData, app);
-        }
-      }
-
-      switch (aData.type) { // can be hosted or packaged.
-        case "hosted":
-          DOMApplicationRegistry.doInstall(message, mm);
-          break;
-
-        case "packaged":
-          message.isPackage = true;
-          DOMApplicationRegistry.doInstallPackage(message, mm);
-          break;
-      }
-    });
-  },
-
-  _autoUpdate: function(aData, aOldApp) { return Task.spawn((function*() {
-    debug("_autoUpdate app of type " + aData.type);
-
-    if (aOldApp.apkPackageName != aData.apkPackageName) {
-      // This happens when the app was installed as a shortcut via the old
-      // runtime and is now being updated to an APK.
-      debug("update apkPackageName from " + aOldApp.apkPackageName + " to " + aData.apkPackageName);
-      aOldApp.apkPackageName = aData.apkPackageName;
-    }
-
-    if (aData.type == "hosted") {
-      this._deleteAppcachePath(aData.manifest);
-      let oldManifest = yield DOMApplicationRegistry.getManifestFor(aData.manifestURL);
-      yield DOMApplicationRegistry.updateHostedApp(aData, aOldApp.id, aOldApp, oldManifest, aData.manifest);
-    } else {
-      yield this._autoUpdatePackagedApp(aData, aOldApp);
-    }
-
-    this._postInstall(aData.profilePath, aData.manifest, aOldApp.origin, aOldApp.apkPackageName, aOldApp.manifestURL);
-  }).bind(this)); },
-
-  _autoUpdatePackagedApp: Task.async(function*(aData, aOldApp) {
-    debug("_autoUpdatePackagedApp: " + aData.manifestURL);
-
-    if (aData.updateManifest && aData.zipFilePath) {
-      aData.updateManifest.package_path = aData.zipFilePath;
-    }
-
-    // updatePackagedApp just prepares the update, after which we must
-    // download the package via the misnamed startDownload and then apply it
-    // via applyDownload.
-    yield DOMApplicationRegistry.updatePackagedApp(aData, aOldApp.id, aOldApp, aData.updateManifest);
-
-    try {
-      yield DOMApplicationRegistry.startDownload(aData.manifestURL);
-    } catch (ex if ex == "PACKAGE_UNCHANGED") {
-      debug("package unchanged");
-      // If the package is unchanged, then there's nothing more to do.
-      return;
-    }
-
-    yield DOMApplicationRegistry.applyDownload(aData.manifestURL);
-  }),
-
-  _checkingForUpdates: false,
-
-  checkForUpdates: function(userInitiated) { return Task.spawn((function*() {
-    debug("checkForUpdates");
-
-    // Don't start checking for updates if we're already doing so.
-    // TODO: Consider cancelling the old one and starting a new one anyway
-    // if the user requested this one.
-    if (this._checkingForUpdates) {
-      debug("already checking for updates");
-      return;
-    }
-    this._checkingForUpdates = true;
-
-    try {
-      let installedApps = yield this._getInstalledApps();
-      if (installedApps.length === 0) {
-        return;
-      }
-
-      // Map APK names to APK versions.
-      let apkNameToVersion = yield this._getAPKVersions(installedApps.map(app =>
-        app.apkPackageName).filter(apkPackageName => !!apkPackageName)
-      );
-
-      // Map manifest URLs to APK versions, which is what the service needs
-      // in order to tell us which apps are outdated; and also map them to app
-      // objects, which the downloader/installer uses to download/install APKs.
-      // XXX Will this cause us to update apps without packages, and if so,
-      // does that satisfy the legacy migration story?
-      let manifestUrlToApkVersion = {};
-      let manifestUrlToApp = {};
-      for (let app of installedApps) {
-        manifestUrlToApkVersion[app.manifestURL] = apkNameToVersion[app.apkPackageName] || 0;
-        manifestUrlToApp[app.manifestURL] = app;
-      }
-
-      let outdatedApps = yield this._getOutdatedApps(manifestUrlToApkVersion, userInitiated);
-
-      if (outdatedApps.length === 0) {
-        // If the user asked us to check for updates, tell 'em we came up empty.
-        if (userInitiated) {
-          this._notify({
-            title: Strings.GetStringFromName("noUpdatesTitle"),
-            message: Strings.GetStringFromName("noUpdatesMessage"),
-            icon: "drawable://alert_app",
-          });
-        }
-        return;
-      }
-
-      let usingLan = function() {
-        let network = Cc["@mozilla.org/network/network-link-service;1"].getService(Ci.nsINetworkLinkService);
-        return (network.linkType == network.LINK_TYPE_WIFI || network.linkType == network.LINK_TYPE_ETHERNET);
-      };
-
-      let updateAllowed = function() {
-        let autoUpdatePref = Services.prefs.getCharPref("app.update.autodownload");
-
-        return (autoUpdatePref == "enabled") || (autoUpdatePref == "wifi" && usingLan());
-      };
-
-      if (updateAllowed()) {
-        yield this._updateApks(outdatedApps.map((url) => manifestUrlToApp[url]));
-      } else {
-        let names = outdatedApps.map((url) => manifestUrlToApp[url].name).join(", ");
-        let accepted = yield this._notify({
-          title: PluralForm.get(outdatedApps.length, Strings.GetStringFromName("retrieveUpdateTitle")).
-                 replace("#1", outdatedApps.length),
-          message: getFormattedPluralForm("retrieveUpdateMessage", [names], outdatedApps.length),
-          icon: "drawable://alert_app",
-        }).dismissed;
-
-        if (accepted) {
-          yield this._updateApks(outdatedApps.map((url) => manifestUrlToApp[url]));
-        }
-      }
-    }
-    // There isn't a catch block because we want the error to propagate through
-    // the promise chain, so callers can receive it and choose to respond to it.
-    finally {
-      // Ensure we update the _checkingForUpdates flag even if there's an error;
-      // otherwise the process will get stuck and never check for updates again.
-      this._checkingForUpdates = false;
-    }
-  }).bind(this)); },
-
-  _getAPKVersions: function(packageNames) {
-    return Messaging.sendRequestForResult({
-      type: "Webapps:GetApkVersions",
-      packageNames: packageNames 
-    }).then(data => data.versions);
-  },
-
-  _getInstalledApps: function() {
-    let deferred = Promise.defer();
-    AppsServiceChild.DOMApplicationRegistry.getAll(apps => deferred.resolve(apps));
-    return deferred.promise;
-  },
-
-  _getOutdatedApps: function(installedApps, userInitiated) {
-    let deferred = Promise.defer();
-
-    let data = JSON.stringify({ installed: installedApps });
-
-    let notification;
-    if (userInitiated) {
-      notification = this._notify({
-        title: Strings.GetStringFromName("checkingForUpdatesTitle"),
-        message: Strings.GetStringFromName("checkingForUpdatesMessage"),
-        icon: "drawable://alert_app_animation",
-        progress: NaN,
-      });
-    }
-
-    let request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
-                  createInstance(Ci.nsIXMLHttpRequest).
-                  QueryInterface(Ci.nsIXMLHttpRequestEventTarget);
-    request.mozBackgroundRequest = true;
-    request.open("POST", Services.prefs.getCharPref(UPDATE_URL_PREF), true);
-    request.channel.loadFlags = Ci.nsIChannel.LOAD_ANONYMOUS |
-                                Ci.nsIChannel.LOAD_BYPASS_CACHE |
-                                Ci.nsIChannel.INHIBIT_CACHING;
-    request.onload = function() {
-      if (userInitiated) {
-        notification.cancel();
-      }
-      deferred.resolve(JSON.parse(this.response).outdated);
-    };
-    request.onerror = function() {
-      if (userInitiated) {
-        notification.cancel();
-      }
-      deferred.reject(this.status || this.statusText);
-    };
-    request.setRequestHeader("Content-Type", "application/json");
-    request.setRequestHeader("Content-Length", data.length);
-
-    request.send(data);
-
-    return deferred.promise;
-  },
-
-  _updateApks: function(aApps) { return Task.spawn((function*() {
-    // Notify the user that we're in the progress of downloading updates.
-    let downloadingNames = aApps.map((app) => app.name).join(", ");
-    let notification = this._notify({
-      title: PluralForm.get(aApps.length, Strings.GetStringFromName("retrievingUpdateTitle")).
-             replace("#1", aApps.length),
-      message: getFormattedPluralForm("retrievingUpdateMessage", [downloadingNames], aApps.length),
-      icon: "drawable://alert_download_animation",
-      // TODO: make this a determinate progress indicator once we can determine
-      // the sizes of the APKs and observe their progress.
-      progress: NaN,
-    });
-
-    // Download the APKs for the given apps.  We do this serially to avoid
-    // saturating the user's network connection.
-    // TODO: download APKs in parallel (or at least more than one at a time)
-    // if it seems reasonable.
-    let downloadedApks = [];
-    let downloadFailedApps = [];
-    for (let app of aApps) {
-      try {
-        let filePath = yield this._downloadApk(app.manifestURL);
-        downloadedApks.push({ app: app, filePath: filePath });
-      } catch(ex) {
-        downloadFailedApps.push(app);
-      }
-    }
-
-    notification.cancel();
-
-    // Notify the user if any downloads failed, but don't do anything
-    // when the user accepts/cancels the notification.
-    // In the future, we might prompt the user to retry the download.
-    if (downloadFailedApps.length > 0) {
-      let downloadFailedNames = downloadFailedApps.map((app) => app.name).join(", ");
-      this._notify({
-        title: PluralForm.get(downloadFailedApps.length, Strings.GetStringFromName("retrievalFailedTitle")).
-               replace("#1", downloadFailedApps.length),
-        message: getFormattedPluralForm("retrievalFailedMessage", [downloadFailedNames], downloadFailedApps.length),
-        icon: "drawable://alert_app",
-      });
-    }
-
-    // If we weren't able to download any APKs, then there's nothing more to do.
-    if (downloadedApks.length === 0) {
-      return;
-    }
-
-    // Prompt the user to update the apps for which we downloaded APKs, and wait
-    // until they accept/cancel the notification.
-    let downloadedNames = downloadedApks.map((apk) => apk.app.name).join(", ");
-    let accepted = yield this._notify({
-      title: PluralForm.get(downloadedApks.length, Strings.GetStringFromName("installUpdateTitle")).
-             replace("#1", downloadedApks.length),
-      message: getFormattedPluralForm("installUpdateMessage2", [downloadedNames], downloadedApks.length),
-      icon: "drawable://alert_app",
-    }).dismissed;
-
-    if (accepted) {
-      // The user accepted the notification, so install the downloaded APKs.
-      for (let apk of downloadedApks) {
-        let msg = {
-          app: apk.app,
-          // TODO: figure out why Webapps:InstallApk needs the "from" property.
-          from: apk.app.installOrigin,
-        };
-        Messaging.sendRequestForResult({
-          type: "Webapps:InstallApk",
-          filePath: apk.filePath,
-          data: msg,
-        }).catch((error) => {
-          // There's no page to report back to so drop the error.
-          // TODO: we should notify the user about this failure.
-          debug("APK install failed : " + error);
-        });
-      }
-    } else {
-      // The user cancelled the notification, so remove the downloaded APKs.
-      for (let apk of downloadedApks) {
-        try {
-          yield OS.file.remove(apk.filePath);
-        } catch(ex) {
-          debug("error removing " + apk.filePath + " for cancelled update: " + ex);
-        }
-      }
-    }
-
-  }).bind(this)); },
-
-  _notify: function(aOptions) {
-    dump("_notify: " + aOptions.title);
-
-    // Resolves to true if the notification is "clicked" (i.e. touched)
-    // and false if the notification is "cancelled" by swiping it away.
-    let dismissed = Promise.defer();
-
-    // TODO: make notifications expandable so users can expand them to read text
-    // that gets cut off in standard notifications.
-    let id = Notifications.create({
-      title: aOptions.title,
-      message: aOptions.message,
-      icon: aOptions.icon,
-      progress: aOptions.progress,
-      onClick: function(aId, aCookie) {
-        dismissed.resolve(true);
-      },
-      onCancel: function(aId, aCookie) {
-        dismissed.resolve(false);
-      },
-    });
-
-    // Return an object with a promise that resolves when the notification
-    // is dismissed by the user along with a method for cancelling it,
-    // so callers who want to wait for user action can do so, while those
-    // who want to control the notification's lifecycle can do that instead.
-    return {
-      dismissed: dismissed.promise,
-      cancel: function() {
-        Notifications.cancel(id);
-      },
-    };
-  },
-
-  autoUninstall: function(aData) {
-    DOMApplicationRegistry.registryReady.then(() => {
-      for (let id in DOMApplicationRegistry.webapps) {
-        let app = DOMApplicationRegistry.webapps[id];
-        if (aData.apkPackageNames.indexOf(app.apkPackageName) > -1) {
-          debug("attempting to uninstall " + app.name);
-          DOMApplicationRegistry.uninstall(app.manifestURL).then(
-            function() {
-              debug("success uninstalling " + app.name);
-            },
-            function(error) {
-              debug("error uninstalling " + app.name + ": " + error);
-            }
-          );
-        }
-      }
-    });
-  },
-};
deleted file mode 100644
--- a/mobile/android/modules/WebappManagerWorker.js
+++ /dev/null
@@ -1,52 +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/. */
-
-importScripts("resource://gre/modules/osfile.jsm");
-importScripts("resource://gre/modules/workers/require.js");
-var Log = require("resource://gre/modules/AndroidLog.jsm");
-
-// Define the "log" function as a binding of the Log.d function so it specifies
-// the "debug" priority and a log tag.
-var log = Log.d.bind(null, "WebappManagerWorker");
-
-// (eslint-disable: see bug 1177901)
-onmessage = function(event) { // eslint-disable-line no-undef
-  let { url, path } = event.data;
-
-  let file = OS.File.open(path, { truncate: true });
-  let request = new XMLHttpRequest({ mozSystem: true });
-
-  request.open("GET", url, true);
-  request.responseType = "moz-chunked-arraybuffer";
-
-  request.onprogress = function(event) {
-    log("onprogress: received " + request.response.byteLength + " bytes");
-    let bytesWritten = file.write(new Uint8Array(request.response));
-    log("onprogress: wrote " + bytesWritten + " bytes");
-  };
-
-  request.onreadystatechange = function(event) {
-    log("onreadystatechange: " + request.readyState);
-
-    if (request.readyState !== 4) {
-      return;
-    }
-
-    file.close();
-
-    if (request.status === 200) {
-      postMessage({ type: "success" });
-    } else {
-      try {
-        OS.File.remove(path);
-      } catch(ex) {
-        log("error removing " + path + ": " + ex);
-      }
-      let statusMessage = request.status + " - " + request.statusText;
-      postMessage({ type: "failure", message: statusMessage });
-    }
-  };
-
-  request.send(null);
-}
--- a/mobile/android/modules/moz.build
+++ b/mobile/android/modules/moz.build
@@ -25,16 +25,14 @@ EXTRA_JS_MODULES += [
     'PageActions.jsm',
     'Prompt.jsm',
     'RuntimePermissions.jsm',
     'Sanitizer.jsm',
     'SharedPreferences.jsm',
     'Snackbars.jsm',
     'SSLExceptions.jsm',
     'TabMirror.jsm',
-    'WebappManager.jsm',
-    'WebappManagerWorker.js',
 ]
 
 if not CONFIG['MOZ_B2GDROID']:
     EXTRA_JS_MODULES += [
         'FxAccountsWebChannel.jsm',
     ]