I have a usability issue when requesting extra permissions on Facebook.
According to Facebook's documentation, the FB.login
function should only be called after a click because most browsers block pop-ups by any other means.
The problem occurs when I am using the FB.login
function in the middle of my application in order to request extra permissions to post an image (according to Facebook best practices I leave to request this permission at the last moment).
Before ordering the permission I check if the user has not previously granted it. Which led me to the following construction:
Permission check function:
function checkPermissions(perms, callback, failCallback) {
FB.api('/me/permissions', function (response) {
var fbPerms = response.data[0];
var haveAllPermissions = true;
if (typeof perms === 'string') {
perms = [ perms ];
}
for (var i in perms) {
if (fbPerms[perms[i]] == null) {
haveAllPermissions = false;
break;
}
}
if (haveAllPermissions) {
callback();
} else {
failCallback();
}
});
}
The "broken" version
Use the following construction (activated by a click of a button):
// Verifica permissões
checkPermissions("publish_actions",
// Em caso de sucesso cria o request
generateRequest,
// Em caso de fracasso
function () {
// requisita a permissão
FB.login(function () {
// Verifica a permissão novamente
checkPermissions("publish_actions",
// Em caso de sucesso cria o request
generateRequest,
// Em caso de fracasso notifica o usuário
function () {
alert("Permissão negada");
// Reativa o botão para postar colagens
$("#gerarColagem").one('click', enviaColagem);
});
}, {scope: "publish_actions"});
});
You can see the code in action link (by clicking on the Post button).
The problem
As I'm checking with permission publish_actions
the popup is not directly linked to the click. Even though a click activates the stream, the call to FB.login
is actually tied to a callback
. Result: Browsers are blocking the login pop-up.
The undesirable solution
I can skip the first check for permissions and force a stream of login
always (if the user has already granted the permission everything happens silently):
FB.login(function () {
// Verifica a permissão novamente
checkPermissions("publish_actions",
// Em caso de sucesso cria o request
generateRequest,
// Em caso de fracasso notifica o usuário
function () {
alert("Permissão negada");
// Reativa o botão para postar colagens
$("#gerarColagem").one('click', enviaColagem);
});
}, {scope: "publish_actions"});
In this case (by skipping the first permission check) the popup normally opens since the FB.login
method is responding directly to the click. The downside is that it is calling the login method every time, making users who have previously granted permission handle an unnecessary and recurring overhead.
In the happy scenario the user will grant the permission the first time they click "Post". The "broken" version ensures that these users do not pass through a login stream unnecessarily; everything works correctly after the first authorization.
So, my question is: How do I structure my calls to make and request permissions with FB.login
without the browser blocking the Facebook pop-up? Is there any way to check the permissions before calling FB.login
without the browser blocking the popup?
Perfect scenery
publish_actions
Alternate scenario:
publish_actions