Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3516412
D7236.id24536.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
8 KB
Referenced Files
None
Subscribers
None
D7236.id24536.diff
View Options
diff --git a/lib/types/media-types.js b/lib/types/media-types.js
--- a/lib/types/media-types.js
+++ b/lib/types/media-types.js
@@ -511,6 +511,12 @@
+time: number, // ms
+exceptionMessage: ?string,
}
+ | {
+ +success: false,
+ +reason: 'encryption_exception',
+ +time: number, // ms
+ +exceptionMessage: ?string,
+ }
| {
+success: false,
+reason: 'save_unsupported',
diff --git a/native/input/input-state-container.react.js b/native/input/input-state-container.react.js
--- a/native/input/input-state-container.react.js
+++ b/native/input/input-state-container.react.js
@@ -96,6 +96,7 @@
type PendingMultimediaUploads,
type MultimediaProcessingStep,
} from './input-state.js';
+import { encryptMedia } from '../media/encryption-utils.js';
import { disposeTempFile } from '../media/file-utils.js';
import { processMedia } from '../media/media-utils.js';
import { displayActionResultModal } from '../navigation/action-result-modal.js';
@@ -159,6 +160,8 @@
replyCallbacks: Array<(message: string) => void> = [];
pendingThreadCreations = new Map<string, Promise<string>>();
pendingThreadUpdateHandlers = new Map<string, (ThreadInfo) => mixed>();
+ // TODO: we want to send encrypted media if thread is in the Comm community
+ sendEncryptedMedia: boolean = false;
// When the user sends a multimedia message that triggers the creation of a
// sidebar, the sidebar gets created right away, but the message needs to wait
@@ -634,12 +637,15 @@
() => {
const creatorID = this.props.viewerID;
invariant(creatorID, 'need viewer ID in order to send a message');
- const messageInfo = createMediaMessageInfo({
- localID: localMessageID,
- threadID: threadInfo.id,
- creatorID,
- media,
- });
+ const messageInfo = createMediaMessageInfo(
+ {
+ localID: localMessageID,
+ threadID: threadInfo.id,
+ creatorID,
+ media,
+ },
+ { forceMultimediaMessageType: this.sendEncryptedMedia },
+ );
this.props.dispatch({
type: createLocalMessageActionType,
payload: messageInfo,
@@ -677,6 +683,7 @@
let userTime;
let errorMessage;
let reportPromise;
+ const filesToDispose = [];
const onUploadFinished = async (result: MediaMissionResult) => {
if (!this.props.mediaReportsEnabled) {
@@ -717,6 +724,9 @@
onUploadFailed(localMediaID, message);
return await onUploadFinished(processResult);
}
+ if (processResult.shouldDisposePath) {
+ filesToDispose.push(processResult.shouldDisposePath);
+ }
processedMedia = processResult;
} catch (e) {
onUploadFailed(localMediaID, 'processing failed');
@@ -728,7 +738,33 @@
});
}
- const { uploadURI, shouldDisposePath, filename, mime } = processedMedia;
+ let encryptionSteps = [];
+ if (this.sendEncryptedMedia) {
+ const encryptionStart = Date.now();
+ try {
+ const { result: encryptionResult, ...encryptionReturn } =
+ await encryptMedia(processedMedia);
+ encryptionSteps = encryptionReturn.steps;
+ if (!encryptionResult.success) {
+ onUploadFailed(localMediaID, encryptionResult.reason);
+ return await onUploadFinished(encryptionResult);
+ }
+ if (encryptionResult.shouldDisposePath) {
+ filesToDispose.push(encryptionResult.shouldDisposePath);
+ }
+ processedMedia = encryptionResult;
+ } catch (e) {
+ onUploadFailed(localMediaID, 'encryption failed');
+ return await onUploadFinished({
+ success: false,
+ reason: 'encryption_exception',
+ time: Date.now() - encryptionStart,
+ exceptionMessage: getMessageForException(e),
+ });
+ }
+ }
+
+ const { uploadURI, filename, mime } = processedMedia;
const { hasWiFi } = this.props;
@@ -745,9 +781,11 @@
{
...processedMedia.dimensions,
loop:
- processedMedia.mediaType === 'video'
+ processedMedia.mediaType === 'video' ||
+ processedMedia.mediaType === 'encrypted_video'
? processedMedia.loop
: undefined,
+ encryptionKey: processedMedia.encryptionKey,
},
{
onProgress: (percent: number) =>
@@ -762,7 +800,10 @@
),
);
- if (processedMedia.mediaType === 'video') {
+ if (
+ processedMedia.mediaType === 'video' ||
+ processedMedia.mediaType === 'encrypted_video'
+ ) {
uploadPromises.push(
this.props.uploadMultimedia(
{
@@ -773,6 +814,7 @@
{
...processedMedia.dimensions,
loop: false,
+ encryptionKey: processedMedia.thumbnailEncryptionKey,
},
{
uploadBlob: this.uploadBlob,
@@ -793,38 +835,70 @@
}
if (
- (processedMedia.mediaType === 'photo' && uploadResult) ||
- (processedMedia.mediaType === 'video' &&
+ ((processedMedia.mediaType === 'photo' ||
+ processedMedia.mediaType === 'encrypted_photo') &&
+ uploadResult) ||
+ ((processedMedia.mediaType === 'video' ||
+ processedMedia.mediaType === 'encrypted_video') &&
uploadResult &&
uploadThumbnailResult)
) {
+ const { encryptionKey } = processedMedia;
const { id, uri, dimensions, loop } = uploadResult;
serverID = id;
+ const mediaSourcePayload =
+ processedMedia.mediaType === 'encrypted_photo' ||
+ processedMedia.mediaType === 'encrypted_video'
+ ? {
+ type: processedMedia.mediaType,
+ holder: uri,
+ encryptionKey,
+ }
+ : {
+ type: uploadResult.mediaType,
+ uri,
+ };
let updateMediaPayload = {
messageID: localMessageID,
currentMediaID: localMediaID,
mediaUpdate: {
id,
- type: uploadResult.mediaType,
- uri,
+ ...mediaSourcePayload,
dimensions,
localMediaSelection: undefined,
loop: uploadResult.mediaType === 'video' ? loop : undefined,
},
};
- if (processedMedia.mediaType === 'video') {
+ if (
+ processedMedia.mediaType === 'video' ||
+ processedMedia.mediaType === 'encrypted_video'
+ ) {
invariant(uploadThumbnailResult, 'uploadThumbnailResult exists');
const { uri: thumbnailURI, id: thumbnailID } = uploadThumbnailResult;
- updateMediaPayload = {
- ...updateMediaPayload,
- mediaUpdate: {
- ...updateMediaPayload.mediaUpdate,
- thumbnailURI,
- thumbnailID,
- },
- };
+ const { thumbnailEncryptionKey } = processedMedia;
+
+ if (processedMedia.mediaType === 'encrypted_video') {
+ updateMediaPayload = {
+ ...updateMediaPayload,
+ mediaUpdate: {
+ ...updateMediaPayload.mediaUpdate,
+ thumbnailID,
+ thumbnailHolder: thumbnailURI,
+ thumbnailEncryptionKey,
+ },
+ };
+ } else {
+ updateMediaPayload = {
+ ...updateMediaPayload,
+ mediaUpdate: {
+ ...updateMediaPayload.mediaUpdate,
+ thumbnailID,
+ thumbnailURI,
+ },
+ };
+ }
}
// When we dispatch this action, it updates Redux and triggers the
@@ -841,6 +915,7 @@
const processSteps = await reportPromise;
reportPromise = null;
steps.push(...processSteps);
+ steps.push(...encryptionSteps);
steps.push({
step: 'upload',
success: !!uploadResult,
@@ -856,17 +931,19 @@
const cleanupPromises = [];
- if (shouldDisposePath) {
+ if (filesToDispose.length > 0) {
// If processMedia needed to do any transcoding before upload, we dispose
// of the resultant temporary file here. Since the transcoded temporary
// file is only used for upload, we can dispose of it after processMedia
// (reportPromise) and the upload are complete
- cleanupPromises.push(
- (async () => {
- const disposeStep = await disposeTempFile(shouldDisposePath);
- steps.push(disposeStep);
- })(),
- );
+ filesToDispose.forEach(shouldDisposePath => {
+ cleanupPromises.push(
+ (async () => {
+ const disposeStep = await disposeTempFile(shouldDisposePath);
+ steps.push(disposeStep);
+ })(),
+ );
+ });
}
// if there's a thumbnail we'll temporarily unlink it here
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Dec 23, 2:24 PM (19 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2694331
Default Alt Text
D7236.id24536.diff (8 KB)
Attached To
Mode
D7236: [native] Encrypt files during media mission
Attached
Detach File
Event Timeline
Log In to Comment