Commit f1f3e06f authored by Peter E Conn's avatar Peter E Conn Committed by Commit Bot

🤝 Notify user that a Trusted Web Activity is running in Chrome.

Notify the user via Toast that an opened Trusted Web Activity is part
of Chrome and therefore will have access to their cookies, autofill
data, etc.

This is shown at most once per week for a single app.

Bug: 813100
Change-Id: I7f921637ffa042ff4d0f076ad4ca007708f06879
Reviewed-on: https://chromium-review.googlesource.com/1097399
Commit-Queue: Peter Conn <peconn@chromium.org>
Reviewed-by: default avatarBenoit L <lizeb@chromium.org>
Reviewed-by: default avatarBernhard Bauer <bauerb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#566784}
parent ad05d4a4
...@@ -395,6 +395,7 @@ public class OriginVerifier { ...@@ -395,6 +395,7 @@ public class OriginVerifier {
ThreadUtils.assertOnUiThread(); ThreadUtils.assertOnUiThread();
if (sPackageToCachedOrigins != null) sPackageToCachedOrigins.clear(); if (sPackageToCachedOrigins != null) sPackageToCachedOrigins.clear();
ChromePreferenceManager.getInstance().setVerifiedDigitalAssetLinks(Collections.emptySet()); ChromePreferenceManager.getInstance().setVerifiedDigitalAssetLinks(Collections.emptySet());
ChromePreferenceManager.getInstance().clearAllTrustedWebActivityLastDisclosureTimes();
} }
private native long nativeInit(Profile profile); private native long nativeInit(Profile profile);
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.browserservices;
import android.content.Context;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
import org.chromium.ui.widget.Toast;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
* Since Trusted Web Activities are part of Chrome they have access to the cookie jar and have the
* same reporting and metrics as other parts of Chrome. However, they have no UI making the fact
* they are part of Chrome obvious to the user. Therefore we show a disclosure Toast whenever an
* app opens a Trusted Web Activity, at most once per week per app.
*/
public class TrustedWebActivityDisclosure {
private static final int DISCLOSURE_PERIOD_DAYS = 7;
/**
* Show the "Running in Chrome" disclosure (Toast) if one hasn't been shown recently.
*/
public static void showIfNeeded(Context context, String packageName) {
ChromePreferenceManager prefs = ChromePreferenceManager.getInstance();
Date now = new Date();
Date lastShown = prefs.getTrustedWebActivityLastDisclosureTime(packageName);
long millisSince = now.getTime() - lastShown.getTime();
long daysSince = TimeUnit.DAYS.convert(millisSince, TimeUnit.MILLISECONDS);
if (daysSince <= DISCLOSURE_PERIOD_DAYS) return;
prefs.setTrustedWebActivityLastDisclosureTime(packageName, now);
String disclosure = context.getResources().getString(R.string.twa_running_in_chrome);
Toast.makeText(context, disclosure, Toast.LENGTH_LONG).show();
}
private TrustedWebActivityDisclosure() {}
}
...@@ -11,6 +11,7 @@ import org.chromium.base.ContextUtils; ...@@ -11,6 +11,7 @@ import org.chromium.base.ContextUtils;
import org.chromium.chrome.browser.crash.MinidumpUploadService.ProcessType; import org.chromium.chrome.browser.crash.MinidumpUploadService.ProcessType;
import java.util.Collections; import java.util.Collections;
import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
import java.util.Locale; import java.util.Locale;
import java.util.Set; import java.util.Set;
...@@ -78,6 +79,8 @@ public class ChromePreferenceManager { ...@@ -78,6 +79,8 @@ public class ChromePreferenceManager {
private static final String VERIFIED_DIGITAL_ASSET_LINKS = private static final String VERIFIED_DIGITAL_ASSET_LINKS =
"verified_digital_asset_links"; "verified_digital_asset_links";
private static final String TRUSTED_WEB_ACTIVITY_LAST_DISCLOSURE_TIME =
"trusted_web_activity_last_disclosure_time:";
private static class LazyHolder { private static class LazyHolder {
static final ChromePreferenceManager INSTANCE = new ChromePreferenceManager(); static final ChromePreferenceManager INSTANCE = new ChromePreferenceManager();
...@@ -523,6 +526,43 @@ public class ChromePreferenceManager { ...@@ -523,6 +526,43 @@ public class ChromePreferenceManager {
mSharedPreferences.edit().putStringSet(VERIFIED_DIGITAL_ASSET_LINKS, links).apply(); mSharedPreferences.edit().putStringSet(VERIFIED_DIGITAL_ASSET_LINKS, links).apply();
} }
/**
* Private convenience method to create a Preferences Key to hold the last time the given
* package displayed a "Running in Chrome" disclosure while opening a Trusted Web Activity.
*/
private static String getTrustedWebActivityDisclosureTimeKey(String packageName) {
return TRUSTED_WEB_ACTIVITY_LAST_DISCLOSURE_TIME + packageName;
}
/**
* Gets the last time a disclosure was shown while opening a Trusted Web Activity for the given
* package. Returns a Date object representing the Unix epoch if no data was found.
*/
public Date getTrustedWebActivityLastDisclosureTime(String packageName) {
return new Date(readLong(getTrustedWebActivityDisclosureTimeKey(packageName), 0));
}
/**
* Sets the last time a disclosure was shown while opening a Trusted Web Activity for the given
* package.
*/
public void setTrustedWebActivityLastDisclosureTime(String packageName, Date time) {
writeLong(getTrustedWebActivityDisclosureTimeKey(packageName), time.getTime());
}
/**
* Wipes all recordings of the last disclosure times for packages opening TWAs.
*/
public void clearAllTrustedWebActivityLastDisclosureTimes() {
SharedPreferences.Editor ed = mSharedPreferences.edit();
for (String key : mSharedPreferences.getAll().keySet()) {
if (!key.startsWith(TRUSTED_WEB_ACTIVITY_LAST_DISCLOSURE_TIME)) continue;
ed.remove(key);
}
ed.apply();
}
/** /**
* Writes the given int value to the named shared preference. * Writes the given int value to the named shared preference.
* @param key The name of the preference to modify. * @param key The name of the preference to modify.
......
...@@ -48,6 +48,7 @@ import org.chromium.chrome.browser.browserservices.BrowserSessionDataProvider; ...@@ -48,6 +48,7 @@ import org.chromium.chrome.browser.browserservices.BrowserSessionDataProvider;
import org.chromium.chrome.browser.browserservices.Origin; import org.chromium.chrome.browser.browserservices.Origin;
import org.chromium.chrome.browser.browserservices.OriginVerifier; import org.chromium.chrome.browser.browserservices.OriginVerifier;
import org.chromium.chrome.browser.browserservices.OriginVerifier.OriginVerificationListener; import org.chromium.chrome.browser.browserservices.OriginVerifier.OriginVerificationListener;
import org.chromium.chrome.browser.browserservices.TrustedWebActivityDisclosure;
import org.chromium.chrome.browser.browserservices.UkmRecorder; import org.chromium.chrome.browser.browserservices.UkmRecorder;
import org.chromium.chrome.browser.compositor.layouts.LayoutManager; import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
import org.chromium.chrome.browser.customtabs.CustomTabAppMenuPropertiesDelegate; import org.chromium.chrome.browser.customtabs.CustomTabAppMenuPropertiesDelegate;
...@@ -197,6 +198,7 @@ public class WebappActivity extends SingleTabActivity { ...@@ -197,6 +198,7 @@ public class WebappActivity extends SingleTabActivity {
BrowserServicesMetrics.recordTwaOpened(); BrowserServicesMetrics.recordTwaOpened();
// Occasionally verification occurs in the background while there is no active Tab. // Occasionally verification occurs in the background while there is no active Tab.
if (areTabModelsInitialized() && getActivityTab() != null) { if (areTabModelsInitialized() && getActivityTab() != null) {
TrustedWebActivityDisclosure.showIfNeeded(WebappActivity.this, packageName);
mUkmRecorder.recordTwaOpened(getActivityTab().getWebContents()); mUkmRecorder.recordTwaOpened(getActivityTab().getWebContents());
} }
} }
......
...@@ -3204,7 +3204,7 @@ However, you aren’t invisible. Going incognito doesn’t hide your browsing fr ...@@ -3204,7 +3204,7 @@ However, you aren’t invisible. Going incognito doesn’t hide your browsing fr
<ph name="ITEM_NAME">%1$s<ex>item_name</ex></ph> (<ph name="ITEM_ID">%2$s<ex>item id</ex></ph>) <ph name="ITEM_NAME">%1$s<ex>item_name</ex></ph> (<ph name="ITEM_ID">%2$s<ex>item id</ex></ph>)
</message> </message>
<!-- WebAPK related strings --> <!-- WebAPK/TWA related strings -->
<message name="IDS_WEBAPK_RUNNING_IN_CHROME_DISCLOSURE" desc="Message on the notification that indicates a WebApk may use Chrome data."> <message name="IDS_WEBAPK_RUNNING_IN_CHROME_DISCLOSURE" desc="Message on the notification that indicates a WebApk may use Chrome data.">
This app is running in Chrome. This app is running in Chrome.
</message> </message>
...@@ -3226,6 +3226,9 @@ However, you aren’t invisible. Going incognito doesn’t hide your browsing fr ...@@ -3226,6 +3226,9 @@ However, you aren’t invisible. Going incognito doesn’t hide your browsing fr
<message name="IDS_WEBAPP_NETWORK_ERROR_MESSAGE_TUNNEL_CONNECTION_FAILED" desc="The error message for ERROR_TUNNEL_CONNECTION_FAILED."> <message name="IDS_WEBAPP_NETWORK_ERROR_MESSAGE_TUNNEL_CONNECTION_FAILED" desc="The error message for ERROR_TUNNEL_CONNECTION_FAILED.">
Establishing a tunnel via proxy server failed Establishing a tunnel via proxy server failed
</message> </message>
<message name="IDS_TWA_RUNNING_IN_CHROME" desc="Disclosure on opening a TWA that it may use Chrome data. Shown on a Toast." translateable="false">
Running in Chrome.
</message>
<!-- Keyboard shortcuts in Android N--> <!-- Keyboard shortcuts in Android N-->
<message name="IDS_KEYBOARD_SHORTCUT_OPEN_NEW_TAB" desc="A text label that appears next to the keyboard shortcut to open a new tab in Chrome. The shortcut description is shown in a system dialog along with all other supported shortcuts. [CHAR-LIMIT=55]"> <message name="IDS_KEYBOARD_SHORTCUT_OPEN_NEW_TAB" desc="A text label that appears next to the keyboard shortcut to open a new tab in Chrome. The shortcut description is shown in a system dialog along with all other supported shortcuts. [CHAR-LIMIT=55]">
......
...@@ -161,11 +161,12 @@ chrome_java_sources = [ ...@@ -161,11 +161,12 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/browserservices/BrowserSessionContentHandler.java", "java/src/org/chromium/chrome/browser/browserservices/BrowserSessionContentHandler.java",
"java/src/org/chromium/chrome/browser/browserservices/BrowserSessionContentUtils.java", "java/src/org/chromium/chrome/browser/browserservices/BrowserSessionContentUtils.java",
"java/src/org/chromium/chrome/browser/browserservices/BrowserSessionDataProvider.java", "java/src/org/chromium/chrome/browser/browserservices/BrowserSessionDataProvider.java",
"java/src/org/chromium/chrome/browser/browserservices/OriginVerifier.java",
"java/src/org/chromium/chrome/browser/browserservices/UkmRecorder.java",
"java/src/org/chromium/chrome/browser/browserservices/Origin.java", "java/src/org/chromium/chrome/browser/browserservices/Origin.java",
"java/src/org/chromium/chrome/browser/browserservices/OriginVerifier.java",
"java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java", "java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java",
"java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java", "java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java",
"java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityDisclosure.java",
"java/src/org/chromium/chrome/browser/browserservices/UkmRecorder.java",
"java/src/org/chromium/chrome/browser/browsing_data/UrlFilters.java", "java/src/org/chromium/chrome/browser/browsing_data/UrlFilters.java",
"java/src/org/chromium/chrome/browser/childaccounts/ChildAccountFeedbackReporter.java", "java/src/org/chromium/chrome/browser/childaccounts/ChildAccountFeedbackReporter.java",
"java/src/org/chromium/chrome/browser/childaccounts/ChildAccountService.java", "java/src/org/chromium/chrome/browser/childaccounts/ChildAccountService.java",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment