diff options
author | Jorge Ruesga <jorge@ruesga.com> | 2014-03-20 05:05:56 +0100 |
---|---|---|
committer | Jorge Ruesga <jorge@ruesga.com> | 2014-03-20 05:11:17 +0100 |
commit | f722214dff88bcc427e8a2a20790ff3543314947 (patch) | |
tree | 5af69514d83b0450aa02b0c2af08dc0dedf6e3c0 | |
parent | b6d3b71bf15e3778f8c76dab2c78be1a89683624 (diff) | |
download | android_packages_apps_CMFileManager-f722214dff88bcc427e8a2a20790ff3543314947.tar.gz android_packages_apps_CMFileManager-f722214dff88bcc427e8a2a20790ff3543314947.tar.bz2 android_packages_apps_CMFileManager-f722214dff88bcc427e8a2a20790ff3543314947.zip |
CMFM: Allow restrict access to secondary users
Change-Id: I1bffbb32a5f02ab4ca5cdcdbc21d40c7bb299933
JIRA: CYAN-1630
Issue: https://jira.cyanogenmod.org/browse/CYAN-1630
Signed-off-by: Jorge Ruesga <jorge@ruesga.com>
9 files changed, 242 insertions, 4 deletions
diff --git a/res/values/strings.xml b/res/values/strings.xml index 77fea1ef..f23d5198 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -645,6 +645,10 @@ <string name="pref_access_mode_root">Root Access mode</string> <!-- Preferences - General - Root access mode summary --> <string name="pref_access_mode_root_summary">Root Access mode\n\nWarning! This mode allows operations that could break your device. It\'s your responsibility to ensure that an operation is safe</string> + <!-- Preferences - General - Restrict secondary users access title --> + <string name="pref_restrict_secondary_users_access_title">Restrict users access</string> + <!-- Preferences - General - Restrict secondary users access summary --> + <string name="pref_restrict_secondary_users_access_summary">Restrict access to the whole system to secondary users</string> <!-- Preferences - Search - Results category --> <string name="pref_search_results_category">Results</string> <!-- Preferences - Search - Show relevance widget --> diff --git a/res/xml/preferences_general.xml b/res/xml/preferences_general.xml index 2bfbf09c..07316ea5 100644 --- a/res/xml/preferences_general.xml +++ b/res/xml/preferences_general.xml @@ -88,6 +88,14 @@ android:defaultValue="0" android:persistent="true" /> + <!-- Restrict secondary users access --> + <CheckBoxPreference + android:key="cm_filemanager_restrict_secondary_users_access" + android:title="@string/pref_restrict_secondary_users_access_title" + android:summary="@string/pref_restrict_secondary_users_access_summary" + android:persistent="false" + android:defaultValue="false" /> + <!-- Capture debug traces --> <CheckBoxPreference android:key="cm_filemanager_show_debug_traces" diff --git a/src/com/cyanogenmod/filemanager/FileManagerApplication.java b/src/com/cyanogenmod/filemanager/FileManagerApplication.java index 2aba2941..be475dff 100644 --- a/src/com/cyanogenmod/filemanager/FileManagerApplication.java +++ b/src/com/cyanogenmod/filemanager/FileManagerApplication.java @@ -36,6 +36,7 @@ import com.cyanogenmod.filemanager.preferences.Preferences; import com.cyanogenmod.filemanager.ui.ThemeManager; import com.cyanogenmod.filemanager.ui.ThemeManager.Theme; import com.cyanogenmod.filemanager.util.AIDHelper; +import com.cyanogenmod.filemanager.util.AndroidHelper; import com.cyanogenmod.filemanager.util.MimeTypeHelper; import java.io.File; @@ -438,6 +439,41 @@ public final class FileManagerApplication extends Application { return mode; } + public static boolean isRestrictSecondaryUsersAccess(Context context) { + String value = Preferences.getWorldReadableProperties( + context, FileManagerSettings.SETTINGS_RESTRICT_SECONDARY_USERS_ACCESS.getId()); + if (value == null) { + value = String.valueOf(FileManagerSettings.SETTINGS_RESTRICT_SECONDARY_USERS_ACCESS. + getDefaultValue()); + } + return Boolean.parseBoolean(value); + } + + public static boolean checkRestrictSecondaryUsersAccess(Context context, boolean isChroot) { + if (!AndroidHelper.isSecondaryUser(context)) { + return true; + } + boolean needChroot = !isChroot && isRestrictSecondaryUsersAccess(context); + if (!needChroot) { + return true; + } + + try { + Preferences.savePreference( + FileManagerSettings.SETTINGS_ACCESS_MODE, AccessMode.SAFE, true); + } catch (Throwable ex) { + Log.w(TAG, "can't save console preference", ex); //$NON-NLS-1$ + } + ConsoleBuilder.changeToNonPrivilegedConsole(context); + + // Notify the change + Intent intent = new Intent(FileManagerSettings.INTENT_SETTING_CHANGED); + intent.putExtra(FileManagerSettings.EXTRA_SETTING_CHANGED_KEY, + FileManagerSettings.SETTINGS_ACCESS_MODE.getId()); + context.sendBroadcast(intent); + return false; + } + /** * Method that reads the system properties */ diff --git a/src/com/cyanogenmod/filemanager/activities/NavigationActivity.java b/src/com/cyanogenmod/filemanager/activities/NavigationActivity.java index 759d7550..8f5fcd26 100644 --- a/src/com/cyanogenmod/filemanager/activities/NavigationActivity.java +++ b/src/com/cyanogenmod/filemanager/activities/NavigationActivity.java @@ -242,6 +242,22 @@ public class NavigationActivity extends Activity } } + // Restricted access + if (key.compareTo(FileManagerSettings. + SETTINGS_RESTRICT_SECONDARY_USERS_ACCESS.getId()) == 0) { + if (AndroidHelper.isSecondaryUser(context)) { + try { + Preferences.savePreference( + FileManagerSettings.SETTINGS_ACCESS_MODE, + AccessMode.SAFE, true); + } catch (Throwable ex) { + Log.w(TAG, "can't save console preference", ex); //$NON-NLS-1$ + } + ConsoleBuilder.changeToNonPrivilegedConsole(context); + createChRooted(); + } + } + // Filetime format mode if (key.compareTo(FileManagerSettings. SETTINGS_FILETIME_FORMAT_MODE.getId()) == 0) { @@ -424,6 +440,16 @@ public class NavigationActivity extends Activity } @Override + protected void onResume() { + super.onResume(); + + // Check restrictions + if (!FileManagerApplication.checkRestrictSecondaryUsersAccess(this, mChRooted)) { + return; + } + } + + @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); // Sync the toggle state after onRestoreInstanceState has occurred. diff --git a/src/com/cyanogenmod/filemanager/activities/preferences/GeneralPreferenceFragment.java b/src/com/cyanogenmod/filemanager/activities/preferences/GeneralPreferenceFragment.java index f4643907..2821ce91 100644 --- a/src/com/cyanogenmod/filemanager/activities/preferences/GeneralPreferenceFragment.java +++ b/src/com/cyanogenmod/filemanager/activities/preferences/GeneralPreferenceFragment.java @@ -23,6 +23,7 @@ import android.os.Bundle; import android.preference.CheckBoxPreference; import android.preference.ListPreference; import android.preference.Preference; +import android.preference.PreferenceCategory; import android.preference.Preference.OnPreferenceChangeListener; import android.util.Log; @@ -33,6 +34,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.util.AndroidHelper; /** * A class that manages the commons options of the application @@ -50,6 +52,7 @@ public class GeneralPreferenceFragment extends TitlePreferenceFragment { private CheckBoxPreference mDisplayThumbs; private CheckBoxPreference mUseFlinger; private ListPreference mAccessMode; + private CheckBoxPreference mRestrictSecondaryUsersAccess; private CheckBoxPreference mDebugTraces; /** @@ -62,6 +65,7 @@ public class GeneralPreferenceFragment extends TitlePreferenceFragment { @Override public boolean onPreferenceChange(final Preference preference, Object newValue) { boolean ret = true; + boolean notify = false; String key = preference.getKey(); if (DEBUG) { @@ -120,9 +124,21 @@ public class GeneralPreferenceFragment extends TitlePreferenceFragment { preference.setSummary(summary[valueId]); } + // Restricted secondary users access + else if (FileManagerSettings.SETTINGS_RESTRICT_SECONDARY_USERS_ACCESS.getId(). + compareTo(key) == 0) { + String value = String.valueOf(newValue); + if (Preferences.writeWorldReadableProperty(getActivity(), key, value)) { + ((CheckBoxPreference) preference).setChecked((Boolean) newValue); + updateAccessModeStatus(); + notify = true; + } + ret = false; + } + // Notify the change (only if fragment is loaded. Default values are loaded // while not in loaded mode) - if (GeneralPreferenceFragment.this.mLoaded && ret) { + if (GeneralPreferenceFragment.this.mLoaded && (ret || notify)) { Intent intent = new Intent(FileManagerSettings.INTENT_SETTING_CHANGED); intent.putExtra( FileManagerSettings.EXTRA_SETTING_CHANGED_KEY, preference.getKey()); @@ -206,8 +222,24 @@ public class GeneralPreferenceFragment extends TitlePreferenceFragment { FileManagerSettings.SETTINGS_ACCESS_MODE.getId(), defaultValue); this.mOnChangeListener.onPreferenceChange(this.mAccessMode, value); - // If device is not rooted, this setting cannot be changed - this.mAccessMode.setEnabled(FileManagerApplication.isDeviceRooted()); + updateAccessModeStatus(); + + // Capture Debug traces + this.mRestrictSecondaryUsersAccess = + (CheckBoxPreference)findPreference( + FileManagerSettings.SETTINGS_RESTRICT_SECONDARY_USERS_ACCESS.getId()); + if (!AndroidHelper.hasSupportForMultipleUsers(getActivity()) || + AndroidHelper.isSecondaryUser(getActivity())) { + // Remove if device doesn't support multiple users accounts or the current user + // is a secondary user + PreferenceCategory category = (PreferenceCategory) findPreference( + "general_advanced_settings"); + category.removePreference(this.mRestrictSecondaryUsersAccess); + } else { + this.mRestrictSecondaryUsersAccess.setChecked( + FileManagerApplication.isRestrictSecondaryUsersAccess(getActivity())); + this.mRestrictSecondaryUsersAccess.setOnPreferenceChangeListener(this.mOnChangeListener); + } // Capture Debug traces this.mDebugTraces = @@ -219,6 +251,14 @@ public class GeneralPreferenceFragment extends TitlePreferenceFragment { this.mLoaded = true; } + private void updateAccessModeStatus() { + // If device is not rooted, or is a restricted user, this setting cannot be changed + final Context context = getActivity(); + boolean restrictedAccess = AndroidHelper.isSecondaryUser(context) && + FileManagerApplication.isRestrictSecondaryUsersAccess(context); + this.mAccessMode.setEnabled(FileManagerApplication.isDeviceRooted() && !restrictedAccess); + } + /** * {@inheritDoc} */ diff --git a/src/com/cyanogenmod/filemanager/console/ConsoleBuilder.java b/src/com/cyanogenmod/filemanager/console/ConsoleBuilder.java index ce066a2e..51f29818 100644 --- a/src/com/cyanogenmod/filemanager/console/ConsoleBuilder.java +++ b/src/com/cyanogenmod/filemanager/console/ConsoleBuilder.java @@ -29,6 +29,7 @@ import com.cyanogenmod.filemanager.console.shell.PrivilegedConsole; import com.cyanogenmod.filemanager.preferences.AccessMode; import com.cyanogenmod.filemanager.preferences.FileManagerSettings; import com.cyanogenmod.filemanager.preferences.Preferences; +import com.cyanogenmod.filemanager.util.AndroidHelper; import com.cyanogenmod.filemanager.util.DialogHelper; import java.io.FileNotFoundException; @@ -188,7 +189,19 @@ public final class ConsoleBuilder { FileManagerApplication.getAccessMode().compareTo(AccessMode.ROOT) == 0; boolean advancedMode = FileManagerApplication.getAccessMode().compareTo(AccessMode.SAFE) != 0; - if (superuserMode && !advancedMode) { + boolean restrictedMode = + AndroidHelper.hasSupportForMultipleUsers(context) && !AndroidHelper.isUserOwner(); + if (restrictedMode) { + // Is a secondary user. Restrict access to the whole system + try { + Preferences.savePreference( + FileManagerSettings.SETTINGS_ACCESS_MODE, AccessMode.SAFE, true); + } catch (Throwable ex) { + Log.w(TAG, "can't save console preference", ex); //$NON-NLS-1$ + } + superuserMode = false; + } + else if (superuserMode && !advancedMode) { try { Preferences.savePreference( FileManagerSettings.SETTINGS_ACCESS_MODE, AccessMode.PROMPT, true); diff --git a/src/com/cyanogenmod/filemanager/preferences/FileManagerSettings.java b/src/com/cyanogenmod/filemanager/preferences/FileManagerSettings.java index 4d2bb2fa..93309dae 100644 --- a/src/com/cyanogenmod/filemanager/preferences/FileManagerSettings.java +++ b/src/com/cyanogenmod/filemanager/preferences/FileManagerSettings.java @@ -36,6 +36,13 @@ public enum FileManagerSettings { SETTINGS_ACCESS_MODE("cm_filemanager_access_mode", AccessMode.SAFE), //$NON-NLS-1$ /** + * When secondary users will have a chrooted console + * @hide + */ + SETTINGS_RESTRICT_SECONDARY_USERS_ACCESS("cm_filemanager_restrict_secondary_users_access", + Boolean.TRUE), //$NON-NLS-1$ + + /** * The initial directory to be used. * @hide */ diff --git a/src/com/cyanogenmod/filemanager/preferences/Preferences.java b/src/com/cyanogenmod/filemanager/preferences/Preferences.java index 171c63d4..3cdc595e 100644 --- a/src/com/cyanogenmod/filemanager/preferences/Preferences.java +++ b/src/com/cyanogenmod/filemanager/preferences/Preferences.java @@ -19,10 +19,16 @@ package com.cyanogenmod.filemanager.preferences; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; +import android.os.UserHandle; import android.util.Log; import com.cyanogenmod.filemanager.FileManagerApplication; +import com.cyanogenmod.filemanager.util.AndroidHelper; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; import java.io.InvalidClassException; import java.util.ArrayList; import java.util.Collections; @@ -30,6 +36,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.Set; /** @@ -49,6 +56,11 @@ public final class Preferences { * @hide */ public static final String SETTINGS_FILENAME = "com.cyanogenmod.filemanager"; //$NON-NLS-1$ + /** + * The name of the file manager public readable shared properties file. + * @hide + */ + public static final String SHARED_PROPERTIES_FILENAME = "shared.properties"; /** * The list of configuration listeners. @@ -130,6 +142,84 @@ public final class Preferences { SETTINGS_FILENAME, Context.MODE_PRIVATE); } + private static File getWorldReadablePropertiesFile(Context context) { + String dataDir = context.getApplicationInfo().dataDir; + if (AndroidHelper.isSecondaryUser(context)) { + dataDir = dataDir.replace(String.valueOf(UserHandle.myUserId()), + String.valueOf(UserHandle.USER_OWNER)); + } + return new File(dataDir, SHARED_PROPERTIES_FILENAME); + } + + public static String getWorldReadableProperties(Context context, String key) { + Properties props = new Properties(); + FileReader reader = null; + try { + reader = new FileReader(getWorldReadablePropertiesFile(context)); + props.load(reader); + } catch (IOException ex) { + // Ignore + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException ex) { + // Ignore + } + } + } + return props.getProperty(key); + } + + public static boolean writeWorldReadableProperty(Context context, String key, String value) { + if (AndroidHelper.isSecondaryUser(context)) { + // Not allowed + return false; + } + Properties props = new Properties(); + FileReader reader = null; + FileWriter writer = null; + try { + File dst = getWorldReadablePropertiesFile(context); + if (!dst.exists()) { + dst.createNewFile(); + dst.setWritable(true, true); + dst.setReadable(true, false); + dst.setExecutable(false); + } + reader = new FileReader(dst); + props.load(reader); + try { + props.load(new FileReader(dst)); + } catch (IOException ex) { + return false; + } + props.put(key, value); + writer = new FileWriter(dst); + props.store(writer, null); + return true; + + } catch (IOException ex) { + // Ignore + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException ex) { + // Ignore + } + } + if (writer != null) { + try { + writer.close(); + } catch (IOException ex) { + // Ignore + } + } + } + return false; + } + /** * Method that saves a preference. * diff --git a/src/com/cyanogenmod/filemanager/util/AndroidHelper.java b/src/com/cyanogenmod/filemanager/util/AndroidHelper.java index 57260ec1..f014b0d8 100644 --- a/src/com/cyanogenmod/filemanager/util/AndroidHelper.java +++ b/src/com/cyanogenmod/filemanager/util/AndroidHelper.java @@ -20,6 +20,8 @@ import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.content.res.Resources; +import android.os.UserHandle; +import android.os.UserManager; import android.util.DisplayMetrics; import android.view.ViewConfiguration; @@ -101,4 +103,16 @@ public final class AndroidHelper { return false; } + public static boolean hasSupportForMultipleUsers(Context context) { + return UserManager.supportsMultipleUsers(); + } + + public static boolean isUserOwner() { + return UserHandle.myUserId() == UserHandle.USER_OWNER; + } + + public static boolean isSecondaryUser(Context context) { + return AndroidHelper.hasSupportForMultipleUsers(context) + && !AndroidHelper.isUserOwner(); + } } |