Add confirmation on first webview open.

This commit is contained in:
John Preston 2022-04-06 11:45:51 +04:00
parent 73c5988e7e
commit 646682b6a0
6 changed files with 101 additions and 13 deletions

View file

@ -1720,6 +1720,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_open_link" = "Open"; "lng_open_link" = "Open";
"lng_allow_bot_pass" = "Allow {bot_name} to pass your Telegram name and ID to the web pages you open via this bot?"; "lng_allow_bot_pass" = "Allow {bot_name} to pass your Telegram name and ID to the web pages you open via this bot?";
"lng_allow_bot" = "Allow"; "lng_allow_bot" = "Allow";
"lng_allow_bot_webview" = "{bot_name} would like to open its web app to proceed.\n\nIt will be able to access your **IP address** and basic device info.";
"lng_url_auth_open_confirm" = "Do you want to open {link}?"; "lng_url_auth_open_confirm" = "Do you want to open {link}?";
"lng_url_auth_login_option" = "Log in to {domain} as {user}"; "lng_url_auth_login_option" = "Log in to {domain} as {user}";
"lng_url_auth_allow_messages" = "Allow {bot} to send me messages"; "lng_url_auth_allow_messages" = "Allow {bot} to send me messages";

View file

@ -224,18 +224,24 @@ void activateBotCommand(
case ButtonType::WebView: { case ButtonType::WebView: {
if (const auto bot = msg->getMessageBot()) { if (const auto bot = msg->getMessageBot()) {
bot->session().attachWebView().request( if (sessionController) {
bot, bot->session().attachWebView().request(
bot, sessionController,
{ .text = button->text, .url = button->data }); bot,
bot,
{ .text = button->text, .url = button->data });
}
} }
} break; } break;
case ButtonType::SimpleWebView: { case ButtonType::SimpleWebView: {
if (const auto bot = msg->getMessageBot()) { if (const auto bot = msg->getMessageBot()) {
bot->session().attachWebView().requestSimple( if (sessionController) {
bot, bot->session().attachWebView().requestSimple(
{ .text = button->text, .url = button->data }); sessionController,
bot,
{ .text = button->text, .url = button->data });
}
} }
} break; } break;
} }

View file

@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/dropdown_menu.h" #include "ui/widgets/dropdown_menu.h"
#include "ui/widgets/popup_menu.h" #include "ui/widgets/popup_menu.h"
#include "ui/widgets/menu/menu_item_base.h" #include "ui/widgets/menu/menu_item_base.h"
#include "ui/text/text_utilities.h"
#include "ui/effects/ripple_animation.h" #include "ui/effects/ripple_animation.h"
#include "window/themes/window_theme.h" #include "window/themes/window_theme.h"
#include "window/window_controller.h" #include "window/window_controller.h"
@ -31,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/basic_click_handlers.h" #include "ui/basic_click_handlers.h"
#include "history/history.h" #include "history/history.h"
#include "history/history_item.h" #include "history/history_item.h"
#include "storage/storage_account.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "base/random.h" #include "base/random.h"
#include "base/timer_rpl.h" #include "base/timer_rpl.h"
@ -325,6 +327,7 @@ void AttachWebView::request(
} }
void AttachWebView::request( void AttachWebView::request(
Window::SessionController *controller,
not_null<PeerData*> peer, not_null<PeerData*> peer,
not_null<UserData*> bot, not_null<UserData*> bot,
const WebViewButton &button) { const WebViewButton &button) {
@ -339,7 +342,13 @@ void AttachWebView::request(
_bot = bot; _bot = bot;
_peer = peer; _peer = peer;
request(button); if (controller) {
confirmOpen(controller, [=] {
request(button);
});
} else {
request(button);
}
} }
void AttachWebView::request(const WebViewButton &button) { void AttachWebView::request(const WebViewButton &button) {
@ -444,7 +453,11 @@ void AttachWebView::requestAddToMenu(
if (!contextPeer) { if (!contextPeer) {
return false; return false;
} }
request(contextPeer, bot, { .startCommand = startCommand }); request(
nullptr,
contextPeer,
bot,
{ .startCommand = startCommand });
return true; return true;
}; };
result.match([&](const MTPDattachMenuBotsBot &data) { result.match([&](const MTPDattachMenuBotsBot &data) {
@ -529,15 +542,22 @@ void AttachWebView::resolveUsername(
} }
void AttachWebView::requestSimple( void AttachWebView::requestSimple(
not_null<Window::SessionController*> controller,
not_null<UserData*> bot, not_null<UserData*> bot,
const WebViewButton &button) { const WebViewButton &button) {
cancel(); cancel();
_bot = bot; _bot = bot;
_peer = bot; _peer = bot;
confirmOpen(controller, [=] {
requestSimple(button);
});
}
void AttachWebView::requestSimple(const WebViewButton &button) {
using Flag = MTPmessages_RequestSimpleWebView::Flag; using Flag = MTPmessages_RequestSimpleWebView::Flag;
_requestId = _session->api().request(MTPmessages_RequestSimpleWebView( _requestId = _session->api().request(MTPmessages_RequestSimpleWebView(
MTP_flags(Flag::f_theme_params), MTP_flags(Flag::f_theme_params),
bot->inputUser, _bot->inputUser,
MTP_bytes(button.url), MTP_bytes(button.url),
MTP_dataJSON(MTP_bytes(Window::Theme::WebViewParams())) MTP_dataJSON(MTP_bytes(Window::Theme::WebViewParams()))
)).done([=](const MTPSimpleWebViewResult &result) { )).done([=](const MTPSimpleWebViewResult &result) {
@ -552,6 +572,32 @@ void AttachWebView::requestSimple(
}).send(); }).send();
} }
void AttachWebView::confirmOpen(
not_null<Window::SessionController*> controller,
Fn<void()> done) {
if (!_bot) {
return;
} else if (_bot->isVerified()
|| _bot->session().local().isBotTrustedOpenWebView(_bot->id)) {
done();
return;
}
const auto callback = [=] {
_bot->session().local().markBotTrustedOpenWebView(_bot->id);
controller->hideLayer();
done();
};
controller->show(Ui::MakeConfirmBox({
.text = tr::lng_allow_bot_webview(
tr::now,
lt_bot_name,
Ui::Text::Bold(_bot->name),
Ui::Text::RichLangValue),
.confirmed = callback,
.confirmText = tr::lng_box_ok(),
}));
}
void AttachWebView::ClearAll() { void AttachWebView::ClearAll() {
while (!ActiveWebViews().empty()) { while (!ActiveWebViews().empty()) {
ActiveWebViews().front()->cancel(); ActiveWebViews().front()->cancel();
@ -706,7 +752,7 @@ std::unique_ptr<Ui::DropdownMenu> MakeAttachBotsMenu(
const auto callback = [=] { const auto callback = [=] {
const auto active = controller->activeChatCurrent(); const auto active = controller->activeChatCurrent();
if (const auto history = active.history()) { if (const auto history = active.history()) {
bots->request(history->peer, bot.user, {}); bots->request(nullptr, history->peer, bot.user, {});
} }
}; };
auto action = base::make_unique_q<BotAction>( auto action = base::make_unique_q<BotAction>(

View file

@ -56,10 +56,12 @@ public:
const QString &botUsername, const QString &botUsername,
const QString &startCommand); const QString &startCommand);
void request( void request(
Window::SessionController *controller,
not_null<PeerData*> peer, not_null<PeerData*> peer,
not_null<UserData*> bot, not_null<UserData*> bot,
const WebViewButton &button); const WebViewButton &button);
void requestSimple( void requestSimple(
not_null<Window::SessionController*> controller,
not_null<UserData*> bot, not_null<UserData*> bot,
const WebViewButton &button); const WebViewButton &button);
@ -84,10 +86,15 @@ public:
private: private:
void resolve(); void resolve();
void request(const WebViewButton &button); void request(const WebViewButton &button);
void requestSimple(const WebViewButton &button);
void resolveUsername( void resolveUsername(
const QString &username, const QString &username,
Fn<void(not_null<PeerData*>)> done); Fn<void(not_null<PeerData*>)> done);
void confirmOpen(
not_null<Window::SessionController*> controller,
Fn<void()> done);
void toggleInMenu( void toggleInMenu(
not_null<UserData*> bot, not_null<UserData*> bot,
bool enabled, bool enabled,

View file

@ -2797,6 +2797,31 @@ bool Account::isBotTrustedPayment(PeerId botId) {
&& ((i->second & BotTrustFlag::Payment) != 0); && ((i->second & BotTrustFlag::Payment) != 0);
} }
void Account::markBotTrustedOpenWebView(PeerId botId) {
if (isBotTrustedOpenWebView(botId)) {
return;
}
const auto i = _trustedBots.find(botId);
if (i == end(_trustedBots)) {
_trustedBots.emplace(
botId,
BotTrustFlag::NoOpenGame | BotTrustFlag::OpenWebView);
} else {
i->second |= BotTrustFlag::OpenWebView;
}
writeTrustedBots();
}
bool Account::isBotTrustedOpenWebView(PeerId botId) {
if (!_trustedBotsRead) {
readTrustedBots();
_trustedBotsRead = true;
}
const auto i = _trustedBots.find(botId);
return (i != end(_trustedBots))
&& ((i->second & BotTrustFlag::OpenWebView) != 0);
}
bool Account::encrypt( bool Account::encrypt(
const void *src, const void *src,
void *dst, void *dst,

View file

@ -157,6 +157,8 @@ public:
[[nodiscard]] bool isBotTrustedOpenGame(PeerId botId); [[nodiscard]] bool isBotTrustedOpenGame(PeerId botId);
void markBotTrustedPayment(PeerId botId); void markBotTrustedPayment(PeerId botId);
[[nodiscard]] bool isBotTrustedPayment(PeerId botId); [[nodiscard]] bool isBotTrustedPayment(PeerId botId);
void markBotTrustedOpenWebView(PeerId botId);
[[nodiscard]] bool isBotTrustedOpenWebView(PeerId botId);
[[nodiscard]] bool encrypt( [[nodiscard]] bool encrypt(
const void *src, const void *src,
@ -178,8 +180,9 @@ private:
Failed, Failed,
}; };
enum class BotTrustFlag : uchar { enum class BotTrustFlag : uchar {
NoOpenGame = (1 << 0), NoOpenGame = (1 << 0),
Payment = (1 << 1), Payment = (1 << 1),
OpenWebView = (1 << 2),
}; };
friend inline constexpr bool is_flag_type(BotTrustFlag) { return true; }; friend inline constexpr bool is_flag_type(BotTrustFlag) { return true; };