Fix possible crash in global search requests.

This commit is contained in:
John Preston 2020-07-02 11:13:50 +04:00
parent 17312a1eec
commit 120ce27894
2 changed files with 39 additions and 32 deletions

View file

@ -160,7 +160,8 @@ void Widget::BottomButton::paintEvent(QPaintEvent *e) {
Widget::Widget( Widget::Widget(
QWidget *parent, QWidget *parent,
not_null<Window::SessionController*> controller) not_null<Window::SessionController*> controller)
: Window::AbstractSectionWidget(parent, controller) : Window::AbstractSectionWidget(parent, controller)
, _api(&controller->session().mtp())
, _searchControls(this) , _searchControls(this)
, _mainMenuToggle(_searchControls, st::dialogsMenuToggle) , _mainMenuToggle(_searchControls, st::dialogsMenuToggle)
, _searchForNarrowFilters(_searchControls, st::dialogsSearchForNarrowFilters) , _searchForNarrowFilters(_searchControls, st::dialogsSearchForNarrowFilters)
@ -434,7 +435,9 @@ void Widget::fullSearchRefreshOn(rpl::producer<> events) {
_searchTimer.stop(); _searchTimer.stop();
_searchCache.clear(); _searchCache.clear();
_singleMessageSearch.clear(); _singleMessageSearch.clear();
_searchQueries.clear(); for (const auto &[requestId, query] : base::take(_searchQueries)) {
session().api().request(requestId).cancel();
}
_searchQuery = QString(); _searchQuery = QString();
_scroll->scrollToY(0); _scroll->scrollToY(0);
cancelSearchRequest(); cancelSearchRequest();
@ -769,7 +772,7 @@ bool Widget::onSearchMessages(bool searchCache) {
auto q = _filter->getLastText().trimmed(); auto q = _filter->getLastText().trimmed();
if (q.isEmpty() && !_searchFromUser) { if (q.isEmpty() && !_searchFromUser) {
cancelSearchRequest(); cancelSearchRequest();
session().api().request(base::take(_peerSearchRequest)).cancel(); _api.request(base::take(_peerSearchRequest)).cancel();
return true; return true;
} }
if (searchCache) { if (searchCache) {
@ -779,8 +782,8 @@ bool Widget::onSearchMessages(bool searchCache) {
if (!success) { if (!success) {
return false; return false;
} }
const auto i = _searchCache.constFind(q); const auto i = _searchCache.find(q);
if (i != _searchCache.cend()) { if (i != _searchCache.end()) {
_searchQuery = q; _searchQuery = q;
_searchQueryFrom = _searchFromUser; _searchQueryFrom = _searchFromUser;
_searchNextRate = 0; _searchNextRate = 0;
@ -790,7 +793,7 @@ bool Widget::onSearchMessages(bool searchCache) {
_searchInChat _searchInChat
? SearchRequestType::PeerFromStart ? SearchRequestType::PeerFromStart
: SearchRequestType::FromStart, : SearchRequestType::FromStart,
i.value(), i->second,
0); 0);
result = true; result = true;
} }
@ -834,7 +837,7 @@ bool Widget::onSearchMessages(bool searchCache) {
_searchInHistoryRequest = 0; _searchInHistoryRequest = 0;
finish(); finish();
}).send(); }).send();
_searchQueries.insert(_searchRequest, _searchQuery); _searchQueries.emplace(_searchRequest, _searchQuery);
return _searchRequest; return _searchRequest;
}); });
//} else if (const auto feed = _searchInChat.feed()) { // #feed //} else if (const auto feed = _searchInChat.feed()) { // #feed
@ -851,7 +854,7 @@ bool Widget::onSearchMessages(bool searchCache) {
// }).fail([=](const RPCError &error) { // }).fail([=](const RPCError &error) {
// searchFailed(type, error, _searchRequest); // searchFailed(type, error, _searchRequest);
// }).send(); // }).send();
// _searchQueries.insert(_searchRequest, _searchQuery); // _searchQueries.emplace(_searchRequest, _searchQuery);
} else { } else {
const auto type = SearchRequestType::FromStart; const auto type = SearchRequestType::FromStart;
const auto flags = session().settings().skipArchiveInSearch() const auto flags = session().settings().skipArchiveInSearch()
@ -871,23 +874,23 @@ bool Widget::onSearchMessages(bool searchCache) {
}).fail([=](const RPCError &error) { }).fail([=](const RPCError &error) {
searchFailed(type, error, _searchRequest); searchFailed(type, error, _searchRequest);
}).send(); }).send();
_searchQueries.insert(_searchRequest, _searchQuery); _searchQueries.emplace(_searchRequest, _searchQuery);
} }
} }
const auto query = Api::ConvertPeerSearchQuery(q); const auto query = Api::ConvertPeerSearchQuery(q);
if (searchForPeersRequired(query)) { if (searchForPeersRequired(query)) {
if (searchCache) { if (searchCache) {
auto i = _peerSearchCache.constFind(query); auto i = _peerSearchCache.find(query);
if (i != _peerSearchCache.cend()) { if (i != _peerSearchCache.end()) {
_peerSearchQuery = query; _peerSearchQuery = query;
_peerSearchRequest = 0; _peerSearchRequest = 0;
peerSearchReceived(i.value(), 0); peerSearchReceived(i->second, 0);
result = true; result = true;
} }
} else if (_peerSearchQuery != query) { } else if (_peerSearchQuery != query) {
_peerSearchQuery = query; _peerSearchQuery = query;
_peerSearchFull = false; _peerSearchFull = false;
_peerSearchRequest = session().api().request(MTPcontacts_Search( _peerSearchRequest = _api.request(MTPcontacts_Search(
MTP_string(_peerSearchQuery), MTP_string(_peerSearchQuery),
MTP_int(SearchPeopleLimit) MTP_int(SearchPeopleLimit)
)).done([=](const MTPcontacts_Found &result, mtpRequestId requestId) { )).done([=](const MTPcontacts_Found &result, mtpRequestId requestId) {
@ -895,7 +898,7 @@ bool Widget::onSearchMessages(bool searchCache) {
}).fail([=](const RPCError &error, mtpRequestId requestId) { }).fail([=](const RPCError &error, mtpRequestId requestId) {
peopleFailed(error, requestId); peopleFailed(error, requestId);
}).send(); }).send();
_peerSearchQueries.insert(_peerSearchRequest, _peerSearchQuery); _peerSearchQueries.emplace(_peerSearchRequest, _peerSearchQuery);
} }
} else { } else {
_peerSearchQuery = query; _peerSearchQuery = query;
@ -1004,7 +1007,7 @@ void Widget::onSearchMore() {
finish(); finish();
}).send(); }).send();
if (!offsetId) { if (!offsetId) {
_searchQueries.insert(_searchRequest, _searchQuery); _searchQueries.emplace(_searchRequest, _searchQuery);
} }
return _searchRequest; return _searchRequest;
}); });
@ -1027,7 +1030,7 @@ void Widget::onSearchMore() {
// searchFailed(type, error, _searchRequest); // searchFailed(type, error, _searchRequest);
// }).send(); // }).send();
// if (!offsetId) { // if (!offsetId) {
// _searchQueries.insert(_searchRequest, _searchQuery); // _searchQueries.emplace(_searchRequest, _searchQuery);
// } // }
} else { } else {
const auto type = offsetId const auto type = offsetId
@ -1053,7 +1056,7 @@ void Widget::onSearchMore() {
searchFailed(type, error, _searchRequest); searchFailed(type, error, _searchRequest);
}).send(); }).send();
if (!offsetId) { if (!offsetId) {
_searchQueries.insert(_searchRequest, _searchQuery); _searchQueries.emplace(_searchRequest, _searchQuery);
} }
} }
} else if (_searchInMigrated && !_searchFullMigrated) { } else if (_searchInMigrated && !_searchFullMigrated) {
@ -1106,8 +1109,8 @@ void Widget::searchReceived(
if (state == WidgetState::Filtered) { if (state == WidgetState::Filtered) {
if (type == SearchRequestType::FromStart || type == SearchRequestType::PeerFromStart) { if (type == SearchRequestType::FromStart || type == SearchRequestType::PeerFromStart) {
auto i = _searchQueries.find(requestId); auto i = _searchQueries.find(requestId);
if (i != _searchQueries.cend()) { if (i != _searchQueries.end()) {
_searchCache[i.value()] = result; _searchCache[i->second] = result;
_searchQueries.erase(i); _searchQueries.erase(i);
} }
} }
@ -1215,9 +1218,8 @@ void Widget::peerSearchReceived(
auto q = _peerSearchQuery; auto q = _peerSearchQuery;
if (state == WidgetState::Filtered) { if (state == WidgetState::Filtered) {
auto i = _peerSearchQueries.find(requestId); auto i = _peerSearchQueries.find(requestId);
if (i != _peerSearchQueries.cend()) { if (i != _peerSearchQueries.end()) {
q = i.value(); _peerSearchCache[i->second] = result;
_peerSearchCache[q] = result;
_peerSearchQueries.erase(i); _peerSearchQueries.erase(i);
} }
} }
@ -1359,7 +1361,9 @@ void Widget::applyFilterUpdate(bool force) {
if (filterText.isEmpty()) { if (filterText.isEmpty()) {
_peerSearchCache.clear(); _peerSearchCache.clear();
_peerSearchQueries.clear(); for (const auto &[requestId, query] : base::take(_peerSearchQueries)) {
_api.request(requestId).cancel();
}
_peerSearchQuery = QString(); _peerSearchQuery = QString();
} }
@ -1416,7 +1420,9 @@ void Widget::setSearchInChat(Key chat, UserData *from) {
void Widget::clearSearchCache() { void Widget::clearSearchCache() {
_searchCache.clear(); _searchCache.clear();
_singleMessageSearch.clear(); _singleMessageSearch.clear();
_searchQueries.clear(); for (const auto &[requestId, query] : base::take(_searchQueries)) {
session().api().request(requestId).cancel();
}
_searchQuery = QString(); _searchQuery = QString();
_searchQueryFrom = nullptr; _searchQueryFrom = nullptr;
cancelSearchRequest(); cancelSearchRequest();
@ -1720,10 +1726,8 @@ void Widget::scrollToEntry(const RowDescriptor &entry) {
void Widget::cancelSearchRequest() { void Widget::cancelSearchRequest() {
session().api().request(base::take(_searchRequest)).cancel(); session().api().request(base::take(_searchRequest)).cancel();
if (_searchInHistoryRequest) { session().data().histories().cancelRequest(
session().data().histories().cancelRequest(_searchInHistoryRequest); base::take(_searchInHistoryRequest));
_searchInHistoryRequest = 0;
}
} }
bool Widget::onCancelSearch() { bool Widget::onCancelSearch() {

View file

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/effects/animations.h" #include "ui/effects/animations.h"
#include "ui/widgets/scroll_area.h" #include "ui/widgets/scroll_area.h"
#include "ui/special_buttons.h" #include "ui/special_buttons.h"
#include "mtproto/sender.h"
#include "api/api_single_message_search.h" #include "api/api_single_message_search.h"
class RPCError; class RPCError;
@ -174,6 +175,8 @@ private:
void startScrollUpButtonAnimation(bool shown); void startScrollUpButtonAnimation(bool shown);
void updateScrollUpPosition(); void updateScrollUpPosition();
MTP::Sender _api;
bool _dragInScroll = false; bool _dragInScroll = false;
bool _dragForward = false; bool _dragForward = false;
QTimer _chooseByDragTimer; QTimer _chooseByDragTimer;
@ -225,11 +228,11 @@ private:
int _searchInHistoryRequest = 0; // Not real mtpRequestId. int _searchInHistoryRequest = 0; // Not real mtpRequestId.
mtpRequestId _searchRequest = 0; mtpRequestId _searchRequest = 0;
QMap<QString, MTPmessages_Messages> _searchCache; base::flat_map<QString, MTPmessages_Messages> _searchCache;
Api::SingleMessageSearch _singleMessageSearch; Api::SingleMessageSearch _singleMessageSearch;
QMap<mtpRequestId, QString> _searchQueries; base::flat_map<mtpRequestId, QString> _searchQueries;
QMap<QString, MTPcontacts_Found> _peerSearchCache; base::flat_map<QString, MTPcontacts_Found> _peerSearchCache;
QMap<mtpRequestId, QString> _peerSearchQueries; base::flat_map<mtpRequestId, QString> _peerSearchQueries;
QPixmap _widthAnimationCache; QPixmap _widthAnimationCache;