From bd55a099638a6e0cdaa0099ed0e303e9f55451c8 Mon Sep 17 00:00:00 2001 From: Maksym Malyhin Date: Wed, 27 Feb 2019 18:31:44 -0500 Subject: [PATCH 01/11] FIRStorageUploadTask: validate data and fileURL before upload (#2350) --- .../Tests/Unit/FIRStorageReferenceTests.m | 19 +++++++ Firebase/Storage/FIRStorageUploadTask.m | 49 ++++++++++++++++--- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m b/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m index 767b9f72783..43a397b5740 100644 --- a/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m +++ b/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m @@ -162,4 +162,23 @@ - (void)testCopy { XCTAssertNotEqual(ref, copiedRef); } +- (void)test_GivenReferenceWithPath_WhenPutNonExistingFile_ThenCompletionIsCalledWithError { + NSString *tempFilePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"temp.data"]; + FIRStorageReference *ref = [self.storage referenceWithPath:tempFilePath]; + + NSURL *dummyFileURL = [NSURL fileURLWithPath:@"some_non_existing-folder/file.data"]; + + XCTestExpectation *expectation = [self expectationWithDescription:@"completionExpectation"]; + + [ref putFile:dummyFileURL + metadata:nil + completion:^(FIRStorageMetadata * _Nullable metadata, NSError * _Nullable error) { + [expectation fulfill]; + XCTAssertNotNil(error); + XCTAssertNil(metadata); + }]; + + [self waitForExpectationsWithTimeout:0.5 handler:NULL]; +} + @end diff --git a/Firebase/Storage/FIRStorageUploadTask.m b/Firebase/Storage/FIRStorageUploadTask.m index 0324974a52f..dcc95c8ad26 100644 --- a/Firebase/Storage/FIRStorageUploadTask.m +++ b/Firebase/Storage/FIRStorageUploadTask.m @@ -72,6 +72,13 @@ - (void)dealloc { - (void)enqueue { __weak FIRStorageUploadTask *weakSelf = self; + NSError *contentValidationError; + if (![self isContentToUploadValid:&contentValidationError]) { + self.error = contentValidationError; + [self finishTaskWithStatus:FIRStorageTaskStatusFailure snapshot:self.snapshot]; + return; + } + [self dispatchAsync:^() { FIRStorageUploadTask *strongSelf = weakSelf; @@ -113,6 +120,10 @@ - (void)enqueue { [uploadFetcher setUploadData:strongSelf->_uploadData]; uploadFetcher.comment = @"Data UploadTask"; } else if (strongSelf->_fileURL) { + NSError *fileReachabilityError; + if (![strongSelf->_fileURL checkResourceIsReachableAndReturnError:&fileReachabilityError]) { + + } [uploadFetcher setUploadFileURL:strongSelf->_fileURL]; uploadFetcher.comment = @"File UploadTask"; } @@ -145,9 +156,8 @@ - (void)enqueue { self.state = FIRStorageTaskStateFailed; self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference]; self.metadata = self->_uploadMetadata; - [self fireHandlersForStatus:FIRStorageTaskStatusFailure snapshot:self.snapshot]; - [self removeAllObservers]; - self->_fetcherCompletion = nil; + + [self finishTaskWithStatus:FIRStorageTaskStatusFailure snapshot:self.snapshot]; return; } @@ -164,9 +174,7 @@ - (void)enqueue { self.error = [FIRStorageErrors errorWithInvalidRequest:data]; } - [self fireHandlersForStatus:FIRStorageTaskStatusSuccess snapshot:self.snapshot]; - [self removeAllObservers]; - self->_fetcherCompletion = nil; + [self finishTaskWithStatus:FIRStorageTaskStatusSuccess snapshot:self.snapshot]; }; #pragma clang diagnostic pop @@ -177,6 +185,35 @@ - (void)enqueue { }]; } +- (void)finishTaskWithStatus:(FIRStorageTaskStatus)status + snapshot:(FIRStorageTaskSnapshot *)snapshot { + [self fireHandlersForStatus:status snapshot:self.snapshot]; + [self removeAllObservers]; + self->_fetcherCompletion = nil; +} + +- (BOOL)isContentToUploadValid:(NSError **)outError { + if (_uploadData != nil) { + return YES; + } + + NSError *fileReachabilityError; + if (![_fileURL checkResourceIsReachableAndReturnError:&fileReachabilityError]) { + if (outError != NULL) { + *outError = [NSError errorWithDomain:FIRStorageErrorDomain + code:FIRStorageErrorCodeUnknown + userInfo:@ { + NSUnderlyingErrorKey: fileReachabilityError, + NSLocalizedDescriptionKey: @"File is not available" + }]; + } + + return NO; + } + + return YES; +} + #pragma mark - Upload Management - (void)cancel { From ef986b98345fc5f27a4a08dbd26bb6d84aaf16be Mon Sep 17 00:00:00 2001 From: Maksym Malyhin Date: Wed, 27 Feb 2019 18:35:42 -0500 Subject: [PATCH 02/11] FIRStorageReferenceTests: Verify a specific error (#2350) --- Example/Storage/Tests/Unit/FIRStorageReferenceTests.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m b/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m index 43a397b5740..d81478c22c5 100644 --- a/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m +++ b/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m @@ -176,6 +176,10 @@ - (void)test_GivenReferenceWithPath_WhenPutNonExistingFile_ThenCompletionIsCalle [expectation fulfill]; XCTAssertNotNil(error); XCTAssertNil(metadata); + + XCTAssertEqualObjects(error.domain, FIRStorageErrorDomain); + XCTAssertEqual(error.code, FIRStorageErrorCodeUnknown); + XCTAssertEqualObjects(error.localizedDescription, @"File is not available"); }]; [self waitForExpectationsWithTimeout:0.5 handler:NULL]; From 0f11535992ed91d2746a47d2bba3a24531e974d9 Mon Sep 17 00:00:00 2001 From: Maksym Malyhin Date: Thu, 28 Feb 2019 09:54:51 -0500 Subject: [PATCH 03/11] Code cleanup. More informative error. --- Firebase/Storage/FIRStorageUploadTask.m | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Firebase/Storage/FIRStorageUploadTask.m b/Firebase/Storage/FIRStorageUploadTask.m index dcc95c8ad26..e3c32befbe4 100644 --- a/Firebase/Storage/FIRStorageUploadTask.m +++ b/Firebase/Storage/FIRStorageUploadTask.m @@ -120,10 +120,6 @@ - (void)enqueue { [uploadFetcher setUploadData:strongSelf->_uploadData]; uploadFetcher.comment = @"Data UploadTask"; } else if (strongSelf->_fileURL) { - NSError *fileReachabilityError; - if (![strongSelf->_fileURL checkResourceIsReachableAndReturnError:&fileReachabilityError]) { - - } [uploadFetcher setUploadFileURL:strongSelf->_fileURL]; uploadFetcher.comment = @"File UploadTask"; } @@ -200,11 +196,13 @@ - (BOOL)isContentToUploadValid:(NSError **)outError { NSError *fileReachabilityError; if (![_fileURL checkResourceIsReachableAndReturnError:&fileReachabilityError]) { if (outError != NULL) { + NSString *description = + [NSString stringWithFormat:@"File at URL: %@ is not reachable", _fileURL]; *outError = [NSError errorWithDomain:FIRStorageErrorDomain code:FIRStorageErrorCodeUnknown userInfo:@ { NSUnderlyingErrorKey: fileReachabilityError, - NSLocalizedDescriptionKey: @"File is not available" + NSLocalizedDescriptionKey: description }]; } From 92bca47ffdc85f6660ce37cb5f5b64317397418b Mon Sep 17 00:00:00 2001 From: Maksym Malyhin Date: Thu, 28 Feb 2019 10:01:33 -0500 Subject: [PATCH 04/11] FIRStorageReference: error message, test fix (#2350) --- Example/Storage/Tests/Unit/FIRStorageReferenceTests.m | 3 ++- Firebase/Storage/FIRStorageUploadTask.m | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m b/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m index d81478c22c5..847b7fa3fe9 100644 --- a/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m +++ b/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m @@ -179,7 +179,8 @@ - (void)test_GivenReferenceWithPath_WhenPutNonExistingFile_ThenCompletionIsCalle XCTAssertEqualObjects(error.domain, FIRStorageErrorDomain); XCTAssertEqual(error.code, FIRStorageErrorCodeUnknown); - XCTAssertEqualObjects(error.localizedDescription, @"File is not available"); + XCTAssertEqualObjects(error.localizedDescription, + @"File at URL: file:///some_non_existing-folder/file.data is not reachable"); }]; [self waitForExpectationsWithTimeout:0.5 handler:NULL]; diff --git a/Firebase/Storage/FIRStorageUploadTask.m b/Firebase/Storage/FIRStorageUploadTask.m index e3c32befbe4..e8fc74e9b47 100644 --- a/Firebase/Storage/FIRStorageUploadTask.m +++ b/Firebase/Storage/FIRStorageUploadTask.m @@ -197,7 +197,7 @@ - (BOOL)isContentToUploadValid:(NSError **)outError { if (![_fileURL checkResourceIsReachableAndReturnError:&fileReachabilityError]) { if (outError != NULL) { NSString *description = - [NSString stringWithFormat:@"File at URL: %@ is not reachable", _fileURL]; + [NSString stringWithFormat:@"File at URL: %@ is not reachable", _fileURL.absoluteString]; *outError = [NSError errorWithDomain:FIRStorageErrorDomain code:FIRStorageErrorCodeUnknown userInfo:@ { From fc70bdb50b007950c8c5a817b13283816795f660 Mon Sep 17 00:00:00 2001 From: Maksym Malyhin Date: Thu, 28 Feb 2019 10:57:17 -0500 Subject: [PATCH 05/11] Run ./scripts/style.sh --- .../Tests/Unit/FIRStorageReferenceTests.m | 23 ++++++++++--------- Firebase/Storage/FIRStorageUploadTask.m | 8 +++---- Firestore/Source/Local/FSTLocalStore.mm | 7 +++--- .../firebase/firestore/model/field_value.cc | 6 +++-- 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m b/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m index 847b7fa3fe9..7a804fb5a58 100644 --- a/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m +++ b/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m @@ -171,17 +171,18 @@ - (void)test_GivenReferenceWithPath_WhenPutNonExistingFile_ThenCompletionIsCalle XCTestExpectation *expectation = [self expectationWithDescription:@"completionExpectation"]; [ref putFile:dummyFileURL - metadata:nil - completion:^(FIRStorageMetadata * _Nullable metadata, NSError * _Nullable error) { - [expectation fulfill]; - XCTAssertNotNil(error); - XCTAssertNil(metadata); - - XCTAssertEqualObjects(error.domain, FIRStorageErrorDomain); - XCTAssertEqual(error.code, FIRStorageErrorCodeUnknown); - XCTAssertEqualObjects(error.localizedDescription, - @"File at URL: file:///some_non_existing-folder/file.data is not reachable"); - }]; + metadata:nil + completion:^(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error) { + [expectation fulfill]; + XCTAssertNotNil(error); + XCTAssertNil(metadata); + + XCTAssertEqualObjects(error.domain, FIRStorageErrorDomain); + XCTAssertEqual(error.code, FIRStorageErrorCodeUnknown); + XCTAssertEqualObjects( + error.localizedDescription, + @"File at URL: file:///some_non_existing-folder/file.data is not reachable"); + }]; [self waitForExpectationsWithTimeout:0.5 handler:NULL]; } diff --git a/Firebase/Storage/FIRStorageUploadTask.m b/Firebase/Storage/FIRStorageUploadTask.m index e8fc74e9b47..55f41d262a4 100644 --- a/Firebase/Storage/FIRStorageUploadTask.m +++ b/Firebase/Storage/FIRStorageUploadTask.m @@ -197,12 +197,12 @@ - (BOOL)isContentToUploadValid:(NSError **)outError { if (![_fileURL checkResourceIsReachableAndReturnError:&fileReachabilityError]) { if (outError != NULL) { NSString *description = - [NSString stringWithFormat:@"File at URL: %@ is not reachable", _fileURL.absoluteString]; + [NSString stringWithFormat:@"File at URL: %@ is not reachable", _fileURL.absoluteString]; *outError = [NSError errorWithDomain:FIRStorageErrorDomain code:FIRStorageErrorCodeUnknown - userInfo:@ { - NSUnderlyingErrorKey: fileReachabilityError, - NSLocalizedDescriptionKey: description + userInfo:@{ + NSUnderlyingErrorKey : fileReachabilityError, + NSLocalizedDescriptionKey : description }]; } diff --git a/Firestore/Source/Local/FSTLocalStore.mm b/Firestore/Source/Local/FSTLocalStore.mm index eabe3c58080..c2d02d229bd 100644 --- a/Firestore/Source/Local/FSTLocalStore.mm +++ b/Firestore/Source/Local/FSTLocalStore.mm @@ -376,9 +376,10 @@ - (nullable FSTMutationBatch *)nextMutationBatchAfterBatchID:(BatchId)batchID { } - (nullable FSTMaybeDocument *)readDocument:(const DocumentKey &)key { - return self.persistence.run("ReadDocument", [&]() -> FSTMaybeDocument *_Nullable { - return [self.localDocuments documentForKey:key]; - }); + return self.persistence.run( + "ReadDocument", [&]() -> FSTMaybeDocument *_Nullable { + return [self.localDocuments documentForKey:key]; + }); } - (FSTQueryData *)allocateQuery:(FSTQuery *)query { diff --git a/Firestore/core/src/firebase/firestore/model/field_value.cc b/Firestore/core/src/firebase/firestore/model/field_value.cc index 37acaf485ad..84e049f6594 100644 --- a/Firestore/core/src/firebase/firestore/model/field_value.cc +++ b/Firestore/core/src/firebase/firestore/model/field_value.cc @@ -468,7 +468,8 @@ void FieldValue::SwitchTo(const Type type) { case Type::Object: object_value_.~unique_ptr(); break; - default: {} // The other types where there is nothing to worry about. + default: { + } // The other types where there is nothing to worry about. } tag_ = type; // Must call constructor explicitly for any non-POD type to initialize. @@ -506,7 +507,8 @@ void FieldValue::SwitchTo(const Type type) { new (&object_value_) std::unique_ptr(absl::make_unique()); break; - default: {} // The other types where there is nothing to worry about. + default: { + } // The other types where there is nothing to worry about. } } From 5009de3e64e21e7f69f7b7e013b6273663c9aa3e Mon Sep 17 00:00:00 2001 From: Maksym Malyhin Date: Thu, 28 Feb 2019 11:17:24 -0500 Subject: [PATCH 06/11] #2350: Punctuation --- Firebase/Storage/FIRStorageUploadTask.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firebase/Storage/FIRStorageUploadTask.m b/Firebase/Storage/FIRStorageUploadTask.m index 55f41d262a4..0d8d370f1d0 100644 --- a/Firebase/Storage/FIRStorageUploadTask.m +++ b/Firebase/Storage/FIRStorageUploadTask.m @@ -197,7 +197,7 @@ - (BOOL)isContentToUploadValid:(NSError **)outError { if (![_fileURL checkResourceIsReachableAndReturnError:&fileReachabilityError]) { if (outError != NULL) { NSString *description = - [NSString stringWithFormat:@"File at URL: %@ is not reachable", _fileURL.absoluteString]; + [NSString stringWithFormat:@"File at URL: %@ is not reachable.", _fileURL.absoluteString]; *outError = [NSError errorWithDomain:FIRStorageErrorDomain code:FIRStorageErrorCodeUnknown userInfo:@{ From 6a731aebe4b5804109264c0331965c4e7e742c50 Mon Sep 17 00:00:00 2001 From: Maksym Malyhin Date: Thu, 28 Feb 2019 11:20:38 -0500 Subject: [PATCH 07/11] FIRStorageReferenceTests: naming (#2350) --- Example/Storage/Tests/Unit/FIRStorageReferenceTests.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m b/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m index 7a804fb5a58..028962e4231 100644 --- a/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m +++ b/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m @@ -162,7 +162,7 @@ - (void)testCopy { XCTAssertNotEqual(ref, copiedRef); } -- (void)test_GivenReferenceWithPath_WhenPutNonExistingFile_ThenCompletionIsCalledWithError { +- (void)testReferenceWithNonExistentFileFailsWithCompletion { NSString *tempFilePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"temp.data"]; FIRStorageReference *ref = [self.storage referenceWithPath:tempFilePath]; From c335c43795126965d640b24be20e447f0cf88b75 Mon Sep 17 00:00:00 2001 From: Maksym Malyhin Date: Thu, 28 Feb 2019 11:43:23 -0500 Subject: [PATCH 08/11] Run ./scripts/style.sh --- Firestore/Source/Local/FSTLocalStore.mm | 7 +++---- Firestore/core/src/firebase/firestore/model/field_value.cc | 6 ++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Firestore/Source/Local/FSTLocalStore.mm b/Firestore/Source/Local/FSTLocalStore.mm index c2d02d229bd..eabe3c58080 100644 --- a/Firestore/Source/Local/FSTLocalStore.mm +++ b/Firestore/Source/Local/FSTLocalStore.mm @@ -376,10 +376,9 @@ - (nullable FSTMutationBatch *)nextMutationBatchAfterBatchID:(BatchId)batchID { } - (nullable FSTMaybeDocument *)readDocument:(const DocumentKey &)key { - return self.persistence.run( - "ReadDocument", [&]() -> FSTMaybeDocument *_Nullable { - return [self.localDocuments documentForKey:key]; - }); + return self.persistence.run("ReadDocument", [&]() -> FSTMaybeDocument *_Nullable { + return [self.localDocuments documentForKey:key]; + }); } - (FSTQueryData *)allocateQuery:(FSTQuery *)query { diff --git a/Firestore/core/src/firebase/firestore/model/field_value.cc b/Firestore/core/src/firebase/firestore/model/field_value.cc index 84e049f6594..37acaf485ad 100644 --- a/Firestore/core/src/firebase/firestore/model/field_value.cc +++ b/Firestore/core/src/firebase/firestore/model/field_value.cc @@ -468,8 +468,7 @@ void FieldValue::SwitchTo(const Type type) { case Type::Object: object_value_.~unique_ptr(); break; - default: { - } // The other types where there is nothing to worry about. + default: {} // The other types where there is nothing to worry about. } tag_ = type; // Must call constructor explicitly for any non-POD type to initialize. @@ -507,8 +506,7 @@ void FieldValue::SwitchTo(const Type type) { new (&object_value_) std::unique_ptr(absl::make_unique()); break; - default: { - } // The other types where there is nothing to worry about. + default: {} // The other types where there is nothing to worry about. } } From 3dbf22c2a7a6e3e9bc643772b7e644a70e2e2c8a Mon Sep 17 00:00:00 2001 From: Maksym Malyhin Date: Thu, 28 Feb 2019 13:17:15 -0500 Subject: [PATCH 09/11] Tests fixed (#2350) --- Example/Storage/Tests/Unit/FIRStorageReferenceTests.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m b/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m index 028962e4231..6c4a7fb04ed 100644 --- a/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m +++ b/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m @@ -181,7 +181,7 @@ - (void)testReferenceWithNonExistentFileFailsWithCompletion { XCTAssertEqual(error.code, FIRStorageErrorCodeUnknown); XCTAssertEqualObjects( error.localizedDescription, - @"File at URL: file:///some_non_existing-folder/file.data is not reachable"); + @"File at URL: file:///some_non_existing-folder/file.data is not reachable."); }]; [self waitForExpectationsWithTimeout:0.5 handler:NULL]; From 1155787cc4254aa3665635c36d174ba6d7f01b4c Mon Sep 17 00:00:00 2001 From: Maksym Malyhin Date: Thu, 28 Feb 2019 17:16:48 -0500 Subject: [PATCH 10/11] FIRStorageReferenceTests fixed for Mac OS (#2350) --- Example/Storage/Tests/Unit/FIRStorageReferenceTests.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m b/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m index 6c4a7fb04ed..2bec6d59332 100644 --- a/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m +++ b/Example/Storage/Tests/Unit/FIRStorageReferenceTests.m @@ -179,9 +179,9 @@ - (void)testReferenceWithNonExistentFileFailsWithCompletion { XCTAssertEqualObjects(error.domain, FIRStorageErrorDomain); XCTAssertEqual(error.code, FIRStorageErrorCodeUnknown); - XCTAssertEqualObjects( - error.localizedDescription, - @"File at URL: file:///some_non_existing-folder/file.data is not reachable."); + NSString *expectedDescription = [NSString + stringWithFormat:@"File at URL: %@ is not reachable.", dummyFileURL.absoluteString]; + XCTAssertEqualObjects(error.localizedDescription, expectedDescription); }]; [self waitForExpectationsWithTimeout:0.5 handler:NULL]; From d376ee1a49282e487051d0f476a0091658d17042 Mon Sep 17 00:00:00 2001 From: Maksym Malyhin Date: Sun, 3 Mar 2019 15:47:45 -0500 Subject: [PATCH 11/11] FIRStorageUploadTask: validate content just before uploading (#2350) --- Firebase/Storage/FIRStorageUploadTask.m | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Firebase/Storage/FIRStorageUploadTask.m b/Firebase/Storage/FIRStorageUploadTask.m index 0d8d370f1d0..0aba3ab431b 100644 --- a/Firebase/Storage/FIRStorageUploadTask.m +++ b/Firebase/Storage/FIRStorageUploadTask.m @@ -72,13 +72,6 @@ - (void)dealloc { - (void)enqueue { __weak FIRStorageUploadTask *weakSelf = self; - NSError *contentValidationError; - if (![self isContentToUploadValid:&contentValidationError]) { - self.error = contentValidationError; - [self finishTaskWithStatus:FIRStorageTaskStatusFailure snapshot:self.snapshot]; - return; - } - [self dispatchAsync:^() { FIRStorageUploadTask *strongSelf = weakSelf; @@ -86,6 +79,13 @@ - (void)enqueue { return; } + NSError *contentValidationError; + if (![strongSelf isContentToUploadValid:&contentValidationError]) { + strongSelf.error = contentValidationError; + [strongSelf finishTaskWithStatus:FIRStorageTaskStatusFailure snapshot:strongSelf.snapshot]; + return; + } + strongSelf.state = FIRStorageTaskStateQueueing; NSMutableURLRequest *request = [strongSelf.baseRequest mutableCopy];