Skip to content
This repository was archived by the owner on Jul 22, 2024. It is now read-only.

Commit 483f245

Browse files
keianhzobluemarvin
authored andcommitted
Dialog for requesting permission for storing voice samples (#1507)
* Added a dialog for requesting permission for storing voice samples * Do not store samples in private mode * Continue to voice search if the data collection is not allowed
1 parent 4cab6e4 commit 483f245

11 files changed

Lines changed: 329 additions & 10 deletions

File tree

app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,6 +1284,11 @@ public void openNewWindow(String uri) {
12841284
newWindow.getSessionStack().newSessionWithUrl(uri);
12851285
}
12861286

1287+
@Override
1288+
public WindowWidget getFocusedWindow() {
1289+
return mWindows.getFocusedWindow();
1290+
}
1291+
12871292
private native void addWidgetNative(int aHandle, WidgetPlacement aPlacement);
12881293
private native void updateWidgetNative(int aHandle, WidgetPlacement aPlacement);
12891294
private native void updateVisibleWidgetsNative();

app/src/common/shared/org/mozilla/vrbrowser/browser/SettingsStore.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ SettingsStore getInstance(final @NonNull Context aContext) {
5252
public final static boolean TRACKING_DEFAULT = true;
5353
public final static boolean NOTIFICATIONS_DEFAULT = true;
5454
public final static boolean SPEECH_DATA_COLLECTION_DEFAULT = false;
55+
public final static boolean SPEECH_DATA_COLLECTION_REVIEWED_DEFAULT = false;
5556
public final static boolean SERVO_DEFAULT = false;
5657
public final static int UA_MODE_DEFAULT = GeckoSessionSettings.USER_AGENT_MODE_VR;
5758
public final static int INPUT_MODE_DEFAULT = 1;
@@ -542,5 +543,16 @@ public void setNotificationsEnabled(boolean isEnabled) {
542543
editor.putBoolean(mContext.getString(R.string.settings_key_notifications), isEnabled);
543544
editor.commit();
544545
}
546+
547+
public boolean isSpeechDataCollectionReviewed() {
548+
return mPrefs.getBoolean(
549+
mContext.getString(R.string.settings_key_speech_data_collection_reviewed), SPEECH_DATA_COLLECTION_REVIEWED_DEFAULT);
550+
}
551+
552+
public void setSpeechDataCollectionReviewed(boolean isEnabled) {
553+
SharedPreferences.Editor editor = mPrefs.edit();
554+
editor.putBoolean(mContext.getString(R.string.settings_key_speech_data_collection_reviewed), isEnabled);
555+
editor.commit();
556+
}
545557
}
546558

app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/NavigationBarWidget.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,7 @@ private void enterVRVideo(@VideoProjectionMenuWidget.VideoProjectionFlags int aP
574574
this.setVisible(false);
575575
if (mFullScreenMedia != null && mFullScreenMedia.getWidth() > 0 && mFullScreenMedia.getHeight() > 0) {
576576
final boolean resetBorder = aProjection == VideoProjectionMenuWidget.VIDEO_PROJECTION_360 ||
577-
aProjection == VideoProjectionMenuWidget.VIDEO_PROJECTION_360_STEREO;
577+
aProjection == VideoProjectionMenuWidget.VIDEO_PROJECTION_360_STEREO;
578578
mAttachedWindow.enableVRVideoMode(mFullScreenMedia.getWidth(), mFullScreenMedia.getHeight(), resetBorder);
579579
// Handle video resize while in VR video playback
580580
mFullScreenMedia.setResizeDelegate((width, height) -> {
@@ -844,6 +844,7 @@ public void OnVoiceSearchClicked() {
844844
mVoiceSearchWidget.hide(REMOVE_WIDGET);
845845

846846
} else {
847+
mVoiceSearchWidget.getPlacement().parentHandle = mAttachedWindow.getHandle();
847848
mVoiceSearchWidget.show(REQUEST_FOCUS);
848849
}
849850
}

app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WidgetManagerDelegate.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,5 @@ interface WorldClickListener {
7979
boolean isPermissionGranted(@NonNull String permission);
8080
void requestPermission(String uri, @NonNull String permission, GeckoSession.PermissionDelegate.Callback aCallback);
8181
void openNewWindow(@NonNull String uri);
82+
WindowWidget getFocusedWindow();
8283
}

app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.mozilla.gecko.util.ThreadUtils;
2323
import androidx.annotation.NonNull;
2424
import androidx.annotation.Nullable;
25+
import androidx.annotation.StringRes;
2526

2627
import org.mozilla.geckoview.AllowOrDeny;
2728
import org.mozilla.geckoview.GeckoDisplay;
@@ -35,6 +36,7 @@
3536
import org.mozilla.vrbrowser.browser.engine.SessionStack;
3637
import org.mozilla.vrbrowser.telemetry.TelemetryWrapper;
3738
import org.mozilla.vrbrowser.ui.views.BookmarksView;
39+
import org.mozilla.vrbrowser.ui.widgets.dialogs.AppDialogWidget;
3840
import org.mozilla.vrbrowser.ui.widgets.dialogs.ContextMenuWidget;
3941
import org.mozilla.vrbrowser.ui.widgets.dialogs.MaxWindowsWidget;
4042
import org.mozilla.vrbrowser.ui.widgets.prompts.AlertPromptWidget;
@@ -72,6 +74,7 @@ public class WindowWidget extends UIWidget implements SessionChangeListener,
7274
private TextPromptWidget mTextPrompt;
7375
private AuthPromptWidget mAuthPrompt;
7476
private NoInternetWidget mNoInternetToast;
77+
private AppDialogWidget mAppDialog;
7578
private ContextMenuWidget mContextMenu;
7679
private int mWidthBackup;
7780
private int mHeightBackup;
@@ -728,6 +731,26 @@ public void showButtonPrompt(String title, @NonNull String msg, @NonNull String[
728731
mConfirmPrompt.show(REQUEST_FOCUS);
729732
}
730733

734+
public void showAppDialog(@NonNull @StringRes int title, @NonNull @StringRes int description, @NonNull @StringRes int [] btnMsg, @NonNull AppDialogWidget.Delegate callback) {
735+
mAppDialog = new AppDialogWidget(getContext());
736+
mAppDialog.mWidgetPlacement.parentHandle = getHandle();
737+
mAppDialog.setTitle(title);
738+
mAppDialog.setMessage(description);
739+
mAppDialog.setButtons(btnMsg);
740+
mAppDialog.setDelegate(callback);
741+
mAppDialog.show(REQUEST_FOCUS);
742+
}
743+
744+
public void showAppDialog(@NonNull String title, @NonNull String description, @NonNull String[] btnMsg, @NonNull AppDialogWidget.Delegate callback) {
745+
mAppDialog = new AppDialogWidget(getContext());
746+
mAppDialog.mWidgetPlacement.parentHandle = getHandle();
747+
mAppDialog.setTitle(title);
748+
mAppDialog.setMessage(description);
749+
mAppDialog.setButtons(btnMsg);
750+
mAppDialog.setDelegate(callback);
751+
mAppDialog.show(REQUEST_FOCUS);
752+
}
753+
731754
public void showMaxWindowsDialog(int maxDialogs) {
732755
mMaxWindowsDialog = new MaxWindowsWidget(getContext());
733756
mMaxWindowsDialog.mWidgetPlacement.parentHandle = getHandle();
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
2+
* This Source Code Form is subject to the terms of the Mozilla Public
3+
* License, v. 2.0. If a copy of the MPL was not distributed with this
4+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5+
6+
package org.mozilla.vrbrowser.ui.widgets.dialogs;
7+
8+
import android.content.Context;
9+
import android.util.AttributeSet;
10+
import android.view.LayoutInflater;
11+
import android.view.View;
12+
import android.view.ViewTreeObserver;
13+
14+
import androidx.annotation.NonNull;
15+
import androidx.annotation.StringRes;
16+
import androidx.databinding.DataBindingUtil;
17+
18+
import org.mozilla.vrbrowser.R;
19+
import org.mozilla.vrbrowser.databinding.AppDialogBinding;
20+
import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate;
21+
import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement;
22+
import org.mozilla.vrbrowser.utils.ViewUtils;
23+
24+
public class AppDialogWidget extends UIDialog {
25+
26+
public interface Delegate {
27+
void onButtonClicked(int index);
28+
void onMessageLinkClicked(@NonNull String url);
29+
}
30+
31+
public static final int LEFT = 0;
32+
public static final int RIGHT = 1;
33+
34+
private AppDialogBinding mBinding;
35+
private Delegate mAppDialogDelegate;
36+
37+
public AppDialogWidget(Context aContext) {
38+
super(aContext);
39+
initialize(aContext);
40+
}
41+
42+
public AppDialogWidget(Context aContext, AttributeSet aAttrs) {
43+
super(aContext, aAttrs);
44+
initialize(aContext);
45+
}
46+
47+
public AppDialogWidget(Context aContext, AttributeSet aAttrs, int aDefStyle) {
48+
super(aContext, aAttrs, aDefStyle);
49+
initialize(aContext);
50+
}
51+
52+
private void initialize(Context aContext) {
53+
LayoutInflater inflater = LayoutInflater.from(aContext);
54+
55+
// Inflate this data binding layout
56+
mBinding = DataBindingUtil.inflate(inflater, R.layout.app_dialog, this, true);
57+
58+
mBinding.leftButton.setOnClickListener(v -> {
59+
if (mAppDialogDelegate != null)
60+
mAppDialogDelegate.onButtonClicked(LEFT);
61+
62+
AppDialogWidget.this.onDismiss();
63+
});
64+
mBinding.rightButton.setOnClickListener(v -> {
65+
if (mAppDialogDelegate != null)
66+
mAppDialogDelegate.onButtonClicked(RIGHT);
67+
68+
AppDialogWidget.this.onDismiss();
69+
});
70+
}
71+
72+
@Override
73+
protected void initializeWidgetPlacement(WidgetPlacement aPlacement) {
74+
aPlacement.visible = false;
75+
aPlacement.width = WidgetPlacement.dpDimension(getContext(), R.dimen.app_dialog_width);
76+
aPlacement.height = WidgetPlacement.pixelDimension(getContext(), R.dimen.browser_width_pixels)/2;
77+
aPlacement.parentAnchorX = 0.5f;
78+
aPlacement.parentAnchorY = 0.5f;
79+
aPlacement.anchorX = 0.5f;
80+
aPlacement.anchorY = 0.5f;
81+
aPlacement.translationZ = WidgetPlacement.unitFromMeters(getContext(), R.dimen.app_dialog_z_distance);
82+
}
83+
84+
85+
@Override
86+
public void show(@ShowFlags int aShowFlags) {
87+
measure(View.MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
88+
View.MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
89+
90+
super.show(aShowFlags);
91+
92+
mWidgetManager.pushWorldBrightness(this, WidgetManagerDelegate.DEFAULT_DIM_BRIGHTNESS);
93+
94+
ViewTreeObserver viewTreeObserver = getViewTreeObserver();
95+
if (viewTreeObserver.isAlive()) {
96+
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
97+
@Override
98+
public void onGlobalLayout() {
99+
getViewTreeObserver().removeOnGlobalLayoutListener(this);
100+
mWidgetPlacement.height = (int)(getHeight()/mWidgetPlacement.density);
101+
mWidgetManager.updateWidget(AppDialogWidget.this);
102+
}
103+
});
104+
}
105+
}
106+
107+
public void hide(@HideFlags int aHideFlags) {
108+
super.hide(aHideFlags);
109+
mWidgetManager.popWorldBrightness(this);
110+
}
111+
112+
// WidgetManagerDelegate.FocusChangeListener
113+
@Override
114+
public void onGlobalFocusChanged(View oldFocus, View newFocus) {
115+
if (oldFocus == this && isVisible() && findViewById(newFocus.getId()) == null) {
116+
onDismiss();
117+
}
118+
}
119+
120+
public void setDelegate(Delegate delegate) {
121+
mAppDialogDelegate = delegate;
122+
}
123+
124+
public void setTitle(@StringRes int title) {
125+
mBinding.title.setText(title);
126+
}
127+
128+
public void setTitle(String title) {
129+
mBinding.title.setText(title);
130+
}
131+
132+
public void setMessage(@StringRes int message) {
133+
ViewUtils.setTextViewHTML(mBinding.message, getResources().getString(message), (widget, url) -> {
134+
if (mAppDialogDelegate != null) {
135+
mAppDialogDelegate.onMessageLinkClicked(url);
136+
onDismiss();
137+
}
138+
});
139+
}
140+
141+
public void setMessage(String message) {
142+
mBinding.message.setText(message);
143+
}
144+
145+
public void setButtons(@StringRes int[] buttons) {
146+
if (buttons.length > 0)
147+
mBinding.leftButton.setText(buttons[LEFT]);
148+
if (buttons.length > 1)
149+
mBinding.rightButton.setText(buttons[RIGHT]);
150+
}
151+
152+
public void setButtons(@NonNull String[] buttons) {
153+
if (buttons.length > 0)
154+
mBinding.leftButton.setText(buttons[LEFT]);
155+
if (buttons.length > 1)
156+
mBinding.rightButton.setText(buttons[RIGHT]);
157+
}
158+
159+
}

app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/VoiceSearchWidget.java

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,18 @@
2323
import com.mozilla.speechlibrary.MozillaSpeechService;
2424
import com.mozilla.speechlibrary.STTResult;
2525

26+
import org.mozilla.gecko.util.ThreadUtils;
2627
import org.mozilla.vrbrowser.R;
2728
import org.mozilla.vrbrowser.audio.AudioEngine;
2829
import org.mozilla.vrbrowser.browser.SettingsStore;
30+
import org.mozilla.vrbrowser.browser.engine.SessionStore;
2931
import org.mozilla.vrbrowser.utils.DeviceType;
3032
import org.mozilla.vrbrowser.ui.views.UIButton;
3133
import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate;
3234
import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement;
3335
import org.mozilla.vrbrowser.utils.LocaleUtils;
3436

37+
import androidx.annotation.NonNull;
3538
import androidx.core.app.ActivityCompat;
3639

3740
public class VoiceSearchWidget extends UIDialog implements WidgetManagerDelegate.PermissionListener,
@@ -90,9 +93,6 @@ private void initialize(Context aContext) {
9093

9194
mMozillaSpeechService = MozillaSpeechService.getInstance();
9295
mMozillaSpeechService.setProductTag(getContext().getString(R.string.voice_app_id));
93-
boolean storeData = SettingsStore.getInstance(aContext).isSpeechDataCollectionEnabled();
94-
mMozillaSpeechService.storeSamples(storeData);
95-
mMozillaSpeechService.storeTranscriptions(storeData);
9696

9797
mVoiceSearchText1 = findViewById(R.id.voiceSearchText1);
9898
mVoiceSearchText2 = findViewById(R.id.voiceSearchText2);
@@ -150,8 +150,7 @@ protected void initializeWidgetPlacement(WidgetPlacement aPlacement) {
150150
aPlacement.parentAnchorY = 0.5f;
151151
aPlacement.anchorX = 0.5f;
152152
aPlacement.anchorY = 0.5f;
153-
aPlacement.translationY = WidgetPlacement.unitFromMeters(getContext(), R.dimen.restart_dialog_world_y);
154-
aPlacement.translationZ = WidgetPlacement.unitFromMeters(getContext(), R.dimen.restart_dialog_world_z);
153+
aPlacement.translationZ = WidgetPlacement.unitFromMeters(getContext(), R.dimen.voice_search_world_z);
155154
}
156155

157156
public void setPlacementForKeyboard(int aHandle) {
@@ -230,6 +229,11 @@ public void startVoiceSearch() {
230229
} else {
231230
String locale = LocaleUtils.getVoiceSearchLocale(getContext());
232231
mMozillaSpeechService.setLanguage(LocaleUtils.mapToMozillaSpeechLocales(locale));
232+
boolean storeData = SettingsStore.getInstance(getContext()).isSpeechDataCollectionEnabled();
233+
if (SessionStore.get().getActiveStore().isPrivateMode())
234+
storeData = false;
235+
mMozillaSpeechService.storeSamples(storeData);
236+
mMozillaSpeechService.storeTranscriptions(storeData);
233237
mMozillaSpeechService.start(getContext().getApplicationContext());
234238
mIsSpeechRecognitionRunning = true;
235239
}
@@ -269,11 +273,37 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, in
269273

270274
@Override
271275
public void show(@ShowFlags int aShowFlags) {
272-
super.show(aShowFlags);
276+
if (SettingsStore.getInstance(getContext()).isSpeechDataCollectionReviewed()) {
277+
super.show(aShowFlags);
273278

274-
setStartListeningState();
279+
setStartListeningState();
275280

276-
startVoiceSearch();
281+
startVoiceSearch();
282+
283+
} else {
284+
mWidgetManager.getFocusedWindow().showAppDialog(
285+
R.string.voice_samples_collect_dialog_title,
286+
R.string.voice_samples_collect_dialog_description,
287+
new int[]{
288+
R.string.voice_samples_collect_dialog_do_not_allow,
289+
R.string.voice_samples_collect_dialog_allow},
290+
new AppDialogWidget.Delegate() {
291+
@Override
292+
public void onButtonClicked(int index) {
293+
SettingsStore.getInstance(getContext()).setSpeechDataCollectionReviewed(true);
294+
if (index == AppDialogWidget.RIGHT) {
295+
SettingsStore.getInstance(getContext()).setSpeechDataCollectionEnabled(true);
296+
}
297+
ThreadUtils.postToUiThread(() -> show(aShowFlags));
298+
}
299+
300+
@Override
301+
public void onMessageLinkClicked(@NonNull String url) {
302+
mWidgetManager.getFocusedWindow().getSessionStack().loadUri(getResources().getString(R.string.private_policy_url));
303+
onDismiss();
304+
}
305+
});
306+
}
277307
}
278308

279309
@Override

0 commit comments

Comments
 (0)