mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 892113 - Dialog to manage installed search providers. r=liuche
This commit is contained in:
parent
5f75eab06c
commit
3414ae30b1
@ -234,6 +234,7 @@ FENNEC_JAVA_FILES = \
|
||||
menu/MenuPanel.java \
|
||||
menu/MenuPopup.java \
|
||||
preferences/SearchPreferenceCategory.java \
|
||||
preferences/SearchEnginePreference.java \
|
||||
widget/AboutHome.java \
|
||||
widget/AboutHomeView.java \
|
||||
widget/AboutHomeSection.java \
|
||||
|
@ -90,7 +90,7 @@ public class AllPagesTab extends AwesomeBarTab implements GeckoEventListener {
|
||||
mSearchEngines = new ArrayList<SearchEngine>();
|
||||
|
||||
registerEventListener("SearchEngines:Data");
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("SearchEngines:Get", null));
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("SearchEngines:GetVisible", null));
|
||||
|
||||
mHandler = new AllPagesHandler();
|
||||
}
|
||||
|
@ -144,6 +144,10 @@ size. -->
|
||||
<!ENTITY pref_about_firefox "About &brandShortName;">
|
||||
<!ENTITY pref_vendor_faqs "FAQs">
|
||||
<!ENTITY pref_vendor_feedback "Give feedback">
|
||||
<!ENTITY pref_search_set_default "Set as default">
|
||||
<!ENTITY pref_search_default "Default">
|
||||
<!ENTITY pref_search_remove "Remove">
|
||||
<!ENTITY pref_search_last_toast "You can\'t remove or disable your last search engine.">
|
||||
|
||||
<!ENTITY datareporting_notification_title "&brandShortName; stats & data">
|
||||
<!ENTITY datareporting_notification_action_long "Choose what information to share">
|
||||
|
229
mobile/android/base/preferences/SearchEnginePreference.java
Normal file
229
mobile/android/base/preferences/SearchEnginePreference.java
Normal file
@ -0,0 +1,229 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.preferences;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.os.Build;
|
||||
import android.preference.Preference;
|
||||
import android.text.SpannableString;
|
||||
import android.util.Log;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.gfx.BitmapUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
/**
|
||||
* Represents an element in the list of search engines on the preferences menu.
|
||||
*/
|
||||
public class SearchEnginePreference extends Preference {
|
||||
private static final String LOGTAG = "SearchEnginePreference";
|
||||
|
||||
// Dimensions, in dp, of the icon to display for this engine.
|
||||
public static int sIconSize;
|
||||
|
||||
// Indices in button array of the AlertDialog of the three buttons.
|
||||
public static final int INDEX_SET_DEFAULT_BUTTON = 0;
|
||||
public static final int INDEX_REMOVE_BUTTON = 1;
|
||||
|
||||
// Cache label to avoid repeated use of the resource system.
|
||||
public final String LABEL_IS_DEFAULT;
|
||||
|
||||
// Specifies if this engine is configured as the default search engine.
|
||||
private boolean mIsDefaultEngine;
|
||||
// Specifies if this engine is one of the ones bundled with the app, which cannot be deleted.
|
||||
private boolean mIsImmutableEngine;
|
||||
|
||||
// Dialog element labels.
|
||||
private String[] mDialogItems;
|
||||
|
||||
// The popup displayed when this element is tapped.
|
||||
private AlertDialog mDialog;
|
||||
|
||||
private final SearchPreferenceCategory mParentCategory;
|
||||
|
||||
/**
|
||||
* Create a preference object to represent a search engine that is attached to category
|
||||
* containingCategory.
|
||||
* @param context The activity context we operate under.
|
||||
* @param parentCategory The PreferenceCategory this object exists within.
|
||||
* @see this.setSearchEngine
|
||||
*/
|
||||
public SearchEnginePreference(Context context, SearchPreferenceCategory parentCategory) {
|
||||
super(context);
|
||||
mParentCategory = parentCategory;
|
||||
|
||||
Resources res = getContext().getResources();
|
||||
|
||||
// Fetch the icon dimensions from the resource file.
|
||||
sIconSize = res.getDimensionPixelSize(R.dimen.searchpreferences_icon_size);
|
||||
setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
SearchEnginePreference sPref = (SearchEnginePreference) preference;
|
||||
sPref.showDialog();
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// Fetch this resource now, instead of every time we ever want to relabel a button.
|
||||
LABEL_IS_DEFAULT = res.getString(R.string.pref_search_default);
|
||||
|
||||
// Set up default dialog items.
|
||||
mDialogItems = new String[] { res.getString(R.string.pref_search_set_default),
|
||||
res.getString(R.string.pref_search_remove) };
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure this Preference object from the Gecko search engine JSON object.
|
||||
* @param geckoEngineJSON The Gecko-formatted JSON object representing the search engine.
|
||||
* @throws JSONException If the JSONObject is invalid.
|
||||
*/
|
||||
public void setSearchEngineFromJSON(JSONObject geckoEngineJSON) throws JSONException {
|
||||
final String engineName = geckoEngineJSON.getString("name");
|
||||
SpannableString titleSpannable = new SpannableString(engineName);
|
||||
mIsImmutableEngine = geckoEngineJSON.getBoolean("immutable");
|
||||
|
||||
if (mIsImmutableEngine) {
|
||||
// Delete the "Remove" option from the menu.
|
||||
mDialogItems = new String[] { getContext().getResources().getString(R.string.pref_search_set_default) };
|
||||
}
|
||||
setTitle(titleSpannable);
|
||||
|
||||
// setIcon is only available on Honeycomb and up.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||
// Create a drawable from the iconURI and assign it to this Preference for display.
|
||||
String iconURI = geckoEngineJSON.getString("iconURI");
|
||||
Bitmap iconBitmap = BitmapUtils.getBitmapFromDataURI(iconURI);
|
||||
Bitmap scaledIconBitmap = Bitmap.createScaledBitmap(iconBitmap, sIconSize, sIconSize, false);
|
||||
BitmapDrawable drawable = new BitmapDrawable(scaledIconBitmap);
|
||||
setIcon(drawable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if this object's UI should show that this is the default engine.
|
||||
* @param isDefault Flag indicating if this represents the default engine.
|
||||
*/
|
||||
public void setIsDefaultEngine(boolean isDefault) {
|
||||
mIsDefaultEngine = isDefault;
|
||||
if (isDefault) {
|
||||
setOrder(0);
|
||||
setSummary(LABEL_IS_DEFAULT);
|
||||
} else {
|
||||
setOrder(1);
|
||||
setSummary("");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the AlertDialog providing options to reconfigure this search engine. Sets an event
|
||||
* listener to disable buttons in the dialog as appropriate after they have been constructed by
|
||||
* Android.
|
||||
* @see this.configureShownDialog
|
||||
* @see this.hideDialog
|
||||
*/
|
||||
public void showDialog() {
|
||||
// If we are the only engine left, then we are the default engine, and none of the options
|
||||
// on this menu can do anything.
|
||||
if (mParentCategory.getPreferenceCount() == 1) {
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(getContext(), R.string.pref_search_last_toast, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// If we are both default and immutable, we have no enabled items to show on the menu - abort.
|
||||
if (mIsDefaultEngine && mIsImmutableEngine) {
|
||||
return;
|
||||
}
|
||||
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
builder.setTitle(getTitle().toString());
|
||||
builder.setItems(mDialogItems, new DialogInterface.OnClickListener() {
|
||||
// Forward the various events that we care about to the container class for handling.
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int indexClicked) {
|
||||
hideDialog();
|
||||
switch (indexClicked) {
|
||||
case INDEX_SET_DEFAULT_BUTTON:
|
||||
mParentCategory.setDefault(SearchEnginePreference.this);
|
||||
break;
|
||||
case INDEX_REMOVE_BUTTON:
|
||||
mParentCategory.uninstall(SearchEnginePreference.this);
|
||||
break;
|
||||
default:
|
||||
Log.w(LOGTAG, "Selected index out of range.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Copy the icon, if any, from this object to the prompt we produce.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||
builder.setIcon(getIcon());
|
||||
}
|
||||
|
||||
// We have to construct the dialog itself on the UI thread.
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mDialog = builder.create();
|
||||
mDialog.setOnShowListener(new DialogInterface.OnShowListener() {
|
||||
// Called when the dialog is shown (so we're finally able to manipulate button enabledness).
|
||||
@Override
|
||||
public void onShow(DialogInterface dialog) {
|
||||
configureShownDialog();
|
||||
}
|
||||
});
|
||||
mDialog.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the dialog we previously created, if any.
|
||||
*/
|
||||
public void hideDialog() {
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Null check so we can chain engine-mutating methods up in SearchPreferenceCategory
|
||||
// without consequence.
|
||||
if (mDialog != null && mDialog.isShowing()) {
|
||||
mDialog.dismiss();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables buttons in the shown AlertDialog as required. The button elements are not created
|
||||
* until after we call show, so this method has to be called from the onShowListener above.
|
||||
* @see this.showDialog
|
||||
*/
|
||||
private void configureShownDialog() {
|
||||
// If we are the default engine, disable the "Set as default" button.
|
||||
TextView defaultButton = (TextView) mDialog.getListView().getChildAt(INDEX_SET_DEFAULT_BUTTON);
|
||||
// Disable "Set as default" button if we are already the default.
|
||||
if (mIsDefaultEngine) {
|
||||
defaultButton.setEnabled(false);
|
||||
// Failure to unregister this listener leads to tapping the button dismissing the dialog
|
||||
// without doing anything.
|
||||
defaultButton.setOnClickListener(null);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,10 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.preferences;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.os.Build;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceCategory;
|
||||
import android.util.AttributeSet;
|
||||
@ -13,38 +14,36 @@ import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoEvent;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.gfx.BitmapUtils;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
|
||||
public class SearchPreferenceCategory extends PreferenceCategory implements GeckoEventListener {
|
||||
public static final String LOGTAG = "SearchPrefCategory";
|
||||
|
||||
private static int sIconSize;
|
||||
private SearchEnginePreference mDefaultEngineReference;
|
||||
|
||||
// These seemingly redundant constructors are mandated by the Android system, else it fails to
|
||||
// inflate this object.
|
||||
|
||||
public SearchPreferenceCategory(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
init();
|
||||
}
|
||||
|
||||
public SearchPreferenceCategory(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public SearchPreferenceCategory(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
sIconSize = getContext().getResources().getDimensionPixelSize(R.dimen.searchpreferences_icon_size);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToActivity() {
|
||||
super.onAttachedToActivity();
|
||||
|
||||
// Request list of search engines from Gecko
|
||||
// Ensures default engine remains at top of list.
|
||||
setOrderingAsAdded(false);
|
||||
|
||||
// Request list of search engines from Gecko.
|
||||
GeckoAppShell.registerEventListener("SearchEngines:Data", this);
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("SearchEngines:Get", null));
|
||||
}
|
||||
@ -52,9 +51,17 @@ public class SearchPreferenceCategory extends PreferenceCategory implements Geck
|
||||
@Override
|
||||
public void handleMessage(String event, final JSONObject data) {
|
||||
if (event.equals("SearchEngines:Data")) {
|
||||
// Parse engines array from JSON. The first element in the array is the default engine.
|
||||
JSONArray engines;
|
||||
JSONObject defaultEngine;
|
||||
final String defaultEngineName;
|
||||
try {
|
||||
engines = data.getJSONArray("searchEngines");
|
||||
if (engines.length() == 0) {
|
||||
return;
|
||||
}
|
||||
defaultEngine = engines.getJSONObject(0);
|
||||
defaultEngineName = defaultEngine.getString("name");
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOGTAG, "Unable to decode search engine data from Gecko.", e);
|
||||
return;
|
||||
@ -66,24 +73,90 @@ public class SearchPreferenceCategory extends PreferenceCategory implements Geck
|
||||
JSONObject engineJSON = engines.getJSONObject(i);
|
||||
final String engineName = engineJSON.getString("name");
|
||||
|
||||
Preference engine = new Preference(getContext());
|
||||
engine.setTitle(engineName);
|
||||
engine.setKey(engineName);
|
||||
|
||||
// The setIcon feature is not available prior to API 11.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||
String iconURI = engineJSON.getString("iconURI");
|
||||
Bitmap iconBitmap = BitmapUtils.getBitmapFromDataURI(iconURI);
|
||||
Bitmap scaledIconBitmap = Bitmap.createScaledBitmap(iconBitmap, sIconSize, sIconSize, false);
|
||||
BitmapDrawable drawable = new BitmapDrawable(scaledIconBitmap);
|
||||
engine.setIcon(drawable);
|
||||
SearchEnginePreference enginePreference = new SearchEnginePreference(getContext(), this);
|
||||
enginePreference.setSearchEngineFromJSON(engineJSON);
|
||||
if (engineName.equals(defaultEngineName)) {
|
||||
// We set this here, not in setSearchEngineFromJSON, because it allows us to
|
||||
// keep a reference to the default engine to use when the AlertDialog
|
||||
// callbacks are used.
|
||||
enginePreference.setIsDefaultEngine(true);
|
||||
mDefaultEngineReference = enginePreference;
|
||||
}
|
||||
addPreference(engine);
|
||||
// TODO: Bug 892113 - Add event listener here for tapping on each element. Produce a dialog to provide options.
|
||||
|
||||
enginePreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
SearchEnginePreference sPref = (SearchEnginePreference) preference;
|
||||
// Display the configuration dialog associated with the tapped engine.
|
||||
sPref.showDialog();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
addPreference(enginePreference);
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOGTAG, "JSONException parsing engine at index " + i, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We are no longer interested in this event from Gecko, as we do not request it again with
|
||||
// this instance.
|
||||
GeckoAppShell.unregisterEventListener("SearchEngines:Data", this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default engine to any available engine. Used if the current default is removed or
|
||||
* disabled.
|
||||
*/
|
||||
private void setFallbackDefaultEngine() {
|
||||
if (getPreferenceCount() > 0) {
|
||||
SearchEnginePreference aEngine = (SearchEnginePreference) getPreference(0);
|
||||
setDefault(aEngine);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to send a particular event string to Gecko with an associated engine name.
|
||||
* @param event The type of event to send.
|
||||
* @param engine The engine to which the event relates.
|
||||
*/
|
||||
private void sendGeckoEngineEvent(String event, SearchEnginePreference engine) {
|
||||
JSONObject json = new JSONObject();
|
||||
try {
|
||||
json.put("engine", engine.getTitle());
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOGTAG, "JSONException creating search engine configuration change message for Gecko.", e);
|
||||
return;
|
||||
}
|
||||
GeckoAppShell.notifyGeckoOfEvent(GeckoEvent.createBroadcastEvent(event, json.toString()));
|
||||
}
|
||||
|
||||
// Methods called by tapping items on the submenus for each search engine are below.
|
||||
|
||||
/**
|
||||
* Removes the given engine from the set of available engines.
|
||||
* @param engine The engine to remove.
|
||||
*/
|
||||
public void uninstall(SearchEnginePreference engine) {
|
||||
removePreference(engine);
|
||||
if (engine == mDefaultEngineReference) {
|
||||
// If they're deleting their default engine, get them a new default engine.
|
||||
setFallbackDefaultEngine();
|
||||
}
|
||||
|
||||
sendGeckoEngineEvent("SearchEngines:Remove", engine);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given engine as the current default engine.
|
||||
* @param engine The intended new default engine.
|
||||
*/
|
||||
public void setDefault(SearchEnginePreference engine) {
|
||||
engine.setIsDefaultEngine(true);
|
||||
mDefaultEngineReference.setIsDefaultEngine(false);
|
||||
mDefaultEngineReference = engine;
|
||||
|
||||
sendGeckoEngineEvent("SearchEngines:SetDefault", engine);
|
||||
}
|
||||
}
|
||||
|
@ -151,6 +151,12 @@
|
||||
<string name="pref_vendor_faqs">&pref_vendor_faqs;</string>
|
||||
<string name="pref_vendor_feedback">&pref_vendor_feedback;</string>
|
||||
|
||||
<!-- Strings used in default search provider config preferences menu -->
|
||||
<string name="pref_search_set_default">&pref_search_set_default;</string>
|
||||
<string name="pref_search_default">&pref_search_default;</string>
|
||||
<string name="pref_search_remove">&pref_search_remove;</string>
|
||||
<string name="pref_search_last_toast">&pref_search_last_toast;</string>
|
||||
|
||||
<string name="datareporting_notification_title">&datareporting_notification_title;</string>
|
||||
<string name="datareporting_notification_action_long">&datareporting_notification_action_long;</string>
|
||||
<string name="datareporting_notification_action">&datareporting_notification_action;</string>
|
||||
|
@ -61,12 +61,7 @@ var ContextMenus = {
|
||||
document.getElementById("contextmenu-disable").setAttribute("hidden", "true");
|
||||
}
|
||||
|
||||
// Only show the "Set as Default" menuitem for enabled non-default search engines.
|
||||
if (addon.type == "search" && enabled && addon.id != Services.search.defaultEngine.name) {
|
||||
document.getElementById("contextmenu-default").removeAttribute("hidden");
|
||||
} else {
|
||||
document.getElementById("contextmenu-default").setAttribute("hidden", "true");
|
||||
}
|
||||
document.getElementById("contextmenu-default").setAttribute("hidden", "true");
|
||||
},
|
||||
|
||||
enable: function(event) {
|
||||
@ -82,17 +77,11 @@ var ContextMenus = {
|
||||
uninstall: function (event) {
|
||||
Addons.uninstall(this.target.addon);
|
||||
this.target = null;
|
||||
},
|
||||
|
||||
setDefaultSearch: function(event) {
|
||||
Addons.setDefaultSearch(this.target.addon);
|
||||
this.target = null;
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
window.addEventListener("popstate", onPopState, false);
|
||||
Services.obs.addObserver(Addons, "browser-search-engine-modified", false);
|
||||
|
||||
AddonManager.addInstallListener(Addons);
|
||||
AddonManager.addAddonListener(Addons);
|
||||
@ -102,7 +91,6 @@ function init() {
|
||||
}
|
||||
|
||||
function uninit() {
|
||||
Services.obs.removeObserver(Addons, "browser-search-engine-modified");
|
||||
AddonManager.removeInstallListener(Addons);
|
||||
AddonManager.removeAddonListener(Addons);
|
||||
}
|
||||
@ -361,16 +349,7 @@ var Addons = {
|
||||
uninstallBtn.removeAttribute("disabled");
|
||||
|
||||
let defaultButton = document.getElementById("default-btn");
|
||||
if (addon.type == "search") {
|
||||
if (addon.id == Services.search.defaultEngine.name)
|
||||
defaultButton.setAttribute("disabled", "true");
|
||||
else
|
||||
defaultButton.removeAttribute("disabled");
|
||||
|
||||
defaultButton.removeAttribute("hidden");
|
||||
} else {
|
||||
defaultButton.setAttribute("hidden", "true");
|
||||
}
|
||||
defaultButton.setAttribute("hidden", "true");
|
||||
|
||||
let box = document.querySelector("#addons-details > .addon-item .options-box");
|
||||
box.innerHTML = "";
|
||||
@ -424,10 +403,7 @@ var Addons = {
|
||||
let listItem = this._getElementForAddon(addon.id);
|
||||
|
||||
let opType;
|
||||
if (addon.type == "search") {
|
||||
addon.engine.hidden = !aValue;
|
||||
opType = aValue ? "needs-enable" : "needs-disable";
|
||||
} else if (addon.type == "theme") {
|
||||
if (addon.type == "theme") {
|
||||
if (aValue) {
|
||||
// We can have only one theme enabled, so disable the current one if any
|
||||
let list = document.getElementById("addons-list");
|
||||
@ -492,30 +468,21 @@ var Addons = {
|
||||
|
||||
let listItem = this._getElementForAddon(addon.id);
|
||||
|
||||
if (addon.type == "search") {
|
||||
// Make sure the engine isn't hidden before removing it, to make sure it's
|
||||
// visible if the user later re-adds it (works around bug 341833)
|
||||
addon.engine.hidden = false;
|
||||
Services.search.removeEngine(addon.engine);
|
||||
// the search-engine-modified observer will take care of updating the list
|
||||
history.back();
|
||||
addon.uninstall();
|
||||
if (addon.pendingOperations & AddonManager.PENDING_UNINSTALL) {
|
||||
this.showRestart();
|
||||
|
||||
// A disabled addon doesn't need a restart so it has no pending ops and
|
||||
// can't be cancelled
|
||||
let opType = this._getOpTypeForOperations(addon.pendingOperations);
|
||||
if (!addon.isActive && opType == "")
|
||||
opType = "needs-uninstall";
|
||||
|
||||
detailItem.setAttribute("opType", opType);
|
||||
listItem.setAttribute("opType", opType);
|
||||
} else {
|
||||
addon.uninstall();
|
||||
if (addon.pendingOperations & AddonManager.PENDING_UNINSTALL) {
|
||||
this.showRestart();
|
||||
|
||||
// A disabled addon doesn't need a restart so it has no pending ops and
|
||||
// can't be cancelled
|
||||
let opType = this._getOpTypeForOperations(addon.pendingOperations);
|
||||
if (!addon.isActive && opType == "")
|
||||
opType = "needs-uninstall";
|
||||
|
||||
detailItem.setAttribute("opType", opType);
|
||||
listItem.setAttribute("opType", opType);
|
||||
} else {
|
||||
list.removeChild(listItem);
|
||||
history.back();
|
||||
}
|
||||
list.removeChild(listItem);
|
||||
history.back();
|
||||
}
|
||||
},
|
||||
|
||||
@ -535,20 +502,6 @@ var Addons = {
|
||||
listItem.setAttribute("opType", opType);
|
||||
},
|
||||
|
||||
setDefaultSearch: function setDefaultSearch(aAddon) {
|
||||
let addon = aAddon || document.querySelector("#addons-details > .addon-item").addon;
|
||||
if (addon.type != "search")
|
||||
return;
|
||||
|
||||
let engine = Services.search.getEngineByName(addon.id);
|
||||
|
||||
// Move the new default search engine to the top of the search engine list.
|
||||
Services.search.moveEngine(engine, 0);
|
||||
Services.search.defaultEngine = engine;
|
||||
|
||||
document.getElementById("default-btn").setAttribute("disabled", "true");
|
||||
},
|
||||
|
||||
showRestart: function showRestart() {
|
||||
this._restartCount++;
|
||||
gChromeWin.XPInstallObserver.showRestartPrompt();
|
||||
@ -590,18 +543,6 @@ var Addons = {
|
||||
element.setAttribute("opType", "needs-restart");
|
||||
},
|
||||
|
||||
observe: function observe(aSubject, aTopic, aData) {
|
||||
if (aTopic == "browser-search-engine-modified") {
|
||||
switch (aData) {
|
||||
case "engine-added":
|
||||
case "engine-removed":
|
||||
case "engine-changed":
|
||||
this.getAddons();
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onInstallFailed: function(aInstall) {
|
||||
},
|
||||
|
||||
|
@ -57,7 +57,6 @@
|
||||
<menuitem id="contextmenu-enable" label="&addonAction.enable;" onclick="ContextMenus.enable();"></menuitem>
|
||||
<menuitem id="contextmenu-disable" label="&addonAction.disable;" onclick="ContextMenus.disable();"></menuitem>
|
||||
<menuitem id="contextmenu-uninstall" label="&addonAction.uninstall;" onclick="ContextMenus.uninstall();"></menuitem>
|
||||
<menuitem id="contextmenu-default" label="&addonAction.setDefault;" onclick="ContextMenus.setDefaultSearch();"></menuitem>
|
||||
</menu>
|
||||
|
||||
<div id="addons-header" class="header">
|
||||
@ -84,7 +83,6 @@
|
||||
<button id="disable-btn" class="show-on-enable hide-on-disable hide-on-uninstall" onclick="Addons.disable();">&addonAction.disable;</button>
|
||||
<button id="uninstall-btn" class="hide-on-uninstall" onclick="Addons.uninstall();">&addonAction.uninstall;</button>
|
||||
<button id="cancel-btn" class="show-on-uninstall" onclick="Addons.cancelUninstall();">&addonAction.undo;</button>
|
||||
<button id="default-btn" class="show-on-enable hide-on-disable hide-on-uninstall" onclick="Addons.setDefaultSearch();">&addonAction.setDefault;</button>
|
||||
</div>
|
||||
<div class="options-header">&aboutAddons.options;</div>
|
||||
<div class="options-box"></div>
|
||||
|
@ -6421,6 +6421,9 @@ var SearchEngines = {
|
||||
|
||||
init: function init() {
|
||||
Services.obs.addObserver(this, "SearchEngines:Get", false);
|
||||
Services.obs.addObserver(this, "SearchEngines:GetVisible", false);
|
||||
Services.obs.addObserver(this, "SearchEngines:SetDefault", false);
|
||||
Services.obs.addObserver(this, "SearchEngines:Remove", false);
|
||||
let contextName = Strings.browser.GetStringFromName("contextmenu.addSearchEngine");
|
||||
let filter = {
|
||||
matches: function (aElement) {
|
||||
@ -6432,21 +6435,36 @@ var SearchEngines = {
|
||||
|
||||
uninit: function uninit() {
|
||||
Services.obs.removeObserver(this, "SearchEngines:Get");
|
||||
Services.obs.removeObserver(this, "SearchEngines:GetVisible");
|
||||
Services.obs.removeObserver(this, "SearchEngines:SetDefault");
|
||||
Services.obs.removeObserver(this, "SearchEngines:Remove");
|
||||
if (this._contextMenuId != null)
|
||||
NativeWindow.contextmenus.remove(this._contextMenuId);
|
||||
},
|
||||
|
||||
_handleSearchEnginesGet: function _handleSearchEnginesGet(rv) {
|
||||
// Fetch list of search engines. all ? All engines : Visible engines only.
|
||||
_handleSearchEnginesGet: function _handleSearchEnginesGet(rv, all) {
|
||||
if (!Components.isSuccessCode(rv)) {
|
||||
Cu.reportError("Could not initialize search service, bailing out.");
|
||||
return;
|
||||
}
|
||||
let engineData = Services.search.getVisibleEngines({});
|
||||
let engineData;
|
||||
if (all) {
|
||||
engineData = Services.search.getEngines({});
|
||||
} else {
|
||||
engineData = Services.search.getVisibleEngines({});
|
||||
}
|
||||
|
||||
// These engines are the bundled ones - they may not be uninstalled.
|
||||
let immutableEngines = Services.search.getDefaultEngines();
|
||||
|
||||
let searchEngines = engineData.map(function (engine) {
|
||||
return {
|
||||
name: engine.name,
|
||||
identifier: engine.identifier,
|
||||
iconURI: (engine.iconURI ? engine.iconURI.spec : null)
|
||||
iconURI: (engine.iconURI ? engine.iconURI.spec : null),
|
||||
hidden: engine.hidden,
|
||||
immutable: immutableEngines.indexOf(engine) != -1
|
||||
};
|
||||
});
|
||||
|
||||
@ -6458,6 +6476,8 @@ var SearchEngines = {
|
||||
suggestTemplate = engine.getSubmission("__searchTerms__", "application/x-suggestions+json").uri.spec;
|
||||
}
|
||||
|
||||
|
||||
// By convention, the currently configured default engine is at position zero in searchEngines.
|
||||
sendMessageToJava({
|
||||
type: "SearchEngines:Data",
|
||||
searchEngines: searchEngines,
|
||||
@ -6470,9 +6490,45 @@ var SearchEngines = {
|
||||
});
|
||||
},
|
||||
|
||||
_handleSearchEnginesGetAll: function _handleSearchEnginesGetAll(rv) {
|
||||
this._handleSearchEnginesGet(rv, true);
|
||||
},
|
||||
_handleSearchEnginesGetVisible: function _handleSearchEnginesGetVisible(rv) {
|
||||
this._handleSearchEnginesGet(rv, false)
|
||||
},
|
||||
|
||||
// Helper method to extract the engine name from a JSON. Simplifies the observe function.
|
||||
_extractEngineFromJSON: function _extractEngineFromJSON(aData) {
|
||||
let data = JSON.parse(aData);
|
||||
return Services.search.getEngineByName(data.engine);
|
||||
},
|
||||
|
||||
observe: function observe(aSubject, aTopic, aData) {
|
||||
if (aTopic == "SearchEngines:Get") {
|
||||
Services.search.init(this._handleSearchEnginesGet.bind(this));
|
||||
let engine;
|
||||
switch(aTopic) {
|
||||
case "SearchEngines:GetVisible":
|
||||
Services.search.init(this._handleSearchEnginesGetVisible.bind(this));
|
||||
break;
|
||||
case "SearchEngines:Get":
|
||||
// Return a list of all engines, including "Hidden" ones.
|
||||
Services.search.init(this._handleSearchEnginesGetAll.bind(this));
|
||||
break;
|
||||
case "SearchEngines:SetDefault":
|
||||
engine = this._extractEngineFromJSON(aData);
|
||||
// Move the new default search engine to the top of the search engine list.
|
||||
Services.search.moveEngine(engine, 0);
|
||||
Services.search.defaultEngine = engine;
|
||||
break;
|
||||
case "SearchEngines:Remove":
|
||||
// Make sure the engine isn't hidden before removing it, to make sure it's
|
||||
// visible if the user later re-adds it (works around bug 341833)
|
||||
engine = this._extractEngineFromJSON(aData);
|
||||
engine.hidden = false;
|
||||
Services.search.removeEngine(engine);
|
||||
break;
|
||||
default:
|
||||
dump("Unexpected message type observed: " + aTopic);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -10,4 +10,3 @@
|
||||
<!ENTITY addonAction.disable "Disable">
|
||||
<!ENTITY addonAction.uninstall "Uninstall">
|
||||
<!ENTITY addonAction.undo "Undo">
|
||||
<!ENTITY addonAction.setDefault "Set as Default">
|
||||
|
@ -2,12 +2,9 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
addonsSearchEngine.description=Integrated Search
|
||||
|
||||
addonType.extension=Extension
|
||||
addonType.theme=Theme
|
||||
addonType.locale=Locale
|
||||
addonType.search=Search
|
||||
|
||||
addonStatus.uninstalled=%S will be uninstalled after restart.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user