From 6adcf660f1673ce32f3c0c0c0b7d7586fd86ad02 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Mon, 4 May 2020 17:38:49 +0400
Subject: [PATCH] Guard click handlers that capture session data.

Click handlers invocation is done by posting on_main,
so in rare cases the session may be already destroyed.
---
 Telegram/SourceFiles/data/data_document.cpp | 31 ++++++++++++----
 Telegram/SourceFiles/data/data_document.h   | 13 ++++---
 Telegram/SourceFiles/data/data_photo.cpp    | 39 ++++++++++++++++-----
 Telegram/SourceFiles/data/data_photo.h      | 18 +++++-----
 Telegram/SourceFiles/data/data_types.h      |  2 +-
 Telegram/lib_base                           |  2 +-
 6 files changed, 75 insertions(+), 30 deletions(-)

diff --git a/Telegram/SourceFiles/data/data_document.cpp b/Telegram/SourceFiles/data/data_document.cpp
index 97d6eb670..6c50e8aab 100644
--- a/Telegram/SourceFiles/data/data_document.cpp
+++ b/Telegram/SourceFiles/data/data_document.cpp
@@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "data/data_document_good_thumbnail.h"
 #include "lang/lang_keys.h"
 #include "inline_bots/inline_bot_layout_item.h"
+#include "main/main_session.h"
 #include "mainwidget.h"
 #include "core/file_utilities.h"
 #include "core/media_active_cache.h"
@@ -296,6 +297,14 @@ QString documentSaveFilename(const DocumentData *data, bool forceSavingAs = fals
 	return FileNameForSave(caption, filter, prefix, name, forceSavingAs, dir);
 }
 
+DocumentClickHandler::DocumentClickHandler(
+	not_null<DocumentData*> document,
+	FullMsgId context)
+: FileClickHandler(context)
+, _session(&document->session())
+, _document(document) {
+}
+
 void DocumentOpenClickHandler::Open(
 		Data::FileOrigin origin,
 		not_null<DocumentData*> data,
@@ -345,7 +354,9 @@ void DocumentOpenClickHandler::Open(
 }
 
 void DocumentOpenClickHandler::onClickImpl() const {
-	Open(context(), document(), getActionItem());
+	if (valid()) {
+		Open(context(), document(), getActionItem());
+	}
 }
 
 void DocumentSaveClickHandler::Save(
@@ -385,14 +396,20 @@ void DocumentSaveClickHandler::Save(
 }
 
 void DocumentSaveClickHandler::onClickImpl() const {
-	Save(context(), document());
+	if (valid()) {
+		Save(context(), document());
+	}
 }
 
 void DocumentCancelClickHandler::onClickImpl() const {
-	const auto data = document();
-	if (!data->date) return;
+	if (!valid()) {
+		return;
+	}
 
-	if (data->uploading()) {
+	const auto data = document();
+	if (!data->date) {
+		return;
+	} else if (data->uploading()) {
 		if (const auto item = data->owner().message(context())) {
 			App::main()->cancelUploadLayer(item);
 		}
@@ -423,7 +440,9 @@ void DocumentOpenWithClickHandler::Open(
 }
 
 void DocumentOpenWithClickHandler::onClickImpl() const {
-	Open(context(), document());
+	if (valid()) {
+		Open(context(), document());
+	}
 }
 
 Data::FileOrigin StickerData::setOrigin() const {
diff --git a/Telegram/SourceFiles/data/data_document.h b/Telegram/SourceFiles/data/data_document.h
index c5991d0bc..3fee6eb38 100644
--- a/Telegram/SourceFiles/data/data_document.h
+++ b/Telegram/SourceFiles/data/data_document.h
@@ -315,16 +315,19 @@ class DocumentClickHandler : public FileClickHandler {
 public:
 	DocumentClickHandler(
 		not_null<DocumentData*> document,
-		FullMsgId context = FullMsgId())
-	: FileClickHandler(context)
-	, _document(document) {
+		FullMsgId context = FullMsgId());
+
+	[[nodiscard]] bool valid() const {
+		return !_session.empty();
 	}
-	not_null<DocumentData*> document() const {
+
+	[[nodiscard]] not_null<DocumentData*> document() const {
 		return _document;
 	}
 
 private:
-	not_null<DocumentData*> _document;
+	const base::weak_ptr<Main::Session> _session;
+	const not_null<DocumentData*> _document;
 
 };
 
diff --git a/Telegram/SourceFiles/data/data_photo.cpp b/Telegram/SourceFiles/data/data_photo.cpp
index 5b5a58881..100d905e4 100644
--- a/Telegram/SourceFiles/data/data_photo.cpp
+++ b/Telegram/SourceFiles/data/data_photo.cpp
@@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "data/data_file_origin.h"
 #include "ui/image/image.h"
 #include "ui/image/image_source.h"
+#include "main/main_session.h"
 #include "mainwidget.h"
 #include "core/application.h"
 #include "facades.h"
@@ -250,22 +251,42 @@ int PhotoData::height() const {
 	return _large->height();
 }
 
+PhotoClickHandler::PhotoClickHandler(
+	not_null<PhotoData*> photo,
+	FullMsgId context,
+	PeerData *peer)
+: FileClickHandler(context)
+, _session(&photo->session())
+, _photo(photo)
+, _peer(peer) {
+}
+
 void PhotoOpenClickHandler::onClickImpl() const {
-	Core::App().showPhoto(this);
+	if (valid()) {
+		Core::App().showPhoto(this);
+	}
 }
 
 void PhotoSaveClickHandler::onClickImpl() const {
-	auto data = photo();
-	if (!data->date) return;
-
-	data->download(context());
+	if (!valid()) {
+		return;
+	}
+	const auto data = photo();
+	if (!data->date) {
+		return;
+	} else {
+		data->download(context());
+	}
 }
 
 void PhotoCancelClickHandler::onClickImpl() const {
-	auto data = photo();
-	if (!data->date) return;
-
-	if (data->uploading()) {
+	if (!valid()) {
+		return;
+	}
+	const auto data = photo();
+	if (!data->date) {
+		return;
+	} else if (data->uploading()) {
 		if (const auto item = data->owner().message(context())) {
 			App::main()->cancelUploadLayer(item);
 		}
diff --git a/Telegram/SourceFiles/data/data_photo.h b/Telegram/SourceFiles/data/data_photo.h
index 9a3315fc6..c9baaafb8 100644
--- a/Telegram/SourceFiles/data/data_photo.h
+++ b/Telegram/SourceFiles/data/data_photo.h
@@ -108,21 +108,23 @@ public:
 	PhotoClickHandler(
 		not_null<PhotoData*> photo,
 		FullMsgId context = FullMsgId(),
-		PeerData *peer = nullptr)
-	: FileClickHandler(context)
-	, _photo(photo)
-	, _peer(peer) {
+		PeerData *peer = nullptr);
+
+	[[nodiscard]] bool valid() const {
+		return !_session.empty();
 	}
-	not_null<PhotoData*> photo() const {
+
+	[[nodiscard]] not_null<PhotoData*> photo() const {
 		return _photo;
 	}
-	PeerData *peer() const {
+	[[nodiscard]] PeerData *peer() const {
 		return _peer;
 	}
 
 private:
-	not_null<PhotoData*> _photo;
-	PeerData *_peer = nullptr;
+	const base::weak_ptr<Main::Session> _session;
+	const not_null<PhotoData*> _photo;
+	PeerData * const _peer = nullptr;
 
 };
 
diff --git a/Telegram/SourceFiles/data/data_types.h b/Telegram/SourceFiles/data/data_types.h
index dd523426d..6a45b7a89 100644
--- a/Telegram/SourceFiles/data/data_types.h
+++ b/Telegram/SourceFiles/data/data_types.h
@@ -483,7 +483,7 @@ public:
 		_context = context;
 	}
 
-	FullMsgId context() const {
+	[[nodiscard]] FullMsgId context() const {
 		return _context;
 	}
 
diff --git a/Telegram/lib_base b/Telegram/lib_base
index d27c3e363..9e01ede66 160000
--- a/Telegram/lib_base
+++ b/Telegram/lib_base
@@ -1 +1 @@
-Subproject commit d27c3e363254b169f8886934df8580fdc76d424e
+Subproject commit 9e01ede6661e2a74697283c7836d4fae433f50ce