summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2017-08-16 07:19:38 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2017-08-16 07:19:38 +0000
commitbf39d1ad15b30150d4bb08df6f63d5fec4e4dacc (patch)
tree474b5d19bf9c08ec0a9c12a1295cb5fde08aa52f
parent78255da9eab1ace35cdb76187f543ac56984c73b (diff)
parent44cab75cb0ec40368597180e06d6d037a76ef41a (diff)
downloadbase-bf39d1ad15b30150d4bb08df6f63d5fec4e4dacc.tar.gz
release-request-447544c9-42cd-4c45-a7c6-4f09361c94db-for-git_oc-dr1-release-4277755 snap-temp-L90500000093605838
Change-Id: I5ccc07f52d318ac0470ace72fa446c0cc1d55bb8
-rw-r--r--core/java/android/service/autofill/AutofillService.java72
-rw-r--r--core/java/android/service/gatekeeper/GateKeeperResponse.java2
-rw-r--r--core/java/android/webkit/WebView.java12
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java8
-rw-r--r--services/core/java/com/android/server/wm/SurfaceControlWithBackground.java8
5 files changed, 93 insertions, 9 deletions
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index c068e6a21db6..53b49f0ba373 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -280,6 +280,76 @@ import com.android.internal.os.SomeArgs;
* calling {@link FillResponse.Builder#setIgnoredIds(AutofillId...)} so the system does not trigger
* a new {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)} when these views are
* focused.
+ *
+ * <h3>Web security</h3>
+ *
+ * <p>When handling autofill requests that represent web pages (typically
+ * view structures whose root's {@link android.app.assist.AssistStructure.ViewNode#getClassName()}
+ * is a {@link android.webkit.WebView}), the service should take the following steps to verify if
+ * the structure can be autofilled with the data associated with the app requesting it:
+ *
+ * <ol>
+ * <li>Use the {@link android.app.assist.AssistStructure.ViewNode#getWebDomain()} to get the
+ * source of the document.
+ * <li>Get the canonical domain using the
+ * <a href="https://publicsuffix.org/>Public Suffix List</a> (see example below).
+ * <li>Use <a href="https://developers.google.com/digital-asset-links/">Digital Asset Links</a>
+ * to obtain the package name and certificate fingerprint of the package corresponding to
+ * the canonical domain.
+ * <li>Make sure the certificate fingerprint matches the value returned by Package Manager
+ * (see "Package verification" section above).
+ * </ol>
+ *
+ * <p>Here's an example on how to get the canonical domain using
+ * <a href="https://github.com/google/guava">Guava</a>:
+ *
+ * <pre class="prettyprint">
+ * private static String getCanonicalDomain(String domain) {
+ * InternetDomainName idn = InternetDomainName.from(domain);
+ * while (!idn.isTopPrivateDomain() && idn != null) {
+ * idn = idn.parent();
+ * }
+ * return idn == null ? null : idn.toString();
+ * }
+ * </pre>
+ *
+ * <p>If the association between the web domain and app package cannot be verified through the steps
+ * above, the service can still autofill the app, but it should warn the user about the potential
+ * data leakage first, and askfor the user to confirm. For example, the service could:
+ *
+ * <ol>
+ * <li>Create a dataset that requires
+ * {@link Dataset.Builder#setAuthentication(android.content.IntentSender) authentication} to
+ * unlock.
+ * <li>Include the web domain in the custom presentation for the
+ * {@link Dataset.Builder#setValue(AutofillId, AutofillValue, android.widget.RemoteViews)
+ * dataset value}.
+ * <li>When the user select that dataset, show a disclaimer dialog explaining that the app is
+ * requesting credentials for a web domain, but the service could not verify if the app owns
+ * that domain. If the user agrees, then the service can unlock the dataset.
+ * <li>Similarly, when adding a {@link SaveInfo} object for the request, the service should
+ * include the above disclaimer in the {@link SaveInfo.Builder#setDescription(CharSequence)}.
+ * </ol>
+ *
+ * <p>This same procedure could also be used when the autofillable data is contained inside an
+ * {@code IFRAME}, in which case the WebView generates a new autofill context when a node inside
+ * the {@code IFRAME} is focused, which the root node containing the {@code IFRAME}'s {@code src}
+ * attribute on {@link android.app.assist.AssistStructure.ViewNode#getWebDomain()}. A typical and
+ * legitimate use case for this scenario is a financial app that allows the user
+ * to login on different bank accounts. For example, a financial app {@code my_financial_app} could
+ * use a WebView that loads contents from {@code banklogin.my_financial_app.com}, which contains an
+ * {@code IFRAME} node whose {@code src} attribute is {@code login.some_bank.com}. When fulfilling
+ * that request, the service could add an
+ * {@link Dataset.Builder#setAuthentication(android.content.IntentSender) authenticated dataset}
+ * whose presentation displays "Username for some_bank.com" and
+ * "Password for some_bank.com". Then when the user taps one of these options, the service
+ * shows the disclaimer dialog explaining that selecting that option would release the
+ * {@code login.some_bank.com} credentials to the {@code my_financial_app}; if the user agrees,
+ * then the service returns an unlocked dataset with the {@code some_bank.com} credentials.
+ *
+ * <p><b>Note:</b> The autofill service could also whitelist well-known browser apps and skip the
+ * verifications above, as long as the service can verify the authenticity of the browser app by
+ * checking its signing certificate.
*/
public abstract class AutofillService extends Service {
private static final String TAG = "AutofillService";
@@ -424,7 +494,7 @@ public abstract class AutofillService extends Service {
* {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)})
* to notify the result of the request.
*
- * <p><b>NOTE: </b>to retrieve the actual value of the field, the service should call
+ * <p><b>Note:</b> To retrieve the actual value of the field, the service should call
* {@link android.app.assist.AssistStructure.ViewNode#getAutofillValue()}; if it calls
* {@link android.app.assist.AssistStructure.ViewNode#getText()} or other methods, there is no
* guarantee such method will return the most recent value of the field.
diff --git a/core/java/android/service/gatekeeper/GateKeeperResponse.java b/core/java/android/service/gatekeeper/GateKeeperResponse.java
index 287dc76a9b01..9b529345851b 100644
--- a/core/java/android/service/gatekeeper/GateKeeperResponse.java
+++ b/core/java/android/service/gatekeeper/GateKeeperResponse.java
@@ -106,6 +106,8 @@ public final class GateKeeperResponse implements Parcelable {
if (mPayload != null) {
dest.writeInt(mPayload.length);
dest.writeByteArray(mPayload);
+ } else {
+ dest.writeInt(0);
}
}
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 2753ff675dec..a0b4a0356233 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2667,6 +2667,18 @@ public class WebView extends AbsoluteLayout
* understood by the {@link android.service.autofill.AutofillService} implementations:
*
* <ol>
+ * <li>Only the HTML nodes inside a {@code FORM} are generated.
+ * <li>The source of the HTML is set using {@link ViewStructure#setWebDomain(String)} in the
+ * node representing the WebView.
+ * <li>If a web page has multiple {@code FORM}s, only the data for the current form is
+ * represented&mdash;if the user taps a field from another form, then the current autofill
+ * context is canceled (by calling {@link android.view.autofill.AutofillManager#cancel()} and
+ * a new context is created for that {@code FORM}.
+ * <li>Similarly, if the page has {@code IFRAME} nodes, they are not initially represented in
+ * the view structure until the user taps a field from a {@code FORM} inside the
+ * {@code IFRAME}, in which case it would be treated the same way as multiple forms described
+ * above, except that the {@link ViewStructure#setWebDomain(String) web domain} of the
+ * {@code FORM} contains the {@code src} attribute from the {@code IFRAME} node.
* <li>If the Android SDK provides a similar View, then should be set with the
* fully-qualified class name of such view.
* <li>The W3C autofill field ({@code autocomplete} tag attribute) maps to
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index cff917394ace..0326299f4efa 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -5433,6 +5433,10 @@ public class AudioService extends IAudioService.Stub
configureHdmiPlugIntent(intent, state);
}
+ if (intent.getAction() == null) {
+ return;
+ }
+
intent.putExtra(CONNECT_INTENT_KEY_STATE, state);
intent.putExtra(CONNECT_INTENT_KEY_ADDRESS, address);
intent.putExtra(CONNECT_INTENT_KEY_PORT_NAME, deviceName);
@@ -5506,9 +5510,7 @@ public class AudioService extends IAudioService.Stub
}
}
}
- if (device != AudioSystem.DEVICE_IN_WIRED_HEADSET) {
- sendDeviceConnectionIntent(device, state, address, deviceName);
- }
+ sendDeviceConnectionIntent(device, state, address, deviceName);
updateAudioRoutes(device, state);
}
}
diff --git a/services/core/java/com/android/server/wm/SurfaceControlWithBackground.java b/services/core/java/com/android/server/wm/SurfaceControlWithBackground.java
index 3603f2ffeed2..b0eaf1488f21 100644
--- a/services/core/java/com/android/server/wm/SurfaceControlWithBackground.java
+++ b/services/core/java/com/android/server/wm/SurfaceControlWithBackground.java
@@ -26,9 +26,8 @@ import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
-import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
-import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManagerPolicy.NAV_BAR_BOTTOM;
import static android.view.WindowManagerPolicy.NAV_BAR_LEFT;
import static android.view.WindowManagerPolicy.NAV_BAR_RIGHT;
@@ -73,9 +72,8 @@ class SurfaceControlWithBackground extends SurfaceControl {
super(s, name, w, h, format, flags, windowType, ownerUid);
// We should only show background behind app windows that are letterboxed in a task.
- if (!windowSurfaceController.mAnimator.mWin.isLetterboxedAppWindow()
- || windowType < FIRST_APPLICATION_WINDOW
- || windowType > LAST_APPLICATION_WINDOW) {
+ if ((windowType != TYPE_BASE_APPLICATION && windowType != TYPE_APPLICATION_STARTING)
+ || !windowSurfaceController.mAnimator.mWin.isLetterboxedAppWindow()) {
return;
}
mWindowSurfaceController = windowSurfaceController;