Fallback to window-based chat in case of blocked third parties cookies

Also affects #261.
This commit is contained in:
Fedor A. Fetisov 2021-08-27 23:10:37 +03:00
parent 0c416c7d7c
commit 2533b362ab
3 changed files with 66 additions and 0 deletions

View File

@ -102,6 +102,11 @@ chat_user_start:
defaults:
_controller: Mibew\Controller\Chat\UserChatController::startAction
chat_user_cookie_set_permission:
path: /chat/cookies-set-permission
defaults:
_controller: Mibew\Controller\Chat\UserChatController::cookieSetPermissionAction
# Pages that are available for all users
button:
path: /b

View File

@ -301,6 +301,12 @@ var Mibew = Mibew || {};
// Call parent constructor.
BasePopup.call(this, options);
/**
* Store options in case we need some of them later.
* @type {Object}
*/
this.options = options;
/**
* Wrapper for popup iframe DOM Element.
* @type {Node}
@ -331,6 +337,12 @@ var Mibew = Mibew || {};
*/
this.isMinified = false;
/**
* Indicates if cookies are blocked.
* @type {Boolean}
*/
this.cookiesBlocked = false;
// Load default styles. These styles hide the popup while real styles
// are loading.
this.attachDefaultStyles();
@ -344,6 +356,18 @@ var Mibew = Mibew || {};
// new page is visited.
this.safeOpen(openedChatUrl);
}
// Check if it's possible to set cookies at all
var rnd = Math.random();
Mibew.Utils.createCookie('mibewCheckToken', rnd);
var checkCookiesBlock = Mibew.Utils.loadScript(options.url.split('?')[0] + '/cookies-set-permission' + '?rnd=' + rnd);
checkCookiesBlock.popup = this;
checkCookiesBlock.onload = function() {
this.popup.cookiesBlocked = false;
};
checkCookiesBlock.onerror = function() {
this.popup.cookiesBlocked = true;
};
};
// Set correct prototype chain for IFrame popup.
@ -394,6 +418,14 @@ var Mibew = Mibew || {};
return;
}
if (this.cookiesBlocked) {
// Last resort. Replace this iframe-based popup with window-based popup
// and try to open a chat in a separate window.
Mibew.Objects.ChatPopups[this.id] = new Mibew.ChatPopup.Window(this.options);
Mibew.Objects.ChatPopups[this.id].open(url);
return;
}
if (!this.wrapperDiv) {
// Create new iframe and its wrapper.
// There is a bug in IE <= 7 that make "name" attribute unchangeble
@ -513,6 +545,10 @@ var Mibew = Mibew || {};
* value is omitted, the chat initialization URL will be loaded.
*/
Mibew.ChatPopup.Window.prototype.open = function(url) {
// Windows is already opened, nothing to do.
if (this.window != null && !this.window.closed) {
return;
}
this.window = window.open(
url || this.buildChatUrl(),
'mibewChat' + this.id,

View File

@ -299,4 +299,29 @@ class UserChatController extends AbstractController
// Expand page
return $this->render('chat', $page);
}
/**
* Check possibility to set cookie on the client side: it's crusial for chat to work,
* since otherwise there will be no session.
*
* @param Request $request Incoming request.
* @return string Empty string.
* @throws AccessDeniedException if the thread with specified ID and token is
* not found.
*/
public function cookieSetPermissionAction(Request $request)
{
$blocked = true;
$token1 = $request->query->get('rnd');
if ($request->cookies->has('mibewCheckToken')) {
$token2 = $request->cookies->get('mibewCheckToken');
if ($token1 === $token2) {
$blocked = false;
}
}
if ($blocked) {
throw new NotFoundException('Cookies are blocked.');
}
return "";
}
}