Bug 1410236 - Deny permission by default if doorhanger is dismissed; r=sebastian

Add a "defaultCallback" option to the doorhanger API that specifies a
callback to call when the doorhanger is dismissed without a button being
clicked. Use that to deny a permission in ContentPermissionPrompt.js
when the doorhanger is dismissed without explicit action.

MozReview-Commit-ID: 9kOAWirI4Ux
This commit is contained in:
Jim Chen 2017-10-30 12:42:30 -04:00
Родитель c9960f7e15
Коммит f568e139e7
5 изменённых файлов: 50 добавлений и 5 удалений

Просмотреть файл

@ -89,7 +89,7 @@ public class DoorHangerPopup extends AnchoredPopup
final EventCallback callback) {
if (event.equals("Doorhanger:Add")) {
final DoorhangerConfig config = makeConfigFromBundle(geckoObject);
addDoorHanger(config, callback);
addDoorHanger(config, callback, (Integer) geckoObject.get("defaultCallback"));
} else if (event.equals("Doorhanger:Remove")) {
final int tabId = geckoObject.getInt("tabID", -1);
@ -166,7 +166,8 @@ public class DoorHangerPopup extends AnchoredPopup
*
* This method must be called on the UI thread.
*/
private void addDoorHanger(final DoorhangerConfig config, final EventCallback callback) {
private void addDoorHanger(final DoorhangerConfig config, final EventCallback callback,
final Integer defaultCallback) {
final int tabId = config.getTabId();
// Don't add a doorhanger for a tab that doesn't exist
if (isGeckoApp && Tabs.getInstance().getTab(tabId) == null) {
@ -185,6 +186,7 @@ public class DoorHangerPopup extends AnchoredPopup
final DoorHanger newDoorHanger = DoorHanger.Get(mContext, config);
newDoorHanger.callback = callback;
newDoorHanger.defaultCallback = defaultCallback;
mDoorHangers.add(newDoorHanger);
mContent.addView(newDoorHanger);
@ -206,6 +208,10 @@ public class DoorHangerPopup extends AnchoredPopup
} else {
doorhanger.callback.sendSuccess(response);
}
// Don't call default callback because a button was clicked.
doorhanger.defaultCallback = null;
removeDoorHanger(doorhanger);
updatePopup();
}
@ -231,6 +237,17 @@ public class DoorHangerPopup extends AnchoredPopup
* This method must be called on the UI thread.
*/
private void removeDoorHanger(final DoorHanger doorHanger) {
// Call default callback if requested.
if (doorHanger.defaultCallback != null) {
final GeckoBundle response = new GeckoBundle(1);
response.putInt("callback", doorHanger.defaultCallback);
if (isGeckoApp) {
EventDispatcher.getInstance().dispatch("Doorhanger:Reply", response);
} else {
doorHanger.callback.sendSuccess(response);
}
}
mDoorHangers.remove(doorHanger);
mContent.removeView(doorHanger);
}

Просмотреть файл

@ -91,6 +91,7 @@ public abstract class DoorHanger extends LinearLayout {
protected long mTimeout;
public EventCallback callback;
public Integer defaultCallback;
protected DoorHanger(Context context, DoorhangerConfig config, Type type) {
super(context);

Просмотреть файл

@ -2344,6 +2344,10 @@ var NativeWindow = {
* type: <type>,
* bundle: <blob-object> }
*
* defaultCallback:
* Callback invoked when the doorhanger is dismissed without
* pressing a button.
*
* @param aCategory
* Doorhanger type to display (e.g., LOGIN)
*/
@ -2363,6 +2367,16 @@ var NativeWindow = {
this._callbacksId++;
});
this._callbacks[this._callbacksId] = {
cb: aOptions && aOptions.defaultCallback,
prompt: this._promptId,
};
if (aOptions && aOptions.defaultCallback) {
aOptions.defaultCallback = undefined;
}
let defaultCallback = this._callbacksId;
this._callbacksId++;
this._promptId++;
let json = {
type: "Doorhanger:Add",
@ -2372,7 +2386,8 @@ var NativeWindow = {
// use the current tab if none is provided
tabID: aTabID || BrowserApp.selectedTab.id,
options: aOptions || {},
category: aCategory
category: aCategory,
defaultCallback: defaultCallback,
};
WindowEventDispatcher.sendRequest(json);
},
@ -2392,8 +2407,10 @@ var NativeWindow = {
if (this.doorhanger._callbacks[reply_id]) {
// Pass the value of the optional checkbox to the callback
let checked = data["checked"];
this.doorhanger._callbacks[reply_id].cb(checked, data.inputs);
if (this.doorhanger._callbacks[reply_id].cb) {
let checked = data["checked"];
this.doorhanger._callbacks[reply_id].cb(checked, data.inputs);
}
let prompt = this.doorhanger._callbacks[reply_id].prompt;
for (let id in this.doorhanger._callbacks) {

Просмотреть файл

@ -157,6 +157,10 @@ ContentPermissionPrompt.prototype = {
options = { checkbox: browserBundle.GetStringFromName(entityName + ".dontAskAgain") };
}
options.defaultCallback = () => {
callback(/* allow */ false);
};
DoorHanger.show(request.window || request.element.ownerGlobal,
message, entityName + request.principal.URI.host,
buttons, options, entityName.toUpperCase());

Просмотреть файл

@ -286,7 +286,13 @@ var DoorHanger = {
buttons: aButtons,
options: aOptions || {},
category: aCategory,
defaultCallback: (aOptions && aOptions.defaultCallback) ? -1 : undefined,
}).then(response => {
if (response.callback === -1) {
// Default case.
aOptions.defaultCallback(response.checked, response.inputs);
return;
}
// Pass the value of the optional checkbox to the callback
callbacks[response.callback](response.checked, response.inputs);
});