Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4372)

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/locale/DefaultSearchEnginePromoDialog.java

Issue 2838833002: 🔍 Introduce default search engine dialog (Closed)
Patch Set: Redo how the dialog is created Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/android/java/src/org/chromium/chrome/browser/locale/DefaultSearchEnginePromoDialog.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/locale/DefaultSearchEnginePromoDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/locale/DefaultSearchEnginePromoDialog.java
new file mode 100644
index 0000000000000000000000000000000000000000..080ecde03b766807892b96e8bac376f09069df9d
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/locale/DefaultSearchEnginePromoDialog.java
@@ -0,0 +1,184 @@
+// Copyright 2017 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.locale;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.view.View;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+import android.widget.RadioGroup.OnCheckedChangeListener;
+
+import org.chromium.base.library_loader.LibraryLoader;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.infobar.InfoBarControlLayout;
+import org.chromium.chrome.browser.search_engines.TemplateUrlService;
+import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl;
+import org.chromium.chrome.browser.widget.PromoDialog;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/** A dialog that forces the user to choose a default search engine. */
+public class DefaultSearchEnginePromoDialog extends PromoDialog implements OnCheckedChangeListener {
+ /** Used to determine the promo dialog contents. */
+ private final int mDialogType;
+
+ /** Run when the dialog is dismissed after the user has chosen a search engine. */
+ private final Runnable mOnDismissed;
+
+ private RadioGroup mRadioGroup;
+ private String mSelectedKeyword;
+
+ /**
+ * Construct and show the dialog. Will be asynchronous if the TemplateUrlService has not yet
+ * been loaded.
+ */
+ public static void create(
Ted C 2017/04/26 20:21:52 maybe this should be called show?
gone 2017/04/26 21:45:15 Done.
+ final Context context, final int dialogType, @Nullable final Runnable onDismissed) {
Ted C 2017/04/26 20:21:52 Should/can dialogType have an associated IntDef?
gone 2017/04/26 21:45:15 Seems like it'd be fine to move it to always be ca
+ assert LibraryLoader.isInitialized();
+
+ // Load up the search engines.
+ final TemplateUrlService instance = TemplateUrlService.getInstance();
+ instance.registerLoadListener(new TemplateUrlService.LoadListener() {
+ @Override
+ public void onTemplateUrlServiceLoaded() {
+ instance.unregisterLoadListener(this);
+ new DefaultSearchEnginePromoDialog(context, dialogType, onDismissed).show();
+ }
+ });
+ instance.load();
+ }
+
+ private DefaultSearchEnginePromoDialog(
+ Context context, int dialogType, @Nullable Runnable onDismissed) {
+ super(context);
+ mDialogType = dialogType;
+ mOnDismissed = onDismissed;
+ setOnDismissListener(this);
+
+ // No one should be able to bypass this dialog by clicking outside or by hitting back.
+ setCancelable(false);
+ setCanceledOnTouchOutside(false);
+ }
+
+ @Override
+ protected DialogParams getDialogParams() {
+ PromoDialog.DialogParams params = new PromoDialog.DialogParams();
+ params.headerStringResource = R.string.search_engine_dialog_title;
+ params.footerStringResource = R.string.search_engine_dialog_footer;
+ params.primaryButtonStringResource = R.string.ok;
+ return params;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ assert LibraryLoader.isInitialized();
Ted C 2017/04/26 20:21:52 Since this happens in the one place you create it
gone 2017/04/26 21:45:15 Done.
+
+ // Set up the general UI.
+ InfoBarControlLayout controls = addControlLayout();
+ updateButtonState();
+
+ // Load up the search engines.
+ TemplateUrlService instance = TemplateUrlService.getInstance();
+ assert instance.isLoaded();
+ List<TemplateUrl> engines = null;
+ if (mDialogType == LocaleManager.SEARCH_ENGINE_PROMO_SHOW_EXISTING) {
+ engines = instance.getSearchEngines();
+ } else {
+ // TODO(dfalcantara): Handle the new user case.
+ assert false;
+ }
+
+ List<CharSequence> engineNames = new ArrayList<>();
+ List<String> engineKeywords = new ArrayList<>();
+ shuffleEngines(engines, engineNames, engineKeywords);
+
+ // Add the search engines to the dialog.
+ mRadioGroup = controls.addRadioButtons(
+ engineNames, engineKeywords, InfoBarControlLayout.INVALID_INDEX);
+ mRadioGroup.setOnCheckedChangeListener(this);
+ }
+
+ @Override
+ public void onCheckedChanged(RadioGroup group, int checkedId) {
+ mSelectedKeyword = null;
+
+ // Run through the RadioGroup to figure out which one was checked.
+ for (int i = 0; i < group.getChildCount(); i++) {
+ View child = group.getChildAt(i);
+ assert child instanceof RadioButton;
+
+ RadioButton button = (RadioButton) child;
+ if (button.isChecked()) {
+ assert mSelectedKeyword == null;
+ mSelectedKeyword = (String) button.getTag();
+ }
+ }
+
+ updateButtonState();
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (view.getId() == R.id.button_primary) {
+ if (mSelectedKeyword == null) {
+ updateButtonState();
+ return;
+ }
+
+ dismiss();
+ } else {
+ assert false : "Unhandled click.";
+ }
+
+ // Don't propagate the click to the parent to prevent circumventing the dialog.
+ }
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ if (mSelectedKeyword == null) {
+ // This shouldn't happen, but in case it does, finish the Activity so that the user has
+ // to respond to the dialog next time.
+ if (getOwnerActivity() != null) getOwnerActivity().finish();
Ted C 2017/04/26 20:21:52 should this be finish and remove task?
gone 2017/04/26 21:45:15 I'd argue for a regular finish() so that the activ
+ } else {
+ TemplateUrlService.getInstance().setSearchEngine(mSelectedKeyword.toString());
+ if (mOnDismissed != null) mOnDismissed.run();
+ // TODO(dfalcantara): Prevent the dialog from appearing again.
+ }
+ }
+
+ private void updateButtonState() {
+ findViewById(R.id.button_primary).setEnabled(mSelectedKeyword != null);
+ }
+
+ private void shuffleEngines(
+ List<TemplateUrl> engines, List<CharSequence> names, List<String> keywords) {
+ ArrayList<Integer> indices = new ArrayList<>();
Ted C 2017/04/26 20:21:52 Could we use: https://developer.android.com/refere
gone 2017/04/26 21:45:15 Works for me.
+ for (int i = 0; i < engines.size(); i++) indices.add(i);
+
+ Random generator = new Random();
+ for (int i = 0; i < indices.size(); i++) {
+ int remaining = indices.size() - i;
+ int shuffleIndex = i + generator.nextInt(remaining);
+
+ if (shuffleIndex != i) {
+ int temp = indices.get(i);
+ indices.set(i, indices.get(shuffleIndex));
+ indices.set(shuffleIndex, temp);
+ }
+ }
+
+ for (Integer index : indices) {
+ TemplateUrl engine = engines.get(index);
+ names.add(engine.getShortName());
+ keywords.add(engine.getKeyword());
+ }
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698