Skip to content

Commit

Permalink
Keep track of blob URLs for revoking (#525)
Browse files Browse the repository at this point in the history
  • Loading branch information
swissspidy committed Jun 21, 2024
1 parent 1424efa commit b7ea974
Show file tree
Hide file tree
Showing 7 changed files with 210 additions and 12 deletions.
142 changes: 130 additions & 12 deletions packages/upload-media/src/store/actions.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { v4 as uuidv4 } from 'uuid';
import { createWorkerFactory } from '@shopify/web-worker';

import { createBlobURL, isBlobURL } from '@wordpress/blob';
import { createBlobURL, isBlobURL, revokeBlobURL } from '@wordpress/blob';
import type { WPDataRegistry } from '@wordpress/data/build-types/registry';
import { store as preferencesStore } from '@wordpress/preferences';

Expand Down Expand Up @@ -48,6 +48,7 @@ import type {
Attachment,
AudioFormat,
BatchId,
CacheBlobUrlAction,
CancelAction,
CreateRestAttachment,
ImageFormat,
Expand All @@ -70,6 +71,7 @@ import type {
RequestApprovalAction,
ResumeItemAction,
ResumeQueueAction,
RevokeBlobUrlsAction,
SetImageSizesAction,
SetMediaSourceTermsAction,
SideloadAdditionalData,
Expand Down Expand Up @@ -128,6 +130,7 @@ type ActionCreators = {
generateThumbnails: typeof generateThumbnails;
uploadOriginal: typeof uploadOriginal;
uploadPoster: typeof uploadPoster;
revokeBlobUrls: typeof revokeBlobUrls;
< T = Record< string, unknown > >( args: T ): void;
};

Expand Down Expand Up @@ -191,6 +194,13 @@ export function addItem( {

const itemId = uuidv4();

const blobUrl = createBlobURL( file );
dispatch< CacheBlobUrlAction >( {
type: Type.CacheBlobUrl,
id: itemId,
blobUrl,
} );

dispatch< AddAction >( {
type: Type.Add,
item: {
Expand All @@ -200,7 +210,7 @@ export function addItem( {
sourceFile: cloneFile( file ),
file,
attachment: {
url: createBlobURL( file ),
url: blobUrl,
},
additionalData: {
generate_sub_sizes: 'server' === thumbnailGeneration,
Expand Down Expand Up @@ -636,6 +646,7 @@ export function processItem( id: QueueItemId ) {
type: Type.Remove,
id,
} );
dispatch.revokeBlobUrls( id );

return;
}
Expand Down Expand Up @@ -788,13 +799,26 @@ export function addPosterForItem( id: QueueItemId ) {
switch ( mediaType ) {
case 'video':
const src = createBlobURL( file );

dispatch< CacheBlobUrlAction >( {
type: Type.CacheBlobUrl,
id,
blobUrl: src,
} );

const poster = await getPosterFromVideo(
src,
`${ getFileBasename( item.file.name ) }-poster`
);

const posterUrl = createBlobURL( poster );

dispatch< CacheBlobUrlAction >( {
type: Type.CacheBlobUrl,
id,
blobUrl: posterUrl,
} );

dispatch.finishOperation( id, {
poster,
attachment: {
Expand All @@ -809,18 +833,34 @@ export function addPosterForItem( id: QueueItemId ) {
/* webpackChunkName: 'pdf' */ '@mexp/pdf'
);

const pdfSrc = createBlobURL( file );

dispatch< CacheBlobUrlAction >( {
type: Type.CacheBlobUrl,
id,
blobUrl: pdfSrc,
} );

// TODO: is this the right place?
// Note: Causes another state update.
const pdfThumbnail = await getImageFromPdf(
createBlobURL( file ),
pdfSrc,
// Same suffix as WP core uses, see https://github.com/WordPress/wordpress-develop/blob/8a5daa6b446e8c70ba22d64820f6963f18d36e92/src/wp-admin/includes/image.php#L609-L634
`${ getFileBasename( item.file.name ) }-pdf`
);

const pdfThumbnailUrl = createBlobURL( pdfThumbnail );

dispatch< CacheBlobUrlAction >( {
type: Type.CacheBlobUrl,
id,
blobUrl: pdfThumbnailUrl,
} );

dispatch.finishOperation( id, {
poster: pdfThumbnail,
attachment: {
poster: createBlobURL( pdfThumbnail ),
poster: pdfThumbnailUrl,
},
} );
break;
Expand Down Expand Up @@ -1304,6 +1344,7 @@ export function cancelItem( id: QueueItemId, error: Error ) {
type: Type.Remove,
id,
} );
dispatch.revokeBlobUrls( id );
};
}

Expand Down Expand Up @@ -1433,18 +1474,25 @@ export function optimizeImageItem(
);
}

const blobUrl = createBlobURL( file );
dispatch< CacheBlobUrlAction >( {
type: Type.CacheBlobUrl,
id,
blobUrl,
} );

if ( args?.requireApproval ) {
dispatch< RequestApprovalAction >( {
type: Type.RequestApproval,
id,
file,
url: createBlobURL( file ),
url: blobUrl,
} );
} else {
dispatch.finishOperation( id, {
file,
attachment: {
url: createBlobURL( file ),
url: blobUrl,
},
} );
}
Expand Down Expand Up @@ -1504,10 +1552,17 @@ export function optimizeVideoItem( id: QueueItemId ) {
break;
}

const blobUrl = createBlobURL( file );
dispatch< CacheBlobUrlAction >( {
type: Type.CacheBlobUrl,
id,
blobUrl,
} );

dispatch.finishOperation( id, {
file,
attachment: {
url: createBlobURL( file ),
url: blobUrl,
},
mediaSourceTerms: [ 'media-optimization' ],
} );
Expand Down Expand Up @@ -1536,10 +1591,17 @@ export function muteVideoItem( id: QueueItemId ) {
);
const file = await muteVideo( item.file );

const blobUrl = createBlobURL( file );
dispatch< CacheBlobUrlAction >( {
type: Type.CacheBlobUrl,
id,
blobUrl,
} );

dispatch.finishOperation( id, {
file,
attachment: {
url: createBlobURL( file ),
url: blobUrl,
},
additionalData: {
mexp_is_muted: true,
Expand Down Expand Up @@ -1586,10 +1648,17 @@ export function optimizeAudioItem( id: QueueItemId ) {
break;
}

const blobUrl = createBlobURL( file );
dispatch< CacheBlobUrlAction >( {
type: Type.CacheBlobUrl,
id,
blobUrl,
} );

dispatch.finishOperation( id, {
file,
attachment: {
url: createBlobURL( file ),
url: blobUrl,
},
mediaSourceTerms: [ 'media-optimization' ],
} );
Expand Down Expand Up @@ -1647,10 +1716,17 @@ export function convertGifItem( id: QueueItemId ) {
break;
}

const blobUrl = createBlobURL( file );
dispatch< CacheBlobUrlAction >( {
type: Type.CacheBlobUrl,
id,
blobUrl,
} );

dispatch.finishOperation( id, {
file,
attachment: {
url: createBlobURL( file ),
url: blobUrl,
},
mediaSourceTerms: [ 'gif-conversion' ],
} );
Expand All @@ -1675,10 +1751,18 @@ export function convertHeifItem( id: QueueItemId ) {

try {
const file = await transcodeHeifImage( item.file );

const blobUrl = createBlobURL( file );
dispatch< CacheBlobUrlAction >( {
type: Type.CacheBlobUrl,
id,
blobUrl,
} );

dispatch.finishOperation( id, {
file,
attachment: {
url: createBlobURL( file ),
url: blobUrl,
},
} );
} catch ( error ) {
Expand Down Expand Up @@ -1753,10 +1837,17 @@ export function resizeCropItem(
);
}

const blobUrl = createBlobURL( file );
dispatch< CacheBlobUrlAction >( {
type: Type.CacheBlobUrl,
id,
blobUrl,
} );

dispatch.finishOperation( id, {
file,
attachment: {
url: createBlobURL( file ),
url: blobUrl,
},
} );
} catch ( error ) {
Expand Down Expand Up @@ -1810,6 +1901,12 @@ export function uploadItem( id: QueueItemId ) {
'image' === getMediaTypeFromMimeType( item.sourceFile.type )
) {
stillUrl = createBlobURL( item.sourceFile );

dispatch< CacheBlobUrlAction >( {
type: Type.CacheBlobUrl,
id,
blobUrl: stillUrl,
} );
}

// TODO: Make this async after upload?
Expand Down Expand Up @@ -1893,6 +1990,12 @@ export function uploadItem( id: QueueItemId ) {
attachment.poster = item.attachment.poster;
} else if ( poster ) {
attachment.poster = createBlobURL( poster );

dispatch< CacheBlobUrlAction >( {
type: Type.CacheBlobUrl,
id,
blobUrl: attachment.poster,
} );
}
}

Expand Down Expand Up @@ -1965,3 +2068,18 @@ export function setImageSizes(
imageSizes,
};
}

export function revokeBlobUrls( id: QueueItemId ) {
return async ( { select, dispatch }: ThunkArgs ) => {
const blobUrls = select.getBlobUrls( id );

for ( const blobUrl of blobUrls ) {
revokeBlobURL( blobUrl );
}

dispatch< RevokeBlobUrlsAction >( {
type: Type.RevokeBlobUrls,
id,
} );
};
}
26 changes: 26 additions & 0 deletions packages/upload-media/src/store/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
type AddAction,
type AddOperationsAction,
type ApproveUploadAction,
type CacheBlobUrlAction,
type CancelAction,
ItemStatus,
type OperationFinishAction,
Expand All @@ -12,6 +13,7 @@ import {
type RequestApprovalAction,
type ResumeItemAction,
type ResumeQueueAction,
type RevokeBlobUrlsAction,
type SetImageSizesAction,
type SetMediaSourceTermsAction,
type State,
Expand All @@ -24,6 +26,7 @@ const DEFAULT_STATE: State = {
mediaSourceTerms: {},
imageSizes: {},
queueStatus: 'active',
blobUrls: {},
};

type Action =
Expand All @@ -41,6 +44,8 @@ type Action =
| RequestApprovalAction
| SetImageSizesAction
| SetMediaSourceTermsAction
| CacheBlobUrlAction
| RevokeBlobUrlsAction
| UnknownAction;

function reducer(
Expand Down Expand Up @@ -226,6 +231,27 @@ function reducer(
imageSizes: action.imageSizes,
};
}

case Type.CacheBlobUrl: {
const blobUrls = state.blobUrls[ action.id ] || [];
return {
...state,
blobUrls: {
...state.blobUrls,
[ action.id ]: [ ...blobUrls, action.blobUrl ],
},
};
}

case Type.RevokeBlobUrls: {
const newBlobUrls = { ...state.blobUrls };
delete newBlobUrls[ action.id ];

return {
...state,
blobUrls: newBlobUrls,
};
}
}

return state;
Expand Down
Loading

0 comments on commit b7ea974

Please sign in to comment.