Skip to content

A few FirebaseStorage bugs on iOS SDK 10 #10374

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
russellwheatley opened this issue Oct 19, 2022 · 12 comments
Closed

A few FirebaseStorage bugs on iOS SDK 10 #10374

russellwheatley opened this issue Oct 19, 2022 · 12 comments

Comments

@russellwheatley
Copy link
Member

russellwheatley commented Oct 19, 2022

Description

I've created a repository with a full reproduction of the issues we experienced trying to integrate FlutterFire with iOS SDK 10. Please see issue reproduction details for the bugs we found. The downloadURL issue may actually be a problem with firebase-tools, not sure.

Reproducing the issue

Here's the repository which illustrates the issues: https://github.com/invertase/ios-sdk-10-issues

Ripped from the README.md of that repository:

To reproduce and what to expect:

  1. Clone repo and pod install. Open xcworkspace in Xcode.
  2. Run Storage emulator and allow all read/write operations in Storage rules.
  3. Run the app.
  4. downloadUrl method fails when using it in combination with the Storage emulator. Press the "downloadUrl emulator failure" button to see the error produced. The response includes a metadata object not stringified which I think is the problem. Comment out the emulator initialization and run app again to see a successful response. It does not contain a
    metadata object.
  5. putFile method fails when there is no "path" property in metadata. Press the "putFile failure" button to see this error: "Fatal error: Internal error enqueueing a Storage task". It's because path does not exist on metadata which is a read only property. It can be worked around using intializeWithDictionary and adding "name" property as it puts "name" on "path" property here
  6. updateMetadata method fails to update customMetadata when you initialise metadata with initWithDictionary. Press the "updateMetadata failure" button to see response does not include updated custom metadata (i.e. "foo":"bar" in this example). If you comment out the way FIRStorageMetadata is initialised here and uncomment here, you will see custom metadata in response.

I have more detailed notes on the PR that landed for FlutterFire here

Firebase SDK Version

10.0.0

Xcode Version

14.0.1

Installation Method

CocoaPods

Firebase Product(s)

Storage

Targeted Platforms

iOS

Relevant Log Output

No response

If using Swift Package Manager, the project's Package.resolved

Expand Package.resolved snippet
Replace this line with the contents of your Package.resolved.

If using CocoaPods, the project's Podfile.lock

Expand Podfile.lock snippet
PODS:
  - FirebaseAppCheckInterop (10.0.0)
  - FirebaseAuthInterop (10.0.0)
  - FirebaseCore (10.0.0):
    - FirebaseCoreInternal (~> 10.0)
    - GoogleUtilities/Environment (~> 7.8)
    - GoogleUtilities/Logger (~> 7.8)
  - FirebaseCoreExtension (10.0.0):
    - FirebaseCore (~> 10.0)
  - FirebaseCoreInternal (10.0.0):
    - "GoogleUtilities/NSData+zlib (~> 7.8)"
  - FirebaseStorage (10.0.0):
    - FirebaseAppCheckInterop (~> 10.0)
    - FirebaseAuthInterop (~> 10.0)
    - FirebaseCore (~> 10.0)
    - FirebaseCoreExtension (~> 10.0)
    - GTMSessionFetcher/Core (~> 2.1)
  - GoogleUtilities/Environment (7.8.0):
    - PromisesObjC (< 3.0, >= 1.2)
  - GoogleUtilities/Logger (7.8.0):
    - GoogleUtilities/Environment
  - "GoogleUtilities/NSData+zlib (7.8.0)"
  - GTMSessionFetcher/Core (2.1.0)
  - PromisesObjC (2.1.1)

DEPENDENCIES:
  - FirebaseCore
  - FirebaseStorage

SPEC REPOS:
  trunk:
    - FirebaseAppCheckInterop
    - FirebaseAuthInterop
    - FirebaseCore
    - FirebaseCoreExtension
    - FirebaseCoreInternal
    - FirebaseStorage
    - GoogleUtilities
    - GTMSessionFetcher
    - PromisesObjC

SPEC CHECKSUMS:
  FirebaseAppCheckInterop: 9a7af9d0a4d9197265cda30194f3644e8aea24f9
  FirebaseAuthInterop: c342679f45bee2a665a3b9148a55fcdb10df8c66
  FirebaseCore: 97f48a3a567a72b8d4daa0f03c3aadb78df4e995
  FirebaseCoreExtension: 449595a035812f16314ca88cebf959e3bb77dd67
  FirebaseCoreInternal: 5eb3960335da5ea30115d57d39db6988c4ad06f3
  FirebaseStorage: 8b0b0630e11b9f3e4a479a26cfccb70ec790ec50
  GoogleUtilities: 1d20a6ad97ef46f67bbdec158ce00563a671ebb7
  GTMSessionFetcher: ffbb25ec00ebcb5201adab0a56d808f6f1902d9f
  PromisesObjC: ab77feca74fa2823e7af4249b8326368e61014cb

PODFILE CHECKSUM: ceb067e068b541148ba09522826f60b3700a4865

COCOAPODS: 1.11.3

@russellwheatley russellwheatley changed the title A Few FirebaseStorage bugs on iOS SDK 10 A few FirebaseStorage bugs on iOS SDK 10 Oct 19, 2022
@mikehardy
Copy link
Contributor

mikehardy commented Oct 19, 2022

Just a note on item 4 - downloadURL - that was the focus of this PR #10370 - which itself was based on the learnings from @russellwheatley in the FlutterFire v10 integration and my carrying that over to react-native-firebase. 10370 would resolve it in this repo, otherwise there will need to be a PR+release in firebase-tools to resolve it. It also points out a need to perhaps run the test harness here against firebase emulator as a matrix entry if possible, as there are a few gaps like this and they will come and go I'm sure.

Also my comment here serves as a subscription, as I collaborated so much with @paulb777 on the storage metadata stuff for firebase-ios-sdk v9 I'm curious if I have any additional changes in react-native-firebase related to this. I did have to do the name/path workaround for putFile as well, for what it's worth.

Cheers!

@paulb777
Copy link
Member

Thanks for the report. We'll investigate and fill in the gaps in our test coverage.

At first glance, #4 should be resolved by #10370, #5 is a duplicate of #10353 and should be resolved by #10356

@paulb777 paulb777 self-assigned this Oct 19, 2022
@paulb777 paulb777 added this to the 10.1.0 - M123 milestone Oct 19, 2022
@enriqueg
Copy link

enriqueg commented Oct 20, 2022

Number 5 happening to me, which value should I put with the "name" key"?

@russellwheatley
Copy link
Member Author

russellwheatley commented Oct 20, 2022

@enriqueg use this method to initialise metadata: https://github.com/firebase/flutterfire/blob/master/packages/firebase_storage/firebase_storage/ios/Classes/FLTFirebaseStoragePlugin.m#L803

add this property: https://github.com/firebase/flutterfire/blob/master/packages/firebase_storage/firebase_storage/ios/Classes/FLTFirebaseStoragePlugin.m#L776-L780

It's the full path to the object in your Storage bucket (e.g. "flutter-tests/image.jpg").

@enriqueg
Copy link

@russellwheatley Thanks so much, it seems to work! very much appreciated!!

andrewheard added a commit that referenced this issue Oct 20, 2022
…thDictionary

Debugging the issue updateMetadata method fails to update customMetadata when you initialise metadata with initWithDictionary. #10374
@paulb777
Copy link
Member

@russellwheatley Do you see number 6 as a regression in 10.0.0? Our testing is showing the same behavior in 8.x and 9.x.

@mikehardy
Copy link
Contributor

mikehardy commented Oct 20, 2022

I am pretty sure (or I hope anyway) that Russell is away from keyboard UK time, however - @russellwheatley you may find the work in react-native-firebase interesting, related to the custom metadata update:

invertase/react-native-firebase#6319 is the pull where I went through everything, there is some information in the description

This specific commit is the one where I altered the custom metadata style based on collaboration with Paul here - invertase/react-native-firebase@2dcb079

that implementation was only necessary I think after storage went swift in v9 of firebase-ios-sdk and is what prompted me to switch implementation style. The new style implemented in that commit needed no change to work with the new v10 release here

I made a corresponding to change to the android implementation so that all 3 platforms (web, apple, android) update customMetadata as a group, so the behavior is coherent cross platform: invertase/react-native-firebase@d602436

test rig to probe conformance, in case it's interesting (you know where these are in general but the link makes it quicker): https://github.com/invertase/react-native-firebase/blob/f2d1363b89fb046388f8336b08852c1ea0c285f2/packages/storage/e2e/StorageReference.e2e.js#L360-L479

@russellwheatley
Copy link
Member Author

Thanks, @mikehardy. Based on your PR notes here: invertase/react-native-firebase#6319. I think it might be worth adding more coverage for FlutterFire around setting/deleting metadata as I'm not sure we have the same implementation to cover the different behaviour across platforms.

@russellwheatley Do you see number 6 as a regression in 10.0.0? Our testing is showing the same behavior in 8.x and 9.x.

@paulb777 I think this implies that it isn't a regression but a bug that has been present for a number of releases.

I would expect my custom metadata to be updated using this implementation unless I'm missing something?

dictionary[@"metadata"] = @{@"foo" : @"bar"};
  FIRStorageMetadata *metadata = [[FIRStorageMetadata alloc] initWithDictionary:dictionary];
    
  FIRStorageReference *reference = [self createStorageRef:downloadUrlFile];
  [reference updateMetadata:metadata
                 completion:^(FIRStorageMetadata *updatedMetadata, NSError *error) {
                   if (error != nil) {
                     NSLog(@"ERROR: %@", error);
                   } else {
					// custom metadata is not updated "@{@"foo" : @"bar"}".
 					// It is removed in this line: https://github.com/firebase/firebase-ios-sdk/blob/master/FirebaseStorage/Sources/StorageMetadata.swift#L259
                     NSLog(@"SUCCESS: %@", updatedMetadata);
                   }
                 }];

It's not a deal breaker for FlutterFire either way as we reverted back to setting custom metadata the way we have done previously:

  FIRStorageMetadata *metadata =[[FIRStorageMetadata alloc] init];
  metadata.customMetadata = @{@"foo" : @"bar"};
  
  FIRStorageReference *reference = [self createStorageRef:downloadUrlFile];
  [reference updateMetadata:metadata
                 completion:^(FIRStorageMetadata *updatedMetadata, NSError *error) {
                   if (error != nil) {
                     NSLog(@"ERROR: %@", error);
                   } else {
					// custom metadata has been successfully updated and is present in: `updatedMetadata`
                     NSLog(@"SUCCESS: %@", updatedMetadata);
                   }
                 }];

@paulb777
Copy link
Member

@maneesht Will you comment on what should happen? The code looks like it goes out of its way to save the dictionary used to initialize the metadata when it's created via initWithDictionary and then to remove those values when the metadata is updated from the server.

@paulb777 paulb777 removed this from the 10.1.0 - M123 milestone Oct 21, 2022
@paulb777
Copy link
Member

Issues 4 and 5 should be addressed in 10.1.0. Issue 6 is still TBD.

@maneesht
Copy link
Contributor

After taking some time to look at this, it seems like initWithDictionary's initial use-case was to initialize data that was received by the server. And then, you mutate customMetadata instead of calling initWithDictionary and then updatedMetadata will call remove to do the diff between the two and send it to the server.

Since this can be confusing to users, it might be best to deprecate or thoroughly explain the usage of this method.

@paulb777
Copy link
Member

Going to close since most of this has been addressed. If #6 remains a concern, please open another issue.

@firebase firebase locked and limited conversation to collaborators Jun 28, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants