Bug 957067 - Stop verifying manifestUrl in installApk. r=wesj
authorMartyn Haigh <martyn.haigh@gmail.com>
Tue, 03 Jun 2014 09:19:00 -0400
changeset 206880 d4625a62c1bb7df0a61ce1f13d80eaf8c61c9c78
parent 206879 e5306a36435b0c892aec93e46f41cd5390abe948
child 206881 35a50dd7629d5e9c04da36d50814e711c40386b1
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswesj
bugs957067
milestone32.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 957067 - Stop verifying manifestUrl in installApk. r=wesj
mobile/android/base/webapp/EventListener.java
mobile/android/modules/WebappManager.jsm
--- a/mobile/android/base/webapp/EventListener.java
+++ b/mobile/android/base/webapp/EventListener.java
@@ -3,47 +3,50 @@
  * 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.ActivityHandlerHelper;
 import org.mozilla.gecko.AppConstants;
 import org.mozilla.gecko.GeckoAppShell;
+import org.mozilla.gecko.GeckoEvent;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.favicons.decoders.FaviconDecoder;
 import org.mozilla.gecko.gfx.BitmapUtils;
 import org.mozilla.gecko.util.ActivityResultHandler;
 import org.mozilla.gecko.EventDispatcher;
-import org.mozilla.gecko.util.GeckoEventListener;
+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 org.mozilla.gecko.WebappAllocator;
 
 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.content.pm.PackageManager.NameNotFoundException;
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.util.Log;
 
 import java.io.File;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
-import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 
-public class EventListener implements GeckoEventListener {
+public class EventListener implements NativeEventListener  {
 
     private static final String LOGTAG = "GeckoWebappEventListener";
 
     public void registerEvents() {
         EventDispatcher.getInstance().registerGeckoThreadListener(this,
             "Webapps:Preinstall",
             "Webapps:InstallApk",
             "Webapps:Postinstall",
@@ -58,20 +61,20 @@ public class EventListener implements Ge
             "Webapps:InstallApk",
             "Webapps:Postinstall",
             "Webapps:Open",
             "Webapps:Uninstall",
             "Webapps:GetApkVersions");
     }
 
     @Override
-    public void handleMessage(String event, JSONObject message) {
+    public void handleMessage(String event, NativeJSObject message, EventCallback callback) {
         try {
             if (AppConstants.MOZ_ANDROID_SYNTHAPKS && event.equals("Webapps:InstallApk")) {
-                installApk(GeckoAppShell.getGeckoInterface().getActivity(), message.getString("filePath"), message.getString("data"));
+                installApk(GeckoAppShell.getGeckoInterface().getActivity(), message, callback);
             } else if (event.equals("Webapps:Postinstall")) {
                 if (AppConstants.MOZ_ANDROID_SYNTHAPKS) {
                     postInstallWebapp(message.getString("apkPackageName"), message.getString("origin"));
                 } else {
                     postInstallWebapp(message.getString("name"),
                                       message.getString("manifestURL"),
                                       message.getString("origin"),
                                       message.getString("iconURL"),
@@ -89,22 +92,22 @@ public class EventListener implements Ge
                 uninstallWebapp(message.getString("origin"));
             } else if (!AppConstants.MOZ_ANDROID_SYNTHAPKS && event.equals("Webapps:Preinstall")) {
                 String name = message.getString("name");
                 String manifestURL = message.getString("manifestURL");
                 String origin = message.getString("origin");
 
                 JSONObject obj = new JSONObject();
                 obj.put("profile", preInstallWebapp(name, manifestURL, origin).toString());
-                EventDispatcher.sendResponse(message, obj);
+                callback.sendSuccess(obj);
             } else if (event.equals("Webapps:GetApkVersions")) {
                 JSONObject obj = new JSONObject();
                 obj.put("versions", getApkVersions(GeckoAppShell.getGeckoInterface().getActivity(),
-                                                   message.getJSONArray("packageNames")));
-                EventDispatcher.sendResponse(message, obj);
+                                                   message.getStringArray("packageNames")));
+                callback.sendSuccess(obj);
             }
         } catch (Exception e) {
             Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
         }
     }
 
     // Not used by MOZ_ANDROID_SYNTHAPKS.
     public static File preInstallWebapp(String aTitle, String aURI, String aOrigin) {
@@ -175,45 +178,47 @@ public class EventListener implements Ge
                 if (proc.processName.equals(targetProcessName)) {
                     android.os.Process.killProcess(proc.pid);
                     break;
                 }
             }
         }
     }
 
-    public static void installApk(final Activity context, String filePath, String data) {
-        // This is the data that mozApps.install sent to Webapps.jsm.
-        JSONObject argsObj = null;
+    public static void installApk(final Activity context, NativeJSObject message, EventCallback callback) {
+        final JSONObject messageData;
 
         // We get the manifest url out of javascript here so we can use it as a checksum
         // in a minute, when a package has been installed.
         String manifestUrl = null;
+        String filePath = null;
+
         try {
-            argsObj = new JSONObject(data);
-            manifestUrl = argsObj.getJSONObject("app").getString("manifestURL");
+            filePath = message.getString("filePath");
+            messageData = new JSONObject(message.getObject("data").toString());
+            manifestUrl = messageData.getJSONObject("app").getString("manifestURL");
         } catch (JSONException e) {
-            Log.e(LOGTAG, "can't get manifest URL from JSON data", e);
-            // TODO: propagate the error back to the mozApps.install caller.
+            Log.wtf(LOGTAG, "Error getting file path and data", e);
+            callback.sendError("Error getting file path and data: " + e.toString());
             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, argsObj);
+        final InstallListener receiver = new InstallListener(manifestUrl, messageData);
 
         // Listen for packages being installed.
         IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
         filter.addDataScheme("package");
         context.registerReceiver(receiver, filter);
 
         File file = new File(filePath);
         if (!file.exists()) {
             Log.wtf(LOGTAG, "APK file doesn't exist at path " + filePath);
-            // TODO: propagate the error back to the mozApps.install caller.
+            callback.sendError("APK file doesn't exist at path " + filePath);
             return;
         }
 
         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() {
@@ -234,25 +239,19 @@ public class EventListener implements Ge
                     }
                 }
             }
         });
     }
 
     private static final int DEFAULT_VERSION_CODE = -1;
 
-    public static JSONObject getApkVersions(Activity context, JSONArray packageNames) {
+    public static JSONObject getApkVersions(Activity context, String[] packageNames) {
         Set<String> packageNameSet = new HashSet<String>();
-        for (int i = 0; i < packageNames.length(); i++) {
-            try {
-                packageNameSet.add(packageNames.getString(i));
-            } catch (JSONException e) {
-                Log.w(LOGTAG, "exception populating settings item", e);
-            }
-        }
+        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)) {
--- a/mobile/android/modules/WebappManager.jsm
+++ b/mobile/android/modules/WebappManager.jsm
@@ -98,17 +98,23 @@ this.WebappManager = {
       aMessageManager.sendAsyncMessage("Webapps:Install:Return:KO", aMessage);
       debug("error downloading APK: " + ex);
       return;
     }
 
     sendMessageToJava({
       type: "Webapps:InstallApk",
       filePath: filePath,
-      data: JSON.stringify(aMessage),
+      data: aMessage,
+    }, (data, error) => {
+      if (!!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.
@@ -488,17 +494,17 @@ this.WebappManager = {
         let msg = {
           app: apk.app,
           // TODO: figure out why Webapps:InstallApk needs the "from" property.
           from: apk.app.installOrigin,
         };
         sendMessageToJava({
           type: "Webapps:InstallApk",
           filePath: apk.filePath,
-          data: JSON.stringify(msg),
+          data: msg,
         });
       }
     } 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) {