Skip to content

Commit 3d3188a

Browse files
author
Becky Zhou
committed
[EoC] Contextual suggestions opt out
Add an item in settings to turn on/off contextual suggestions. [email protected] Bug: 822953 Change-Id: I9533b6afcc21c23ee580e8d7008b6dc3ca1e74d3 Reviewed-on: https://chromium-review.googlesource.com/1006232 Commit-Queue: Becky Zhou <[email protected]> Reviewed-by: Theresa <[email protected]> Reviewed-by: Matthew Jones <[email protected]> Reviewed-by: Bernhard Bauer <[email protected]> Cr-Original-Commit-Position: refs/heads/master@{#550465}(cherry picked from commit 5ea1b5b) Reviewed-on: https://chromium-review.googlesource.com/1015725 Reviewed-by: Becky Zhou <[email protected]> Cr-Commit-Position: refs/branch-heads/3396@{#62} Cr-Branched-From: 9ef2aa8-refs/heads/master@{#550428}
1 parent a9ea7f6 commit 3d3188a

File tree

17 files changed

+297
-29
lines changed

17 files changed

+297
-29
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- Copyright 2018 The Chromium Authors. All rights reserved.
3+
Use of this source code is governed by a BSD-style license that can be
4+
found in the LICENSE file. -->
5+
6+
<PreferenceScreen
7+
xmlns:android="http://schemas.android.com/apk/res/android"
8+
xmlns:chrome="http://schemas.android.com/apk/res-auto">
9+
10+
<org.chromium.chrome.browser.preferences.ChromeSwitchPreference
11+
android:key="contextual_suggestions_switch"
12+
android:summaryOn="@string/text_on"
13+
android:summaryOff="@string/text_off"
14+
chrome:drawDivider="true" />
15+
16+
<org.chromium.chrome.browser.preferences.TextMessagePreference
17+
android:title="@string/contextual_suggestions_description" />
18+
19+
<org.chromium.chrome.browser.preferences.TextMessagePreference
20+
android:key="contextual_suggestions_message" />
21+
22+
</PreferenceScreen>

chrome/android/java/res/xml/main_preferences.xml

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,50 +35,55 @@
3535
android:key="notifications"
3636
android:order="5"
3737
android:title="@string/prefs_notifications"/>
38+
<Preference
39+
android:fragment="org.chromium.chrome.browser.preferences.ContextualSuggestionsPreference"
40+
android:key="contextual_suggestions"
41+
android:order="6"
42+
android:title="@string/prefs_contextual_suggestions"/>
3843
<Preference
3944
android:fragment="org.chromium.chrome.browser.preferences.HomepagePreferences"
4045
android:key="homepage"
41-
android:order="6"
46+
android:order="7"
4247
android:title="@string/options_homepage_title"/>
4348

4449
<PreferenceCategory
4550
android:key="advanced_section"
46-
android:order="7"
51+
android:order="8"
4752
android:title="@string/prefs_section_advanced"/>
4853
<Preference
4954
android:fragment="org.chromium.chrome.browser.preferences.privacy.PrivacyPreferences"
5055
android:key="privacy"
51-
android:order="8"
56+
android:order="9"
5257
android:title="@string/prefs_privacy"/>
5358
<Preference
5459
android:fragment="org.chromium.chrome.browser.preferences.AccessibilityPreferences"
5560
android:key="accessibility"
56-
android:order="9"
61+
android:order="10"
5762
android:title="@string/prefs_accessibility"/>
5863
<Preference
5964
android:fragment="org.chromium.chrome.browser.preferences.website.SiteSettingsPreferences"
6065
android:key="content_settings"
61-
android:order="10"
66+
android:order="11"
6267
android:title="@string/prefs_site_settings"/>
6368
<Preference
6469
android:fragment="org.chromium.chrome.browser.preferences.languages.LanguagesPreferences"
6570
android:key="languages"
66-
android:order="11"
71+
android:order="12"
6772
android:title="@string/prefs_languages"/>
6873
<org.chromium.chrome.browser.preferences.ChromeBasePreference
6974
android:fragment="org.chromium.chrome.browser.preferences.datareduction.DataReductionPreferences"
7075
android:key="data_reduction"
71-
android:order="12"
76+
android:order="13"
7277
android:title="@string/data_reduction_title"/>
7378
<org.chromium.chrome.browser.preferences.ChromeBasePreference
7479
android:fragment="org.chromium.chrome.browser.preferences.download.DownloadPreferences"
7580
android:key="downloads"
76-
android:order="13"
81+
android:order="14"
7782
android:title="@string/menu_downloads"/>
7883
<Preference
7984
android:fragment="org.chromium.chrome.browser.preferences.AboutChromePreferences"
8085
android:key="about_chrome"
81-
android:order="14"
86+
android:order="15"
8287
android:title="@string/prefs_about_chrome"/>
8388

8489
</PreferenceScreen>

chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsBridge.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
* Provides access to contextual suggestions.
2222
*/
2323
@JNINamespace("contextual_suggestions")
24-
class ContextualSuggestionsBridge {
24+
public class ContextualSuggestionsBridge {
2525
private long mNativeContextualSuggestionsBridge;
2626

2727
/** Result of fetching contextual suggestions. */
@@ -56,7 +56,7 @@ public List<ContextualSuggestionsCluster> getClusters() {
5656
/**
5757
* @return Whether the current profile is enterprise policy managed.
5858
*/
59-
static boolean isEnterprisePolicyManaged() {
59+
public static boolean isEnterprisePolicyManaged() {
6060
return nativeIsEnterprisePolicyManaged();
6161
}
6262

chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,9 @@ public void onEnabledStateChanged(boolean enabled) {
153153
}
154154
}
155155

156+
@Override
157+
public void onSettingsStateChanged(boolean enabled) {}
158+
156159
@Override
157160
public void requestSuggestions(String url) {
158161
mCurrentRequestUrl = url;

chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/EnabledStateMonitor.java

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
package org.chromium.chrome.browser.contextual_suggestions;
66

77
import org.chromium.base.VisibleForTesting;
8+
import org.chromium.chrome.browser.preferences.Pref;
9+
import org.chromium.chrome.browser.preferences.PrefChangeRegistrar;
10+
import org.chromium.chrome.browser.preferences.PrefServiceBridge;
811
import org.chromium.chrome.browser.search_engines.TemplateUrlService;
912
import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrlServiceObserver;
1013
import org.chromium.chrome.browser.signin.SigninManager;
@@ -19,22 +22,30 @@
1922
* A monitor that is responsible for detecting changes to conditions required for contextual
2023
* suggestions to be enabled. Alerts its {@link Observer} when state changes.
2124
*/
22-
public class EnabledStateMonitor
23-
implements SyncStateChangedListener, SignInStateObserver, TemplateUrlServiceObserver {
25+
public class EnabledStateMonitor implements SyncStateChangedListener, SignInStateObserver,
26+
TemplateUrlServiceObserver,
27+
PrefChangeRegistrar.PrefObserver {
2428
/** An observer to be notified of enabled state changes. **/
25-
interface Observer {
29+
public interface Observer {
2630
void onEnabledStateChanged(boolean enabled);
31+
void onSettingsStateChanged(boolean enabled);
2732
}
2833

2934
@VisibleForTesting
3035
protected Observer mObserver;
36+
private PrefChangeRegistrar mPrefChangeRegistrar;
37+
38+
/** Whether contextual suggestions are enabled. */
3139
private boolean mEnabled;
3240

41+
/** Whether the user settings for contextual suggestions are enabled. */
42+
private boolean mSettingsEnabled;
43+
3344
/**
3445
* Construct a new {@link EnabledStateMonitor}.
3546
* @param observer The {@link Observer} to be notified of changes to enabled state.
3647
*/
37-
EnabledStateMonitor(Observer observer) {
48+
public EnabledStateMonitor(Observer observer) {
3849
mObserver = observer;
3950
init();
4051
}
@@ -46,19 +57,49 @@ interface Observer {
4657
*/
4758
@VisibleForTesting
4859
protected void init() {
60+
mPrefChangeRegistrar = new PrefChangeRegistrar();
61+
mPrefChangeRegistrar.addObserver(Pref.CONTEXTUAL_SUGGESTIONS_ENABLED, this);
4962
ProfileSyncService.get().addSyncStateChangedListener(this);
5063
SigninManager.get().addSignInStateObserver(this);
5164
TemplateUrlService.getInstance().addObserver(this);
5265
updateEnabledState();
5366
}
5467

5568
/** Destroys the EnabledStateMonitor. */
56-
void destroy() {
69+
public void destroy() {
70+
mPrefChangeRegistrar.destroy();
5771
ProfileSyncService.get().removeSyncStateChangedListener(this);
5872
SigninManager.get().removeSignInStateObserver(this);
5973
TemplateUrlService.getInstance().removeObserver(this);
6074
}
6175

76+
/** @return Whether the user settings for contextual suggestions should be shown. */
77+
public static boolean shouldShowSettings() {
78+
return TemplateUrlService.getInstance().isDefaultSearchEngineGoogle()
79+
&& !AccessibilityUtil.isAccessibilityEnabled()
80+
&& !ContextualSuggestionsBridge.isEnterprisePolicyManaged();
81+
}
82+
83+
/** @return Whether the settings state is currently enabled. */
84+
public static boolean getSettingsEnabled() {
85+
ProfileSyncService service = ProfileSyncService.get();
86+
87+
boolean isUploadToGoogleActive =
88+
service.getUploadToGoogleState(ModelType.HISTORY_DELETE_DIRECTIVES)
89+
== UploadState.ACTIVE;
90+
boolean isGoogleDSE = TemplateUrlService.getInstance().isDefaultSearchEngineGoogle();
91+
boolean isAccessibilityEnabled = AccessibilityUtil.isAccessibilityEnabled();
92+
93+
return isUploadToGoogleActive && isGoogleDSE && !isAccessibilityEnabled
94+
&& !ContextualSuggestionsBridge.isEnterprisePolicyManaged();
95+
}
96+
97+
/** @return Whether the state is currently enabled. */
98+
public static boolean getEnabledState() {
99+
return getSettingsEnabled()
100+
&& PrefServiceBridge.getInstance().getBoolean(Pref.CONTEXTUAL_SUGGESTIONS_ENABLED);
101+
}
102+
62103
/** Called when accessibility mode changes. */
63104
void onAccessibilityModeChanged() {
64105
updateEnabledState();
@@ -84,25 +125,25 @@ public void onTemplateURLServiceChanged() {
84125
updateEnabledState();
85126
}
86127

128+
@Override
129+
public void onPreferenceChange() {
130+
updateEnabledState();
131+
}
132+
87133
/**
88134
* Updates whether contextual suggestions are enabled. Notifies the observer if the
89135
* enabled state has changed.
90136
*/
91137
private void updateEnabledState() {
138+
boolean previousSettingsState = mSettingsEnabled;
92139
boolean previousState = mEnabled;
93140

94-
ProfileSyncService service = ProfileSyncService.get();
95-
96-
boolean isUploadToGoogleActive =
97-
service.getUploadToGoogleState(ModelType.HISTORY_DELETE_DIRECTIVES)
98-
== UploadState.ACTIVE;
99-
boolean isGoogleDSE = TemplateUrlService.getInstance().isDefaultSearchEngineGoogle();
100-
boolean isAccessibilityEnabled = AccessibilityUtil.isAccessibilityEnabled();
101-
102-
mEnabled = isUploadToGoogleActive && isGoogleDSE && !isAccessibilityEnabled
103-
&& !ContextualSuggestionsBridge.isEnterprisePolicyManaged();
141+
mSettingsEnabled = getSettingsEnabled();
142+
mEnabled = getEnabledState();
104143

105-
// TODO(twellington): Add run-time check for opt-out state.
144+
if (mSettingsEnabled != previousSettingsState) {
145+
mObserver.onSettingsStateChanged(mSettingsEnabled);
146+
}
106147

107148
if (mEnabled != previousState) mObserver.onEnabledStateChanged(mEnabled);
108149
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// Copyright 2018 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
package org.chromium.chrome.browser.preferences;
6+
7+
import android.content.Context;
8+
import android.content.Intent;
9+
import android.os.Bundle;
10+
import android.preference.Preference;
11+
import android.preference.PreferenceFragment;
12+
import android.support.annotation.Nullable;
13+
import android.text.SpannableString;
14+
import android.view.View;
15+
16+
import org.chromium.chrome.R;
17+
import org.chromium.chrome.browser.contextual_suggestions.ContextualSuggestionsBridge;
18+
import org.chromium.chrome.browser.contextual_suggestions.EnabledStateMonitor;
19+
import org.chromium.chrome.browser.signin.AccountSigninActivity;
20+
import org.chromium.chrome.browser.signin.SigninAccessPoint;
21+
import org.chromium.chrome.browser.sync.ui.SyncCustomizationFragment;
22+
import org.chromium.chrome.browser.util.IntentUtils;
23+
import org.chromium.components.signin.ChromeSigninController;
24+
import org.chromium.ui.text.NoUnderlineClickableSpan;
25+
import org.chromium.ui.text.SpanApplier;
26+
27+
/**
28+
* Fragment to manage the Contextual Suggestions preference and to explain to the user what it does.
29+
*/
30+
public class ContextualSuggestionsPreference
31+
extends PreferenceFragment implements EnabledStateMonitor.Observer {
32+
private static final String PREF_CONTEXTUAL_SUGGESTIONS_SWITCH =
33+
"contextual_suggestions_switch";
34+
private static final String PREF_CONTEXTUAL_SUGGESTIONS_MESSAGE =
35+
"contextual_suggestions_message";
36+
37+
private ChromeSwitchPreference mSwitch;
38+
private EnabledStateMonitor mEnabledStateMonitor;
39+
40+
@Override
41+
public void onCreate(@Nullable Bundle savedInstanceState) {
42+
super.onCreate(savedInstanceState);
43+
PreferenceUtils.addPreferencesFromResource(this, R.xml.contextual_suggestions_preferences);
44+
getActivity().setTitle(R.string.prefs_contextual_suggestions);
45+
46+
mSwitch = (ChromeSwitchPreference) findPreference(PREF_CONTEXTUAL_SUGGESTIONS_SWITCH);
47+
mEnabledStateMonitor = new EnabledStateMonitor(this);
48+
initialize();
49+
}
50+
51+
@Override
52+
public void onResume() {
53+
super.onResume();
54+
updateSwitch();
55+
}
56+
57+
@Override
58+
public void onDestroy() {
59+
super.onDestroy();
60+
mEnabledStateMonitor.destroy();
61+
}
62+
63+
@Override
64+
public void onEnabledStateChanged(boolean enabled) {}
65+
66+
@Override
67+
public void onSettingsStateChanged(boolean enabled) {
68+
if (mEnabledStateMonitor != null) updateSwitch();
69+
}
70+
71+
/** Helper method to initialize the switch preference and the message preference. */
72+
private void initialize() {
73+
final TextMessagePreference message =
74+
(TextMessagePreference) findPreference(PREF_CONTEXTUAL_SUGGESTIONS_MESSAGE);
75+
final SpannableString spannable = SpanApplier.applySpans(
76+
getResources().getString(R.string.contextual_suggestions_message),
77+
new SpanApplier.SpanInfo("<link>", "</link>", new NoUnderlineClickableSpan() {
78+
@Override
79+
public void onClick(View widget) {
80+
Context context = getActivity();
81+
if (ChromeSigninController.get().isSignedIn()) {
82+
Intent intent = PreferencesLauncher.createIntentForSettingsPage(
83+
context, SyncCustomizationFragment.class.getName());
84+
IntentUtils.safeStartActivity(context, intent);
85+
} else {
86+
startActivity(AccountSigninActivity.createIntentForDefaultSigninFlow(
87+
context, SigninAccessPoint.SETTINGS, false));
88+
}
89+
}
90+
}));
91+
message.setTitle(spannable);
92+
93+
updateSwitch();
94+
mSwitch.setOnPreferenceChangeListener((preference, newValue) -> {
95+
PrefServiceBridge.getInstance().setBoolean(
96+
Pref.CONTEXTUAL_SUGGESTIONS_ENABLED, (boolean) newValue);
97+
return true;
98+
});
99+
mSwitch.setManagedPreferenceDelegate(new ManagedPreferenceDelegate() {
100+
@Override
101+
public boolean isPreferenceControlledByPolicy(Preference preference) {
102+
return ContextualSuggestionsBridge.isEnterprisePolicyManaged();
103+
}
104+
});
105+
}
106+
107+
/** Helper method to update the enabled state of the switch. */
108+
private void updateSwitch() {
109+
mSwitch.setEnabled(EnabledStateMonitor.getSettingsEnabled());
110+
mSwitch.setChecked(EnabledStateMonitor.getEnabledState());
111+
}
112+
}

0 commit comments

Comments
 (0)