Page MenuHomePhabricator

D10910.diff
No OneTemporary

D10910.diff

diff --git a/lib/utils/services-utils.js b/lib/utils/services-utils.js
--- a/lib/utils/services-utils.js
+++ b/lib/utils/services-utils.js
@@ -21,8 +21,18 @@
return `Bearer ${base64EncodedPayload}`;
}
+function createDefaultHTTPRequestHeaders(authMetadata: AuthMetadata): {
+ [string]: string,
+} {
+ const authorization = createHTTPAuthorizationHeader(authMetadata);
+ return {
+ Authorization: authorization,
+ };
+}
+
export {
handleHTTPResponseError,
usingCommServicesAccessToken,
createHTTPAuthorizationHeader,
+ createDefaultHTTPRequestHeaders,
};
diff --git a/native/media/encrypted-image.react.js b/native/media/encrypted-image.react.js
--- a/native/media/encrypted-image.react.js
+++ b/native/media/encrypted-image.react.js
@@ -7,7 +7,7 @@
import { connectionSelector } from 'lib/selectors/keyserver-selectors.js';
import { ashoatKeyserverID } from 'lib/utils/validation-utils.js';
-import { decryptBase64, fetchAndDecryptMedia } from './encryption-utils.js';
+import { decryptBase64, useFetchAndDecryptMedia } from './encryption-utils.js';
import LoadableImage from './loadable-image.react.js';
import { useSelector } from '../redux/redux-utils.js';
import type { ImageSource } from '../types/react-native.js';
@@ -34,6 +34,8 @@
thumbHash: encryptedThumbHash,
} = props;
+ const fetchAndDecryptMedia = useFetchAndDecryptMedia();
+
const mediaCache = React.useContext(MediaCacheContext);
const [source, setSource] = React.useState<?ImageSource>(null);
@@ -96,7 +98,7 @@
return () => {
isMounted = false;
};
- }, [attempt, blobURI, encryptionKey, mediaCache]);
+ }, [attempt, blobURI, encryptionKey, mediaCache, fetchAndDecryptMedia]);
const onLoad = React.useCallback(() => {
onLoadProp && onLoadProp(blobURI);
diff --git a/native/media/encryption-utils.js b/native/media/encryption-utils.js
--- a/native/media/encryption-utils.js
+++ b/native/media/encryption-utils.js
@@ -1,6 +1,7 @@
// @flow
import invariant from 'invariant';
+import * as React from 'react';
import { uintArrayToHexString, hexToUintArray } from 'lib/media/data-utils.js';
import {
@@ -10,14 +11,18 @@
readableFilename,
pathFromURI,
} from 'lib/media/file-utils.js';
+import type { AuthMetadata } from 'lib/shared/identity-client-context.js';
+import { IdentityClientContext } from 'lib/shared/identity-client-context.js';
import type {
MediaMissionFailure,
MediaMissionStep,
DecryptFileMediaMissionStep,
EncryptFileMediaMissionStep,
} from 'lib/types/media-types.js';
+import { isBlobServiceURI } from 'lib/utils/blob-service.js';
import { getMessageForException } from 'lib/utils/errors.js';
import { pad, unpad, calculatePaddedLength } from 'lib/utils/pkcs7-padding.js';
+import { createDefaultHTTPRequestHeaders } from 'lib/utils/services-utils.js';
import { temporaryDirectoryPath } from './file-utils.js';
import { getFetchableURI } from './identifier-utils.js';
@@ -245,26 +250,36 @@
};
}
+type FetchAndDecryptMediaOptions = {
+ +destination: 'file' | 'data_uri',
+ +destinationDirectory?: string,
+};
+
+type FetchAndDecryptMediaOutput = {
+ steps: $ReadOnlyArray<DecryptFileMediaMissionStep>,
+ result: MediaMissionFailure | { success: true, uri: string },
+};
+
async function fetchAndDecryptMedia(
blobURI: string,
encryptionKey: string,
- options: {
- +destination: 'file' | 'data_uri',
- +destinationDirectory?: string,
- },
-): Promise<{
- steps: $ReadOnlyArray<DecryptFileMediaMissionStep>,
- result: MediaMissionFailure | { success: true, uri: string },
-}> {
+ authMetadata: AuthMetadata,
+ options: FetchAndDecryptMediaOptions,
+): Promise<FetchAndDecryptMediaOutput> {
let success = true,
exceptionMessage;
const steps: DecryptFileMediaMissionStep[] = [];
// Step 1. Fetch the file and convert it to a Uint8Array
+ let headers;
+ if (isBlobServiceURI(blobURI)) {
+ headers = createDefaultHTTPRequestHeaders(authMetadata);
+ }
+
const fetchStartTime = Date.now();
let data;
try {
- const response = await fetch(getFetchableURI(blobURI));
+ const response = await fetch(getFetchableURI(blobURI), { headers });
if (!response.ok) {
throw new Error(`HTTP error ${response.status}: ${response.statusText}`);
}
@@ -385,6 +400,29 @@
};
}
+function useFetchAndDecryptMedia(): (
+ blobURI: string,
+ encryptionKey: string,
+ options: FetchAndDecryptMediaOptions,
+) => Promise<FetchAndDecryptMediaOutput> {
+ const identityContext = React.useContext(IdentityClientContext);
+ invariant(identityContext, 'Identity context should be set');
+ const { getAuthMetadata } = identityContext;
+
+ return React.useCallback(
+ async (blobURI, encryptionKey, options) => {
+ const authMetadata = await getAuthMetadata();
+ return fetchAndDecryptMedia(
+ blobURI,
+ encryptionKey,
+ authMetadata,
+ options,
+ );
+ },
+ [getAuthMetadata],
+ );
+}
+
function encryptBase64(
base64: string,
keyBytes?: Uint8Array,
@@ -407,4 +445,10 @@
return commUtilsModule.base64EncodeBuffer(decryptedData.buffer);
}
-export { encryptMedia, fetchAndDecryptMedia, encryptBase64, decryptBase64 };
+export {
+ encryptMedia,
+ fetchAndDecryptMedia,
+ useFetchAndDecryptMedia,
+ encryptBase64,
+ decryptBase64,
+};
diff --git a/native/media/save-media.js b/native/media/save-media.js
--- a/native/media/save-media.js
+++ b/native/media/save-media.js
@@ -42,6 +42,7 @@
type FetchFileInfoResult,
} from './file-utils.js';
import { getMediaLibraryIdentifier } from './identifier-utils.js';
+import { commCoreModule } from '../native-modules.js';
import { displayActionResultModal } from '../navigation/action-result-modal.js';
import { requestAndroidPermission } from '../utils/android-permissions.js';
@@ -377,8 +378,10 @@
): Promise<IntermediateSaveResult> {
const steps: Array<MediaMissionStep> = [];
if (encryptionKey) {
+ const authMetadata = await commCoreModule.getCommServicesAuthMetadata();
+
const { steps: decryptionSteps, result: decryptionResult } =
- await fetchAndDecryptMedia(inputURI, encryptionKey, {
+ await fetchAndDecryptMedia(inputURI, encryptionKey, authMetadata, {
destination: 'file',
destinationDirectory: directory,
});
diff --git a/native/media/video-playback-modal.react.js b/native/media/video-playback-modal.react.js
--- a/native/media/video-playback-modal.react.js
+++ b/native/media/video-playback-modal.react.js
@@ -19,7 +19,7 @@
import { useIsAppBackgroundedOrInactive } from 'lib/shared/lifecycle-utils.js';
import type { MediaInfo } from 'lib/types/media-types.js';
-import { fetchAndDecryptMedia } from './encryption-utils.js';
+import { useFetchAndDecryptMedia } from './encryption-utils.js';
import { formatDuration } from './video-utils.js';
import ConnectedStatusBar from '../connected-status-bar.react.js';
import type { AppNavigationProp } from '../navigation/app-navigator.react.js';
@@ -98,6 +98,7 @@
);
const mediaCache = React.useContext(MediaCacheContext);
+ const fetchAndDecryptMedia = useFetchAndDecryptMedia();
React.useEffect(() => {
// skip for unencrypted videos
@@ -142,7 +143,7 @@
filesystem.unlink(uriToDispose);
}
};
- }, [blobURI, encryptionKey, mediaCache]);
+ }, [blobURI, encryptionKey, mediaCache, fetchAndDecryptMedia]);
const closeButtonX = useValue(-1);
const closeButtonY = useValue(-1);

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 9, 6:55 AM (20 h, 38 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2449898
Default Alt Text
D10910.diff (7 KB)

Event Timeline