2
0
mirror of https://github.com/telegramdesktop/tdesktop synced 2025-09-05 08:55:59 +00:00

WebDocument wrap to HistoryPhoto supported.

Only WebDocument with a valid 'size' field value and with a valid
'documentAttributeImageSize' attribute works wrapped as a photo.
This commit is contained in:
John Preston
2017-03-05 20:33:32 +03:00
parent 7b5985445c
commit 31e3c6a2c6
6 changed files with 255 additions and 72 deletions

View File

@@ -45,6 +45,9 @@ struct DataRequested {
};
QMap<int32, DataRequested> DataRequestedMap;
constexpr auto kDownloadPhotoPartSize = 64 * 1024; // 64kb for photo
constexpr auto kDownloadDocumentPartSize = 128 * 1024; // 128kb for document
} // namespace
struct FileLoaderQueue {
@@ -361,11 +364,11 @@ mtpFileLoader::mtpFileLoader(const StorageImageLocation *location, int32 size, L
_queue = &i.value();
}
mtpFileLoader::mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, int32 version, LocationType type, const QString &to, int32 size, LoadToCacheSetting toCache, LoadFromCloudSetting fromCloud, bool autoLoading)
mtpFileLoader::mtpFileLoader(int32 dc, uint64 id, uint64 accessHash, int32 version, LocationType type, const QString &to, int32 size, LoadToCacheSetting toCache, LoadFromCloudSetting fromCloud, bool autoLoading)
: FileLoader(to, size, type, toCache, fromCloud, autoLoading)
, _dc(dc)
, _id(id)
, _access(access)
, _accessHash(accessHash)
, _version(version) {
auto shiftedDcId = MTP::downloadDcId(_dc, 0);
auto i = queues.find(shiftedDcId);
@@ -375,6 +378,18 @@ mtpFileLoader::mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, i
_queue = &i.value();
}
mtpFileLoader::mtpFileLoader(const WebFileImageLocation *location, int32 size, LoadFromCloudSetting fromCloud, bool autoLoading)
: FileLoader(QString(), size, UnknownFileLocation, LoadToCacheAsWell, fromCloud, autoLoading)
, _dc(location->dc())
, _urlLocation(location) {
auto shiftedDcId = MTP::downloadDcId(_dc, 0);
auto i = queues.find(shiftedDcId);
if (i == queues.cend()) {
i = queues.insert(shiftedDcId, FileLoaderQueue(MaxFileQueries));
}
_queue = &i.value();
}
int32 mtpFileLoader::currentOffset(bool includeSkipped) const {
return (_fileIsOpen ? _file.size() : _data.size()) - (includeSkipped ? 0 : _skippedBytes);
}
@@ -398,36 +413,24 @@ namespace {
}
bool mtpFileLoader::loadPart() {
if (_finished || _lastComplete || (!_requests.isEmpty() && !_size)) {
if (_finished || _lastComplete || (!_dcIndexByRequest.isEmpty() && !_size)) {
if (DebugLogging::FileLoader() && _id) {
DEBUG_LOG(("FileLoader(%1): loadPart() returned, _finished=%2, _lastComplete=%3, _requests.size()=%4, _size=%5").arg(_id).arg(Logs::b(_finished)).arg(Logs::b(_lastComplete)).arg(_requests.size()).arg(_size));
DEBUG_LOG(("FileLoader(%1): loadPart() returned, _finished=%2, _lastComplete=%3, _requests.size()=%4, _size=%5").arg(_id).arg(Logs::b(_finished)).arg(Logs::b(_lastComplete)).arg(_dcIndexByRequest.size()).arg(_size));
}
return false;
}
if (_size && _nextRequestOffset >= _size) {
if (DebugLogging::FileLoader() && _id) {
DEBUG_LOG(("FileLoader(%1): loadPart() returned, _size=%2, _nextRequestOffset=%3, _requests=%4").arg(_id).arg(_size).arg(_nextRequestOffset).arg(serializereqs(_requests)));
DEBUG_LOG(("FileLoader(%1): loadPart() returned, _size=%2, _nextRequestOffset=%3, _requests=%4").arg(_id).arg(_size).arg(_nextRequestOffset).arg(serializereqs(_dcIndexByRequest)));
}
return false;
}
int32 limit = DocumentDownloadPartSize;
MTPInputFileLocation loc;
if (_location) {
loc = MTP_inputFileLocation(MTP_long(_location->volume()), MTP_int(_location->local()), MTP_long(_location->secret()));
limit = DownloadPartSize;
} else {
switch (_locationType) {
case VideoFileLocation:
case AudioFileLocation:
case DocumentFileLocation: loc = MTP_inputDocumentFileLocation(MTP_long(_id), MTP_long(_access), MTP_int(_version)); break;
default: cancel(true); return false; break;
}
}
int32 offset = _nextRequestOffset, dcIndex = 0;
DataRequested &dr(DataRequestedMap[_dc]);
auto offset = _nextRequestOffset;
auto dcIndex = 0;
auto &dr = DataRequestedMap[_dc];
if (_size) {
for (int32 i = 1; i < MTPDownloadSessionsCount; ++i) {
for (auto i = 1; i != MTPDownloadSessionsCount; ++i) {
if (dr.v[i] < dr.v[dcIndex]) {
dcIndex = i;
}
@@ -436,47 +439,86 @@ bool mtpFileLoader::loadPart() {
App::app()->killDownloadSessionsStop(_dc);
mtpRequestId reqId = MTP::send(MTPupload_GetFile(loc, MTP_int(offset), MTP_int(limit)), rpcDone(&mtpFileLoader::partLoaded, offset), rpcFail(&mtpFileLoader::partFailed), MTP::downloadDcId(_dc, dcIndex), 50);
++_queue->queries;
dr.v[dcIndex] += limit;
_requests.insert(reqId, dcIndex);
_nextRequestOffset += limit;
auto requestId = makeRequest(offset, dcIndex);
_dcIndexByRequest.insert(requestId, dcIndex);
if (DebugLogging::FileLoader() && _id) {
DEBUG_LOG(("FileLoader(%1): requested part with offset=%2, _queue->queries=%3, _nextRequestOffset=%4, _requests=%5").arg(_id).arg(offset).arg(_queue->queries).arg(_nextRequestOffset).arg(serializereqs(_requests)));
DEBUG_LOG(("FileLoader(%1): requested part with offset=%2, _queue->queries=%3, _nextRequestOffset=%4, _requests=%5").arg(_id).arg(offset).arg(_queue->queries).arg(_nextRequestOffset).arg(serializereqs(_dcIndexByRequest)));
}
return true;
}
void mtpFileLoader::partLoaded(int32 offset, const MTPupload_File &result, mtpRequestId req) {
Requests::iterator i = _requests.find(req);
if (i == _requests.cend()) {
if (DebugLogging::FileLoader() && _id) {
DEBUG_LOG(("FileLoader(%1): request req=%2 for offset=%3 not found in _requests=%4").arg(_id).arg(req).arg(offset).arg(serializereqs(_requests)));
}
return loadNext();
int mtpFileLoader::partSize() const {
if (_locationType == UnknownFileLocation) {
return kDownloadPhotoPartSize;
}
return kDownloadDocumentPartSize;
}
mtpRequestId mtpFileLoader::makeRequest(int offset, int dcIndex) {
auto limit = partSize();
DataRequestedMap[_dc].v[dcIndex] += limit;
++_queue->queries;
_nextRequestOffset += limit;
if (_urlLocation) {
return MTP::send(MTPupload_GetWebFile(MTP_inputWebFileLocation(MTP_bytes(_urlLocation->url()), MTP_long(_urlLocation->accessHash())), MTP_int(offset), MTP_int(limit)), rpcDone(&mtpFileLoader::webPartLoaded, offset), rpcFail(&mtpFileLoader::partFailed), MTP::downloadDcId(_dc, dcIndex), 50);
}
MTPInputFileLocation loc;
if (_location) {
loc = MTP_inputFileLocation(MTP_long(_location->volume()), MTP_int(_location->local()), MTP_long(_location->secret()));
} else {
loc = MTP_inputDocumentFileLocation(MTP_long(_id), MTP_long(_accessHash), MTP_int(_version));
}
return MTP::send(MTPupload_GetFile(loc, MTP_int(offset), MTP_int(limit)), rpcDone(&mtpFileLoader::normalPartLoaded, offset), rpcFail(&mtpFileLoader::partFailed), MTP::downloadDcId(_dc, dcIndex), 50);
}
void mtpFileLoader::normalPartLoaded(int offset, const MTPupload_File &result, mtpRequestId req) {
if (result.type() != mtpc_upload_file) {
if (DebugLogging::FileLoader() && _id) {
DEBUG_LOG(("FileLoader(%1): bad cons received! %2").arg(_id).arg(result.type()));
}
return cancel(true);
}
auto bytes = gsl::as_bytes(gsl::make_span(result.c_upload_file().vbytes.v));
return partLoaded(offset, bytes, req);
}
int32 limit = (_locationType == UnknownFileLocation) ? DownloadPartSize : DocumentDownloadPartSize;
int32 dcIndex = i.value();
void mtpFileLoader::webPartLoaded(int offset, const MTPupload_WebFile &result, mtpRequestId req) {
if (result.type() != mtpc_upload_webFile) {
if (DebugLogging::FileLoader() && _id) {
DEBUG_LOG(("FileLoader(%1): bad cons received! %2").arg(_id).arg(result.type()));
}
return cancel(true);
}
auto &webFile = result.c_upload_webFile();
if (webFile.vsize.v != _size) {
LOG(("MTP Error: Bad size provided by bot for webDocument: %1, real: %2").arg(_size).arg(webFile.vsize.v));
return cancel(true);
}
auto bytes = gsl::as_bytes(gsl::make_span(webFile.vbytes.v));
return partLoaded(offset, bytes, req);
}
void mtpFileLoader::partLoaded(int offset, base::const_byte_span bytes, mtpRequestId req) {
auto i = _dcIndexByRequest.find(req);
if (i == _dcIndexByRequest.cend()) {
if (DebugLogging::FileLoader() && _id) {
DEBUG_LOG(("FileLoader(%1): request req=%2 for offset=%3 not found in _requests=%4").arg(_id).arg(req).arg(offset).arg(serializereqs(_dcIndexByRequest)));
}
return loadNext();
}
auto limit = partSize();
auto dcIndex = i.value();
DataRequestedMap[_dc].v[dcIndex] -= limit;
--_queue->queries;
_requests.erase(i);
auto &d = result.c_upload_file();
auto &bytes = d.vbytes.v;
_dcIndexByRequest.erase(i);
if (DebugLogging::FileLoader() && _id) {
DEBUG_LOG(("FileLoader(%1): got part with offset=%2, bytes=%3, _queue->queries=%4, _nextRequestOffset=%5, _requests=%6").arg(_id).arg(offset).arg(bytes.size()).arg(_queue->queries).arg(_nextRequestOffset).arg(serializereqs(_requests)));
DEBUG_LOG(("FileLoader(%1): got part with offset=%2, bytes=%3, _queue->queries=%4, _nextRequestOffset=%5, _requests=%6").arg(_id).arg(offset).arg(bytes.size()).arg(_queue->queries).arg(_nextRequestOffset).arg(serializereqs(_dcIndexByRequest)));
}
if (bytes.size()) {
@@ -488,7 +530,7 @@ void mtpFileLoader::partLoaded(int32 offset, const MTPupload_File &result, mtpRe
_skippedBytes += offset - fsize;
}
_file.seek(offset);
if (_file.write(bytes.data(), bytes.size()) != qint64(bytes.size())) {
if (_file.write(reinterpret_cast<const char*>(bytes.data()), bytes.size()) != qint64(bytes.size())) {
return cancel(true);
}
} else {
@@ -498,20 +540,22 @@ void mtpFileLoader::partLoaded(int32 offset, const MTPupload_File &result, mtpRe
_data.resize(offset);
}
if (offset == _data.size()) {
_data.append(bytes.data(), bytes.size());
_data.append(reinterpret_cast<const char*>(bytes.data()), bytes.size());
} else {
_skippedBytes -= bytes.size();
if (int64(offset + bytes.size()) > _data.size()) {
_data.resize(offset + bytes.size());
}
memcpy(_data.data() + offset, bytes.data(), bytes.size());
auto src = bytes;
auto dst = gsl::make_span(_data).subspan(offset, bytes.size());
base::copy_bytes(gsl::as_writeable_bytes(dst), src);
}
}
}
if (!bytes.size() || (bytes.size() % 1024)) { // bad next offset
_lastComplete = true;
}
if (_requests.isEmpty() && (_lastComplete || (_size && _nextRequestOffset >= _size))) {
if (_dcIndexByRequest.isEmpty() && (_lastComplete || (_size && _nextRequestOffset >= _size))) {
if (!_fname.isEmpty() && (_toCache == LoadToCacheAsWell)) {
if (!_fileIsOpen) _fileIsOpen = _file.open(QIODevice::WriteOnly);
if (!_fileIsOpen) {
@@ -534,7 +578,9 @@ void mtpFileLoader::partLoaded(int32 offset, const MTPupload_File &result, mtpRe
}
if (_localStatus == LocalNotFound || _localStatus == LocalFailed) {
if (_locationType != UnknownFileLocation) { // audio, video, document
if (_urlLocation) {
Local::writeImage(storageKey(*_urlLocation), StorageImageSaved(_data));
} else if (_locationType != UnknownFileLocation) { // audio, video, document
MediaKey mkey = mediaKey(_locationType, _dc, _id, _version);
if (!_fname.isEmpty()) {
Local::writeFileLocation(mkey, FileLocation(_fname));
@@ -552,7 +598,7 @@ void mtpFileLoader::partLoaded(int32 offset, const MTPupload_File &result, mtpRe
}
} else {
if (DebugLogging::FileLoader() && _id) {
DEBUG_LOG(("FileLoader(%1): not done yet, _lastComplete=%2, _size=%3, _nextRequestOffset=%4, _requests=%5").arg(_id).arg(Logs::b(_lastComplete)).arg(_size).arg(_nextRequestOffset).arg(serializereqs(_requests)));
DEBUG_LOG(("FileLoader(%1): not done yet, _lastComplete=%2, _size=%3, _nextRequestOffset=%4, _requests=%5").arg(_id).arg(Logs::b(_lastComplete)).arg(_size).arg(_nextRequestOffset).arg(serializereqs(_dcIndexByRequest)));
}
}
if (_finished) {
@@ -572,17 +618,17 @@ bool mtpFileLoader::partFailed(const RPCError &error) {
}
void mtpFileLoader::cancelRequests() {
if (_requests.isEmpty()) return;
if (_dcIndexByRequest.isEmpty()) return;
int32 limit = (_locationType == UnknownFileLocation) ? DownloadPartSize : DocumentDownloadPartSize;
auto limit = partSize();
DataRequested &dr(DataRequestedMap[_dc]);
for (Requests::const_iterator i = _requests.cbegin(), e = _requests.cend(); i != e; ++i) {
for (auto i = _dcIndexByRequest.cbegin(), e = _dcIndexByRequest.cend(); i != e; ++i) {
MTP::cancel(i.key());
int32 dcIndex = i.value();
dr.v[dcIndex] -= limit;
}
_queue->queries -= _requests.size();
_requests.clear();
_queue->queries -= _dcIndexByRequest.size();
_dcIndexByRequest.clear();
if (!_queue->queries) {
Messenger::Instance().killDownloadSessionsStart(_dc);
@@ -597,7 +643,9 @@ bool mtpFileLoader::tryLoadLocal() {
return true;
}
if (_location) {
if (_urlLocation) {
_localTaskId = Local::startImageLoad(storageKey(*_urlLocation), this);
} else if (_location) {
_localTaskId = Local::startImageLoad(storageKey(*_location), this);
} else {
if (_toCache == LoadToCacheAsWell) {