Skip to content

Commit

Permalink
Cherry-pick 0f76043. rdar://106763672
Browse files Browse the repository at this point in the history
    [iOS] Avoid transcoding images on file inputs unless the set of image types is explicitly restricted
    https://bugs.webkit.org/show_bug.cgi?id=267277
    rdar://106763672

    Reviewed by Abrar Rahman Protyasha.

    On iOS, when using an `<input type=file>` that supports images or videos, the
    user has the option to select content from their photo library. Historically,
    in WebKit, selected content has always been transcoded to JPEG (for images)
    and H.264 (for video).

    However, this can be undesirable for users that want to provide the image in
    its original form. In particular, this is important for photo editing applications.
    Furthermore, macOS does not have this general transcoding behavior.

    This patch changes the behavior on iOS so that transcoding to the compatible
    format for images is only performed if the `accept` attribute restricts the set
    of image types. Videos remain exempted from this behavior change due to known
    compatibility issues.

    Note that this change does have non-zero compatibility risk. However, it is more
    correct, and resolves known issues on image editing applications. Sites that
    want a compatibile representation are expected to use the `accept` attribute to
    indicate their need.

    * Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml:

    Introduce a setting so the new behavior can easily be toggled off for testing.

    * Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm:
    (-[WKContentView fileUploadPanelPhotoPickerPrefersOriginalImageFormat:]):
    * Source/WebKit/UIProcess/ios/forms/WKFileUploadPanel.h:
    * Source/WebKit/UIProcess/ios/forms/WKFileUploadPanel.mm:
    (-[WKFileUploadPanel _preferredAssetRepresentationMode]):

    Disable transcoding by the picker if the set of restricted types is empty,
    or contains all image types.

    (-[WKFileUploadPanel _showPhotoPicker]):
    (-[WKFileUploadPanel picker:didFinishPicking:]):

    Continue to transcode video, when the picker does not perform transcoding, for
    compatibility.

    Canonical link: https://commits.webkit.org/275726@main
  • Loading branch information
pxlcoder authored and Mohsin Qureshi committed Mar 12, 2024
1 parent 3855bdb commit 02a5c28
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 2 deletions.
12 changes: 12 additions & 0 deletions Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5063,6 +5063,18 @@ PermissionsAPIEnabled:
WebCore:
default: false

PhotoPickerPrefersOriginalImageFormat:
type: bool
status: internal
humanReadableName: "Photo Picker Prefers Original Image Format"
humanReadableDescription: "Prefer the original image format when selecting photos for file upload"
webcoreBinding: none
condition: HAVE(PHOTOS_UI)
exposed: [ WebKit ]
defaultValue:
WebKit:
default: true

PictographFontFamily:
type: String
status: embedder
Expand Down
8 changes: 8 additions & 0 deletions Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
Original file line number Diff line number Diff line change
Expand Up @@ -9092,6 +9092,14 @@ - (BOOL)fileUploadPanelDestinationIsManaged:(WKFileUploadPanel *)fileUploadPanel
&& [uiDelegate _webView:webView.get() fileUploadPanelContentIsManagedWithInitiatingFrame:wrapper(API::FrameInfo::create(WTFMove(_frameInfoForFileUploadPanel), _page.get())).get()];
}

#if HAVE(PHOTOS_UI)
- (BOOL)fileUploadPanelPhotoPickerPrefersOriginalImageFormat:(WKFileUploadPanel *)fileUploadPanel
{
ASSERT(_fileUploadPanel.get() == fileUploadPanel);
return _page->preferences().photoPickerPrefersOriginalImageFormat();
}
#endif

- (void)_showShareSheet:(const WebCore::ShareDataWithParsedURL&)data inRect:(std::optional<WebCore::FloatRect>)rect completionHandler:(CompletionHandler<void(bool)>&&)completionHandler
{
#if !PLATFORM(WATCHOS) && !PLATFORM(APPLETV)
Expand Down
3 changes: 3 additions & 0 deletions Source/WebKit/UIProcess/ios/forms/WKFileUploadPanel.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ class WebOpenPanelResultListenerProxy;
@optional
- (void)fileUploadPanelDidDismiss:(WKFileUploadPanel *)fileUploadPanel;
- (BOOL)fileUploadPanelDestinationIsManaged:(WKFileUploadPanel *)fileUploadPanel;
#if HAVE(PHOTOS_UI)
- (BOOL)fileUploadPanelPhotoPickerPrefersOriginalImageFormat:(WKFileUploadPanel *)fileUploadPanel;
#endif
@end

#endif // PLATFORM(IOS_FAMILY)
27 changes: 25 additions & 2 deletions Source/WebKit/UIProcess/ios/forms/WKFileUploadPanel.mm
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,25 @@ - (void)_dismissDisplayAnimated:(BOOL)animated
return availableMediaTypeUTIs;
}

#if HAVE(PHOTOS_UI)
- (PHPickerConfigurationAssetRepresentationMode)_preferredAssetRepresentationMode
{
// FIXME (270470): `PHPickerConfigurationAssetRepresentationModeCurrent` should always be used
// and transcoding should be done based on the value of the `accept` attribute

if (![_delegate respondsToSelector:@selector(fileUploadPanelPhotoPickerPrefersOriginalImageFormat:)] || ![_delegate fileUploadPanelPhotoPickerPrefersOriginalImageFormat:self])
return PHPickerConfigurationAssetRepresentationModeCompatible;

if (![_acceptedUTIs count])
return PHPickerConfigurationAssetRepresentationModeCurrent;

if ([_acceptedUTIs containsObject:UTTypeImage.identifier])
return PHPickerConfigurationAssetRepresentationModeCurrent;

return PHPickerConfigurationAssetRepresentationModeCompatible;
}
#endif

#pragma mark - Source selection menu

- (NSString *)_chooseFilesButtonLabel
Expand Down Expand Up @@ -855,7 +874,7 @@ - (void)_showPhotoPicker
#if HAVE(PHOTOS_UI)
auto configuration = adoptNS([allocPHPickerConfigurationInstance() init]);
[configuration setSelectionLimit:_allowMultipleFiles ? 0 : 1];
[configuration setPreferredAssetRepresentationMode:PHPickerConfigurationAssetRepresentationModeCompatible];
[configuration setPreferredAssetRepresentationMode:[self _preferredAssetRepresentationMode]];
[configuration _setAllowsDownscaling:YES];

if (auto allowedImagePickerType = _allowedImagePickerTypes.toSingleValue()) {
Expand Down Expand Up @@ -944,7 +963,11 @@ - (void)picker:(PHPickerViewController *)picker didFinishPicking:(NSArray<PHPick
[self _processPickerResults:results successBlock:^(NSArray<_WKFileUploadItem *> *items) {
ensureOnMainRunLoop([self, strongSelf = retainPtr(self), items = retainPtr(items)] {
[strongSelf->_view _removeTemporaryDirectoriesWhenDeallocated:std::exchange(strongSelf->_temporaryUploadedFileURLs, { })];
[self _chooseMediaItems:items.get()];

if ([self->_photoPicker configuration].preferredAssetRepresentationMode != PHPickerConfigurationAssetRepresentationModeCompatible)
[self _uploadMediaItemsTranscodingVideo:items.get()];
else
[self _chooseMediaItems:items.get()];
});
} failureBlock:^{
ensureOnMainRunLoop([self, strongSelf = retainPtr(self)] {
Expand Down

0 comments on commit 02a5c28

Please sign in to comment.