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
This commit is contained in:
Craig Mautner
2014-04-25 10:09:00 -07:00
parent 3a656ea32e
commit 247ab65a49
3 changed files with 57 additions and 0 deletions

View File

@@ -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();

View File

@@ -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();

View File

@@ -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;