Commit 42776f8a authored by dfalcantara's avatar dfalcantara Committed by Commit bot

🔍 Introduce default search engine dialog

Add a dialog that can be triggered via LocaleManager that allows a user
to choose their default search engine from a randomized list.

DefaultSearchEnginePromoDialog:
* Add a basic dialog that forces a user to select a default search engine.  This
  dialog only shows up for the "existing user" case and (currently) randomizes
  the search engines available as defined in the TemplateUrlService.

* Add the ability to show the DefaultSearchEnginePromoDialog from the
  LocaleManager.  It currently never fires because the logic hasn't landed, but
  it is triggered from ChromeTabbedActivity and SearchActivity.

Things to do:
- Still trying to figure out how to test this.

Screenshots:
https://drive.google.com/corp/drive/u/0/folders/0B7c8ZkXVwskDRmlnZ1g0LXVpMGM

BUG=714223,712836,712833

Review-Url: https://codereview.chromium.org/2838833002
Cr-Commit-Position: refs/heads/master@{#467766}
parent 4ab7eea2
...@@ -916,12 +916,14 @@ public abstract class ChromeActivity extends AsyncInitializationActivity ...@@ -916,12 +916,14 @@ public abstract class ChromeActivity extends AsyncInitializationActivity
} }
/** /**
* Actions that may be run at some point after startup. Place tasks that are not critical to the
* startup path here. This method will be called automatically and should not be called
* directly by subclasses.
*
* Overriding methods should queue tasks on the DeferredStartupHandler before or after calling * Overriding methods should queue tasks on the DeferredStartupHandler before or after calling
* super depending on whether the tasks should run before or after these ones. * super depending on whether the tasks should run before or after these ones.
*/ */
@Override
protected void onDeferredStartup() { protected void onDeferredStartup() {
super.onDeferredStartup();
initDeferredStartupForActivity(); initDeferredStartupForActivity();
DeferredStartupHandler.getInstance().initDeferredStartupForApp(); DeferredStartupHandler.getInstance().initDeferredStartupForApp();
DeferredStartupHandler.getInstance().queueDeferredTasksOnIdleHandler(); DeferredStartupHandler.getInstance().queueDeferredTasksOnIdleHandler();
......
...@@ -207,13 +207,6 @@ public abstract class AsyncInitializationActivity extends AppCompatActivity impl ...@@ -207,13 +207,6 @@ public abstract class AsyncInitializationActivity extends AppCompatActivity impl
mNativeInitializationController.onNativeInitializationComplete(); mNativeInitializationController.onNativeInitializationComplete();
} }
/**
* Actions that may be run at some point after startup. Place tasks that are not critical to the
* startup path here. This method will be called automatically and should not be called
* directly by subclasses.
*/
protected void onDeferredStartup() { }
@Override @Override
public void onStartupFailure() { public void onStartupFailure() {
ProcessInitException e = ProcessInitException e =
......
// 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.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import org.chromium.base.Callback;
import org.chromium.base.library_loader.LibraryLoader;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.infobar.InfoBarControlLayout;
import org.chromium.chrome.browser.locale.LocaleManager.SearchEnginePromoType;
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.Collections;
import java.util.List;
/** 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. */
@SearchEnginePromoType
private final int mDialogType;
/** Called when the dialog is dismissed after the user has chosen a search engine. */
private final Callback<Boolean> mOnDismissed;
private RadioGroup mRadioGroup;
private String mSelectedKeyword;
/**
* Construct and show the dialog. Will be asynchronous if the TemplateUrlService has not yet
* been loaded.
*
* @param context Context to build the dialog with.
* @param dialogType Type of dialog to show.
* @param onDismissed Notified about whether the user chose an engine when it got dismissed.
*/
public static void show(final Context context, @SearchEnginePromoType final int dialogType,
@Nullable final Callback<Boolean> onDismissed) {
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();
}
});
if (!instance.isLoaded()) instance.load();
}
private DefaultSearchEnginePromoDialog(
Context context, int dialogType, @Nullable Callback<Boolean> 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);
// Determine what search engines will be listed.
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;
}
// Shuffle up the engines.
List<CharSequence> engineNames = new ArrayList<>();
List<String> engineKeywords = new ArrayList<>();
Collections.shuffle(engines);
for (int i = 0; i < engines.size(); i++) {
TemplateUrl engine = engines.get(i);
engineNames.add(engine.getShortName());
engineKeywords.add(engine.getKeyword());
}
// Add the search engines to the dialog.
InfoBarControlLayout controls = addControlLayout();
mRadioGroup = controls.addRadioButtons(
engineNames, engineKeywords, InfoBarControlLayout.INVALID_INDEX);
mRadioGroup.setOnCheckedChangeListener(this);
updateButtonState();
}
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
mSelectedKeyword = (String) group.findViewById(checkedId).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();
} else {
TemplateUrlService.getInstance().setSearchEngine(mSelectedKeyword.toString());
// TODO(dfalcantara): Prevent the dialog from appearing again.
}
if (mOnDismissed != null) mOnDismissed.onResult(mSelectedKeyword != null);
}
private void updateButtonState() {
findViewById(R.id.button_primary).setEnabled(mSelectedKeyword != null);
}
}
...@@ -10,6 +10,7 @@ import android.content.SharedPreferences; ...@@ -10,6 +10,7 @@ import android.content.SharedPreferences;
import android.support.annotation.IntDef; import android.support.annotation.IntDef;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import org.chromium.base.Callback;
import org.chromium.base.ContextUtils; import org.chromium.base.ContextUtils;
import org.chromium.base.ThreadUtils; import org.chromium.base.ThreadUtils;
import org.chromium.chrome.R; import org.chromium.chrome.R;
...@@ -178,10 +179,11 @@ public class LocaleManager { ...@@ -178,10 +179,11 @@ public class LocaleManager {
* See {@link LocaleManager#getSearchEnginePromoShowType()} for possible types and logic. * See {@link LocaleManager#getSearchEnginePromoShowType()} for possible types and logic.
* *
* @param context Context showing the dialog. * @param context Context showing the dialog.
* @param onDismissed Run when the dialog has been dismissed. * @param onDismissed Notified when the dialog is dismissed and whether the user acted on it.
* @return Whether such dialog is needed. * @return Whether such dialog is needed.
*/ */
public boolean showSearchEnginePromoIfNeeded(Context context, @Nullable Runnable onDismissed) { public boolean showSearchEnginePromoIfNeeded(
Context context, @Nullable Callback<Boolean> onDismissed) {
int shouldShow = getSearchEnginePromoShowType(); int shouldShow = getSearchEnginePromoShowType();
switch (shouldShow) { switch (shouldShow) {
case SEARCH_ENGINE_PROMO_DONT_SHOW: case SEARCH_ENGINE_PROMO_DONT_SHOW:
...@@ -191,8 +193,8 @@ public class LocaleManager { ...@@ -191,8 +193,8 @@ public class LocaleManager {
return true; return true;
case SEARCH_ENGINE_PROMO_SHOW_EXISTING: case SEARCH_ENGINE_PROMO_SHOW_EXISTING:
case SEARCH_ENGINE_PROMO_SHOW_NEW: case SEARCH_ENGINE_PROMO_SHOW_NEW:
// TODO(dfalcantara): Show the search engine dialog. DefaultSearchEnginePromoDialog.show(context, shouldShow, onDismissed);
return false; return true;
default: default:
assert false; assert false;
return false; return false;
......
...@@ -17,6 +17,7 @@ import android.text.style.StyleSpan; ...@@ -17,6 +17,7 @@ import android.text.style.StyleSpan;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
import org.chromium.base.Callback;
import org.chromium.base.ContextUtils; import org.chromium.base.ContextUtils;
import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordHistogram;
import org.chromium.chrome.R; import org.chromium.chrome.R;
...@@ -47,7 +48,7 @@ public class SogouPromoDialog extends PromoDialog { ...@@ -47,7 +48,7 @@ public class SogouPromoDialog extends PromoDialog {
private static final int CHOICE_ENUM_COUNT = 4; private static final int CHOICE_ENUM_COUNT = 4;
/** Run when the dialog is dismissed. */ /** Run when the dialog is dismissed. */
private final Runnable mOnDismissedRunnable; private final Callback<Boolean> mOnDismissedCallback;
private final LocaleManager mLocaleManager; private final LocaleManager mLocaleManager;
private final ClickableSpan mSpan = new NoUnderlineClickableSpan() { private final ClickableSpan mSpan = new NoUnderlineClickableSpan() {
...@@ -68,12 +69,12 @@ public class SogouPromoDialog extends PromoDialog { ...@@ -68,12 +69,12 @@ public class SogouPromoDialog extends PromoDialog {
* Creates an instance of the dialog. * Creates an instance of the dialog.
*/ */
public SogouPromoDialog( public SogouPromoDialog(
Context context, LocaleManager localeManager, @Nullable Runnable onDismissed) { Context context, LocaleManager localeManager, @Nullable Callback<Boolean> onDismissed) {
super(context); super(context);
mLocaleManager = localeManager; mLocaleManager = localeManager;
setOnDismissListener(this); setOnDismissListener(this);
setCanceledOnTouchOutside(false); setCanceledOnTouchOutside(false);
mOnDismissedRunnable = onDismissed; mOnDismissedCallback = onDismissed;
} }
@Override @Override
...@@ -150,6 +151,6 @@ public class SogouPromoDialog extends PromoDialog { ...@@ -150,6 +151,6 @@ public class SogouPromoDialog extends PromoDialog {
RecordHistogram.recordEnumeratedHistogram( RecordHistogram.recordEnumeratedHistogram(
"SpecialLocale.PromotionDialog", mChoice, CHOICE_ENUM_COUNT); "SpecialLocale.PromotionDialog", mChoice, CHOICE_ENUM_COUNT);
if (mOnDismissedRunnable != null) mOnDismissedRunnable.run(); if (mOnDismissedCallback != null) mOnDismissedCallback.onResult(true);
} }
} }
...@@ -12,6 +12,8 @@ import android.view.LayoutInflater; ...@@ -12,6 +12,8 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import org.chromium.base.Callback;
import org.chromium.base.Log;
import org.chromium.base.VisibleForTesting; import org.chromium.base.VisibleForTesting;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.IntentHandler;
...@@ -19,6 +21,7 @@ import org.chromium.chrome.browser.WebContentsFactory; ...@@ -19,6 +21,7 @@ import org.chromium.chrome.browser.WebContentsFactory;
import org.chromium.chrome.browser.WindowDelegate; import org.chromium.chrome.browser.WindowDelegate;
import org.chromium.chrome.browser.customtabs.CustomTabsConnection; import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
import org.chromium.chrome.browser.init.AsyncInitializationActivity; import org.chromium.chrome.browser.init.AsyncInitializationActivity;
import org.chromium.chrome.browser.locale.LocaleManager;
import org.chromium.chrome.browser.omnibox.AutocompleteController; import org.chromium.chrome.browser.omnibox.AutocompleteController;
import org.chromium.chrome.browser.snackbar.SnackbarManager; import org.chromium.chrome.browser.snackbar.SnackbarManager;
import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarManageable; import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarManageable;
...@@ -34,14 +37,16 @@ import org.chromium.ui.base.ActivityWindowAndroid; ...@@ -34,14 +37,16 @@ import org.chromium.ui.base.ActivityWindowAndroid;
/** Queries the user's default search engine and shows autocomplete suggestions. */ /** Queries the user's default search engine and shows autocomplete suggestions. */
public class SearchActivity extends AsyncInitializationActivity public class SearchActivity extends AsyncInitializationActivity
implements SnackbarManageable, SearchActivityLocationBarLayout.Delegate { implements SnackbarManageable, SearchActivityLocationBarLayout.Delegate {
private static final String TAG = "searchwidget";
/** Setting this field causes the Activity to finish itself immediately for tests. */ /** Setting this field causes the Activity to finish itself immediately for tests. */
private static boolean sIsDisabledForTest; private static boolean sIsDisabledForTest;
/** Main content view. */ /** Main content view. */
private ViewGroup mContentView; private ViewGroup mContentView;
/** Whether the native library has been loaded. */ /** Whether the user is now allowed to perform searches. */
private boolean mIsNativeReady; private boolean mIsActivityUsable;
/** Input submitted before before the native library was loaded. */ /** Input submitted before before the native library was loaded. */
private String mQueuedUrl; private String mQueuedUrl;
...@@ -89,6 +94,10 @@ public class SearchActivity extends AsyncInitializationActivity ...@@ -89,6 +94,10 @@ public class SearchActivity extends AsyncInitializationActivity
setContentView(mContentView); setContentView(mContentView);
// Kick off everything needed for the user to type into the box. // Kick off everything needed for the user to type into the box.
// TODO(dfalcantara): We should prevent the user from doing anything while we're running the
// logic to determine if they need to see a search engine promo. Given
// that the logic requires native to be loaded, we'll have to make some
// easy Java-only first-pass checks.
beginQuery(); beginQuery();
mSearchBox.showCachedZeroSuggestResultsIfAvailable(); mSearchBox.showCachedZeroSuggestResultsIfAvailable();
...@@ -104,7 +113,6 @@ public class SearchActivity extends AsyncInitializationActivity ...@@ -104,7 +113,6 @@ public class SearchActivity extends AsyncInitializationActivity
@Override @Override
public void finishNativeInitialization() { public void finishNativeInitialization() {
super.finishNativeInitialization(); super.finishNativeInitialization();
mIsNativeReady = true;
mTab = new Tab(TabIdManager.getInstance().generateValidId(Tab.INVALID_TAB_ID), mTab = new Tab(TabIdManager.getInstance().generateValidId(Tab.INVALID_TAB_ID),
Tab.INVALID_TAB_ID, false, this, getWindowAndroid(), Tab.INVALID_TAB_ID, false, this, getWindowAndroid(),
...@@ -116,19 +124,32 @@ public class SearchActivity extends AsyncInitializationActivity ...@@ -116,19 +124,32 @@ public class SearchActivity extends AsyncInitializationActivity
mSearchBoxDataProvider.onNativeLibraryReady(mTab); mSearchBoxDataProvider.onNativeLibraryReady(mTab);
mSearchBox.onNativeLibraryReady(); mSearchBox.onNativeLibraryReady();
if (mQueuedUrl != null) loadUrl(mQueuedUrl); // Force the user to choose a search engine if they have to.
final Callback<Boolean> deferredCallback = new Callback<Boolean>() {
mHandler.post(new Runnable() {
@Override @Override
public void run() { public void onResult(Boolean result) {
onDeferredStartup(); finishDeferredInitialization(result);
} }
}); };
if (!LocaleManager.getInstance().showSearchEnginePromoIfNeeded(this, deferredCallback)) {
mHandler.post(new Runnable() {
@Override
public void run() {
deferredCallback.onResult(true);
}
});
}
} }
@Override private void finishDeferredInitialization(Boolean result) {
public void onDeferredStartup() { if (result == null || !result.booleanValue()) {
super.onDeferredStartup(); Log.e(TAG, "User failed to select a default search engine.");
finish();
return;
}
mIsActivityUsable = true;
if (mQueuedUrl != null) loadUrl(mQueuedUrl);
AutocompleteController.nativePrefetchZeroSuggestResults(); AutocompleteController.nativePrefetchZeroSuggestResults();
CustomTabsConnection.getInstance(getApplication()).warmup(0); CustomTabsConnection.getInstance(getApplication()).warmup(0);
...@@ -175,7 +196,7 @@ public class SearchActivity extends AsyncInitializationActivity ...@@ -175,7 +196,7 @@ public class SearchActivity extends AsyncInitializationActivity
@Override @Override
public void loadUrl(String url) { public void loadUrl(String url) {
// Wait until native has loaded. // Wait until native has loaded.
if (!mIsNativeReady) { if (!mIsActivityUsable) {
mQueuedUrl = url; mQueuedUrl = url;
return; return;
} }
......
...@@ -6,14 +6,11 @@ package org.chromium.chrome.browser.searchwidget; ...@@ -6,14 +6,11 @@ package org.chromium.chrome.browser.searchwidget;
import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.library_loader.LibraryLoader;
import org.chromium.chrome.browser.ntp.NewTabPage; import org.chromium.chrome.browser.ntp.NewTabPage;
import org.chromium.chrome.browser.omnibox.LocationBarLayout;
import org.chromium.chrome.browser.search_engines.TemplateUrlService;
import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.toolbar.ToolbarDataProvider; import org.chromium.chrome.browser.toolbar.ToolbarDataProvider;
class SearchBoxDataProvider implements ToolbarDataProvider, TemplateUrlService.LoadListener { class SearchBoxDataProvider implements ToolbarDataProvider {
private Tab mTab; private Tab mTab;
private String mVerbatimUrl;
/** /**
* Called when native library is loaded and a tab has been initialized. * Called when native library is loaded and a tab has been initialized.
...@@ -21,22 +18,7 @@ class SearchBoxDataProvider implements ToolbarDataProvider, TemplateUrlService.L ...@@ -21,22 +18,7 @@ class SearchBoxDataProvider implements ToolbarDataProvider, TemplateUrlService.L
*/ */
public void onNativeLibraryReady(Tab tab) { public void onNativeLibraryReady(Tab tab) {
assert LibraryLoader.isInitialized(); assert LibraryLoader.isInitialized();
mTab = tab; mTab = tab;
TemplateUrlService service = TemplateUrlService.getInstance();
service.registerLoadListener(this);
service.load();
}
@Override
public void onTemplateUrlServiceLoaded() {
// For zero suggest, the default search engine's URL is used as the first suggestion.
TemplateUrlService service = TemplateUrlService.getInstance();
service.unregisterLoadListener(this);
String searchEngineUrl = service.getSearchEngineUrlFromTemplateUrl(
service.getDefaultSearchEngineTemplateUrl().getKeyword());
mVerbatimUrl = LocationBarLayout.splitPathFromUrlDisplayText(searchEngineUrl).first;
} }
@Override @Override
...@@ -72,6 +54,6 @@ class SearchBoxDataProvider implements ToolbarDataProvider, TemplateUrlService.L ...@@ -72,6 +54,6 @@ class SearchBoxDataProvider implements ToolbarDataProvider, TemplateUrlService.L
@Override @Override
public String getCurrentUrl() { public String getCurrentUrl() {
return mVerbatimUrl; return SearchWidgetProvider.getDefaultSearchEngineUrl();
} }
} }
...@@ -28,6 +28,7 @@ import org.chromium.base.library_loader.LibraryLoader; ...@@ -28,6 +28,7 @@ import org.chromium.base.library_loader.LibraryLoader;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.IntentHandler;
import org.chromium.chrome.browser.firstrun.FirstRunFlowSequencer; import org.chromium.chrome.browser.firstrun.FirstRunFlowSequencer;
import org.chromium.chrome.browser.omnibox.LocationBarLayout;
import org.chromium.chrome.browser.search_engines.TemplateUrlService; import org.chromium.chrome.browser.search_engines.TemplateUrlService;
import org.chromium.chrome.browser.search_engines.TemplateUrlService.LoadListener; import org.chromium.chrome.browser.search_engines.TemplateUrlService.LoadListener;
import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrlServiceObserver; import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrlServiceObserver;
...@@ -123,6 +124,9 @@ public class SearchWidgetProvider extends AppWidgetProvider { ...@@ -123,6 +124,9 @@ public class SearchWidgetProvider extends AppWidgetProvider {
private static final Object DELEGATE_LOCK = new Object(); private static final Object DELEGATE_LOCK = new Object();
private static final Object OBSERVER_LOCK = new Object(); private static final Object OBSERVER_LOCK = new Object();
/** The default search engine's root URL. */
private static String sDefaultSearchEngineUrl;
private static SearchWidgetTemplateUrlServiceObserver sObserver; private static SearchWidgetTemplateUrlServiceObserver sObserver;
private static SearchWidgetProviderDelegate sDelegate; private static SearchWidgetProviderDelegate sDelegate;
...@@ -291,6 +295,12 @@ public class SearchWidgetProvider extends AppWidgetProvider { ...@@ -291,6 +295,12 @@ public class SearchWidgetProvider extends AppWidgetProvider {
TemplateUrlService service = TemplateUrlService.getInstance(); TemplateUrlService service = TemplateUrlService.getInstance();
if (!service.isLoaded()) return; if (!service.isLoaded()) return;
// Update the URL that we show for zero-suggest.
String searchEngineUrl = service.getSearchEngineUrlFromTemplateUrl(
service.getDefaultSearchEngineTemplateUrl().getKeyword());
sDefaultSearchEngineUrl =
LocationBarLayout.splitPathFromUrlDisplayText(searchEngineUrl).first;
updateCachedEngineName(service.getDefaultSearchEngineTemplateUrl().getShortName()); updateCachedEngineName(service.getDefaultSearchEngineTemplateUrl().getShortName());
} }
...@@ -383,4 +393,10 @@ public class SearchWidgetProvider extends AppWidgetProvider { ...@@ -383,4 +393,10 @@ public class SearchWidgetProvider extends AppWidgetProvider {
assert sDelegate == null; assert sDelegate == null;
sDelegate = delegate; sDelegate = delegate;
} }
/** See {@link #sDefaultSearchEngineUrl}. */
static String getDefaultSearchEngineUrl() {
// TODO(yusufo): Get rid of this.
return sDefaultSearchEngineUrl;
}
} }
...@@ -296,6 +296,12 @@ CHAR-LIMIT guidelines: ...@@ -296,6 +296,12 @@ CHAR-LIMIT guidelines:
<message name="IDS_SEARCH_ENGINE_RECENTLY_VISITED" desc="Header for the list of recently visited search engines."> <message name="IDS_SEARCH_ENGINE_RECENTLY_VISITED" desc="Header for the list of recently visited search engines.">
Recently visited Recently visited
</message> </message>
<message name="IDS_SEARCH_ENGINE_DIALOG_TITLE" desc="Title shown in the dialog to change search engines">
Choose your search engine
</message>
<message name="IDS_SEARCH_ENGINE_DIALOG_FOOTER" desc="Title shown in the dialog to change search engines">
You can change this later in Settings
</message>
<!-- Autofill and Payments preferences --> <!-- Autofill and Payments preferences -->
<message name="IDS_PREFS_AUTOFILL_AND_PAYMENTS" desc="Title of Autofill and payments settings prefrences. [CHAR-LIMIT=32]"> <message name="IDS_PREFS_AUTOFILL_AND_PAYMENTS" desc="Title of Autofill and payments settings prefrences. [CHAR-LIMIT=32]">
......
...@@ -494,6 +494,7 @@ chrome_java_sources = [ ...@@ -494,6 +494,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/invalidation/InvalidationController.java", "java/src/org/chromium/chrome/browser/invalidation/InvalidationController.java",
"java/src/org/chromium/chrome/browser/invalidation/InvalidationServiceFactory.java", "java/src/org/chromium/chrome/browser/invalidation/InvalidationServiceFactory.java",
"java/src/org/chromium/chrome/browser/invalidation/UniqueIdInvalidationClientNameGenerator.java", "java/src/org/chromium/chrome/browser/invalidation/UniqueIdInvalidationClientNameGenerator.java",
"java/src/org/chromium/chrome/browser/locale/DefaultSearchEnginePromoDialog.java",
"java/src/org/chromium/chrome/browser/locale/LocaleManager.java", "java/src/org/chromium/chrome/browser/locale/LocaleManager.java",
"java/src/org/chromium/chrome/browser/locale/SogouPromoDialog.java", "java/src/org/chromium/chrome/browser/locale/SogouPromoDialog.java",
"java/src/org/chromium/chrome/browser/locale/SpecialLocaleHandler.java", "java/src/org/chromium/chrome/browser/locale/SpecialLocaleHandler.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