Merge branch 'charlesmchen/honorAttachmentFilenames'

This commit is contained in:
Matthew Chen 2017-04-13 16:10:00 -04:00
commit 3e7ecf335c
8 changed files with 106 additions and 62 deletions

View File

@ -138,7 +138,7 @@ CHECKOUT OPTIONS:
:commit: 7054e4b13ee5bcd6d524adb6dc9a726e8c466308
:git: https://github.com/WhisperSystems/JSQMessagesViewController.git
SignalServiceKit:
:commit: 173823e3adaf1ba5e7a3ab731c7d34f48be8cf3a
:commit: 238fd0d9f1b599a87e546240bc3d7ea58998a705
:git: https://github.com/WhisperSystems/SignalServiceKit.git
SocketRocket:
:commit: 877ac7438be3ad0b45ef5ca3969574e4b97112bf

View File

@ -22,7 +22,8 @@ class AttachmentApprovalViewController: UIViewController {
@available(*, unavailable, message:"use attachment: constructor instead.")
required init?(coder aDecoder: NSCoder) {
self.attachment = SignalAttachment.genericAttachment(data: nil,
dataUTI: kUTTypeContent as String)
dataUTI: kUTTypeContent as String,
filename:nil)
super.init(coder: aDecoder)
assertionFailure()
}

View File

@ -162,8 +162,8 @@ NS_ASSUME_NONNULL_BEGIN
+ (void)sendRandomAttachment:(TSThread *)thread
uti:(NSString *)uti {
OWSMessageSender *messageSender = [Environment getCurrent].messageSender;
SignalAttachment *attachment = [SignalAttachment genericAttachmentWithData:[self createRandomNSDataOfSize:256]
dataUTI:uti];
SignalAttachment *attachment =
[SignalAttachment genericAttachmentWithData:[self createRandomNSDataOfSize:256] dataUTI:uti filename:nil];
[ThreadUtil sendMessageWithAttachment:attachment
inThread:thread
messageSender:messageSender];

View File

@ -44,6 +44,7 @@
#import "UIViewController+CameraPermissions.h"
#import "UIViewController+OWS.h"
#import <AddressBookUI/AddressBookUI.h>
#import <AssetsLibrary/AssetsLibrary.h>
#import <ContactsUI/CNContactViewController.h>
#import <JSQMessagesViewController/JSQMessagesBubbleImage.h>
#import <JSQMessagesViewController/JSQMessagesBubbleImageFactory.h>
@ -2176,11 +2177,37 @@ typedef enum : NSUInteger {
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary<NSString *, id> *)info
{
OWSAssert([NSThread isMainThread]);
[UIUtil modalCompletionBlock]();
[self resetFrame];
NSURL *referenceURL = [info valueForKey:UIImagePickerControllerReferenceURL];
if (!referenceURL) {
DDLogVerbose(@"Could not retrieve reference URL for picked asset");
[self imagePickerController:picker didFinishPickingMediaWithInfo:info filename:nil];
return;
}
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *imageAsset) {
ALAssetRepresentation *imageRep = [imageAsset defaultRepresentation];
NSString *filename = [imageRep filename];
[self imagePickerController:picker didFinishPickingMediaWithInfo:info filename:filename];
};
ALAssetsLibrary *assetslibrary = [[ALAssetsLibrary alloc] init];
[assetslibrary assetForURL:referenceURL
resultBlock:resultblock
failureBlock:^(NSError *error) {
DDLogError(@"Error retrieving filename for asset: %@", error);
OWSAssert(0);
}];
}
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary<NSString *, id> *)info
filename:(NSString *)filename
{
OWSAssert([NSThread isMainThread]);
void (^failedToPickAttachment)(NSError *error) = ^void(NSError *error) {
DDLogError(@"failed to pick attachment with error: %@", error);
};
@ -2192,20 +2219,22 @@ typedef enum : NSUInteger {
NSURL *videoURL = info[UIImagePickerControllerMediaURL];
[self dismissViewControllerAnimated:YES
completion:^{
[self sendQualityAdjustedAttachmentForVideo:videoURL];
[self sendQualityAdjustedAttachmentForVideo:videoURL filename:filename];
}];
} else if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) {
// Static Image captured from camera
UIImage *imageFromCamera = [info[UIImagePickerControllerOriginalImage] normalizedImage];
[self dismissViewControllerAnimated:YES
completion:^{
OWSAssert([NSThread isMainThread]);
if (imageFromCamera) {
SignalAttachment *attachment = [SignalAttachment imageAttachmentWithImage:imageFromCamera
dataUTI:(NSString *) kUTTypeJPEG];
SignalAttachment *attachment =
[SignalAttachment imageAttachmentWithImage:imageFromCamera
dataUTI:(NSString *)kUTTypeJPEG
filename:filename];
if (!attachment ||
[attachment hasError]) {
DDLogWarn(@"%@ %s Invalid attachment: %@.",
@ -2247,9 +2276,9 @@ typedef enum : NSUInteger {
return failedToPickAttachment(assetFetchingError);
}
OWSAssert([NSThread isMainThread]);
SignalAttachment *attachment = [SignalAttachment imageAttachmentWithData:imageData
dataUTI:dataUTI];
SignalAttachment *attachment =
[SignalAttachment imageAttachmentWithData:imageData dataUTI:dataUTI filename:filename];
[self dismissViewControllerAnimated:YES
completion:^{
OWSAssert([NSThread isMainThread]);
@ -2312,7 +2341,8 @@ typedef enum : NSUInteger {
return [NSURL fileURLWithPath:basePath];
}
- (void)sendQualityAdjustedAttachmentForVideo:(NSURL *)movieURL {
- (void)sendQualityAdjustedAttachmentForVideo:(NSURL *)movieURL filename:(NSString *)filename
{
AVAsset *video = [AVAsset assetWithURL:movieURL];
AVAssetExportSession *exportSession =
[AVAssetExportSession exportSessionWithAsset:video presetName:AVAssetExportPresetMediumQuality];
@ -2327,24 +2357,25 @@ typedef enum : NSUInteger {
exportSession.outputURL = compressedVideoUrl;
[exportSession exportAsynchronouslyWithCompletionHandler:^{
NSData *videoData = [NSData dataWithContentsOfURL:compressedVideoUrl];
SignalAttachment *attachment = [SignalAttachment videoAttachmentWithData:videoData
dataUTI:(NSString *) kUTTypeMPEG4];
if (!attachment ||
[attachment hasError]) {
DDLogWarn(@"%@ %s Invalid attachment: %@.",
self.tag,
__PRETTY_FUNCTION__,
attachment ? [attachment errorName] : @"Missing data");
[self showErrorAlertForAttachment:attachment];
} else {
[self tryToSendAttachmentIfApproved:attachment];
}
NSError *error;
[[NSFileManager defaultManager] removeItemAtURL:compressedVideoUrl error:&error];
if (error) {
DDLogWarn(@"Failed to remove cached video file: %@", error.debugDescription);
}
dispatch_async(dispatch_get_main_queue(), ^{
SignalAttachment *attachment =
[SignalAttachment videoAttachmentWithData:videoData dataUTI:(NSString *)kUTTypeMPEG4 filename:filename];
if (!attachment || [attachment hasError]) {
DDLogWarn(@"%@ %s Invalid attachment: %@.",
self.tag,
__PRETTY_FUNCTION__,
attachment ? [attachment errorName] : @"Missing data");
[self showErrorAlertForAttachment:attachment];
} else {
[self tryToSendAttachmentIfApproved:attachment];
}
NSError *error;
[[NSFileManager defaultManager] removeItemAtURL:compressedVideoUrl error:&error];
if (error) {
DDLogWarn(@"Failed to remove cached video file: %@", error.debugDescription);
}
});
}];
}
@ -2567,8 +2598,8 @@ typedef enum : NSUInteger {
- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag {
if (flag) {
NSData *audioData = [NSData dataWithContentsOfURL:recorder.url];
SignalAttachment *attachment = [SignalAttachment audioAttachmentWithData:audioData
dataUTI:(NSString *) kUTTypeMPEG4Audio];
SignalAttachment *attachment =
[SignalAttachment audioAttachmentWithData:audioData dataUTI:(NSString *)kUTTypeMPEG4Audio filename:nil];
if (!attachment ||
[attachment hasError]) {
DDLogWarn(@"%@ %s Invalid attachment: %@.",
@ -2671,6 +2702,7 @@ typedef enum : NSUInteger {
if (newGroupModel.groupImage) {
[self.messageSender sendAttachmentData:UIImagePNGRepresentation(newGroupModel.groupImage)
contentType:OWSMimeTypeImagePng
filename:nil
inMessage:message
success:^{
DDLogDebug(@"%@ Successfully sent group update with avatar", self.tag);

View File

@ -317,6 +317,7 @@ static NSString *const kUnwindToMessagesViewSegue = @"UnwindToMessagesViewSegue"
if (model.groupImage) {
[self.messageSender sendAttachmentData:UIImagePNGRepresentation(model.groupImage)
contentType:OWSMimeTypeImagePng
filename:nil
inMessage:message
success:popToThread
failure:removeThreadWithError];

View File

@ -69,6 +69,9 @@ class SignalAttachment: NSObject {
// See: https://developer.apple.com/library/content/documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html
let dataUTI: String
// An optional field that indicates the filename, if known, for this attachment.
let filename: String?
static let kOversizeTextAttachmentUTI = "org.whispersystems.oversize-text-attachment"
static let kUnknownTestAttachmentUTI = "org.whispersystems.unknown"
@ -103,9 +106,10 @@ class SignalAttachment: NSObject {
// This method should not be called directly; use the factory
// methods instead.
internal required init(data: Data, dataUTI: String) {
internal required init(data: Data, dataUTI: String, filename: String?) {
self.data = data
self.dataUTI = dataUTI
self.filename = filename
super.init()
}
@ -268,7 +272,7 @@ class SignalAttachment: NSObject {
assertionFailure()
return nil
}
return imageAttachment(data : data, dataUTI : dataUTI)
return imageAttachment(data : data, dataUTI : dataUTI, filename: nil)
}
}
for dataUTI in videoUTISet {
@ -278,7 +282,7 @@ class SignalAttachment: NSObject {
assertionFailure()
return nil
}
return videoAttachment(data : data, dataUTI : dataUTI)
return videoAttachment(data : data, dataUTI : dataUTI, filename: nil)
}
}
for dataUTI in audioUTISet {
@ -288,7 +292,7 @@ class SignalAttachment: NSObject {
assertionFailure()
return nil
}
return audioAttachment(data : data, dataUTI : dataUTI)
return audioAttachment(data : data, dataUTI : dataUTI, filename: nil)
}
}
@ -298,7 +302,7 @@ class SignalAttachment: NSObject {
assertionFailure()
return nil
}
return genericAttachment(data : data, dataUTI : dataUTI)
return genericAttachment(data : data, dataUTI : dataUTI, filename: nil)
}
// This method should only be called for dataUTIs that
@ -329,17 +333,17 @@ class SignalAttachment: NSObject {
//
// NOTE: The attachment returned by this method may not be valid.
// Check the attachment's error property.
public class func imageAttachment(data imageData: Data?, dataUTI: String) -> SignalAttachment {
public class func imageAttachment(data imageData: Data?, dataUTI: String, filename: String?) -> SignalAttachment {
assert(dataUTI.characters.count > 0)
assert(imageData != nil)
guard let imageData = imageData else {
let attachment = SignalAttachment(data : Data(), dataUTI: dataUTI)
let attachment = SignalAttachment(data : Data(), dataUTI: dataUTI, filename: filename)
attachment.error = .missingData
return attachment
}
let attachment = SignalAttachment(data : imageData, dataUTI: dataUTI)
let attachment = SignalAttachment(data : imageData, dataUTI: dataUTI, filename: filename)
guard inputImageUTISet.contains(dataUTI) else {
attachment.error = .invalidFileFormat
@ -373,7 +377,7 @@ class SignalAttachment: NSObject {
}
Logger.verbose("\(TAG) Compressing attachment as image/jpeg")
return compressImageAsJPEG(image : image, attachment : attachment)
return compressImageAsJPEG(image : image, attachment : attachment, filename:filename)
}
}
@ -409,24 +413,24 @@ class SignalAttachment: NSObject {
//
// NOTE: The attachment returned by this method may nil or not be valid.
// Check the attachment's error property.
public class func imageAttachment(image: UIImage?, dataUTI: String) -> SignalAttachment {
public class func imageAttachment(image: UIImage?, dataUTI: String, filename: String?) -> SignalAttachment {
assert(dataUTI.characters.count > 0)
guard let image = image else {
let attachment = SignalAttachment(data : Data(), dataUTI: dataUTI)
let attachment = SignalAttachment(data : Data(), dataUTI: dataUTI, filename: filename)
attachment.error = .missingData
return attachment
}
// Make a placeholder attachment on which to hang errors if necessary.
let attachment = SignalAttachment(data : Data(), dataUTI: dataUTI)
let attachment = SignalAttachment(data : Data(), dataUTI: dataUTI, filename: filename)
attachment.image = image
Logger.verbose("\(TAG) Writing \(attachment.mimeType) as image/jpeg")
return compressImageAsJPEG(image : image, attachment : attachment)
return compressImageAsJPEG(image : image, attachment : attachment, filename:filename)
}
private class func compressImageAsJPEG(image: UIImage, attachment: SignalAttachment) -> SignalAttachment {
private class func compressImageAsJPEG(image: UIImage, attachment: SignalAttachment, filename: String?) -> SignalAttachment {
assert(attachment.error == nil)
var imageUploadQuality = defaultImageUploadQuality()
@ -445,7 +449,7 @@ class SignalAttachment: NSObject {
}
if jpgImageData.count <= kMaxFileSizeImage {
let recompressedAttachment = SignalAttachment(data : jpgImageData, dataUTI: kUTTypeJPEG as String)
let recompressedAttachment = SignalAttachment(data : jpgImageData, dataUTI: kUTTypeJPEG as String, filename: filename)
recompressedAttachment.image = dstImage
return recompressedAttachment
}
@ -515,11 +519,12 @@ class SignalAttachment: NSObject {
//
// NOTE: The attachment returned by this method may not be valid.
// Check the attachment's error property.
public class func videoAttachment(data: Data?, dataUTI: String) -> SignalAttachment {
public class func videoAttachment(data: Data?, dataUTI: String, filename: String?) -> SignalAttachment {
return newAttachment(data : data,
dataUTI : dataUTI,
validUTISet : videoUTISet,
maxFileSize : kMaxFileSizeVideo)
maxFileSize : kMaxFileSizeVideo,
filename : filename)
}
// MARK: Audio Attachments
@ -528,11 +533,12 @@ class SignalAttachment: NSObject {
//
// NOTE: The attachment returned by this method may not be valid.
// Check the attachment's error property.
public class func audioAttachment(data: Data?, dataUTI: String) -> SignalAttachment {
public class func audioAttachment(data: Data?, dataUTI: String, filename: String?) -> SignalAttachment {
return newAttachment(data : data,
dataUTI : dataUTI,
validUTISet : audioUTISet,
maxFileSize : kMaxFileSizeAudio)
maxFileSize : kMaxFileSizeAudio,
filename : filename)
}
// MARK: Oversize Text Attachments
@ -545,7 +551,8 @@ class SignalAttachment: NSObject {
return newAttachment(data : text?.data(using: .utf8),
dataUTI : kOversizeTextAttachmentUTI,
validUTISet : nil,
maxFileSize : kMaxFileSizeGeneric)
maxFileSize : kMaxFileSizeGeneric,
filename : nil)
}
// MARK: Generic Attachments
@ -554,11 +561,12 @@ class SignalAttachment: NSObject {
//
// NOTE: The attachment returned by this method may not be valid.
// Check the attachment's error property.
public class func genericAttachment(data: Data?, dataUTI: String) -> SignalAttachment {
public class func genericAttachment(data: Data?, dataUTI: String, filename: String?) -> SignalAttachment {
return newAttachment(data : data,
dataUTI : dataUTI,
validUTISet : nil,
maxFileSize : kMaxFileSizeGeneric)
maxFileSize : kMaxFileSizeGeneric,
filename : filename)
}
// MARK: Helper Methods
@ -566,17 +574,18 @@ class SignalAttachment: NSObject {
private class func newAttachment(data: Data?,
dataUTI: String,
validUTISet: Set<String>?,
maxFileSize: Int) -> SignalAttachment {
maxFileSize: Int,
filename: String?) -> SignalAttachment {
assert(dataUTI.characters.count > 0)
assert(data != nil)
guard let data = data else {
let attachment = SignalAttachment(data : Data(), dataUTI: dataUTI)
let attachment = SignalAttachment(data : Data(), dataUTI: dataUTI, filename: filename)
attachment.error = .missingData
return attachment
}
let attachment = SignalAttachment(data : data, dataUTI: dataUTI)
let attachment = SignalAttachment(data : data, dataUTI: dataUTI, filename: filename)
if let validUTISet = validUTISet {
guard validUTISet.contains(dataUTI) else {

View File

@ -32,7 +32,7 @@ class WebRTCCallMessageHandler: NSObject, OWSCallMessageHandler {
Logger.verbose("\(TAG) handling offer from caller:\(callerId)")
let thread = TSContactThread.getOrCreateThread(contactId: callerId)
self.callService.handleReceivedOffer(thread: thread, callId: offer.id, sessionDescription: offer.sessionDescription)
self.callService.handleReceivedOffer(thread: thread, callId: offer.id, sessionDescription: offer.description)
}
public func receivedAnswer(_ answer: OWSSignalServiceProtosCallMessageAnswer, from callerId: String) {
@ -40,7 +40,7 @@ class WebRTCCallMessageHandler: NSObject, OWSCallMessageHandler {
Logger.verbose("\(TAG) handling answer from caller:\(callerId)")
let thread = TSContactThread.getOrCreateThread(contactId: callerId)
self.callService.handleReceivedAnswer(thread: thread, callId: answer.id, sessionDescription: answer.sessionDescription)
self.callService.handleReceivedAnswer(thread: thread, callId: answer.id, sessionDescription: answer.description)
}
public func receivedIceUpdate(_ iceUpdate: OWSSignalServiceProtosCallMessageIceUpdate, from callerId: String) {

View File

@ -78,7 +78,8 @@ NS_ASSUME_NONNULL_BEGIN
}
[messageSender sendAttachmentData:attachment.data
contentType:[attachment mimeType]
contentType:attachment.mimeType
filename:attachment.filename
inMessage:message
success:^{
DDLogDebug(@"%@ Successfully sent message attachment.", self.tag);