trigger-corp / libreforge

Build cross-platform apps with HTML, CSS and JavaScript
MIT License
5 stars 0 forks source link

iOS: File and Capture plugins are not requiring permission to access media #102

Closed hborjaille closed 2 years ago

hborjaille commented 3 years ago

Device information:

App information:

"file": {
      "version": "2.27",
      "config": {
        "usage_description": "Allow access to your camera, microphone, and gallery, to create and upload images or videos incl. sound, and store them on your device or upload them directly from the gallery, e.g. for in app posts, comments or profile picture."
      },
      "disabled": %disable_file_module%
    },
    "capture": {
      "version": "2.26",
      "config": {
        "usage_description": "Allow access to your camera, microphone, and gallery, to create and upload images or videos incl. sound, and store them on your device or upload them directly from the gallery, e.g. for in app posts, comments or profile picture."
      }
    }

To Reproduce

  1. Capture plugin a. Try to record a video or capture a picture

  2. File plugin a. Try to upload a video or a picture

Expected behaviour

The permission request pop up should be displayed to the user. If permission not given, app should not be able to access media. **Actual behaviour**

Related information:

Behaviour of app using file. getImages

johohberg commented 3 years ago

This bug also occurs for older iOS version. It was found for iOS 14.6 and iOS 14.8.

soemo commented 3 years ago

Hello @antoinevg ,

can you please have a look into it. 🙏🏼

frrob commented 3 years ago

Hi @antoinevg, Sorry, that I'm pinging you again here, but we would highly appreciate your input. We see this as a pressing topic that is currently blocking the release of our apps.

Thanks a lot!

Best, Robert

antoinevg commented 3 years ago

Apple did a major overhaul to their image privacy with the last iOS 14 release. To conform we had to switch to their PHPicker image selector control.

Now here's the thing about PHPicker:

  1. It runs out of process, so an app no longer interfaces with it in the same address space.
  2. This means PHPicker no longer needs to ask for permission as it only returns access to the selected photo now, and not the entire use photo gallery.
  3. There may still be instances where you will be prompted for permissions if you're saving to to the photo gallery.

More info: https://developer.apple.com/forums/thread/652819

re: Camera permissions - still works for me. Make sure to delete your app and reboot the phone before testing.

hborjaille commented 3 years ago

@antoinevg I agree with you on PHPicker, but this only should happen for iOS 14+. We should still use UIImagePickerController for earlier versions and we tested on iOS 12 to 13.6 and the permission request views is also not being displayed in any of these, which is the wrong behaviour.

johohberg commented 3 years ago

Only for clarification the Foto capture will not work for iOS 13 and below. I could open the gallery but the photo is not shown in the app in the end. Screenshot 2021-10-06 at 16 15 33

antoinevg commented 3 years ago

We do fall back to UIImagePickerController on older iOS versions:

https://github.com/trigger-corp/trigger.io-file/blob/0f6a60f05e95ecc736a72e7d1d0dac3e9886a28e/inspector/ios-inspector/ForgeModule/file/file_API.m#L25-L35

That said, unless Apple has changed the behavior in an update, UIImagePickerController should still be asking for permissions automatically.

Although again, I seem to recall that at some point UIImagePickerController also switched to running out of process and stopped needing permissions.

Unfortunately I don't have anything on this side that can still run iOS < 14 so I can't check this for you.

Either way, this used to work fine so Apple probably changed something in an update and we'll need to figure out a workaround.

I hope to have a chance to dig deeper early-ish next week.


ps.

If you're feeling brave in the meantime you can try requesting permissions manually and seeing if that fixes things for you. Maybe something like the following in file_API.m:

+ (void)getImages:(ForgeTask*)task {
    int selectionLimit = task.params[@"selectionLimit"] ? [task.params[@"selectionLimit"] intValue] : 1;

    if (@available(iOS 14, *)) {
        [PHPhotoLibrary requestAuthorizationForAccessLevel:PHAccessLevelReadWrite handler:^(PHAuthorizationStatus status) {
            if (status != PHAuthorizationStatusAuthorized) {
                [task error:@"Permission denied. User didn't grant access to storage." type:@"EXPECTED_FAILURE" subtype:nil];
                return;
            }

            PHPickerConfiguration *configuration = [[PHPickerConfiguration alloc] initWithPhotoLibrary:PHPhotoLibrary.sharedPhotoLibrary];
            configuration.selectionLimit = selectionLimit;
            configuration.filter = PHPickerFilter.imagesFilter;
            configuration.preferredAssetRepresentationMode = PHPickerConfigurationAssetRepresentationModeCompatible;
            file_PHPickerDelegate *delegate = [file_PHPickerDelegate withTask:task configuration:configuration];
            [delegate openPicker];
        }];

    } else {
        [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
            if (status != PHAuthorizationStatusAuthorized) {
                [task error:@"Permission denied. User didn't grant access to storage." type:@"EXPECTED_FAILURE" subtype:nil];
                return;
            }
            file_Delegate_deprecated *delegate = [file_Delegate_deprecated withTask:task type:(NSString*)kUTTypeImage];
            [delegate openPicker];
        }];
    }
}
antoinevg commented 2 years ago

I've just published version 2.28 of the file module.

Can you please try updating your config.json and let me know if this sorts out the issue?

Thanks!