Commit 112cfd12 authored by Patrick Noland's avatar Patrick Noland Committed by Commit Bot

[Chromeshine] Rework consent flow and wording

This updates the consent flow to
1) Enable revocation via the consent activity
2) Only present the privacy preference when the user has consented
3) Have the privacy preference launch the consent activity for revocation
instead of being a checkbox

Bug:902490

Change-Id: I34fdc210ee03db100ab9c310ab5fe3d9cda15d76
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1481739
Commit-Queue: Patrick Noland <pnoland@chromium.org>
Reviewed-by: default avatarTheresa <twellington@chromium.org>
Cr-Commit-Position: refs/heads/master@{#638261}
parent fc735f1b
...@@ -34,10 +34,9 @@ ...@@ -34,10 +34,9 @@
android:key="can_make_payment" android:key="can_make_payment"
android:title="@string/can_make_payment_title" android:title="@string/can_make_payment_title"
android:summary="@string/settings_can_make_payment_toggle_label" /> android:summary="@string/settings_can_make_payment_toggle_label" />
<org.chromium.chrome.browser.preferences.ChromeBaseCheckBoxPreference <Preference
android:key="usage_stats_reporting" android:key="usage_stats_reporting"
android:title="@string/usage_stats_setting_title" android:title="@string/usage_stats_setting_title"
android:summary="@string/usage_stats_consent_prompt"
android:persistent="false" /> android:persistent="false" />
<Preference <Preference
android:key="usage_and_crash_reports" android:key="usage_and_crash_reports"
......
...@@ -29,6 +29,7 @@ import org.chromium.chrome.browser.preferences.PreferenceUtils; ...@@ -29,6 +29,7 @@ import org.chromium.chrome.browser.preferences.PreferenceUtils;
import org.chromium.chrome.browser.preferences.PreferencesLauncher; import org.chromium.chrome.browser.preferences.PreferencesLauncher;
import org.chromium.chrome.browser.preferences.SyncAndServicesPreferences; import org.chromium.chrome.browser.preferences.SyncAndServicesPreferences;
import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.usage_stats.UsageStatsConsentDialog;
import org.chromium.ui.text.NoUnderlineClickableSpan; import org.chromium.ui.text.NoUnderlineClickableSpan;
import org.chromium.ui.text.SpanApplier; import org.chromium.ui.text.SpanApplier;
...@@ -141,15 +142,6 @@ public class PrivacyPreferences extends PreferenceFragment ...@@ -141,15 +142,6 @@ public class PrivacyPreferences extends PreferenceFragment
safeBrowsingPref.setOnPreferenceChangeListener(this); safeBrowsingPref.setOnPreferenceChangeListener(this);
safeBrowsingPref.setManagedPreferenceDelegate(mManagedPreferenceDelegate); safeBrowsingPref.setManagedPreferenceDelegate(mManagedPreferenceDelegate);
if (BuildInfo.isAtLeastQ()) {
ChromeBaseCheckBoxPreference usageStatsPref =
(ChromeBaseCheckBoxPreference) findPreference(PREF_USAGE_STATS);
usageStatsPref.setOnPreferenceChangeListener(this);
usageStatsPref.setManagedPreferenceDelegate(mManagedPreferenceDelegate);
} else {
preferenceScreen.removePreference(findPreference(PREF_USAGE_STATS));
}
updateSummaries(); updateSummaries();
} }
...@@ -252,9 +244,16 @@ public class PrivacyPreferences extends PreferenceFragment ...@@ -252,9 +244,16 @@ public class PrivacyPreferences extends PreferenceFragment
: textOff); : textOff);
} }
CheckBoxPreference usageStatsPref = (CheckBoxPreference) findPreference(PREF_USAGE_STATS); Preference usageStatsPref = findPreference(PREF_USAGE_STATS);
if (usageStatsPref != null) { if (usageStatsPref != null) {
usageStatsPref.setChecked(prefServiceBridge.getBoolean(Pref.USAGE_STATS_ENABLED)); if (BuildInfo.isAtLeastQ() && prefServiceBridge.getBoolean(Pref.USAGE_STATS_ENABLED)) {
usageStatsPref.setOnPreferenceClickListener(preference -> {
UsageStatsConsentDialog.create(getActivity(), true, false).show();
return true;
});
} else {
getPreferenceScreen().removePreference(usageStatsPref);
}
} }
} }
......
...@@ -4,78 +4,39 @@ ...@@ -4,78 +4,39 @@
package org.chromium.chrome.browser.usage_stats; package org.chromium.chrome.browser.usage_stats;
import android.app.Activity;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.DialogInterface;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.SynchronousInitializationActivity; import org.chromium.chrome.browser.SynchronousInitializationActivity;
import org.chromium.chrome.browser.widget.PromoDialog;
/** /**
* Activity that prompts the user for consent to share browsing activity with Digital Wellbeing. * Activity that prompts the user for consent to share browsing activity with Digital Wellbeing.
*/ */
public class UsageStatsConsentActivity extends SynchronousInitializationActivity { public class UsageStatsConsentActivity extends SynchronousInitializationActivity {
public static final String UNAUTHORIZE_ACTION =
"org.chromium.chrome.browser.usage_stats.action.UNAUTHORIZE";
private static final String DIGITAL_WELLBEING_PACKAGE_NAME = private static final String DIGITAL_WELLBEING_PACKAGE_NAME =
"com.google.android.apps.wellbeing"; "com.google.android.apps.wellbeing";
UsageStatsConsentDialog mDialog;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
// TODO(pnoland): handle revocation as well as authorization.
ComponentName caller = getCallingActivity(); ComponentName caller = getCallingActivity();
if (caller == null if (caller == null
|| !TextUtils.equals(DIGITAL_WELLBEING_PACKAGE_NAME, caller.getPackageName())) { || !TextUtils.equals(DIGITAL_WELLBEING_PACKAGE_NAME, caller.getPackageName())) {
finish(); finish();
return; return;
} }
PromoDialog promoScreen = makePromoScreen();
promoScreen.show();
} }
@Override @Override
protected void onDestroy() { public void onAttachedToWindow() {
super.onDestroy(); String action = getIntent().getAction();
} boolean isRevocation = TextUtils.equals(action, UNAUTHORIZE_ACTION);
UsageStatsConsentDialog.create(this, isRevocation, true).show();
private PromoDialog makePromoScreen() {
return new PromoDialog(this) {
@Override
protected DialogParams getDialogParams() {
PromoDialog.DialogParams params = new PromoDialog.DialogParams();
params.headerStringResource = R.string.usage_stats_consent_title;
params.subheaderStringResource = R.string.usage_stats_consent_prompt;
params.primaryButtonStringResource = R.string.ok;
params.secondaryButtonStringResource = R.string.cancel;
return params;
}
@Override
public void onDismiss(DialogInterface dialog) {
UsageStatsConsentActivity.this.finish();
}
@Override
public void onClick(View v) {
int id = v.getId();
UsageStatsService service = UsageStatsService.getInstance();
if (id == R.id.button_primary) {
service.setOptInState(true);
UsageStatsConsentActivity.this.setResult(Activity.RESULT_OK);
UsageStatsConsentActivity.this.finish();
} else if (id == R.id.button_secondary) {
service.setOptInState(false);
UsageStatsConsentActivity.this.setResult(Activity.RESULT_CANCELED);
UsageStatsConsentActivity.this.finish();
} else {
assert false : "Unhandled onClick event";
}
}
};
} }
} }
\ No newline at end of file
// Copyright 2019 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.usage_stats;
import android.app.Activity;
import android.content.res.Resources;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.modaldialog.AppModalPresenter;
import org.chromium.ui.modaldialog.ModalDialogManager;
import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType;
import org.chromium.ui.modaldialog.ModalDialogProperties;
import org.chromium.ui.modelutil.PropertyModel;
/**
* Dialog prompting a user to either enable integration with Digital Wellbeing or to revoke
* permission for that integration.
* TODO(pnoland): Revisit the style of this dialog and where it's used(i.e. whether it's used from
* PrivacyPreferences or not) to ensure that the visual style is consistent.
*/
public class UsageStatsConsentDialog {
private Activity mActivity;
private ModalDialogManager mManager;
private PropertyModel mDialogModel;
private boolean mIsRevocation;
private boolean mIsStandaloneActivity;
public static UsageStatsConsentDialog create(
Activity activity, boolean isRevocation, boolean isStandaloneActivity) {
return new UsageStatsConsentDialog(activity, isRevocation, isStandaloneActivity);
}
/** Show this dialog in the context of its enclosing activity. */
public void show() {
Resources resources = mActivity.getResources();
PropertyModel.Builder builder =
new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS)
.with(ModalDialogProperties.CONTROLLER, makeController())
.with(ModalDialogProperties.NEGATIVE_BUTTON_TEXT, resources,
R.string.cancel);
if (mIsRevocation) {
builder.with(ModalDialogProperties.TITLE, resources,
R.string.usage_stats_revocation_prompt)
.with(ModalDialogProperties.MESSAGE, resources,
R.string.usage_stats_revocation_explanation)
.with(ModalDialogProperties.POSITIVE_BUTTON_TEXT, resources, R.string.remove);
} else {
builder.with(ModalDialogProperties.TITLE, resources, R.string.usage_stats_consent_title)
.with(ModalDialogProperties.MESSAGE, resources,
R.string.usage_stats_consent_prompt)
.with(ModalDialogProperties.POSITIVE_BUTTON_TEXT, resources, R.string.show);
}
mDialogModel = builder.build();
mManager = new ModalDialogManager(new AppModalPresenter(mActivity), ModalDialogType.APP);
mManager.showDialog(mDialogModel, ModalDialogType.APP);
}
private UsageStatsConsentDialog(
Activity activity, boolean isRevocation, boolean isStandaloneActivity) {
mActivity = activity;
mIsRevocation = isRevocation;
mIsStandaloneActivity = isStandaloneActivity;
}
private ModalDialogProperties.Controller makeController() {
return new ModalDialogProperties.Controller() {
@Override
public void onClick(PropertyModel model, int buttonType) {
UsageStatsService service = UsageStatsService.getInstance();
int result = Activity.RESULT_CANCELED;
switch (buttonType) {
case ModalDialogProperties.ButtonType.POSITIVE:
service.setOptInState(!mIsRevocation);
result = Activity.RESULT_OK;
break;
case ModalDialogProperties.ButtonType.NEGATIVE:
service.setOptInState(mIsRevocation);
result = Activity.RESULT_CANCELED;
break;
}
if (mIsStandaloneActivity) {
mActivity.setResult(result);
}
dismiss();
}
@Override
public void onDismiss(PropertyModel model, int dismissalCause) {
if (mIsStandaloneActivity) {
mActivity.finish();
}
mManager.destroy();
}
};
}
private void dismiss() {
mManager.destroy();
}
}
\ No newline at end of file
...@@ -254,6 +254,9 @@ CHAR-LIMIT guidelines: ...@@ -254,6 +254,9 @@ CHAR-LIMIT guidelines:
<message name="IDS_CONFIRM" desc="Label for a confirm button. Used in multiple contexts. [CHAR-LIMIT=20]"> <message name="IDS_CONFIRM" desc="Label for a confirm button. Used in multiple contexts. [CHAR-LIMIT=20]">
Confirm Confirm
</message> </message>
<message name="IDS_SHOW" desc="Label for a show button. Used in multiple contexts. [CHAR-LIMIT=20]">
Show
</message>
<!-- Main Preferences --> <!-- Main Preferences -->
<message name="IDS_PREFERENCES" desc="Title for Chrome's Settings."> <message name="IDS_PREFERENCES" desc="Title for Chrome's Settings.">
...@@ -4045,13 +4048,19 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p ...@@ -4045,13 +4048,19 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
</message> </message>
<!-- Usage Stats strings --> <!-- Usage Stats strings -->
<message name="IDS_USAGE_STATS_CONSENT_TITLE" desc="Title for activity authorizing Digital Wellbeing to access Chrome usage data"> <message name="IDS_USAGE_STATS_CONSENT_TITLE" desc="Title for activity authorizing Digital Wellbeing to access Chrome usage data">
Connect Chrome to Digital Wellbeing? Show your Chrome activity in Digital Wellbeing?
</message> </message>
<message name="IDS_USAGE_STATS_CONSENT_PROMPT" desc="Consent prompt when authorizing Digital Wellbeing to access Chrome usage data"> <message name="IDS_USAGE_STATS_CONSENT_PROMPT" desc="Consent prompt when authorizing Digital Wellbeing to access Chrome usage data">
Allow Digital Wellbeing to show websites you visited You can see sites you visit in Chrome and set timers for them.\n\nGoogle gets info about the sites you set timers for and how long you visit them. This info is used to make Digital Wellbeing better.
</message>
<message name="IDS_USAGE_STATS_SETTING_TITLE" desc="Title for setting removing Digital Wellbeing's access to Chrome usage data">
Remove your Chrome activity from Digital Wellbeing
</message>
<message name="IDS_USAGE_STATS_REVOCATION_PROMPT" desc="Prompt for removing Digital Wellbeing's access to Chrome usage data">
Remove your Chrome activity from Digital Wellbeing?
</message> </message>
<message name="IDS_USAGE_STATS_SETTING_TITLE" desc="Title for setting toggling Digital Wellbeing to access Chrome usage data"> <message name="IDS_USAGE_STATS_REVOCATION_EXPLANATION" desc="Explanation of the effect of revoking Digital Wellbeing's access to Chrome usage data">
Connect to Digital Wellbeing Sites you visit in Chrome won't show. All site timers will be deleted.
</message> </message>
<message name="IDS_USAGE_STATS_SITE_PAUSED" desc="Message when a website is suspended due to exceeding a user-defined limit"> <message name="IDS_USAGE_STATS_SITE_PAUSED" desc="Message when a website is suspended due to exceeding a user-defined limit">
Site paused Site paused
......
31d97a96a4fdd511ca20cbe0269d6c9438bafdb0
\ No newline at end of file
80616bf5a8556aa427e879651a52a4a13ac93206 31d97a96a4fdd511ca20cbe0269d6c9438bafdb0
\ No newline at end of file \ No newline at end of file
80616bf5a8556aa427e879651a52a4a13ac93206 31d97a96a4fdd511ca20cbe0269d6c9438bafdb0
\ No newline at end of file \ No newline at end of file
38644129ac6e5d255091c42ca5ddf01f71ac9e36
\ No newline at end of file
cb952ebac04dfca80271fd7a62c536db99235acf 04aa439f36c56fa16b89c6b4eec192fb240e3586
\ No newline at end of file \ No newline at end of file
...@@ -1679,6 +1679,7 @@ chrome_java_sources = [ ...@@ -1679,6 +1679,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/usage_stats/TokenTracker.java", "java/src/org/chromium/chrome/browser/usage_stats/TokenTracker.java",
"java/src/org/chromium/chrome/browser/usage_stats/UsageStatsBridge.java", "java/src/org/chromium/chrome/browser/usage_stats/UsageStatsBridge.java",
"java/src/org/chromium/chrome/browser/usage_stats/UsageStatsConsentActivity.java", "java/src/org/chromium/chrome/browser/usage_stats/UsageStatsConsentActivity.java",
"java/src/org/chromium/chrome/browser/usage_stats/UsageStatsConsentDialog.java",
"java/src/org/chromium/chrome/browser/usage_stats/UsageStatsService.java", "java/src/org/chromium/chrome/browser/usage_stats/UsageStatsService.java",
"java/src/org/chromium/chrome/browser/usage_stats/WebsiteEvent.java", "java/src/org/chromium/chrome/browser/usage_stats/WebsiteEvent.java",
"java/src/org/chromium/chrome/browser/util/AccessibilityUtil.java", "java/src/org/chromium/chrome/browser/util/AccessibilityUtil.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