Bug 689330 - "update LauncherShortcuts to use the new web apps repository" [r=mark.finkle]
authorSriram Ramasubramanian <sriram@mozilla.com>
Tue, 04 Oct 2011 17:45:00 -0400
changeset 78783 109adc21b581e7fa81551bbbc342b3a60391ddfa
parent 78782 0cd9ed297f73e19341910c182b3031ef7272a0b8
child 78784 628c7f04dbbc5a3682ad9d8f8e77b0865ce8e500
push id506
push userclegnitto@mozilla.com
push dateWed, 09 Nov 2011 02:03:18 +0000
treeherdermozilla-aurora@63587fc7bb93 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmark.finkle
bugs689330
milestone10.0a1
Bug 689330 - "update LauncherShortcuts to use the new web apps repository" [r=mark.finkle]
embedding/android/GeckoAppShell.java
embedding/android/LauncherShortcuts.java.in
--- a/embedding/android/GeckoAppShell.java
+++ b/embedding/android/GeckoAppShell.java
@@ -692,21 +692,21 @@ public class GeckoAppShell
     }
     static void scheduleRestart() {
         Log.i("GeckoAppJava", "scheduling restart");
         gRestartScheduled = true;
     }
 
     // "Installs" an application by creating a shortcut
     static void createShortcut(String aTitle, String aURI, String aIconData, String aType) {
-        Log.w("GeckoAppJava", "createShortcut for " + aURI + " [" + aTitle + "]");
+        Log.w("GeckoAppJava", "createShortcut for " + aURI + " [" + aTitle + "] > " + aType);
 
         // the intent to be launched by the shortcut
         Intent shortcutIntent = new Intent();
-        if (aType == "webapp") {
+        if (aType.equalsIgnoreCase("webapp")) {
             shortcutIntent.setAction("org.mozilla.gecko.WEBAPP");
             shortcutIntent.putExtra("args", "--webapp=" + aURI);
         } else {
             shortcutIntent.setAction("org.mozilla.gecko.BOOKMARK");
             shortcutIntent.putExtra("args", "--url=" + aURI);
         }
         shortcutIntent.setClassName(GeckoApp.mAppContext,
                                     GeckoApp.mAppContext.getPackageName() + ".App");
--- a/embedding/android/LauncherShortcuts.java.in
+++ b/embedding/android/LauncherShortcuts.java.in
@@ -36,16 +36,19 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #filter substitution
 package @ANDROID_PACKAGE_NAME@;
 
 import java.io.*;
+import java.util.*;
+
+import org.json.*;
 
 import org.mozilla.gecko.*;
 
 import android.os.*;
 import android.content.*;
 import android.app.*;
 import android.text.*;
 import android.util.*;
@@ -53,132 +56,177 @@ import android.widget.*;
 import android.database.sqlite.*;
 import android.database.*;
 import android.view.*;
 import android.net.Uri;
 import android.graphics.*;
 
 
 public class LauncherShortcuts extends ListActivity {
-    public static final String CREATE_SHORTCUT = "org.mozilla.gecko.CREATE_SHORTCUT";
 
-    public class LauncherCursorAdapter extends SimpleCursorAdapter {
-        private Cursor _cursor;
-        private Context _context;
-
-        public LauncherCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
-            // Using the older, deprecated constructor so we can work on API < 11
-            super(context, layout, c, from, to);
-            _cursor = c;
-            _context = context;
-        }
-
-        @Override
-        public void bindView(View view, Context context, Cursor cursor) {
-            ImageView imageView = (ImageView) view.findViewById(R.id.favicon);
-    
-            String favicon = cursor.getString(3);
-            byte[] raw = Base64.decode(favicon.substring(22), Base64.DEFAULT);
-            Bitmap bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeByteArray(raw, 0, raw.length), 48, 48, true);
-            imageView.setImageBitmap(bitmap);
-
-            super.bindView(view, context, cursor);
-        }
-    }
-
-    private Cursor getCursor(Context context) {
-        File home = new File(context.getFilesDir(), "mozilla");
-        if (!home.exists())
-            return null;
-
-        File profile = null;
-        String[] files = home.list();
-        for (int i = 0; i < files.length; i++) {
-            if (files[i].endsWith(".default")) {
-                profile = new File(home, files[i]);
-                break;
-            }
-        }
-
-        if (profile == null)
-            return null;
-
-        File webapps = new File(profile, "webapps.sqlite");
-        if (!webapps.exists())
-            return null;
-
-        Log.i("LauncherShortcuts", "Opening: " + webapps.getPath());
-        mDb = SQLiteDatabase.openDatabase(webapps.getPath(), null, SQLiteDatabase.OPEN_READONLY | SQLiteDatabase.NO_LOCALIZED_COLLATORS);
-        return mDb.rawQuery("SELECT rowid as _id, title, uri, icon FROM webapps", null);
-    }
-    
-    private Cursor mCursor;
-    private SQLiteDatabase mDb;
+    private ArrayList <HashMap<String, String>> mWebappsList;
+    private File mWebappsFolder;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
         setContentView(R.layout.launch_app_list);
 
         final Intent intent = getIntent();
         final String action = intent.getAction();
 
         if (Intent.ACTION_CREATE_SHORTCUT.equals(action)) {
-            mCursor = getCursor(this);
-            if (mCursor != null) {
-                // After selecting an item, the empty view can flash on screen. Clear
-                // the text so we don't see it.
-                TextView emptyText = (TextView)findViewById(android.R.id.empty);
-                emptyText.setText("");
-
-                // Load the list using a custom adapter so we can create the bitmaps
-                ListAdapter adapter = new LauncherCursorAdapter(
-                    this,
-                    R.layout.launch_app_listitem,
-                    mCursor,
-                    new String[] {"title"},
-                    new int[] {R.id.title}
-                );
-                setListAdapter(adapter);
-            }
+            // Doing it as a background task, as it involves file access
+            new FetchWebApps().execute();
         }
     }
 
     @Override
     public void onListItemClick(ListView l, View v, int position, long id) {
-        mCursor.moveToPosition(position);
-
+        HashMap<String, String> map = mWebappsList.get((int) id);
+        
+        String uri = map.get("uri").toString();
+        String title = map.get("title").toString();
+        String appKey = map.get("appKey").toString();
+        String favicon = map.get("favicon").toString();
+        
+        File manifestFile = new File(mWebappsFolder, appKey + "/manifest.json");
+        
+        // Parse the contents into a string
+        String manifestJson = new String();
+        try {
+            BufferedReader in = new BufferedReader(new FileReader(manifestFile));
+            String line = new String();
+            
+            while ((line = in.readLine()) != null) {
+                manifestJson += line;
+            }
+        } catch (IOException e) { }
+        
+        try {
+            JSONObject manifest = (JSONObject) new JSONTokener(manifestJson).nextValue();
+            uri += manifest.getString("launch_path");
+        } catch (JSONException e) { }
+        
         Intent shortcutintent = new Intent("org.mozilla.gecko.WEBAPP");
         shortcutintent.setClass(this, App.class);
-        shortcutintent.putExtra("args", "--webapp=" + mCursor.getString(2));
+        shortcutintent.putExtra("args", "--webapp=" + uri);
 
         Intent intent = new Intent();
-        intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, mCursor.getString(1));
+        intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, title);
         intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutintent);
 
-        String favicon = mCursor.getString(3);
-        byte[] raw = Base64.decode(favicon.substring(22), Base64.DEFAULT);
-
         DisplayMetrics dm = new DisplayMetrics();
         getWindowManager().getDefaultDisplay().getMetrics(dm);
         int size;
         switch (dm.densityDpi) {
             case DisplayMetrics.DENSITY_MEDIUM:
                 size = 48;
                 break;
             case DisplayMetrics.DENSITY_HIGH:
                 size = 72;
                 break;
             default:
                 size = 72;
         }
 
-        Bitmap bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeByteArray(raw, 0, raw.length), size, size, true);
+        Bitmap bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeFile(favicon), size, size, true);
         intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, bitmap);
 
         // Now, return the result to the launcher
         setResult(RESULT_OK, intent);
-        mDb.close();
-        mCursor.close();
         finish();
     }
+    
+    private class FetchWebApps extends AsyncTask<Void, Void, Void> {
+        
+        @Override
+        protected Void doInBackground(Void... unused) {
+            mWebappsList = null;
+            
+            Context context = getApplicationContext();
+            
+            File home = new File(context.getFilesDir(), "mozilla");
+            if (!home.exists())
+                home = new File(context.getExternalFilesDir(null).getPath(), "mozilla");
+            
+            if (!home.exists())
+                return null;
+
+            File profile = null;
+            String[] files = home.list();
+            for (String file : files) {
+                if (file.endsWith(".default")) {
+                    profile = new File(home, file);
+                    break;
+                }
+            }
+
+            if (profile == null)
+                return null;
+
+            // Save the folder path to be used during click event
+            mWebappsFolder = new File(profile, "webapps");
+            if (!mWebappsFolder.exists())
+                return null;
+
+            File webapps = new File(mWebappsFolder, "webapps.json");
+            if (!webapps.exists())
+                return null;
+
+            // Parse the contents into a string
+            String webappsJson = new String();
+            try {
+                BufferedReader in = new BufferedReader(new FileReader(webapps));
+                String line = new String();
+                
+                while ((line = in.readLine()) != null) {
+                    webappsJson += line;
+                }
+            } catch (IOException e) { }
+
+            if (webappsJson.length() == 0)
+                return null;
+            
+            mWebappsList = new ArrayList<HashMap<String, String>>();
+
+            try {
+                JSONObject webApps = (JSONObject) new JSONTokener(webappsJson).nextValue();
+
+                Iterator<Object> appKeys = webApps.keys();
+                HashMap<String, String> map;
+
+                while (appKeys.hasNext()) {
+                    String appKey = appKeys.next().toString();
+                    JSONObject app = webApps.getJSONObject(appKey);
+                    
+                    map = new HashMap<String, String>();
+                    map.put("appKey", appKey);
+                    map.put("favicon", mWebappsFolder.getPath() + "/" + appKey + "/icon.png");
+                    map.put("title", app.getString("title"));
+                    map.put("uri", app.getString("appURI"));
+                    
+                    mWebappsList.add(map);
+                }
+                
+            } catch (JSONException e) {}
+            
+            return null;
+        }
+        
+        @Override
+        protected void onPostExecute(Void unused) {
+            if (mWebappsList != null) {
+                TextView emptyText = (TextView)findViewById(android.R.id.empty);
+                emptyText.setText("");
+
+                setListAdapter(new SimpleAdapter(
+                    LauncherShortcuts.this,
+                    mWebappsList,
+                    R.layout.launch_app_listitem,
+                    new String[] { "favicon", "title" },
+                    new int[] { R.id.favicon, R.id.title }
+                ));
+            }
+        }
+    }
 }