Bug 760708 - Add ability to remove homescreen shortcuts. r=mfinkle
authorWes Johnston <wjohnston@mozilla.com>
Wed, 06 Jun 2012 13:52:14 -0700
changeset 96015 762be48017394066b64bc4d56ece5cf00653db7b
parent 96014 5f12b1053019ebba1e8be45ce6e93e59ab49b18b
child 96016 eb7306640e5f3b292ce07e8fec1a7dda518455d5
push id22869
push useremorley@mozilla.com
push dateThu, 07 Jun 2012 09:35:19 +0000
treeherdermozilla-central@3933384d8315 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmfinkle
bugs760708
milestone16.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 760708 - Add ability to remove homescreen shortcuts. r=mfinkle
mobile/android/base/AndroidManifest.xml.in
mobile/android/base/GeckoApp.java
mobile/android/base/GeckoAppShell.java
mobile/android/chrome/content/browser.js
--- a/mobile/android/base/AndroidManifest.xml.in
+++ b/mobile/android/base/AndroidManifest.xml.in
@@ -14,16 +14,17 @@
 
 #include ../sync/manifests/SyncAndroidManifest_permissions.xml.in
 
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
     <uses-permission android:name="android.permission.INTERNET"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
     <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
+    <uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"/>
 
     <uses-permission android:name="android.permission.WAKE_LOCK"/>
     <uses-permission android:name="android.permission.VIBRATE"/>
     <uses-permission android:name="@ANDROID_PACKAGE_NAME@.permissions.PASSWORD_PROVIDER"/>
 
 #ifdef MOZ_WEBSMS_BACKEND
     <!-- WebSMS -->
     <uses-permission android:name="android.permission.SEND_SMS"/>
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -1267,16 +1267,21 @@ abstract public class GeckoApp
                             ret.put("exploreByTouch", false);
                         } catch (Exception ex) {
                             Log.e(LOGTAG, "Error building JSON arguments for Accessibility:Ready:", ex);
                         }
                         GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Accessibility:Settings",
                                                                                        ret.toString()));
                     }
                 });
+            } else if (event.equals("Shortcut:Remove")) {
+                final String url = message.getString("url");
+                final String title = message.getString("title");
+                final String title = message.getString("shortcutType");
+                GeckoAppShell.removeShortcut(title, url, type);
             }
         } catch (Exception e) {
             Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
         }
     }
 
     public void showAboutHome() {
         Runnable r = new AboutHomeRunnable(true);
@@ -2003,16 +2008,17 @@ abstract public class GeckoApp
         GeckoAppShell.registerGeckoEventListener("CharEncoding:State", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Update:Restart", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Tab:HasTouchListener", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Tab:ViewportMetadata", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Session:StatePurged", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Bookmark:Insert", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Accessibility:Event", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Accessibility:Ready", GeckoApp.mAppContext);
+        GeckoAppShell.registerGeckoEventListener("Shortcut:Remove", GeckoApp.mAppContext);
 
         if (SmsManager.getInstance() != null) {
           SmsManager.getInstance().start();
         }
 
         mBatteryReceiver = new GeckoBatteryManager();
         mBatteryReceiver.registerFor(mAppContext);
 
@@ -2336,16 +2342,17 @@ abstract public class GeckoApp
         GeckoAppShell.unregisterGeckoEventListener("Permissions:Data", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("CharEncoding:Data", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("CharEncoding:State", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Tab:HasTouchListener", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Session:StatePurged", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Bookmark:Insert", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Accessibility:Event", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Accessibility:Ready", GeckoApp.mAppContext);
+        GeckoAppShell.unregisterGeckoEventListener("Shortcut:Remove", GeckoApp.mAppContext);
 
         if (mFavicons != null)
             mFavicons.close();
 
         if (SmsManager.getInstance() != null) {
             SmsManager.getInstance().stop();
             if (isFinishing())
                 SmsManager.getInstance().shutdown();
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -803,16 +803,45 @@ public class GeckoAppShell
                 intent.putExtra("duplicate", false);
 
                 intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
                 GeckoApp.mAppContext.sendBroadcast(intent);
             }
         });
     }
 
+    public static void removeShortcut(final String aTitle, final String aURI, final String aType) {
+        getHandler().post(new Runnable() {
+            public void run() {
+                Log.w(LOGTAG, "removeShortcut for " + aURI + " [" + aTitle + "] > " + aType);
+        
+                // the intent to be launched by the shortcut
+                Intent shortcutIntent = new Intent();
+                if (aType.equalsIgnoreCase(SHORTCUT_TYPE_WEBAPP)) {
+                    shortcutIntent.setAction(GeckoApp.ACTION_WEBAPP);
+                } else {
+                    shortcutIntent.setAction(GeckoApp.ACTION_BOOKMARK);
+                }
+                shortcutIntent.setData(Uri.parse(aURI));
+                shortcutIntent.setClassName(GeckoApp.mAppContext,
+                                            GeckoApp.mAppContext.getPackageName() + ".App");
+        
+                Intent intent = new Intent();
+                intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
+                if (aTitle != null)
+                    intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, aTitle);
+                else
+                    intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, aURI);
+
+                intent.setAction("com.android.launcher.action.UNINSTALL_SHORTCUT");
+                GeckoApp.mAppContext.sendBroadcast(intent);
+            }
+        });
+    }
+
     static private Bitmap getLauncherIcon(Bitmap aSource, String aType) {
         final int kOffset = 6;
         final int kRadius = 5;
         int kIconSize;
         int kOverlaySize;
         switch (getDpi()) {
             case DisplayMetrics.DENSITY_MEDIUM:
                 kIconSize = 48;
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -5156,27 +5156,27 @@ var WebappsUI = {
   observe: function observe(aSubject, aTopic, aData) {
     let data = JSON.parse(aData);
     switch (aTopic) {
       case "webapps-ask-install":
         this.doInstall(data);
         break;
       case "webapps-launch":
         DOMApplicationRegistry.getManifestFor(data.origin, (function(aManifest) {
-	   if (!aManifest)
-	     return;
+          if (!aManifest)
+            return;
           let manifest = new DOMApplicationManifest(aManifest, data.origin);
           this.openURL(manifest.fullLaunchPath(), data.origin);
         }).bind(this));
         break;
       case "webapps-sync-install":
         // Wait until we know the app install worked, then make a homescreen shortcut
         DOMApplicationRegistry.getManifestFor(data.origin, (function(aManifest) {
-	   if (!aManifest)
-	     return;
+          if (!aManifest)
+            return;
           let manifest = new DOMApplicationManifest(aManifest, data.origin);
 
           // Add a homescreen shortcut
           this.createShortcut(manifest.name, manifest.fullLaunchPath(), manifest.iconURLForSize("64"), "webapp");
 
           // Create a system notification allowing the user to launch the app
           let observer = {
             observe: function (aSubject, aTopic) {