| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- /*
- * Copyright 2017 Google
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #import <TargetConditionals.h>
- #if TARGET_OS_IOS || TARGET_OS_TV || (defined(TARGET_OS_VISION) && TARGET_OS_VISION)
- #import "FirebaseCore/Extension/FirebaseCoreInternal.h"
- #import "FirebaseInAppMessaging/Sources/FIRCore+InAppMessaging.h"
- #import "FirebaseInAppMessaging/Sources/Private/Data/FIRIAMMessageContentData.h"
- #import "FirebaseInAppMessaging/Sources/Private/Data/FIRIAMMessageContentDataWithImageURL.h"
- #import "FirebaseInAppMessaging/Sources/Runtime/FIRIAMSDKRuntimeErrorCodes.h"
- static NSInteger const SuccessHTTPStatusCode = 200;
- @interface FIRIAMMessageContentDataWithImageURL ()
- @property(nonatomic, readwrite, nullable, copy) NSString *titleText;
- @property(nonatomic, readwrite, nonnull, copy) NSString *bodyText;
- @property(nonatomic, copy, nullable) NSString *actionButtonText;
- @property(nonatomic, copy, nullable) NSString *secondaryActionButtonText;
- @property(nonatomic, copy, nullable) NSURL *actionURL;
- @property(nonatomic, copy, nullable) NSURL *secondaryActionURL;
- @property(nonatomic, nullable, copy) NSURL *imageURL;
- @property(nonatomic, nullable, copy) NSURL *landscapeImageURL;
- @property(readonly) NSURLSession *URLSession;
- @end
- @implementation FIRIAMMessageContentDataWithImageURL
- - (instancetype)initWithMessageTitle:(nullable NSString *)title
- messageBody:(nullable NSString *)body
- actionButtonText:(nullable NSString *)actionButtonText
- secondaryActionButtonText:(nullable NSString *)secondaryActionButtonText
- actionURL:(nullable NSURL *)actionURL
- secondaryActionURL:(nullable NSURL *)secondaryActionURL
- imageURL:(nullable NSURL *)imageURL
- landscapeImageURL:(nullable NSURL *)landscapeImageURL
- usingURLSession:(nullable NSURLSession *)URLSession {
- if (self = [super init]) {
- _titleText = title;
- _bodyText = body;
- _imageURL = imageURL;
- _landscapeImageURL = landscapeImageURL;
- _actionButtonText = actionButtonText;
- _secondaryActionButtonText = secondaryActionButtonText;
- _actionURL = actionURL;
- _secondaryActionURL = secondaryActionURL;
- if (imageURL) {
- _URLSession = URLSession ? URLSession : [NSURLSession sharedSession];
- }
- }
- return self;
- }
- #pragma protocol FIRIAMMessageContentData
- - (NSString *)description {
- return [NSString stringWithFormat:@"Message content: title '%@',"
- "body '%@', imageURL '%@', action URL '%@'",
- self.titleText, self.bodyText, self.imageURL, self.actionURL];
- }
- - (NSString *)getTitleText {
- return _titleText;
- }
- - (NSString *)getBodyText {
- return _bodyText;
- }
- - (nullable NSString *)getActionButtonText {
- return _actionButtonText;
- }
- - (void)loadImageDataWithBlock:(void (^)(NSData *_Nullable standardImageData,
- NSData *_Nullable landscapeImageData,
- NSError *_Nullable error))block {
- if (!block) {
- // no need for any further action if block is nil
- return;
- }
- if (!_imageURL && !_landscapeImageURL) {
- // no image data since image url is nil
- block(nil, nil, nil);
- } else if (!_landscapeImageURL) {
- // Only fetch standard image.
- [self fetchImageFromURL:_imageURL
- withBlock:^(NSData *_Nullable imageData, NSError *_Nullable error) {
- block(imageData, nil, error);
- }];
- } else if (!_imageURL) {
- // Only fetch portrait image.
- [self fetchImageFromURL:_landscapeImageURL
- withBlock:^(NSData *_Nullable imageData, NSError *_Nullable error) {
- block(nil, imageData, error);
- }];
- } else {
- // Fetch both images separately, call completion when they're both fetched.
- __block NSData *portrait = nil;
- __block NSData *landscape = nil;
- __block NSError *landscapeImageLoadError = nil;
- [self fetchImageFromURL:_imageURL
- withBlock:^(NSData *_Nullable imageData, NSError *_Nullable error) {
- __weak FIRIAMMessageContentDataWithImageURL *weakSelf = self;
- // If the portrait image fails to load, we treat this as a failure.
- if (error) {
- // Cancel landscape image fetch.
- [weakSelf.URLSession invalidateAndCancel];
- block(nil, nil, error);
- return;
- }
- portrait = imageData;
- if (landscape || landscapeImageLoadError) {
- block(portrait, landscape, nil);
- }
- }];
- [self fetchImageFromURL:_landscapeImageURL
- withBlock:^(NSData *_Nullable imageData, NSError *_Nullable error) {
- if (error) {
- landscapeImageLoadError = error;
- } else {
- landscape = imageData;
- }
- if (portrait) {
- block(portrait, landscape, nil);
- }
- }];
- }
- }
- - (void)fetchImageFromURL:(NSURL *)imageURL
- withBlock:(void (^)(NSData *_Nullable imageData, NSError *_Nullable error))block {
- NSURLRequest *imageDataRequest = [NSURLRequest requestWithURL:imageURL];
- NSURLSessionDataTask *task = [_URLSession
- dataTaskWithRequest:imageDataRequest
- completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
- if (error) {
- FIRLogWarning(kFIRLoggerInAppMessaging, @"I-IAM000003", @"Error in fetching image: %@",
- error);
- block(nil, error);
- } else {
- if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
- NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
- if (httpResponse.statusCode == SuccessHTTPStatusCode) {
- if (httpResponse.MIMEType == nil || ![httpResponse.MIMEType hasPrefix:@"image"]) {
- NSString *errorDesc =
- [NSString stringWithFormat:@"No image MIME type %@"
- " detected for URL %@",
- httpResponse.MIMEType, self.imageURL];
- FIRLogWarning(kFIRLoggerInAppMessaging, @"I-IAM000004", @"%@", errorDesc);
- NSError *error =
- [NSError errorWithDomain:kFirebaseInAppMessagingErrorDomain
- code:FIRIAMSDKRuntimeErrorNonImageMimetypeFromImageURL
- userInfo:@{NSLocalizedDescriptionKey : errorDesc}];
- block(nil, error);
- } else {
- block(data, nil);
- }
- } else {
- NSString *errorDesc =
- [NSString stringWithFormat:@"Failed HTTP request to crawl image %@: "
- "HTTP status code as %ld",
- self->_imageURL, (long)httpResponse.statusCode];
- FIRLogWarning(kFIRLoggerInAppMessaging, @"I-IAM000001", @"%@", errorDesc);
- NSError *error = [NSError errorWithDomain:NSURLErrorDomain
- code:httpResponse.statusCode
- userInfo:@{NSLocalizedDescriptionKey : errorDesc}];
- block(nil, error);
- }
- } else {
- NSString *errorDesc =
- [NSString stringWithFormat:@"Internal error: got a non HTTP response from "
- @"fetching image for image URL as %@",
- imageURL];
- FIRLogWarning(kFIRLoggerInAppMessaging, @"I-IAM000002", @"%@", errorDesc);
- NSError *error = [NSError errorWithDomain:NSURLErrorDomain
- code:FIRIAMSDKRuntimeErrorNonHTTPResponseForImage
- userInfo:@{NSLocalizedDescriptionKey : errorDesc}];
- block(nil, error);
- }
- }
- }];
- [task resume];
- }
- @end
- #endif // TARGET_OS_IOS || TARGET_OS_TV || (defined(TARGET_OS_VISION) && TARGET_OS_VISION)
|