Changeset 181476 in webkit
- Timestamp:
- Mar 13, 2015, 1:08:56 AM (11 years ago)
- Location:
- trunk/Source/WebKit2
- Files:
-
- 3 edited
-
ChangeLog (modified) (1 diff)
-
Platform/spi/ios/UIKitSPI.h (modified) (2 diffs)
-
UIProcess/ios/forms/WKFileUploadPanel.mm (modified) (22 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit2/ChangeLog
r181448 r181476 1 2015-03-12 Jon Honeycutt <jhoneycutt@apple.com> 2 3 Use UIDocumentMenuViewController to allow selection of files from 4 iCloud Drive in WKFileUploadPanel 5 6 Part of <https://bugs.webkit.org/show_bug.cgi?id=142596> WebKit on 7 iOS should support file upload from iCloud Drive 8 <rdar://problem/12178991> 9 10 Reviewed by Andy Estes. 11 12 * Platform/spi/ios/UIKitSPI.h: 13 Include UIDocumentMenuViewController_Private.h if it exists. If not, 14 declare this new SPI. 15 16 * UIProcess/ios/forms/WKFileUploadPanel.mm: 17 (fallbackIconForFile): 18 Create a UIDocumentInteractionController for the file, and return a 19 thumbnail image from its smallest icon. 20 21 (iconForImageFile): 22 If we can get a UIImage from the file, create a thumbnail from it. 23 Otherwise, call fallbackIconForFile(). 24 25 (iconForVideoFile): 26 Code moved from -[_WKVideoFileUploadItem displayImage]. 27 28 (iconForFile): 29 Get the file's extension, and get the extension's preferred UTI. If the 30 UTI is an image type, call iconForImageFile(). If it's a video type, 31 call iconForVideoFile(). Otherwise, return the fallback icon. 32 33 (-[_WKFileUploadItem initWithFileURL:]): 34 Added an initializer that takes a file URL. 35 36 (-[_WKFileUploadItem fileURL]): 37 (-[_WKImageFileUploadItem initWithFileURL:originalImage:]): 38 (-[_WKVideoFileUploadItem displayImage]): 39 (WKFileUploadPanel): 40 Inherit from UIDocumentPickerDelegate and UIDocumentMenuDelegate. Add 41 an ivar for the document menu controller. 42 43 (-[WKFileUploadPanel dealloc]): 44 (-[WKFileUploadPanel presentWithParameters:resultListener:]): 45 If instances of UIDocumentMenuViewController respond to 46 -_setIgnoreApplicationEntitlementForImport:, meaning we can disable the 47 assertion that the current app has the iCloud Documents entitlement, 48 then show the document picker menu. Otherwise, show the current source 49 selection UI. The runtime check will be removed when a newer UIKit is 50 available. 51 52 (UTIsForMIMETypes): 53 Return the UTIs for the <input> element's "accept" attribute's MIME 54 type list. 55 56 (-[WKFileUploadPanel _mediaTypesForPickerSourceType:]): 57 Call UTIsForMIMETypes(). Fall back to available source types for this 58 picker type. 59 60 (-[WKFileUploadPanel _documentPickerMenuMediaTypes]): 61 Call UTIsForMIMETypes(). Fall back to the all-encompassing 62 "public.item" UTI. 63 64 (-[WKFileUploadPanel _photoLibraryButtonLabel]): 65 (-[WKFileUploadPanel _cameraButtonLabel]): 66 Factored out of -_showMediaSourceSelectionSheet. Return the 67 appropriate label for the camera button, based on whether it can take a 68 photo or video, or return nil if the camera is not available. 69 70 (-[WKFileUploadPanel _showMediaSourceSelectionSheet]): 71 Changed to use -_cameraButtonLabel and 72 -_presentForCurrentInterfaceIdiom:. 73 74 (-[WKFileUploadPanel _showDocumentPickerMenu]): 75 Create a UIDocumentMenuViewController, and populate it with options to 76 open the photo library or take a picture or video. If iCloud Drive or 77 other document sources are available, they will be added automatically. 78 79 (-[WKFileUploadPanel _presentForCurrentInterfaceIdiom:]): 80 (-[WKFileUploadPanel documentMenu:didPickDocumentPicker:]): 81 (-[WKFileUploadPanel documentMenuWasCancelled:]): 82 (-[WKFileUploadPanel documentPicker:didPickDocumentAtURL:]): 83 (-[WKFileUploadPanel documentPickerWasCancelled:]): 84 (-[WKFileUploadPanel _uploadItemFromMediaInfo:successBlock:failureBlock:]): 85 86 (-[_WKImageFileUploadItem initWithFilePath:originalImage:]): Deleted. 87 (-[_WKImageFileUploadItem fileURL]): Deleted. 88 (-[_WKVideoFileUploadItem initWithFilePath:mediaURL:]): Deleted. 89 (-[_WKVideoFileUploadItem fileURL]): Deleted. 90 1 91 2015-03-11 Enrica Casucci <enrica@apple.com> 2 92 -
trunk/Source/WebKit2/Platform/spi/ios/UIKitSPI.h
r180965 r181476 70 70 #import <UIKit/_UINavigationParallaxTransition.h> 71 71 72 // FIXME: Unconditionally include this file when a new SDK is available. <rdar://problem/20150072> 73 #if defined(__has_include) && __has_include(<UIKit/UIDocumentMenuViewController_Private.h>) 74 #import <UIKit/UIDocumentMenuViewController_Private.h> 75 #else 76 @interface UIDocumentMenuViewController (Details) 77 @property (nonatomic, assign, setter = _setIgnoreApplicationEntitlementForImport:, getter = _ignoreApplicationEntitlementForImport) BOOL _ignoreApplicationEntitlementForImport; 78 @end 79 #endif 80 72 81 #else 73 82 … … 659 668 @end 660 669 670 @interface UIDocumentMenuViewController (Details) 671 @property (nonatomic, assign, setter = _setIgnoreApplicationEntitlementForImport:, getter = _ignoreApplicationEntitlementForImport) BOOL _ignoreApplicationEntitlementForImport; 672 @end 673 661 674 #endif // USE(APPLE_INTERNAL_SDK) 662 675 -
trunk/Source/WebKit2/UIProcess/ios/forms/WKFileUploadPanel.mm
r178080 r181476 58 58 #define kCMTimeZero getkCMTimeZero() 59 59 60 61 #pragma mark - _WKFileUploadItem 60 #pragma mark - Icon generation 62 61 63 62 static CGRect squareCropRectForSize(CGSize size) … … 106 105 } 107 106 107 static UIImage* fallbackIconForFile(NSURL *file) 108 { 109 ASSERT_ARG(file, [file isFileURL]); 110 111 UIDocumentInteractionController *interactionController = [UIDocumentInteractionController interactionControllerWithURL:file]; 112 return thumbnailSizedImageForImage(interactionController.icons[0]); 113 } 114 115 static UIImage* iconForImageFile(NSURL *file) 116 { 117 ASSERT_ARG(file, [file isFileURL]); 118 119 if (UIImage *image = [UIImage imageWithContentsOfFile:file.path]) 120 return thumbnailSizedImageForImage(image); 121 122 LOG_ERROR("WKFileUploadPanel: Error creating thumbnail image for image: %@", file); 123 return fallbackIconForFile(file); 124 } 125 126 static UIImage* iconForVideoFile(NSURL *file) 127 { 128 ASSERT_ARG(file, [file isFileURL]); 129 130 RetainPtr<AVURLAsset> asset = adoptNS([allocAVURLAssetInstance() initWithURL:file options:nil]); 131 RetainPtr<AVAssetImageGenerator> generator = adoptNS([allocAVAssetImageGeneratorInstance() initWithAsset:asset.get()]); 132 [generator setAppliesPreferredTrackTransform:YES]; 133 134 NSError *error = nil; 135 RetainPtr<CGImageRef> imageRef = adoptCF([generator copyCGImageAtTime:kCMTimeZero actualTime:nil error:&error]); 136 if (!imageRef) { 137 LOG_ERROR("WKFileUploadPanel: Error creating image for video '%@': %@", file, error); 138 return fallbackIconForFile(file); 139 } 140 141 RetainPtr<UIImage> image = adoptNS([[UIImage alloc] initWithCGImage:imageRef.get()]); 142 return thumbnailSizedImageForImage(image.get()); 143 } 144 145 static UIImage* iconForFile(NSURL *file) 146 { 147 ASSERT_ARG(file, [file isFileURL]); 148 149 NSString *fileExtension = file.pathExtension; 150 if (!fileExtension.length) 151 return nil; 152 153 RetainPtr<CFStringRef> fileUTI = adoptCF(UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)fileExtension, 0)); 154 155 if (UTTypeConformsTo(fileUTI.get(), kUTTypeImage)) 156 return iconForImageFile(file); 157 158 if (UTTypeConformsTo(fileUTI.get(), kUTTypeMovie)) 159 return iconForVideoFile(file); 160 161 return fallbackIconForFile(file); 162 } 163 164 165 #pragma mark - _WKFileUploadItem 108 166 109 167 @interface _WKFileUploadItem : NSObject 168 - (instancetype)initWithFileURL:(NSURL *)fileURL; 110 169 @property (nonatomic, readonly, getter=isVideo) BOOL video; 111 170 @property (nonatomic, readonly) NSURL *fileURL; … … 113 172 @end 114 173 115 @implementation _WKFileUploadItem 174 @implementation _WKFileUploadItem { 175 RetainPtr<NSURL> _fileURL; 176 } 177 178 - (instancetype)initWithFileURL:(NSURL *)fileURL 179 { 180 if (!(self = [super init])) 181 return nil; 182 183 ASSERT([fileURL isFileURL]); 184 ASSERT([[NSFileManager defaultManager] fileExistsAtPath:fileURL.path]); 185 _fileURL = fileURL; 186 return self; 187 } 116 188 117 189 - (BOOL)isVideo … … 123 195 - (NSURL *)fileURL 124 196 { 197 return _fileURL.get(); 198 } 199 200 - (UIImage *)displayImage 201 { 125 202 ASSERT_NOT_REACHED(); 126 203 return nil; 127 204 } 128 205 129 - (UIImage *)displayImage130 {131 ASSERT_NOT_REACHED();132 return nil;133 }134 135 206 @end 136 207 137 208 138 209 @interface _WKImageFileUploadItem : _WKFileUploadItem 139 - (instancetype)initWithFile Path:(NSString *)filePathoriginalImage:(UIImage *)originalImage;210 - (instancetype)initWithFileURL:(NSURL *)fileURL originalImage:(UIImage *)originalImage; 140 211 @end 141 212 142 213 @implementation _WKImageFileUploadItem { 143 RetainPtr<NSString> _filePath;144 214 RetainPtr<UIImage> _originalImage; 145 215 } 146 216 147 - (instancetype)initWithFile Path:(NSString *)filePathoriginalImage:(UIImage *)originalImage148 { 149 if (!(self = [super init ]))217 - (instancetype)initWithFileURL:(NSURL *)fileURL originalImage:(UIImage *)originalImage 218 { 219 if (!(self = [super initWithFileURL:fileURL])) 150 220 return nil; 151 _filePath = filePath; 221 152 222 _originalImage = originalImage; 153 223 return self; … … 159 229 } 160 230 161 - (NSURL *)fileURL162 {163 return [NSURL fileURLWithPath:_filePath.get()];164 }165 166 231 - (UIImage *)displayImage 167 232 { … … 173 238 174 239 @interface _WKVideoFileUploadItem : _WKFileUploadItem 175 - (instancetype)initWithFilePath:(NSString *)filePath mediaURL:(NSURL *)mediaURL;176 240 @end 177 241 178 @implementation _WKVideoFileUploadItem { 179 RetainPtr<NSString> _filePath; 180 RetainPtr<NSURL> _mediaURL; 181 } 182 183 - (instancetype)initWithFilePath:(NSString *)filePath mediaURL:(NSURL *)mediaURL 184 { 185 if (!(self = [super init])) 186 return nil; 187 _filePath = filePath; 188 _mediaURL = mediaURL; 189 return self; 190 } 242 @implementation _WKVideoFileUploadItem 191 243 192 244 - (BOOL)isVideo … … 195 247 } 196 248 197 - (NSURL *)fileURL198 {199 return [NSURL fileURLWithPath:_filePath.get()];200 }201 202 249 - (UIImage *)displayImage 203 250 { 204 RetainPtr<AVURLAsset> asset = adoptNS([allocAVURLAssetInstance() initWithURL:_mediaURL.get() options:nil]); 205 RetainPtr<AVAssetImageGenerator> generator = adoptNS([allocAVAssetImageGeneratorInstance() initWithAsset:asset.get()]); 206 [generator setAppliesPreferredTrackTransform:YES]; 207 208 NSError *error = nil; 209 RetainPtr<CGImageRef> imageRef = adoptCF([generator copyCGImageAtTime:kCMTimeZero actualTime:nil error:&error]); 210 if (error) { 211 LOG_ERROR("_WKVideoFileUploadItem: Error creating image for video: %@", _mediaURL.get()); 212 return nil; 213 } 214 215 RetainPtr<UIImage> image = adoptNS([[UIImage alloc] initWithCGImage:imageRef.get()]); 216 return thumbnailSizedImageForImage(image.get()); 251 return iconForVideoFile(self.fileURL); 217 252 } 218 253 … … 222 257 #pragma mark - WKFileUploadPanel 223 258 224 @interface WKFileUploadPanel () <UIPopoverControllerDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate >259 @interface WKFileUploadPanel () <UIPopoverControllerDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UIDocumentPickerDelegate, UIDocumentMenuDelegate> 225 260 @end 226 261 … … 233 268 BOOL _usingCamera; 234 269 RetainPtr<UIImagePickerController> _imagePicker; 235 RetainPtr<UIAlertController> _actionSheetController;236 270 RetainPtr<UIViewController> _presentationViewController; // iPhone always. iPad for Fullscreen Camera. 237 271 RetainPtr<UIPopoverController> _presentationPopover; // iPad for action sheet and Photo Library. 272 RetainPtr<UIDocumentMenuViewController> _documentMenuController; 273 RetainPtr<UIAlertController> _actionSheetController; 238 274 } 239 275 … … 250 286 [_imagePicker setDelegate:nil]; 251 287 [_presentationPopover setDelegate:nil]; 288 [_documentMenuController setDelegate:nil]; 289 252 290 [super dealloc]; 253 291 } … … 306 344 _mimeTypes = adoptNS([mimeTypes copy]); 307 345 346 // FIXME: Remove this check and the fallback code when a new SDK is available. <rdar://problem/20150072> 347 if ([UIDocumentMenuViewController instancesRespondToSelector:@selector(_setIgnoreApplicationEntitlementForImport:)]) { 348 [self _showDocumentPickerMenu]; 349 return; 350 } 351 352 // Fall back to showing the old-style source selection sheet. 308 353 // If there is no camera or this is type=multiple, just show the image picker for the photo library. 309 354 // Otherwise, show an action sheet for the user to choose between camera or library. … … 335 380 } 336 381 337 #pragma mark - Action Sheet382 #pragma mark - Media Types 338 383 339 384 static bool stringHasPrefixCaseInsensitive(NSString *str, NSString *prefix) … … 343 388 } 344 389 345 - (NSArray *)_mediaTypesForPickerSourceType:(UIImagePickerControllerSourceType)sourceType 390 static NSArray *UTIsForMIMETypes(NSArray *mimeTypes) 346 391 { 347 392 // The HTML5 spec mentions the literal "image/*" and "video/*" strings. … … 350 395 // So, "image/jpeg" would make the picker display all images types. 351 396 NSMutableSet *mediaTypes = [NSMutableSet set]; 352 for (NSString *mimeType in _mimeTypes.get()) { 397 for (NSString *mimeType in mimeTypes) { 398 // FIXME: We should support more MIME type -> UTI mappings. <http://webkit.org/b/142614> 353 399 if (stringHasPrefixCaseInsensitive(mimeType, @"image/")) 354 400 [mediaTypes addObject:(NSString *)kUTTypeImage]; … … 357 403 } 358 404 359 if ([mediaTypes count]) 360 return [mediaTypes allObjects]; 405 return mediaTypes.allObjects; 406 } 407 408 - (NSArray *)_mediaTypesForPickerSourceType:(UIImagePickerControllerSourceType)sourceType 409 { 410 NSArray *mediaTypes = UTIsForMIMETypes(_mimeTypes.get()); 411 if (mediaTypes.count) 412 return mediaTypes; 361 413 362 414 // Fallback to every supported media type if there is no filter. … … 364 416 } 365 417 366 - (void)_showMediaSourceSelectionSheet 367 { 368 NSString *existingString = WEB_UI_STRING_KEY("Photo Library", "Photo Library (file upload action sheet)", "File Upload alert sheet button string for choosing an existing media item from the Photo Library"); 369 NSString *cancelString = WEB_UI_STRING_KEY("Cancel", "Cancel (file upload action sheet)", "File Upload alert sheet button string to cancel"); 418 - (NSArray *)_documentPickerMenuMediaTypes 419 { 420 NSArray *mediaTypes = UTIsForMIMETypes(_mimeTypes.get()); 421 if (mediaTypes.count) 422 return mediaTypes; 423 424 // Fallback to every supported media type if there is no filter. 425 return @[@"public.item"]; 426 } 427 428 #pragma mark - Source selection menu 429 430 - (NSString *)_photoLibraryButtonLabel 431 { 432 return WEB_UI_STRING_KEY("Photo Library", "Photo Library (file upload action sheet)", "File Upload alert sheet button string for choosing an existing media item from the Photo Library"); 433 } 434 435 - (NSString *)_cameraButtonLabel 436 { 437 if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) 438 return nil; 370 439 371 440 // Choose the appropriate string for the camera button. 372 NSString *cameraString;373 441 NSArray *filteredMediaTypes = [self _mediaTypesForPickerSourceType:UIImagePickerControllerSourceTypeCamera]; 374 442 BOOL containsImageMediaType = [filteredMediaTypes containsObject:(NSString *)kUTTypeImage]; … … 376 444 ASSERT(containsImageMediaType || containsVideoMediaType); 377 445 if (containsImageMediaType && containsVideoMediaType) 378 cameraString = WEB_UI_STRING_KEY("Take Photo or Video", "Take Photo or Video (file upload action sheet)", "File Upload alert sheet camera button string for taking photos or videos"); 379 else if (containsVideoMediaType) 380 cameraString = WEB_UI_STRING_KEY("Take Video", "Take Video (file upload action sheet)", "File Upload alert sheet camera button string for taking only videos"); 381 else 382 cameraString = WEB_UI_STRING_KEY("Take Photo", "Take Photo (file upload action sheet)", "File Upload alert sheet camera button string for taking only photos"); 446 return WEB_UI_STRING_KEY("Take Photo or Video", "Take Photo or Video (file upload action sheet)", "File Upload alert sheet camera button string for taking photos or videos"); 447 448 if (containsVideoMediaType) 449 return WEB_UI_STRING_KEY("Take Video", "Take Video (file upload action sheet)", "File Upload alert sheet camera button string for taking only videos"); 450 451 return WEB_UI_STRING_KEY("Take Photo", "Take Photo (file upload action sheet)", "File Upload alert sheet camera button string for taking only photos"); 452 } 453 454 - (void)_showMediaSourceSelectionSheet 455 { 456 NSString *existingString = [self _photoLibraryButtonLabel]; 457 NSString *cameraString = [self _cameraButtonLabel]; 458 NSString *cancelString = WEB_UI_STRING_KEY("Cancel", "Cancel (file upload action sheet)", "File Upload alert sheet button string to cancel"); 383 459 384 460 _actionSheetController = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; … … 403 479 [_actionSheetController addAction:photoLibraryAction]; 404 480 405 if (UICurrentUserInterfaceIdiomIsPad()) 406 [self _presentPopoverWithContentViewController:_actionSheetController.get() animated:YES]; 407 else 408 [self _presentFullscreenViewController:_actionSheetController.get() animated:YES]; 481 [self _presentForCurrentInterfaceIdiom:_actionSheetController.get()]; 482 } 483 484 - (void)_showDocumentPickerMenu 485 { 486 // FIXME: Support multiple file selection when implemented. <rdar://17177981> 487 // FIXME: We call -_setIgnoreApplicationEntitlementForImport: before initialization, because the assertion we're trying 488 // to suppress is in the initializer. <rdar://problem/20137692> tracks doing this with a private initializer. 489 _documentMenuController = adoptNS([UIDocumentMenuViewController alloc]); 490 [_documentMenuController _setIgnoreApplicationEntitlementForImport:YES]; 491 [_documentMenuController initWithDocumentTypes:[self _documentPickerMenuMediaTypes] inMode:UIDocumentPickerModeImport]; 492 [_documentMenuController setDelegate:self]; 493 494 // FIXME: Need icons for Camera and Photo Library options. 495 [_documentMenuController addOptionWithTitle:[self _photoLibraryButtonLabel] image:nil order:UIDocumentMenuOrderFirst handler:^{ 496 [self _showPhotoPickerWithSourceType:UIImagePickerControllerSourceTypePhotoLibrary]; 497 }]; 498 499 if (NSString *cameraString = [self _cameraButtonLabel]) { 500 [_documentMenuController addOptionWithTitle:cameraString image:nil order:UIDocumentMenuOrderFirst handler:^{ 501 _usingCamera = YES; 502 [self _showPhotoPickerWithSourceType:UIImagePickerControllerSourceTypeCamera]; 503 }]; 504 } 505 506 [self _presentForCurrentInterfaceIdiom:_documentMenuController.get()]; 409 507 } 410 508 … … 432 530 #pragma mark - Presenting View Controllers 433 531 532 - (void)_presentForCurrentInterfaceIdiom:(UIViewController *)viewController 533 { 534 if (UICurrentUserInterfaceIdiomIsPad()) 535 [self _presentPopoverWithContentViewController:viewController animated:YES]; 536 else 537 [self _presentFullscreenViewController:viewController animated:YES]; 538 } 539 434 540 - (void)_presentPopoverWithContentViewController:(UIViewController *)contentViewController animated:(BOOL)animated 435 541 { … … 453 559 - (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController 454 560 { 561 [self _cancel]; 562 } 563 564 #pragma mark - UIDocumentMenuDelegate implementation 565 566 - (void)documentMenu:(UIDocumentMenuViewController *)documentMenu didPickDocumentPicker:(UIDocumentPickerViewController *)documentPicker 567 { 568 documentPicker.delegate = self; 569 documentPicker.modalPresentationStyle = UIModalPresentationFullScreen; 570 571 [self _presentForCurrentInterfaceIdiom:documentPicker]; 572 } 573 574 - (void)documentMenuWasCancelled:(UIDocumentMenuViewController *)documentMenu 575 { 576 [self _dismissDisplayAnimated:YES]; 577 [self _cancel]; 578 } 579 580 #pragma mark - UIDocumentPickerControllerDelegate implementation 581 582 - (void)documentPicker:(UIDocumentPickerViewController *)documentPicker didPickDocumentAtURL:(NSURL *)url 583 { 584 [self _dismissDisplayAnimated:YES]; 585 [self _chooseFiles:@[url] displayString:url.lastPathComponent iconImage:iconForFile(url)]; 586 } 587 588 - (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)documentPicker 589 { 590 [self _dismissDisplayAnimated:YES]; 455 591 [self _cancel]; 456 592 } … … 575 711 } 576 712 577 NSString *filePath = [mediaURL path]; 578 successBlock(adoptNS([[_WKVideoFileUploadItem alloc] initWithFilePath:filePath mediaURL:mediaURL]).get()); 713 successBlock(adoptNS([[_WKVideoFileUploadItem alloc] initWithFileURL:mediaURL]).get()); 579 714 return; 580 715 } … … 628 763 } 629 764 630 successBlock(adoptNS([[_WKImageFileUploadItem alloc] initWithFile Path:filePathoriginalImage:originalImage]).get());765 successBlock(adoptNS([[_WKImageFileUploadItem alloc] initWithFileURL:[NSURL fileURLWithPath:filePath] originalImage:originalImage]).get()); 631 766 }); 632 767 return;
Note:
See TracChangeset
for help on using the changeset viewer.