зеркало из https://github.com/mozilla/gecko-dev.git
Bug 706876 - Create "Clear Site Settings" menuitem. r=mfinkle
This commit is contained in:
Родитель
ddf6778a19
Коммит
3ed223571b
|
@ -544,6 +544,9 @@ abstract public class GeckoApp
|
|||
intent = new Intent(this, GeckoPreferences.class);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
case R.id.site_settings:
|
||||
GeckoAppShell.sendEventToGecko(new GeckoEvent("Permissions:Get", null));
|
||||
return true;
|
||||
case R.id.addons:
|
||||
GeckoAppShell.sendEventToGecko(new GeckoEvent("about:addons"));
|
||||
return true;
|
||||
|
@ -976,6 +979,10 @@ abstract public class GeckoApp
|
|||
tab.setAgentMode(agentMode);
|
||||
if (tab == Tabs.getInstance().getSelectedTab())
|
||||
updateAgentModeMenuItem(tab, agentMode);
|
||||
} else if (event.equals("Permissions:Data")) {
|
||||
String host = message.getString("host");
|
||||
JSONArray permissions = message.getJSONArray("permissions");
|
||||
showSiteSettingsDialog(host, permissions);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
|
||||
|
@ -1030,6 +1037,73 @@ abstract public class GeckoApp
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param aPermissions
|
||||
* Array of JSON objects to represent site permissions.
|
||||
* Example: { type: "offline-app", setting: "Store Offline Data: Allow" }
|
||||
*/
|
||||
private void showSiteSettingsDialog(String aHost, JSONArray aPermissions) {
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
|
||||
View customTitleView = getLayoutInflater().inflate(R.layout.site_setting_title, null);
|
||||
((TextView) customTitleView.findViewById(R.id.title)).setText(R.string.site_settings_title);
|
||||
((TextView) customTitleView.findViewById(R.id.host)).setText(aHost);
|
||||
builder.setCustomTitle(customTitleView);
|
||||
|
||||
// If there are no permissions to clear, show the user a message about that.
|
||||
// In the future, we want to disable the menu item if there are no permissions to clear.
|
||||
if (aPermissions.length() == 0) {
|
||||
builder.setMessage(R.string.site_settings_no_settings);
|
||||
} else {
|
||||
// Eventually we should use a list adapter and custom checkable list items
|
||||
// to make a two-line UI to match the mock-ups
|
||||
CharSequence[] items = new CharSequence[aPermissions.length()];
|
||||
boolean[] states = new boolean[aPermissions.length()];
|
||||
for (int i = 0; i < aPermissions.length(); i++) {
|
||||
try {
|
||||
items[i] = aPermissions.getJSONObject(i).
|
||||
getString("setting");
|
||||
// Make all the items checked by default
|
||||
states[i] = true;
|
||||
} catch (JSONException e) {
|
||||
Log.i(LOGTAG, "JSONException: " + e);
|
||||
}
|
||||
}
|
||||
builder.setMultiChoiceItems(items, states, new DialogInterface.OnMultiChoiceClickListener(){
|
||||
public void onClick(DialogInterface dialog, int item, boolean state) {
|
||||
// Do nothing
|
||||
}
|
||||
});
|
||||
builder.setPositiveButton(R.string.site_settings_clear, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
ListView listView = ((AlertDialog) dialog).getListView();
|
||||
SparseBooleanArray checkedItemPositions = listView.getCheckedItemPositions();
|
||||
|
||||
// An array of the indices of the permissions we want to clear
|
||||
JSONArray permissionsToClear = new JSONArray();
|
||||
for (int i = 0; i < checkedItemPositions.size(); i++) {
|
||||
boolean checked = checkedItemPositions.get(i);
|
||||
if (checked)
|
||||
permissionsToClear.put(i);
|
||||
}
|
||||
GeckoAppShell.sendEventToGecko(new GeckoEvent("Permissions:Clear", permissionsToClear.toString()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
builder.setNegativeButton(R.string.site_settings_cancel, new DialogInterface.OnClickListener(){
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dialog.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
builder.create().show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void handleDoorHanger(JSONObject geckoObject) throws JSONException {
|
||||
final String message = geckoObject.getString("message");
|
||||
final String value = geckoObject.getString("value");
|
||||
|
@ -1463,6 +1537,7 @@ abstract public class GeckoApp
|
|||
GeckoAppShell.registerGeckoEventListener("ToggleChrome:Show", GeckoApp.mAppContext);
|
||||
GeckoAppShell.registerGeckoEventListener("AgentMode:Changed", GeckoApp.mAppContext);
|
||||
GeckoAppShell.registerGeckoEventListener("FormAssist:AutoComplete", GeckoApp.mAppContext);
|
||||
GeckoAppShell.registerGeckoEventListener("Permissions:Data", GeckoApp.mAppContext);
|
||||
|
||||
mConnectivityFilter = new IntentFilter();
|
||||
mConnectivityFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||
|
@ -1693,6 +1768,7 @@ abstract public class GeckoApp
|
|||
GeckoAppShell.unregisterGeckoEventListener("ToggleChrome:Show", GeckoApp.mAppContext);
|
||||
GeckoAppShell.unregisterGeckoEventListener("AgentMode:Changed", GeckoApp.mAppContext);
|
||||
GeckoAppShell.unregisterGeckoEventListener("FormAssist:AutoComplete", GeckoApp.mAppContext);
|
||||
GeckoAppShell.unregisterGeckoEventListener("Permissions:Data", GeckoApp.mAppContext);
|
||||
|
||||
mFavicons.close();
|
||||
|
||||
|
|
|
@ -192,6 +192,7 @@ RES_LAYOUT = \
|
|||
res/layout/notification_icon_text.xml \
|
||||
res/layout/notification_progress.xml \
|
||||
res/layout/notification_progress_text.xml \
|
||||
res/layout/site_setting_title.xml \
|
||||
res/layout/tabs_row.xml \
|
||||
res/layout/tabs_tray.xml \
|
||||
res/layout/list_item_header.xml \
|
||||
|
|
|
@ -80,3 +80,8 @@
|
|||
<!ENTITY save_as_pdf "Save as PDF">
|
||||
<!ENTITY agent_request_desktop "Request Desktop Site">
|
||||
<!ENTITY agent_request_mobile "Request Mobile Site">
|
||||
|
||||
<!ENTITY site_settings_title "Clear Site Settings">
|
||||
<!ENTITY site_settings_cancel "Cancel">
|
||||
<!ENTITY site_settings_clear "Clear">
|
||||
<!ENTITY site_settings_no_settings "There are no settings to clear.">
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
<item android:id="@+id/preferences"
|
||||
android:title="@string/preferences" />
|
||||
|
||||
<item android:id="@+id/site_settings"
|
||||
android:title="@string/site_settings_title" />
|
||||
|
||||
<item android:id="@+id/addons"
|
||||
android:title="@string/addons"/>
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView android:id="@+id/title"
|
||||
style="?android:attr/windowTitleStyle"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="6dip"
|
||||
android:paddingBottom="0dip"
|
||||
android:paddingLeft="10dip"
|
||||
android:paddingRight="10dip"/>
|
||||
|
||||
<TextView android:id="@+id/host"
|
||||
style="?android:attr/windowTitleStyle"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="2dip"
|
||||
android:paddingBottom="6dip"
|
||||
android:paddingLeft="10dip"
|
||||
android:paddingRight="10dip"/>
|
||||
|
||||
</LinearLayout>
|
|
@ -82,4 +82,9 @@
|
|||
<string name="forward">&forward;</string>
|
||||
<string name="new_tab">&new_tab;</string>
|
||||
<string name="addons">&addons;</string>
|
||||
|
||||
<string name="site_settings_title">&site_settings_title;</string>
|
||||
<string name="site_settings_cancel">&site_settings_cancel;</string>
|
||||
<string name="site_settings_clear">&site_settings_clear;</string>
|
||||
<string name="site_settings_no_settings">&site_settings_no_settings;</string>
|
||||
</resources>
|
||||
|
|
|
@ -207,6 +207,7 @@ var BrowserApp = {
|
|||
XPInstallObserver.init();
|
||||
ConsoleAPI.init();
|
||||
ClipboardHelper.init();
|
||||
PermissionsHelper.init();
|
||||
|
||||
// Init LoginManager
|
||||
Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
|
||||
|
@ -3259,3 +3260,159 @@ var PluginHelper = {
|
|||
return overflows;
|
||||
}
|
||||
};
|
||||
|
||||
var PermissionsHelper = {
|
||||
|
||||
_permissonTypes: ["password", "geo", "popup", "indexedDB",
|
||||
"offline-app", "desktop-notification"],
|
||||
_permissionStrings: {
|
||||
"password": {
|
||||
label: "password.rememberPassword",
|
||||
allowed: "password.remember",
|
||||
denied: "password.never"
|
||||
},
|
||||
"geo": {
|
||||
label: "geolocation.shareLocation",
|
||||
allowed: "geolocation.alwaysShare",
|
||||
denied: "geolocation.neverShare"
|
||||
},
|
||||
"popup": {
|
||||
label: "blockPopups.label",
|
||||
allowed: "popupButtonAlwaysAllow2",
|
||||
denied: "popupButtonNeverWarn2"
|
||||
},
|
||||
"indexedDB": {
|
||||
label: "offlineApps.storeOfflineData",
|
||||
allowed: "offlineApps.allow",
|
||||
denied: "offlineApps.never"
|
||||
},
|
||||
"offline-app": {
|
||||
label: "offlineApps.storeOfflineData",
|
||||
allowed: "offlineApps.allow",
|
||||
denied: "offlineApps.never"
|
||||
},
|
||||
"desktop-notification": {
|
||||
label: "desktopNotification.useNotifications",
|
||||
allowed: "desktopNotification.allow",
|
||||
denied: "desktopNotification.dontAllow"
|
||||
}
|
||||
},
|
||||
|
||||
init: function init() {
|
||||
Services.obs.addObserver(this, "Permissions:Get", false);
|
||||
Services.obs.addObserver(this, "Permissions:Clear", false);
|
||||
},
|
||||
|
||||
observe: function observe(aSubject, aTopic, aData) {
|
||||
let uri = BrowserApp.selectedBrowser.currentURI;
|
||||
|
||||
switch (aTopic) {
|
||||
case "Permissions:Get":
|
||||
let permissions = [];
|
||||
for (let i = 0; i < this._permissonTypes.length; i++) {
|
||||
let type = this._permissonTypes[i];
|
||||
let value = this.getPermission(uri, type);
|
||||
|
||||
// Only add the permission if it was set by the user
|
||||
if (value == Services.perms.UNKNOWN_ACTION)
|
||||
continue;
|
||||
|
||||
// Get the strings that correspond to the permission type
|
||||
let typeStrings = this._permissionStrings[type];
|
||||
let label = Strings.browser.GetStringFromName(typeStrings["label"]);
|
||||
|
||||
// Get the key to look up the appropriate string entity
|
||||
let valueKey = value == Services.perms.ALLOW_ACTION ?
|
||||
"allowed" : "denied";
|
||||
let valueString = Strings.browser.GetStringFromName(typeStrings[valueKey]);
|
||||
|
||||
// If we implement a two-line UI, we will need to pass the label and
|
||||
// value individually and let java handle the formatting
|
||||
let setting = Strings.browser.formatStringFromName("siteSettings.labelToValue",
|
||||
[ label, valueString ], 2)
|
||||
permissions.push({
|
||||
type: type,
|
||||
setting: setting
|
||||
});
|
||||
}
|
||||
|
||||
// Keep track of permissions, so we know which ones to clear
|
||||
this._currentPermissions = permissions;
|
||||
|
||||
sendMessageToJava({
|
||||
gecko: {
|
||||
type: "Permissions:Data",
|
||||
host: uri.host,
|
||||
permissions: permissions
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case "Permissions:Clear":
|
||||
// An array of the indices of the permissions we want to clear
|
||||
let permissionsToClear = JSON.parse(aData);
|
||||
|
||||
for (let i = 0; i < permissionsToClear.length; i++) {
|
||||
let indexToClear = permissionsToClear[i];
|
||||
let permissionType = this._currentPermissions[indexToClear]["type"];
|
||||
this.clearPermission(uri, permissionType);
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the permission value stored for a specified permission type.
|
||||
*
|
||||
* @param aType
|
||||
* The permission type string stored in permission manager.
|
||||
* e.g. "cookie", "geo", "indexedDB", "popup", "image"
|
||||
*
|
||||
* @return A permission value defined in nsIPermissionManager.
|
||||
*/
|
||||
getPermission: function getPermission(aURI, aType) {
|
||||
// Password saving isn't a nsIPermissionManager permission type, so handle
|
||||
// it seperately.
|
||||
if (aType == "password") {
|
||||
// By default, login saving is enabled, so if it is disabled, the
|
||||
// user selected the never remember option
|
||||
if (!Services.logins.getLoginSavingEnabled(aURI.prePath))
|
||||
return Services.perms.DENY_ACTION;
|
||||
|
||||
// Check to see if the user ever actually saved a login
|
||||
if (Services.logins.countLogins(aURI.prePath, "", ""))
|
||||
return Services.perms.ALLOW_ACTION;
|
||||
|
||||
return Services.perms.UNKNOWN_ACTION;
|
||||
}
|
||||
|
||||
// Geolocation consumers use testExactPermission
|
||||
if (aType == "geo")
|
||||
return Services.perms.testExactPermission(aURI, aType);
|
||||
|
||||
return Services.perms.testPermission(aURI, aType);
|
||||
},
|
||||
|
||||
/**
|
||||
* Clears a user-set permission value for the site given a permission type.
|
||||
*
|
||||
* @param aType
|
||||
* The permission type string stored in permission manager.
|
||||
* e.g. "cookie", "geo", "indexedDB", "popup", "image"
|
||||
*/
|
||||
clearPermission: function clearPermission(aURI, aType) {
|
||||
// Password saving isn't a nsIPermissionManager permission type, so handle
|
||||
// it seperately.
|
||||
if (aType == "password") {
|
||||
// Get rid of exisiting stored logings
|
||||
let logins = Services.logins.findLogins({}, aURI.prePath, "", "");
|
||||
for (let i = 0; i < logins.length; i++) {
|
||||
Services.logins.removeLogin(logins[i]);
|
||||
}
|
||||
// Re-set login saving to enabled
|
||||
Services.logins.setLoginSavingEnabled(aURI.prePath, true);
|
||||
} else {
|
||||
Services.perms.remove(aURI.host, aType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,6 +122,10 @@ popupButtonAllowOnce=Show
|
|||
popupButtonAlwaysAllow2=Always Show
|
||||
popupButtonNeverWarn2=Never Show
|
||||
|
||||
# LOCALIZATION NOTE (blockPopups.label): Label that will be used in
|
||||
# site settings dialog.
|
||||
blockPopups.label=Block Popups
|
||||
|
||||
# Telemetry
|
||||
telemetry.optin.message=Help improve %S by sending anonymous usage information to Mozilla?
|
||||
telemetry.optin.yes=Yes
|
||||
|
@ -147,12 +151,20 @@ identity.ownerUnknown2=(unknown)
|
|||
# Geolocation UI
|
||||
geolocation.allow=Share
|
||||
geolocation.dontAllow=Don't share
|
||||
geolocation.alwaysAllow=Always Share
|
||||
geolocation.neverAllow=Never Share
|
||||
geolocation.wantsTo=%S wants your location.
|
||||
# LOCALIZATION NOTE (geolocation.shareLocation): Label that will be used in
|
||||
# site settings dialog.
|
||||
geolocation.shareLocation=Share Location
|
||||
|
||||
# Desktop notification UI
|
||||
desktopNotification.allow=Allow
|
||||
desktopNotification.dontAllow=Don't allow
|
||||
desktopNotification.wantsTo=%S wants to use notifications.
|
||||
# LOCALIZATION NOTE (desktopNotification.useNotifications): Label that will be
|
||||
# used in site settings dialog.
|
||||
desktopNotification.useNotifications=Use Notifications
|
||||
|
||||
# New Tab Popup
|
||||
# LOCALIZATION NOTE (newtabpopup): Semi-colon list of plural forms.
|
||||
|
@ -169,6 +181,9 @@ offlineApps.available2=%S wants to store data on your device for offline use.
|
|||
offlineApps.allow=Allow
|
||||
offlineApps.never=Don't Allow
|
||||
offlineApps.notNow=Not Now
|
||||
# LOCALIZATION NOTE (offlineApps.storeOfflineData): Label that will be used in
|
||||
# site settings dialog.
|
||||
offlineApps.storeOfflineData=Store Offline Data
|
||||
|
||||
# New-style ContentPermissionPrompt values
|
||||
offlineApps.dontAllow=Don't Allow
|
||||
|
@ -184,6 +199,16 @@ openWebappsManage.allow=Allow
|
|||
openWebappsManage.dontAllow=Don't Allow
|
||||
openWebappsManage.wantsTo=%S wants to manage applications on your device.
|
||||
|
||||
# LOCALIZATION NOTE (password.rememberPassword): Label that will be used in
|
||||
# site settings dialog.
|
||||
password.rememberPassword=Remember Password
|
||||
# LOCALIZATION NOTE (password.remember): This should match
|
||||
# promptRememberButtonText in passwordmgr.properties
|
||||
password.remember=Remember
|
||||
# LOCALIZATION NOTE (password.never): This should match
|
||||
# promptNeverForSiteButtonText in passwordmgr.properties
|
||||
password.never=Never
|
||||
|
||||
# Bookmark List
|
||||
bookmarkList.desktop=Desktop Bookmarks
|
||||
|
||||
|
@ -278,3 +303,9 @@ timer.end=%1$S: %2$Sms
|
|||
clickToPlayFlash.message=This page contains flash content. Would you like to play it?
|
||||
clickToPlayFlash.yes=Yes
|
||||
clickToPlayFlash.no=No
|
||||
|
||||
# Site settings dialog
|
||||
# LOCALIZATION NOTE (siteSettings.labelToValue): This string will be used to
|
||||
# dislay a list of current permissions settings for a site.
|
||||
# Example: "Store Offline Data: Allow"
|
||||
siteSettings.labelToValue=%S: %S
|
||||
|
|
Загрузка…
Ссылка в новой задаче