From f538aeea50fc77bbae0029f2b8ac99f63c8bec65 Mon Sep 17 00:00:00 2001 From: Beaudan Brown Date: Fri, 18 Oct 2019 11:23:50 +1100 Subject: [PATCH] Remove old link preview system --- background.html | 1 - js/link_previews_helper.js | 168 ------------------------------------- js/models/messages.js | 82 +----------------- 3 files changed, 1 insertion(+), 250 deletions(-) delete mode 100644 js/link_previews_helper.js diff --git a/background.html b/background.html index cf102a562..acad1030c 100644 --- a/background.html +++ b/background.html @@ -667,7 +667,6 @@ - diff --git a/js/link_previews_helper.js b/js/link_previews_helper.js deleted file mode 100644 index 3fb756bad..000000000 --- a/js/link_previews_helper.js +++ /dev/null @@ -1,168 +0,0 @@ -/* global - Signal, - textsecure, - StringView -*/ - -/* eslint-disable no-bitwise */ - -// eslint-disable-next-line func-names -(function() { - 'use strict'; - - window.Signal = window.Signal || {}; - window.Signal.LinkPreviews = window.Signal.LinkPreviews || {}; - - // A cache mapping url to fetched previews - const previewCache = {}; - - async function makeChunkedRequest(url) { - const PARALLELISM = 3; - const size = await textsecure.messaging.getProxiedSize(url); - const chunks = await Signal.LinkPreviews.getChunkPattern(size); - - let results = []; - const jobs = chunks.map(chunk => async () => { - const { start, end } = chunk; - - const result = await textsecure.messaging.makeProxiedRequest(url, { - start, - end, - returnArrayBuffer: true, - }); - - return { - ...chunk, - ...result, - }; - }); - - while (jobs.length > 0) { - const activeJobs = []; - for (let i = 0, max = PARALLELISM; i < max; i += 1) { - if (!jobs.length) { - break; - } - - const job = jobs.shift(); - activeJobs.push(job()); - } - - // eslint-disable-next-line no-await-in-loop - results = results.concat(await Promise.all(activeJobs)); - } - - if (!results.length) { - throw new Error('No responses received'); - } - - const { contentType } = results[0]; - const data = Signal.LinkPreviews.assembleChunks(results); - - return { - contentType, - data, - }; - } - - async function sha256(string) { - const arraybuffer = new TextEncoder('utf-8').encode(string); - const digest = await window.crypto.subtle.digest('SHA-256', arraybuffer); - return StringView.arrayBufferToHex(digest); - } - - // Wrapper function which utilizes cache - async function getPreview(url, skipCache = false) { - // If we have a request cached then use that - if (!skipCache && url in previewCache) { - return previewCache[url]; - } - - // Start the request - const promise = _getPreview(url).catch(e => { - window.log.error(e); - - // If we get an error then we can purge the cache - if (url in previewCache) { - delete previewCache[url]; - } - - return null; - }); - previewCache[url] = promise; - - return promise; - } - - async function _getPreview(url) { - let html; - try { - html = await textsecure.messaging.makeProxiedRequest(url); - } catch (error) { - if (error.code >= 300) { - throw new Error(`Failed to fetch html: ${error}`); - } - } - - const title = Signal.LinkPreviews.getTitleMetaTag(html); - const imageUrl = Signal.LinkPreviews.getImageMetaTag(html); - - let image; - let objectUrl; - try { - if (imageUrl) { - if (!Signal.LinkPreviews.isMediaLinkInWhitelist(imageUrl)) { - const primaryDomain = Signal.LinkPreviews.getDomain(url); - const imageDomain = Signal.LinkPreviews.getDomain(imageUrl); - throw new Error( - `imageUrl for domain ${primaryDomain} did not match media whitelist. Domain: ${imageDomain}` - ); - } - - const data = await makeChunkedRequest(imageUrl); - - // Calculate dimensions - const file = new Blob([data.data], { - type: data.contentType, - }); - objectUrl = URL.createObjectURL(file); - - const dimensions = await Signal.Types.VisualAttachment.getImageDimensions( - { - objectUrl, - logger: window.log, - } - ); - - image = { - ...data, - ...dimensions, - contentType: file.type, - }; - } - } catch (error) { - // We still want to show the preview if we failed to get an image - window.log.error( - 'getPreview failed to get image for link preview:', - error.message - ); - } finally { - if (objectUrl) { - URL.revokeObjectURL(objectUrl); - } - } - - const hash = await sha256(url); - - return { - title, - url, - image, - hash, - }; - } - - window.Signal.LinkPreviews.helper = { - getPreview, - }; -})(); diff --git a/js/models/messages.js b/js/models/messages.js index cb5927484..874b76196 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -21,13 +21,7 @@ window.Whisper = window.Whisper || {}; - const { - Message: TypedMessage, - Contact, - PhoneNumber, - Attachment, - Errors, - } = Signal.Types; + const { Message: TypedMessage, Contact, PhoneNumber, Errors } = Signal.Types; const { deleteExternalMessageFiles, @@ -35,7 +29,6 @@ loadAttachmentData, loadQuoteData, loadPreviewData, - writeAttachment, upgradeMessageSchema, } = window.Signal.Migrations; const { bytesFromString } = window.Signal.Crypto; @@ -96,9 +89,6 @@ this.on('unload', this.unload); this.on('expired', this.onExpired); this.setToExpire(); - - this.updatePreview(); - // Keep props ready const generateProps = () => { if (this.isExpirationTimerUpdate()) { @@ -161,73 +151,6 @@ // eslint-disable-next-line no-bitwise return !!(this.get('flags') & flag); }, - async updatePreview() { - // Don't generate link previews if user has turned them off - if (!storage.get('linkPreviews', false)) { - return; - } - - if (this.updatingPreview) { - return; - } - - // Only update the preview if we don't have any set - const preview = this.get('preview'); - if (!_.isEmpty(preview)) { - return; - } - - // Make sure we have links we can preview - const links = Signal.LinkPreviews.findLinks(this.get('body')); - const firstLink = links.find(link => - Signal.LinkPreviews.isLinkInWhitelist(link) - ); - if (!firstLink) { - return; - } - - this.updatingPreview = true; - - try { - const result = await Signal.LinkPreviews.helper.getPreview(firstLink); - - const { image, title, hash } = result; - - // A link preview isn't worth showing unless we have either a title or an image - if (!result || !(image || title)) { - this.updatingPreview = false; - return; - } - - // Save the image to disk - const { data } = image; - const extension = Attachment.getFileExtension(image); - if (data && extension) { - const hash32 = hash.substring(0, 32); - try { - const filePath = await writeAttachment({ - data, - path: `previews/${hash32}.${extension}`, - }); - - // return the image without the data - result.image = _.omit({ ...image, path: filePath }, 'data'); - } catch (e) { - window.log.warn('Failed to write preview to disk', e); - } - } - - // Save it!! - this.set({ preview: [result] }); - await window.Signal.Data.saveMessage(this.attributes, { - Message: Whisper.Message, - }); - } catch (e) { - window.log.warn(`Failed to load previews for message: ${this.id}`); - } finally { - this.updatingPreview = false; - } - }, getEndSessionTranslationKey() { const sessionType = this.get('endSessionType'); if (sessionType === 'ongoing') { @@ -1872,9 +1795,6 @@ schemaVersion: dataMessage.schemaVersion, }); - // Update the previews if we need to - message.updatePreview(); - if (type === 'outgoing') { const receipts = Whisper.DeliveryReceipts.forMessage( conversation,