summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Amith Yamasani <yamasani@google.com> 2013-08-01 17:18:03 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2013-08-01 17:18:03 +0000
commit3d38fa301ca502882b1bbe06c030d037289636b7 (patch)
tree646230c49aeb3f6ff9a225c40c266a9e77c94c4b
parent5d3dff1d66f99fbd5bef9178e62d789119c02ad1 (diff)
parent364ed4dda42882b600dce48319881ff58464fced (diff)
Merge "PreferenceActivity Fragment security"
-rw-r--r--api/current.txt1
-rw-r--r--core/java/android/app/Fragment.java4
-rw-r--r--core/java/android/preference/PreferenceActivity.java38
3 files changed, 41 insertions, 2 deletions
diff --git a/api/current.txt b/api/current.txt
index 9d6a3292baf1..620e5412d99d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -18355,6 +18355,7 @@ package android.preference {
method public boolean hasHeaders();
method public void invalidateHeaders();
method public boolean isMultiPane();
+ method protected boolean isValidFragment(java.lang.String);
method public void loadHeadersFromResource(int, java.util.List<android.preference.PreferenceActivity.Header>);
method public void onBuildHeaders(java.util.List<android.preference.PreferenceActivity.Header>);
method public android.content.Intent onBuildStartFragmentIntent(java.lang.String, android.os.Bundle, int, int);
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 6933a7afd698..f8a1d82f76f2 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -580,6 +580,10 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
if (clazz == null) {
// Class not found in the cache, see if it's real, and try to add it
clazz = context.getClassLoader().loadClass(fname);
+ if (!Fragment.class.isAssignableFrom(clazz)) {
+ throw new InstantiationException("Trying to instantiate a class " + fname
+ + " that is not a Fragment", new ClassCastException());
+ }
sClassMap.put(fname, clazz);
}
Fragment f = (Fragment)clazz.newInstance();
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index ec97efb0df28..7a41f3cfa55b 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -33,6 +33,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.AttributeSet;
+import android.util.Log;
import android.util.TypedValue;
import android.util.Xml;
import android.view.LayoutInflater;
@@ -124,6 +125,8 @@ public abstract class PreferenceActivity extends ListActivity implements
PreferenceManager.OnPreferenceTreeClickListener,
PreferenceFragment.OnPreferenceStartFragmentCallback {
+ private static final String TAG = "PreferenceActivity";
+
// Constants for state save/restore
private static final String HEADERS_TAG = ":android:headers";
private static final String CUR_HEADER_TAG = ":android:cur_header";
@@ -132,6 +135,9 @@ public abstract class PreferenceActivity extends ListActivity implements
/**
* When starting this activity, the invoking Intent can contain this extra
* string to specify which fragment should be initially displayed.
+ * <p/>Starting from Key Lime Pie, when this argument is passed in, the PreferenceActivity
+ * will call isValidFragment() to confirm that the fragment class name is valid for this
+ * activity.
*/
public static final String EXTRA_SHOW_FRAGMENT = ":android:show_fragment";
@@ -299,7 +305,7 @@ public abstract class PreferenceActivity extends ListActivity implements
* are valid.
*/
public static final long HEADER_ID_UNDEFINED = -1;
-
+
/**
* Description of a single Header item that the user can select.
*/
@@ -877,7 +883,27 @@ public abstract class PreferenceActivity extends ListActivity implements
} finally {
if (parser != null) parser.close();
}
+ }
+ /**
+ * Subclasses should override this method and verify that the given fragment is a valid type
+ * to be attached to this activity. The default implementation returns <code>true</code> prior
+ * to Key Lime Pie, <code>false</code> otherwise.
+ * @param f the class name of the Fragment about to be attached to this activity.
+ * @return true if the fragment class name is valid for this Activity and false otherwise.
+ */
+ protected boolean isValidFragment(String fragmentName) {
+ if (getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.KEY_LIME_PIE) {
+ Log.w(TAG, "Subclasses of PreferenceActivity must override isValidFragment(String)"
+ + " to verify that the Fragment class is valid! " + this.getClass().getName()
+ + " has not checked if fragment " + fragmentName + " is valid.");
+ // Return true for now, but will eventually return false when all bundled apps
+ // have been modified. TODO: change to return false
+ return true;
+ } else {
+ Log.i(TAG, "PreferenceActivity built on pre-KLP launching fragment: " + fragmentName);
+ return true;
+ }
}
/**
@@ -1146,6 +1172,10 @@ public abstract class PreferenceActivity extends ListActivity implements
private void switchToHeaderInner(String fragmentName, Bundle args, int direction) {
getFragmentManager().popBackStack(BACK_STACK_PREFS,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
+ if (!isValidFragment(fragmentName)) {
+ throw new IllegalArgumentException("Invalid fragment for this activity: "
+ + fragmentName);
+ }
Fragment f = Fragment.instantiate(this, fragmentName, args);
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
@@ -1275,6 +1305,10 @@ public abstract class PreferenceActivity extends ListActivity implements
if (mSinglePane) {
startWithFragment(fragmentClass, args, resultTo, resultRequestCode, titleRes, 0);
} else {
+ if (!isValidFragment(fragmentClass)) {
+ throw new IllegalArgumentException("Invalid fragment for this activity: "
+ + fragmentClass);
+ }
Fragment f = Fragment.instantiate(this, fragmentClass, args);
if (resultTo != null) {
f.setTargetFragment(resultTo, resultRequestCode);
@@ -1291,7 +1325,7 @@ public abstract class PreferenceActivity extends ListActivity implements
transaction.commitAllowingStateLoss();
}
}
-
+
/**
* Called by a preference panel fragment to finish itself.
*