Bug 776027 - Move intent handling to IntentHelper. r=wesj
authorJosh Dover <gerfuls@gmail.com>
Fri, 25 Apr 2014 16:28:00 +0200
changeset 180947 95742dfbee4935c374555e354085651904ec8df5
parent 180903 e19812f5695283848e15b9b98fc06f4f97a7d79b
child 180948 c15e4803607d883069fc9e274bbb399cb6f3e5b5
push id26687
push usercbook@mozilla.com
push dateWed, 30 Apr 2014 13:02:09 +0000
treeherdermozilla-central@727238c13756 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswesj
bugs776027
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 776027 - Move intent handling to IntentHelper. r=wesj
mobile/android/base/GeckoApp.java
mobile/android/base/IntentHelper.java
mobile/android/base/moz.build
mobile/android/base/util/JSONUtils.java
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -632,59 +632,17 @@ public abstract class GeckoApp
                     startActivity(i);
                 } else if (!message.isNull("phone")) {
                     Uri contactUri = Uri.parse(message.getString("phone"));       
                     Intent i = new Intent(ContactsContract.Intents.SHOW_OR_CREATE_CONTACT, contactUri);
                     startActivity(i);
                 } else {
                     // something went wrong.
                     Log.e(LOGTAG, "Received Contact:Add message with no email nor phone number");
-                }                
-            } else if (event.equals("Intent:GetHandlers")) {
-                Intent intent = GeckoAppShell.getOpenURIIntent((Context) this, message.optString("url"),
-                    message.optString("mime"), message.optString("action"), message.optString("title"));
-                String[] handlers = GeckoAppShell.getHandlersForIntent(intent);
-                List<String> appList = Arrays.asList(handlers);
-                JSONObject handlersJSON = new JSONObject();
-                handlersJSON.put("apps", new JSONArray(appList));
-                EventDispatcher.sendResponse(message, handlersJSON);
-            } else if (event.equals("Intent:Open")) {
-                GeckoAppShell.openUriExternal(message.optString("url"),
-                    message.optString("mime"), message.optString("packageName"),
-                    message.optString("className"), message.optString("action"), message.optString("title"));
-            } else if (event.equals("Intent:OpenForResult")) {
-                Intent intent = GeckoAppShell.getOpenURIIntent(this,
-                                                               message.optString("url"),
-                                                               message.optString("mime"),
-                                                               message.optString("action"),
-                                                               message.optString("title"));
-                intent.setClassName(message.optString("packageName"), message.optString("className"));
-
-                intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-
-                final JSONObject originalMessage = message;
-                ActivityHandlerHelper.startIntentForActivity(this,
-                                                             intent,
-                        new ActivityResultHandler() {
-                            @Override
-                            public void onActivityResult (int resultCode, Intent data) {
-                                JSONObject response = new JSONObject();
-
-                                try {
-                                    if (data != null) {
-                                        response.put("extras", bundleToJSON(data.getExtras()));
-                                    }
-                                    response.put("resultCode", resultCode);
-                                } catch (JSONException e) {
-                                    Log.w(LOGTAG, "Error building JSON response.", e);
-                                }
-
-                                EventDispatcher.sendResponse(originalMessage, response);
-                            }
-                        });
+                }
             } else if (event.equals("Locale:Set")) {
                 setLocale(message.getString("locale"));
             } else if (event.equals("NativeApp:IsDebuggable")) {
                 JSONObject ret = new JSONObject();
                 ret.put("isDebuggable", getIsDebuggable());
                 EventDispatcher.sendResponse(message, ret);
             } else if (event.equals("SystemUI:Visibility")) {
                 setSystemUiVisible(message.getBoolean("visible"));
@@ -835,33 +793,16 @@ public abstract class GeckoApp
                             GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Toast:Hidden", buttonId));
                         }
                     }
                 });
             }
         });
     }
 
-    private JSONObject bundleToJSON(Bundle bundle) {
-        JSONObject json = new JSONObject();
-        if (bundle == null) {
-            return json;
-        }
-
-        for (String key : bundle.keySet()) {
-            try {
-                json.put(key, bundle.get(key));
-            } catch (JSONException e) {
-                Log.w(LOGTAG, "Error building JSON response.", e);
-            }
-        }
-
-        return json;
-    }
-
     private void addFullScreenPluginView(View view) {
         if (mFullScreenPluginView != null) {
             Log.w(LOGTAG, "Already have a fullscreen plugin view");
             return;
         }
 
         setFullScreen(true);
 
@@ -1350,16 +1291,17 @@ public abstract class GeckoApp
                         GeckoApp.this.onLocaleReady(uiLocale);
                     }
                 });
             }
         });
 
         GeckoAppShell.setNotificationClient(makeNotificationClient());
         NotificationHelper.init(getApplicationContext());
+        IntentHelper.init(this);
     }
 
     /**
      * At this point, the resource system and the rest of the browser are
      * aware of the locale.
      *
      * Now we can display strings!
      *
@@ -1563,19 +1505,16 @@ public abstract class GeckoApp
         registerEventListener("Share:Text");
         registerEventListener("Image:SetAs");
         registerEventListener("Sanitize:ClearHistory");
         registerEventListener("Update:Check");
         registerEventListener("Update:Download");
         registerEventListener("Update:Install");
         registerEventListener("PrivateBrowsing:Data");
         registerEventListener("Contact:Add");
-        registerEventListener("Intent:Open");
-        registerEventListener("Intent:OpenForResult");
-        registerEventListener("Intent:GetHandlers");
         registerEventListener("Locale:Set");
         registerEventListener("NativeApp:IsDebuggable");
         registerEventListener("SystemUI:Visibility");
 
         EventListener.registerEvents();
 
         if (SmsManager.getInstance() != null) {
           SmsManager.getInstance().start();
@@ -2099,18 +2038,16 @@ public abstract class GeckoApp
         unregisterEventListener("Share:Text");
         unregisterEventListener("Image:SetAs");
         unregisterEventListener("Sanitize:ClearHistory");
         unregisterEventListener("Update:Check");
         unregisterEventListener("Update:Download");
         unregisterEventListener("Update:Install");
         unregisterEventListener("PrivateBrowsing:Data");
         unregisterEventListener("Contact:Add");
-        unregisterEventListener("Intent:Open");
-        unregisterEventListener("Intent:GetHandlers");
         unregisterEventListener("Locale:Set");
         unregisterEventListener("NativeApp:IsDebuggable");
         unregisterEventListener("SystemUI:Visibility");
 
         EventListener.unregisterEvents();
 
         deleteTempFiles();
 
@@ -2122,16 +2059,17 @@ public abstract class GeckoApp
             mFormAssistPopup.destroy();
         if (mContactService != null)
             mContactService.destroy();
         if (mPromptService != null)
             mPromptService.destroy();
         if (mTextSelection != null)
             mTextSelection.destroy();
         NotificationHelper.destroy();
+        IntentHelper.destroy();
 
         if (SmsManager.getInstance() != null) {
             SmsManager.getInstance().stop();
             if (isFinishing())
                 SmsManager.getInstance().shutdown();
         }
 
         final HealthRecorder rec = mHealthRecorder;
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/IntentHelper.java
@@ -0,0 +1,134 @@
+/* -*- 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;
+
+import org.mozilla.gecko.util.ActivityResultHandler;
+import org.mozilla.gecko.util.GeckoEventListener;
+import org.mozilla.gecko.util.JSONUtils;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.List;
+
+public final class IntentHelper implements GeckoEventListener {
+    private static final String LOGTAG = "GeckoIntentHelper";
+    private static final String[] EVENTS = {
+        "Intent:GetHandlers",
+        "Intent:Open",
+        "Intent:OpenForResult"
+    };
+    private static IntentHelper instance;
+
+    private Activity activity;
+
+    private IntentHelper(Activity activity) {
+        this.activity = activity;
+        for (String event : EVENTS) {
+            GeckoAppShell.getEventDispatcher().registerEventListener(event, this);
+        }
+    }
+
+    public static IntentHelper init(Activity activity) {
+        if (instance == null) {
+            instance = new IntentHelper(activity);
+        } else {
+            Log.w(LOGTAG, "IntentHelper.init() called twice, ignoring.");
+        }
+
+        return instance;
+    }
+
+    public static void destroy() {
+        if (instance != null) {
+            for (String event : EVENTS) {
+                GeckoAppShell.getEventDispatcher().unregisterEventListener(event, instance);
+            }
+
+            instance = null;
+        }
+    }
+
+    @Override
+    public void handleMessage(String event, JSONObject message) {
+        try {
+            if (event.equals("Intent:GetHandlers")) {
+                getHandlers(message);
+            } else if (event.equals("Intent:Open")) {
+                open(message);
+            } else if (event.equals("Intent:OpenForResult")) {
+                openForResult(message);
+            }
+        } catch (JSONException e) {
+            Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
+        }
+    }
+
+    private void getHandlers(JSONObject message) throws JSONException {
+        final Intent intent = GeckoAppShell.getOpenURIIntent(activity,
+                                                             message.optString("url"),
+                                                             message.optString("mime"),
+                                                             message.optString("action"),
+                                                             message.optString("title"));
+        final List<String> appList = Arrays.asList(GeckoAppShell.getHandlersForIntent(intent));
+
+        final JSONObject response = new JSONObject();
+        response.put("apps", new JSONArray(appList));
+        EventDispatcher.sendResponse(message, response);
+    }
+
+    private void open(JSONObject message) throws JSONException {
+        GeckoAppShell.openUriExternal(message.optString("url"),
+                                      message.optString("mime"),
+                                      message.optString("packageName"),
+                                      message.optString("className"),
+                                      message.optString("action"),
+                                      message.optString("title"));
+    }
+
+    private void openForResult(final JSONObject message) throws JSONException {
+        Intent intent = GeckoAppShell.getOpenURIIntent(activity,
+                                                       message.optString("url"),
+                                                       message.optString("mime"),
+                                                       message.optString("action"),
+                                                       message.optString("title"));
+        intent.setClassName(message.optString("packageName"), message.optString("className"));
+        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+
+        ActivityHandlerHelper.startIntentForActivity(activity, intent, new ResultHandler(message));
+    }
+
+    private static class ResultHandler implements ActivityResultHandler {
+        private final JSONObject message;
+
+        public ResultHandler(JSONObject message) {
+            this.message = message;
+        }
+
+        @Override
+        public void onActivityResult (int resultCode, Intent data) {
+            JSONObject response = new JSONObject();
+
+            try {
+                if (data != null) {
+                    response.put("extras", JSONUtils.bundleToJSON(data.getExtras()));
+                }
+                response.put("resultCode", resultCode);
+            } catch (JSONException e) {
+                Log.w(LOGTAG, "Error building JSON response.", e);
+            }
+
+            EventDispatcher.sendResponse(message, response);
+        }
+    }
+}
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -282,16 +282,17 @@ gbjar.sources += [
     'home/TabMenuStrip.java',
     'home/TabMenuStripLayout.java',
     'home/TopSitesGridItemView.java',
     'home/TopSitesGridView.java',
     'home/TopSitesPanel.java',
     'home/TopSitesThumbnailView.java',
     'home/TwoLinePageRow.java',
     'InputMethods.java',
+    'IntentHelper.java',
     'JavaAddonManager.java',
     'LightweightTheme.java',
     'LightweightThemeDrawable.java',
     'LocaleManager.java',
     'MediaCastingBar.java',
     'MemoryMonitor.java',
     'menu/GeckoMenu.java',
     'menu/GeckoMenuInflater.java',
--- a/mobile/android/base/util/JSONUtils.java
+++ b/mobile/android/base/util/JSONUtils.java
@@ -4,25 +4,51 @@
 
 package org.mozilla.gecko.util;
 
 import java.util.UUID;
 
 import org.json.JSONException;
 import org.json.JSONObject;
 
+import android.os.Bundle;
+import android.util.Log;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.UUID;
+
 public final class JSONUtils {
+    private static final String LOGTAG = "GeckoJSONUtils";
+
     private JSONUtils() {}
 
     public static UUID getUUID(String name, JSONObject json) {
         String uuid = json.optString(name, null);
         return (uuid != null) ? UUID.fromString(uuid) : null;
     }
 
     public static void putUUID(String name, UUID uuid, JSONObject json) {
         String uuidString = uuid.toString();
         try {
             json.put(name, uuidString);
         } catch (JSONException e) {
             throw new IllegalArgumentException(name + "=" + uuidString, e);
         }
     }
+
+    public static JSONObject bundleToJSON(Bundle bundle) {
+        if (bundle == null || bundle.isEmpty()) {
+            return null;
+        }
+
+        JSONObject json = new JSONObject();
+        for (String key : bundle.keySet()) {
+            try {
+                json.put(key, bundle.get(key));
+            } catch (JSONException e) {
+                Log.w(LOGTAG, "Error building JSON response.", e);
+            }
+        }
+
+        return json;
+    }
 }