OSDN Git Service

Implement a dialog that warns the user that we must expose the content of the file
authorMartin Brabham <optedoblivion@cyngn.com>
Wed, 15 Apr 2015 22:33:25 +0000 (15:33 -0700)
committerMatt Garnes <matt@cyngn.com>
Fri, 17 Apr 2015 01:32:33 +0000 (01:32 +0000)
by copying it out to an unsecure location in order to allow the external applications
to read the files.

Change-Id: I163ccd21678f413170e44cf3e8d341cd4747b1ac
(cherry picked from commit 58928e7facbdd63d4320748b277e94417fe402bb)

14 files changed:
AndroidManifest.xml
res/values/strings.xml
src/com/cyanogenmod/filemanager/FileManagerApplication.java
src/com/cyanogenmod/filemanager/activities/NavigationActivity.java
src/com/cyanogenmod/filemanager/activities/SearchActivity.java
src/com/cyanogenmod/filemanager/listeners/OnRequestRefreshListener.java
src/com/cyanogenmod/filemanager/providers/secure/ISecureChoiceCompleteListener.java [new file with mode: 0644]
src/com/cyanogenmod/filemanager/providers/secure/SecureCacheCleanupService.java [new file with mode: 0644]
src/com/cyanogenmod/filemanager/providers/secure/SecureChoiceClickListener.java [new file with mode: 0644]
src/com/cyanogenmod/filemanager/providers/secure/SecureChoiceRefreshListener.java [new file with mode: 0644]
src/com/cyanogenmod/filemanager/providers/secure/SecureChoiceSelectionListener.java [new file with mode: 0644]
src/com/cyanogenmod/filemanager/ui/policy/CopyMoveActionPolicy.java
src/com/cyanogenmod/filemanager/ui/policy/IntentsActionPolicy.java
src/com/cyanogenmod/filemanager/ui/widgets/NavigationView.java

index ba672a0..c5c5d6b 100644 (file)
@@ -31,6 +31,7 @@
   <uses-permission android:name="android.permission.ACCESS_SUPERUSER"/>
   <uses-permission android:name="android.permission.NFC"/>
   <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
+  <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
   <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
   <uses-permission android:name="com.cyanogenmod.filemanager.permissions.READ_THEME"/>
 
         <action android:name="android.intent.action.VIEW" />
       </intent-filter>
     </activity>
+    <service android:name=".providers.secure.SecureCacheCleanupService">
+      <intent-filter>
+        <action android:name="android.intent.action.BOOT_COMPLETED" />
+        <action android:name="android.intent.action.QUICKBOOT_POWERON" />
+        <action android:name="com.cyanogenmod.filemanager.ACTION_START_CLEANUP"/>
+      </intent-filter>
+    </service>
 
   </application>
 
index 0fe06ac..b1601bc 100644 (file)
     <string name="secure_storage_unlock_validation_length">Password must have at least <xliff:g id="characters">%1$d</xliff:g> characters.</string>
     <!-- Secure Storage unlock validation, equal -->
     <string name="secure_storage_unlock_validation_equals">Passwords do not match.</string>
+    <!-- Secure storage open file warning -->
+    <string name="secure_storage_open_file_warning">This will copy the file out to a temporary
+        unencrypted location.  This will be cleared after 1 hour.</string>
+
 
     <!-- Print messages -->
     <!-- Unsupported document format -->
     <string name="welcome_msg">Welcome to the CyanogenMod file manager.\n\nThis app allows you to explore the file system and do operations that could break your device. To prevent damage, the app will start in a safe, low-privileged mode.\n\nYou can access the advanced, full-privileged mode via Settings. It\'s your responsibility to ensure that an operation doesn\'t break your system.\n\nThe CyanogenMod Team</string>
 
     <string name="activity_not_found_exception">Couldn\'t find an app to open this file</string>
+
 </resources>
index 3855c04..20a7073 100644 (file)
@@ -35,6 +35,7 @@ import com.cyanogenmod.filemanager.preferences.AccessMode;
 import com.cyanogenmod.filemanager.preferences.FileManagerSettings;
 import com.cyanogenmod.filemanager.preferences.ObjectStringIdentifier;
 import com.cyanogenmod.filemanager.preferences.Preferences;
+import com.cyanogenmod.filemanager.providers.secure.SecureCacheCleanupService;
 import com.cyanogenmod.filemanager.service.MimeTypeIndexService;
 import com.cyanogenmod.filemanager.ui.ThemeManager;
 import com.cyanogenmod.filemanager.ui.ThemeManager.Theme;
@@ -183,6 +184,9 @@ public final class FileManagerApplication extends Application {
         MimeTypeIndexService.indexFileRoot(this, externalStorage.getAbsolutePath());
         MimeTypeIndexService.indexFileRoot(this, Environment.getRootDirectory().getAbsolutePath());
 
+        // Schedule in case not scheduled (i.e. never booted with this app on device
+        SecureCacheCleanupService.scheduleCleanup(getApplicationContext());
+
     }
 
     /**
index 1f4946a..454e8f0 100644 (file)
@@ -1949,6 +1949,11 @@ public class NavigationActivity extends Activity
         // Ignored
     }
 
+    @Override
+    public void onCancel(){
+        // nop
+    }
+
     /**
      * {@inheritDoc}
      */
index 66218bc..4aa8697 100644 (file)
@@ -1213,6 +1213,11 @@ public class SearchActivity extends Activity
         }
     }
 
+    @Override
+    public void onCancel() {
+        // nop
+    }
+
     /**
      * Method that returns to previous activity.
      *
index 817bdff..da307c3 100644 (file)
@@ -48,4 +48,9 @@ public interface OnRequestRefreshListener {
      * @param o The object where to navigate to
      */
     void onNavigateTo(Object o);
+
+    /**
+     * Invoked on action cancel
+     */
+    void onCancel();
 }
diff --git a/src/com/cyanogenmod/filemanager/providers/secure/ISecureChoiceCompleteListener.java b/src/com/cyanogenmod/filemanager/providers/secure/ISecureChoiceCompleteListener.java
new file mode 100644 (file)
index 0000000..b0aea03
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+* Copyright (C) 2015 The CyanogenMod Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.cyanogenmod.filemanager.providers.secure;
+
+import java.io.File;
+
+/**
+ * ISecureChoiceCompleteListener
+ * <pre>
+ *     This interface is to notify the caller
+ *     in this case
+ *     {@link com.cyanogenmod.filemanager.ui.policy.IntentsActionPolicy}
+ *     that the operation is complete
+ * </pre>
+ */
+public interface ISecureChoiceCompleteListener {
+    public void onComplete(File cacheFile);
+    public void onCancelled();
+}
diff --git a/src/com/cyanogenmod/filemanager/providers/secure/SecureCacheCleanupService.java b/src/com/cyanogenmod/filemanager/providers/secure/SecureCacheCleanupService.java
new file mode 100644 (file)
index 0000000..6accb43
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+* Copyright (C) 2015 The CyanogenMod Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.cyanogenmod.filemanager.providers.secure;
+
+import android.app.AlarmManager;
+import android.app.IntentService;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import com.cyanogenmod.filemanager.model.FileSystemObject;
+import com.cyanogenmod.filemanager.util.FileHelper;
+
+import java.io.File;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * SecureCacheCleanupService
+ * <pre>
+ *    Service that cleans up cache
+ * </pre>
+ *
+ * @see {@link android.app.IntentService}
+ */
+public class SecureCacheCleanupService extends IntentService {
+
+    // Constants
+    private static final String ACTION_START = "com.cyanogenmod.filemanager.ACTION_START_CLEANUP";
+    private static final String NAME = "cleanup-service";
+
+    /**
+     * Creates an IntentService.  Invoked by your subclass's constructor.
+     */
+    public SecureCacheCleanupService() {
+        super(NAME);
+    }
+
+    @Override
+    protected void onHandleIntent(Intent intent) {
+        String action = intent.getAction();
+        if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
+            scheduleCleanup(this);
+        } else if (ACTION_START.equals(action)) {
+            cleanupOperation();
+        }
+    }
+
+    private void cleanupOperation() {
+        File cacheDir = new File(getExternalCacheDir(), SecureChoiceClickListener.CACHE_DIR);
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTimeInMillis(System.currentTimeMillis());
+        calendar.add(Calendar.HOUR, -1);
+        Date cutoff = calendar.getTime();
+
+        if (!cacheDir.exists()) {
+            return;
+        }
+
+        // Get list of files
+        File[] files = cacheDir.listFiles();
+
+        if (files == null) {
+            return;
+        }
+
+        // Delete all, won't run if list is empty
+        for (File file : files) {
+            FileSystemObject fso = FileHelper.createFileSystemObject(file);
+            Date lastAccessDate = fso.getLastAccessedTime();
+            if (lastAccessDate.before(cutoff)) {
+                file.delete();
+            }
+        }
+
+        // Check again after deletion
+        files = cacheDir.listFiles();
+
+        // If no files, cancel alarm
+        if (files == null || files.length < 1) {
+            cancelAlarm(this);
+        }
+
+    }
+
+    /**
+     * Schedule a cleanup alarm
+     *
+     * @param context {@link android.content.Context}
+     *
+     * @throws IllegalArgumentException {@link java.lang.IllegalArgumentException}
+     */
+    public static void scheduleCleanup(Context context) throws IllegalArgumentException {
+        if (context == null) {
+            throw new IllegalArgumentException("'context' cannot be null!");
+        }
+        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+        Intent intent = new Intent(context, SecureCacheCleanupService.class);
+        intent.setAction(ACTION_START);
+        PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
+        alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, 1000,
+                AlarmManager.INTERVAL_HOUR, pendingIntent);
+    }
+
+    /**
+     * Cancel a cleanup alarm
+     *
+     * @param context {@link android.content.Context}
+     *
+     * @throws IllegalArgumentException {@link java.lang.IllegalArgumentException}
+     */
+    public static void cancelAlarm(Context context) throws IllegalArgumentException {
+        if (context == null) {
+            throw new IllegalArgumentException("'context' cannot be null!");
+        }
+        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+        Intent intent = new Intent(context, SecureCacheCleanupService.class);
+        intent.setAction(ACTION_START);
+        PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
+        alarmManager.cancel(pendingIntent);
+    }
+}
diff --git a/src/com/cyanogenmod/filemanager/providers/secure/SecureChoiceClickListener.java b/src/com/cyanogenmod/filemanager/providers/secure/SecureChoiceClickListener.java
new file mode 100644 (file)
index 0000000..3e20b99
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+* Copyright (C) 2015 The CyanogenMod Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.cyanogenmod.filemanager.providers.secure;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import com.cyanogenmod.filemanager.model.FileSystemObject;
+import com.cyanogenmod.filemanager.ui.policy.CopyMoveActionPolicy;
+import com.cyanogenmod.filemanager.ui.policy.CopyMoveActionPolicy.LinkedResource;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * SecureChoiceClickListener
+ * <pre>
+ *    This listens for the secure choice user selection
+ * </pre>
+ *
+ * @see {@link android.content.DialogInterface.OnClickListener}
+ */
+public class SecureChoiceClickListener implements DialogInterface.OnClickListener {
+
+    // Constants
+    /* package */ static final String CACHE_DIR = ".opened-files";
+
+    // Members
+    private Context mContext;
+    private FileSystemObject mFso;
+    private ISecureChoiceCompleteListener mListener;
+
+    /**
+     * Constructor
+     *
+     * @param context {@link android.content.Context}
+     * @param fso {@link com.cyanogenmod.filemanager.model.FileSystemObject}
+     *
+     * @throws IllegalArgumentException {@link java.lang.IllegalArgumentException}
+     */
+    public SecureChoiceClickListener(Context context, FileSystemObject fso,
+            ISecureChoiceCompleteListener listener) throws IllegalArgumentException {
+        if (context == null) {
+            throw new IllegalArgumentException("'context' cannot be null!");
+        }
+        if (fso == null) {
+            throw new IllegalArgumentException("'fso' cannot be null!");
+        }
+        if (listener == null) {
+            throw new IllegalArgumentException("'listener' cannot be null!");
+        }
+        mContext = context;
+        mFso = fso;
+        mListener = listener;
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        switch (which) {
+            case AlertDialog.BUTTON_POSITIVE:
+                performUserFlow();
+                break;
+            default:
+                break;
+        }
+    }
+
+    private void performUserFlow() {
+        List<LinkedResource> selection = new ArrayList<LinkedResource>();
+        File hiddenCacheDirectory = new File(mContext.getExternalCacheDir(), CACHE_DIR);
+        // Check if the hidden directory exists
+        if (!hiddenCacheDirectory.exists()) {
+            hiddenCacheDirectory.mkdirs();
+        }
+        final File tmpFso = new File(hiddenCacheDirectory, mFso.getName());
+        selection.add(new LinkedResource(new File(mFso.getFullPath()), tmpFso));
+        CopyMoveActionPolicy.copyFileSystemObjects(mContext, selection,
+                new SecureChoiceSelectionListener(tmpFso),
+                new SecureChoiceRefreshListener(tmpFso, mListener));
+
+    }
+}
diff --git a/src/com/cyanogenmod/filemanager/providers/secure/SecureChoiceRefreshListener.java b/src/com/cyanogenmod/filemanager/providers/secure/SecureChoiceRefreshListener.java
new file mode 100644 (file)
index 0000000..cf0e21c
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+* Copyright (C) 2015 The CyanogenMod Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.cyanogenmod.filemanager.providers.secure;
+
+import com.cyanogenmod.filemanager.listeners.OnRequestRefreshListener;
+
+import java.io.File;
+
+/**
+ * SecureChoiceRefreshListener
+ * <pre>
+ *    This is just a chained callback
+ * </pre>
+ *
+ * @see {@link com.cyanogenmod.filemanager.listeners.OnRequestRefreshListener}
+ */
+/* package */ class SecureChoiceRefreshListener implements OnRequestRefreshListener {
+
+    // Members
+    private File mCacheFile;
+    private ISecureChoiceCompleteListener mListener;
+
+    /**
+     * Constructor
+     *
+     * @param listener
+     * {@link com.cyanogenmod.filemanager.providers.secure.ISecureChoiceCompleteListener}
+     *
+     * @throws IllegalArgumentException {@link java.lang.IllegalArgumentException}
+     */
+    public SecureChoiceRefreshListener(File cacheFile, ISecureChoiceCompleteListener listener)
+            throws IllegalArgumentException {
+        if (cacheFile == null) {
+            throw new IllegalArgumentException("'cacheFile' cannot be null!");
+        }
+        if (listener == null) {
+            throw new IllegalArgumentException("'listener' cannot be null!");
+        }
+        mCacheFile = cacheFile;
+        mListener = listener;
+    }
+
+    @Override
+    public void onRequestRefresh(Object o, boolean clearSelection) {
+        mListener.onComplete(mCacheFile);
+    }
+
+    @Override
+    public void onRequestBookmarksRefresh() {
+
+    }
+
+    @Override
+    public void onRequestRemove(Object o, boolean clearSelection) {
+
+    }
+
+    @Override
+    public void onNavigateTo(Object o) {
+
+    }
+
+    @Override
+    public void onCancel() {
+        mListener.onCancelled();
+    }
+}
diff --git a/src/com/cyanogenmod/filemanager/providers/secure/SecureChoiceSelectionListener.java b/src/com/cyanogenmod/filemanager/providers/secure/SecureChoiceSelectionListener.java
new file mode 100644 (file)
index 0000000..7e8b255
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+* Copyright (C) 2015 The CyanogenMod Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.cyanogenmod.filemanager.providers.secure;
+
+import com.cyanogenmod.filemanager.listeners.OnSelectionListener;
+import com.cyanogenmod.filemanager.model.FileSystemObject;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * SecureChoiceSelectionListener
+ * <pre>
+ *     This is something that the copy/move pipeline needs in order to
+ *     pass a conditional check in {@link com.cyanogenmod.filemanager.ui.policy
+ *     .CopyMoveActionPolicy}
+ * </pre>
+ *
+ * @see {@link com.cyanogenmod.filemanager.listeners.OnSelectionListener}
+ */
+/* package */ class SecureChoiceSelectionListener implements OnSelectionListener {
+
+    // Members
+    private File mFile;
+
+    /**
+     * Constructor
+     *
+     * @param fso {@link java.io.File}
+     * @throws IllegalArgumentException {@link java.lang.IllegalArgumentException}
+     */
+    public SecureChoiceSelectionListener(File fso) throws IllegalArgumentException {
+        if (fso == null) {
+            throw new IllegalArgumentException("'fso' cannot be null!");
+        }
+        mFile = fso;
+    }
+
+    @Override
+    public void onToggleSelection(FileSystemObject fso) {
+
+    }
+
+    @Override
+    public void onDeselectAll() {
+
+    }
+
+    @Override
+    public void onSelectAllVisibleItems() {
+
+    }
+
+    @Override
+    public void onDeselectAllVisibleItems() {
+
+    }
+
+    @Override
+    public List<FileSystemObject> onRequestSelectedFiles() {
+        return null;
+    }
+
+    @Override
+    public List<FileSystemObject> onRequestCurrentItems() {
+        return null;
+    }
+
+    @Override
+    public String onRequestCurrentDir() {
+        return mFile.getParent();
+    }
+
+}
index c2dde32..c8f6139 100644 (file)
@@ -19,12 +19,10 @@ package com.cyanogenmod.filemanager.ui.policy;
 import android.app.AlertDialog;
 import android.content.Context;
 import android.content.DialogInterface;
-import android.content.DialogInterface.OnCancelListener;
 import android.text.Html;
 import android.text.Spanned;
 
 import com.cyanogenmod.filemanager.R;
-import com.cyanogenmod.filemanager.console.CancelledOperationException;
 import com.cyanogenmod.filemanager.console.Console;
 import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory;
 import com.cyanogenmod.filemanager.console.RelaunchableException;
@@ -356,6 +354,9 @@ public final class CopyMoveActionPolicy extends ActionsPolicy {
                 if (mDstConsole != null) {
                     mDstConsole.onCancel();
                 }
+                if (mOnRequestRefreshListener != null) {
+                    mOnRequestRefreshListener.onCancel();
+                }
                 refreshUIAfterCompletion();
             }
 
index 5dcab23..aeeb4c9 100644 (file)
@@ -17,7 +17,6 @@
 package com.cyanogenmod.filemanager.ui.policy;
 
 import android.content.ComponentName;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.DialogInterface.OnCancelListener;
 import android.content.DialogInterface.OnDismissListener;
@@ -30,7 +29,6 @@ import android.os.Bundle;
 import android.provider.MediaStore;
 import android.util.Log;
 import android.widget.Toast;
-
 import com.cyanogenmod.filemanager.R;
 import com.cyanogenmod.filemanager.activities.ShortcutActivity;
 import com.cyanogenmod.filemanager.console.secure.SecureConsole;
@@ -38,6 +36,9 @@ import com.cyanogenmod.filemanager.model.FileSystemObject;
 import com.cyanogenmod.filemanager.model.RegularFile;
 import com.cyanogenmod.filemanager.providers.SecureResourceProvider;
 import com.cyanogenmod.filemanager.providers.SecureResourceProvider.AuthorizationResource;
+import com.cyanogenmod.filemanager.providers.secure.ISecureChoiceCompleteListener;
+import com.cyanogenmod.filemanager.providers.secure.SecureCacheCleanupService;
+import com.cyanogenmod.filemanager.providers.secure.SecureChoiceClickListener;
 import com.cyanogenmod.filemanager.ui.dialogs.AssociationsDialog;
 import com.cyanogenmod.filemanager.util.DialogHelper;
 import com.cyanogenmod.filemanager.util.ExceptionUtil;
@@ -100,12 +101,69 @@ public final class IntentsActionPolicy extends ActionsPolicy {
      */
     public static void openFileSystemObject(
             final Context ctx, final FileSystemObject fso, final boolean choose,
-            OnCancelListener onCancelListener, OnDismissListener onDismissListener) {
+            final OnCancelListener onCancelListener, final OnDismissListener onDismissListener) {
         try {
             // Create the intent to open the file
-            Intent intent = new Intent();
+            final Intent intent = new Intent();
             intent.setAction(android.content.Intent.ACTION_VIEW);
 
+            // [NOTE][MSB]: Short circuit to pop up dialog informing user we need to copy out the
+            // file until we find a better solution.
+            if (fso.isSecure()) {
+                // [TODO][MSB]: Check visible cache for existing file but I need to split up
+                // resolveIntent function properly for this to be successful
+                DialogHelper.createTwoButtonsQuestionDialog(
+                        ctx,
+                        R.string.ok,
+                        R.string.cancel,
+                        R.string.warning_title,
+                        ctx.getResources().getString(R.string.secure_storage_open_file_warning),
+                        new SecureChoiceClickListener(ctx, fso,
+                                new ISecureChoiceCompleteListener() {
+                                    private boolean isCancelled = false;
+                                    @Override
+                                    public void onComplete(File cacheFile) {
+                                        if (isCancelled) {
+                                            return;
+                                        }
+                                        // Schedule cleanup alarm
+                                        SecureCacheCleanupService.scheduleCleanup(ctx);
+
+                                        FileSystemObject cacheFso = FileHelper
+                                                .createFileSystemObject(cacheFile);
+                                        // Obtain the mime/type and passed it to intent
+                                        String mime = MimeTypeHelper.getMimeType(ctx, cacheFso);
+                                        if (mime != null) {
+                                            intent.setDataAndType(getUriFromFile(ctx, cacheFso),
+                                                    mime);
+                                        } else {
+                                            intent.setData(getUriFromFile(ctx, cacheFso));
+                                        }
+                                        // Resolve the intent
+                                        resolveIntent(
+                                                ctx,
+                                                intent,
+                                                choose,
+                                                createInternalIntents(ctx, cacheFso),
+                                                0,
+                                                R.string.associations_dialog_openwith_title,
+                                                R.string.associations_dialog_openwith_action,
+                                                true,
+                                                onCancelListener,
+                                                onDismissListener);
+                                    }
+
+                                    @Override
+                                    public void onCancelled() {
+                                        isCancelled = true;
+                                        Toast.makeText(ctx, R.string.cancelled_message, Toast
+                                                .LENGTH_SHORT).show();
+                                    }
+                                }))
+                        .show();
+                return;
+            }
+
             // Obtain the mime/type and passed it to intent
             String mime = MimeTypeHelper.getMimeType(ctx, fso);
             if (mime != null) {
@@ -119,7 +177,7 @@ public final class IntentsActionPolicy extends ActionsPolicy {
                     ctx,
                     intent,
                     choose,
-                    createInternalIntents(ctx,  fso),
+                    createInternalIntents(ctx, fso),
                     0,
                     R.string.associations_dialog_openwith_title,
                     R.string.associations_dialog_openwith_action,
index 099f0ed..4f02b5d 100644 (file)
@@ -1266,6 +1266,11 @@ BreadcrumbListener, OnSelectionChangedListener, OnSelectionListener, OnRequestRe
         // Ignored
     }
 
+    @Override
+    public void onCancel() {
+        // nop
+    }
+
     /**
      * {@inheritDoc}
      */