summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Craig Mautner <cmautner@google.com> 2014-04-25 10:09:00 -0700
committer Craig Mautner <cmautner@google.com> 2014-04-25 11:20:01 -0700
commit247ab65a4985470feff9cb5b5d40d2b8c64f5ada (patch)
tree3935d27508ad4b80347fb8af33af0d9fad87e5e8
parent3a656ea32e6d6489f4bc45884e5acede9fe2de51 (diff)
Throw exception from startActivity if not allowed.
The ActivityView.startActivity method may defer calling ActivityContainer.startActivity if the ActivityView is not yet visible. If the activity being started doesn't have allowEmbedded attribute set to true then the SecurityException will not be thrown until the ActivityView is visible. In such a case the caller of ActivityView.startActivity cannot catch the SecurityException. This fix checks the attribute at the time ActivityView.startActivity is called. Fixes bug 14317210. Change-Id: I7fff23e39b67a9a0aa1b2e555920d02ae38906d9
-rw-r--r--core/java/android/app/ActivityView.java21
-rw-r--r--core/java/android/app/IActivityContainer.aidl2
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java34
3 files changed, 57 insertions, 0 deletions
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index edf21dde82e2..a810134f28f2 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -147,6 +147,7 @@ public class ActivityView extends ViewGroup {
if (mSurface != null) {
mActivityContainer.startActivity(intent);
} else {
+ mActivityContainer.checkEmbeddedAllowed(intent);
mQueuedIntent = intent;
mQueuedPendingIntent = null;
}
@@ -162,6 +163,7 @@ public class ActivityView extends ViewGroup {
if (mSurface != null) {
mActivityContainer.startActivityIntentSender(iIntentSender);
} else {
+ mActivityContainer.checkEmbeddedAllowedIntentSender(iIntentSender);
mQueuedPendingIntent = iIntentSender;
mQueuedIntent = null;
}
@@ -177,6 +179,7 @@ public class ActivityView extends ViewGroup {
if (mSurface != null) {
mActivityContainer.startActivityIntentSender(iIntentSender);
} else {
+ mActivityContainer.checkEmbeddedAllowedIntentSender(iIntentSender);
mQueuedPendingIntent = iIntentSender;
mQueuedIntent = null;
}
@@ -326,6 +329,24 @@ public class ActivityView extends ViewGroup {
}
}
+ void checkEmbeddedAllowed(Intent intent) {
+ try {
+ mIActivityContainer.checkEmbeddedAllowed(intent);
+ } catch (RemoteException e) {
+ throw new RuntimeException(
+ "ActivityView: Unable to startActivity from Intent. " + e);
+ }
+ }
+
+ void checkEmbeddedAllowedIntentSender(IIntentSender intentSender) {
+ try {
+ mIActivityContainer.checkEmbeddedAllowedIntentSender(intentSender);
+ } catch (RemoteException e) {
+ throw new RuntimeException(
+ "ActivityView: Unable to startActivity from IntentSender. " + e);
+ }
+ }
+
int getDisplayId() {
try {
return mIActivityContainer.getDisplayId();
diff --git a/core/java/android/app/IActivityContainer.aidl b/core/java/android/app/IActivityContainer.aidl
index cc3b10cfa88f..52884f744b73 100644
--- a/core/java/android/app/IActivityContainer.aidl
+++ b/core/java/android/app/IActivityContainer.aidl
@@ -29,6 +29,8 @@ interface IActivityContainer {
void setSurface(in Surface surface, int width, int height, int density);
int startActivity(in Intent intent);
int startActivityIntentSender(in IIntentSender intentSender);
+ void checkEmbeddedAllowed(in Intent intent);
+ void checkEmbeddedAllowedIntentSender(in IIntentSender intentSender);
int getDisplayId();
boolean injectEvent(in InputEvent event);
void release();
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 0b6f7d155d17..28b1df52db6b 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -3057,6 +3057,40 @@ public final class ActivityStackSupervisor implements DisplayListener {
null, 0, FORCE_NEW_TASK_FLAGS, FORCE_NEW_TASK_FLAGS, null, this);
}
+ private void checkEmbeddedAllowedInner(Intent intent, String resolvedType) {
+ int userId = mService.handleIncomingUser(Binder.getCallingPid(),
+ Binder.getCallingUid(), mCurrentUser, false, true, "ActivityContainer", null);
+ if (resolvedType == null) {
+ resolvedType = intent.getType();
+ if (resolvedType == null && intent.getData() != null
+ && "content".equals(intent.getData().getScheme())) {
+ resolvedType = mService.getProviderMimeType(intent.getData(), userId);
+ }
+ }
+ ActivityInfo aInfo = resolveActivity(intent, resolvedType, 0, null, null, userId);
+ if ((aInfo.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) {
+ throw new SecurityException(
+ "Attempt to embed activity that has not set allowEmbedded=\"true\"");
+ }
+ }
+
+ /** Throw a SecurityException if allowEmbedded is not true */
+ @Override
+ public final void checkEmbeddedAllowed(Intent intent) {
+ checkEmbeddedAllowedInner(intent, null);
+ }
+
+ /** Throw a SecurityException if allowEmbedded is not true */
+ @Override
+ public final void checkEmbeddedAllowedIntentSender(IIntentSender intentSender) {
+ if (!(intentSender instanceof PendingIntentRecord)) {
+ throw new IllegalArgumentException("Bad PendingIntent object");
+ }
+ PendingIntentRecord pendingIntent = (PendingIntentRecord) intentSender;
+ checkEmbeddedAllowedInner(pendingIntent.key.requestIntent,
+ pendingIntent.key.requestResolvedType);
+ }
+
@Override
public IBinder asBinder() {
return this;