1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.launcher2;
18
19import android.content.BroadcastReceiver;
20import android.content.ContentResolver;
21import android.content.Context;
22import android.content.Intent;
23import android.content.SharedPreferences;
24import android.database.Cursor;
25import android.net.Uri;
26import android.widget.Toast;
27
28import com.android.launcher.R;
29
30import java.net.URISyntaxException;
31import java.util.ArrayList;
32import java.util.HashSet;
33import java.util.Iterator;
34import java.util.Set;
35
36public class UninstallShortcutReceiver extends BroadcastReceiver {
37    private static final String ACTION_UNINSTALL_SHORTCUT =
38            "com.android.launcher.action.UNINSTALL_SHORTCUT";
39
40    // The set of shortcuts that are pending uninstall
41    private static ArrayList<PendingUninstallShortcutInfo> mUninstallQueue =
42            new ArrayList<PendingUninstallShortcutInfo>();
43
44    // Determines whether to defer uninstalling shortcuts immediately until
45    // disableAndFlushUninstallQueue() is called.
46    private static boolean mUseUninstallQueue = false;
47
48    private static class PendingUninstallShortcutInfo {
49        Intent data;
50
51        public PendingUninstallShortcutInfo(Intent rawData) {
52            data = rawData;
53        }
54    }
55
56    public void onReceive(Context context, Intent data) {
57        if (!ACTION_UNINSTALL_SHORTCUT.equals(data.getAction())) {
58            return;
59        }
60
61        PendingUninstallShortcutInfo info = new PendingUninstallShortcutInfo(data);
62        if (mUseUninstallQueue) {
63            mUninstallQueue.add(info);
64        } else {
65            processUninstallShortcut(context, info);
66        }
67    }
68
69    static void enableUninstallQueue() {
70        mUseUninstallQueue = true;
71    }
72
73    static void disableAndFlushUninstallQueue(Context context) {
74        mUseUninstallQueue = false;
75        Iterator<PendingUninstallShortcutInfo> iter = mUninstallQueue.iterator();
76        while (iter.hasNext()) {
77            processUninstallShortcut(context, iter.next());
78            iter.remove();
79        }
80    }
81
82    private static void processUninstallShortcut(Context context,
83            PendingUninstallShortcutInfo pendingInfo) {
84        String spKey = LauncherApplication.getSharedPreferencesKey();
85        SharedPreferences sharedPrefs = context.getSharedPreferences(spKey, Context.MODE_PRIVATE);
86
87        final Intent data = pendingInfo.data;
88
89        LauncherApplication app = (LauncherApplication) context.getApplicationContext();
90        synchronized (app) {
91            removeShortcut(context, data, sharedPrefs);
92        }
93    }
94
95    private static void removeShortcut(Context context, Intent data,
96            final SharedPreferences sharedPrefs) {
97        Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
98        String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
99        boolean duplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true);
100
101        if (intent != null && name != null) {
102            final ContentResolver cr = context.getContentResolver();
103            Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI,
104                new String[] { LauncherSettings.Favorites._ID, LauncherSettings.Favorites.INTENT },
105                LauncherSettings.Favorites.TITLE + "=?", new String[] { name }, null);
106
107            final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
108            final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
109
110            boolean changed = false;
111
112            try {
113                while (c.moveToNext()) {
114                    try {
115                        if (intent.filterEquals(Intent.parseUri(c.getString(intentIndex), 0))) {
116                            final long id = c.getLong(idIndex);
117                            final Uri uri = LauncherSettings.Favorites.getContentUri(id, false);
118                            cr.delete(uri, null, null);
119                            changed = true;
120                            if (!duplicate) {
121                                break;
122                            }
123                        }
124                    } catch (URISyntaxException e) {
125                        // Ignore
126                    }
127                }
128            } finally {
129                c.close();
130            }
131
132            if (changed) {
133                cr.notifyChange(LauncherSettings.Favorites.CONTENT_URI, null);
134                Toast.makeText(context, context.getString(R.string.shortcut_uninstalled, name),
135                        Toast.LENGTH_SHORT).show();
136            }
137
138            // Remove any items due to be animated
139            boolean appRemoved;
140            Set<String> newApps = new HashSet<String>();
141            newApps = sharedPrefs.getStringSet(InstallShortcutReceiver.NEW_APPS_LIST_KEY, newApps);
142            synchronized (newApps) {
143                do {
144                    appRemoved = newApps.remove(intent.toUri(0).toString());
145                } while (appRemoved);
146            }
147            if (appRemoved) {
148                final Set<String> savedNewApps = newApps;
149                new Thread("setNewAppsThread-remove") {
150                    public void run() {
151                        synchronized (savedNewApps) {
152                            SharedPreferences.Editor editor = sharedPrefs.edit();
153                            editor.putStringSet(InstallShortcutReceiver.NEW_APPS_LIST_KEY,
154                                    savedNewApps);
155                            if (savedNewApps.isEmpty()) {
156                                // Reset the page index if there are no more items
157                                editor.putInt(InstallShortcutReceiver.NEW_APPS_PAGE_KEY, -1);
158                            }
159                            editor.commit();
160                        }
161                    }
162                }.start();
163            }
164        }
165    }
166}
167