Title: [176041] trunk/Source
Revision
176041
Author
[email protected]
Date
2014-11-12 14:52:15 -0800 (Wed, 12 Nov 2014)

Log Message

WK1: Support default actions for images
https://bugs.webkit.org/show_bug.cgi?id=138668
-and corresponding-
rdar://problem/18785434

Reviewed by Tim Horton.

Source/WebCore:

Symbol needed for copying image.
* WebCore.exp.in:

Source/WebKit/mac:

* WebView/WebActionMenuController.h:
* WebView/WebActionMenuController.mm:
(-[WebActionMenuController didCloseMenu:withEvent:]):
(-[WebActionMenuController _defaultMenuItemsForImage:]):
(-[WebActionMenuController _copyImage:]):
(temporaryPhotosDirectoryPath):
(pathToPhotoOnDisk):
(-[WebActionMenuController _canAddMediaToPhotos]):
(-[WebActionMenuController _addImageToPhotos:]):
(-[WebActionMenuController _saveImageToDownloads:]):
(-[WebActionMenuController sharingServicePicker:sharingServicesForItems:mask:proposedSharingServices:]):
(-[WebActionMenuController sharingServicePicker:delegateForSharingService:]):
(-[WebActionMenuController sharingService:sourceWindowForShareItems:sharingContentScope:]):
(-[WebActionMenuController _createActionMenuItemForTag:withHitTestResult:]):
(-[WebActionMenuController _defaultMenuItemsForHitTestResult:]):
* WebView/WebUIDelegatePrivate.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (176040 => 176041)


--- trunk/Source/WebCore/ChangeLog	2014-11-12 22:39:30 UTC (rev 176040)
+++ trunk/Source/WebCore/ChangeLog	2014-11-12 22:52:15 UTC (rev 176041)
@@ -1,3 +1,15 @@
+2014-11-12  Beth Dakin  <[email protected]>
+
+        WK1: Support default actions for images
+        https://bugs.webkit.org/show_bug.cgi?id=138668
+        -and corresponding-
+        rdar://problem/18785434
+
+        Reviewed by Tim Horton.
+
+        Symbol needed for copying image.
+        * WebCore.exp.in:
+
 2014-11-05  Ada Chan  <[email protected]>
 
         Implement new plug-in API for muting plug-ins

Modified: trunk/Source/WebCore/WebCore.exp.in (176040 => 176041)


--- trunk/Source/WebCore/WebCore.exp.in	2014-11-12 22:39:30 UTC (rev 176040)
+++ trunk/Source/WebCore/WebCore.exp.in	2014-11-12 22:52:15 UTC (rev 176041)
@@ -1280,6 +1280,7 @@
 __ZN7WebCore6Editor7commandERKN3WTF6StringE
 __ZN7WebCore6Editor7copyURLERKNS_3URLERKN3WTF6StringE
 __ZN7WebCore6Editor7outdentEv
+__ZN7WebCore6Editor9copyImageERKNS_13HitTestResultE
 __ZN7WebCore6JSNode6s_infoE
 __ZN7WebCore6JSNode9toWrappedEN3JSC7JSValueE
 __ZN7WebCore6LengthC1EN3WTF7PassRefINS_16CalculationValueEEE

Modified: trunk/Source/WebKit/mac/ChangeLog (176040 => 176041)


--- trunk/Source/WebKit/mac/ChangeLog	2014-11-12 22:39:30 UTC (rev 176040)
+++ trunk/Source/WebKit/mac/ChangeLog	2014-11-12 22:52:15 UTC (rev 176041)
@@ -1,3 +1,29 @@
+2014-11-12  Beth Dakin  <[email protected]>
+
+        WK1: Support default actions for images
+        https://bugs.webkit.org/show_bug.cgi?id=138668
+        -and corresponding-
+        rdar://problem/18785434
+
+        Reviewed by Tim Horton.
+
+        * WebView/WebActionMenuController.h:
+        * WebView/WebActionMenuController.mm:
+        (-[WebActionMenuController didCloseMenu:withEvent:]):
+        (-[WebActionMenuController _defaultMenuItemsForImage:]):
+        (-[WebActionMenuController _copyImage:]):
+        (temporaryPhotosDirectoryPath):
+        (pathToPhotoOnDisk):
+        (-[WebActionMenuController _canAddMediaToPhotos]):
+        (-[WebActionMenuController _addImageToPhotos:]):
+        (-[WebActionMenuController _saveImageToDownloads:]):
+        (-[WebActionMenuController sharingServicePicker:sharingServicesForItems:mask:proposedSharingServices:]):
+        (-[WebActionMenuController sharingServicePicker:delegateForSharingService:]):
+        (-[WebActionMenuController sharingService:sourceWindowForShareItems:sharingContentScope:]):
+        (-[WebActionMenuController _createActionMenuItemForTag:withHitTestResult:]):
+        (-[WebActionMenuController _defaultMenuItemsForHitTestResult:]):
+        * WebView/WebUIDelegatePrivate.h:
+
 2014-11-11  Beth Dakin  <[email protected]>
 
         Action menu hit testing is not working properly with all WK1 apps

Modified: trunk/Source/WebKit/mac/WebView/WebActionMenuController.h (176040 => 176041)


--- trunk/Source/WebKit/mac/WebView/WebActionMenuController.h	2014-11-12 22:39:30 UTC (rev 176040)
+++ trunk/Source/WebKit/mac/WebView/WebActionMenuController.h	2014-11-12 22:52:15 UTC (rev 176041)
@@ -24,15 +24,19 @@
  */
 
 #import "WebUIDelegatePrivate.h"
+
+#import <AppKit/NSSharingService.h>
 #import <WebCore/HitTestResult.h>
+#import <wtf/RetainPtr.h>
 
 @class WebView;
 
-@interface WebActionMenuController : NSObject {
+@interface WebActionMenuController : NSObject <NSSharingServiceDelegate, NSSharingServicePickerDelegate> {
 @private
     WebView *_webView;
     WebActionMenuType _type;
     WebCore::HitTestResult _hitTestResult;
+    RetainPtr<NSSharingServicePicker> _sharingServicePicker;
 }
 
 - (id)initWithWebView:(WebView *)webView;

Modified: trunk/Source/WebKit/mac/WebView/WebActionMenuController.mm (176040 => 176041)


--- trunk/Source/WebKit/mac/WebView/WebActionMenuController.mm	2014-11-12 22:39:30 UTC (rev 176040)
+++ trunk/Source/WebKit/mac/WebView/WebActionMenuController.mm	2014-11-12 22:52:15 UTC (rev 176041)
@@ -35,6 +35,8 @@
 #import "WebSystemInterface.h"
 #import "WebUIDelegatePrivate.h"
 #import "WebViewInternal.h"
+#import <ImageIO/ImageIO.h>
+#import <ImageKit/ImageKit.h>
 #import <WebCore/DictionaryLookup.h>
 #import <WebCore/Editor.h>
 #import <WebCore/Element.h>
@@ -42,6 +44,8 @@
 #import <WebCore/Frame.h>
 #import <WebCore/FrameView.h>
 #import <WebCore/HTMLConverter.h>
+#import <WebCore/NSSharingServicePickerSPI.h>
+#import <WebCore/NSSharingServiceSPI.h>
 #import <WebCore/NSViewSPI.h>
 #import <WebCore/Page.h>
 #import <WebCore/Range.h>
@@ -56,6 +60,9 @@
 SOFT_LINK_FRAMEWORK_IN_UMBRELLA(Quartz, QuickLookUI)
 SOFT_LINK_CLASS(QuickLookUI, QLPreviewBubble)
 
+SOFT_LINK_FRAMEWORK_IN_UMBRELLA(Quartz, ImageKit)
+SOFT_LINK_CLASS(ImageKit, IKSlideshow)
+
 @class QLPreviewBubble;
 @interface NSObject (WKQLPreviewBubbleDetails)
 @property (copy) NSArray * controls;
@@ -155,6 +162,7 @@
         return;
 
     _type = WebActionMenuNone;
+    _sharingServicePicker = nil;
 }
 
 #pragma mark Link actions
@@ -256,6 +264,127 @@
     return @[ openLinkItem.get(), previewLinkItem.get(), [NSMenuItem separatorItem], readingListItem.get() ];
 }
 
+#pragma mark Image actions
+
+- (NSArray *)_defaultMenuItemsForImage:(WebElementDictionary *)hitTestResult
+{
+    RetainPtr<NSMenuItem> copyImageItem = [self _createActionMenuItemForTag:WebActionMenuItemTagCopyImage withHitTestResult:hitTestResult];
+
+    RetainPtr<NSMenuItem> addToPhotosItem;
+    if ([self _canAddMediaToPhotos])
+        addToPhotosItem = [self _createActionMenuItemForTag:WebActionMenuItemTagAddImageToPhotos withHitTestResult:hitTestResult];
+    else
+        addToPhotosItem = [NSMenuItem separatorItem];
+
+    RetainPtr<NSMenuItem> saveToDownloadsItem = [self _createActionMenuItemForTag:WebActionMenuItemTagSaveImageToDownloads withHitTestResult:hitTestResult];
+    if (!_webView.downloadDelegate)
+        [saveToDownloadsItem setEnabled:NO];
+
+
+    RetainPtr<NSMenuItem> shareItem = [self _createActionMenuItemForTag:WebActionMenuItemTagShareImage withHitTestResult:hitTestResult];
+    if (Image* image = _hitTestResult.image()) {
+        RetainPtr<CGImageRef> cgImage = image->getCGImageRef();
+        RetainPtr<NSImage> nsImage = adoptNS([[NSImage alloc] initWithCGImage:cgImage.get() size:NSZeroSize]);
+        _sharingServicePicker = adoptNS([[NSSharingServicePicker alloc] initWithItems:@[ nsImage.get() ]]);
+        [_sharingServicePicker setDelegate:self];
+        [shareItem setSubmenu:[_sharingServicePicker menu]];
+    }
+
+    return @[ copyImageItem.get(), addToPhotosItem.get(), saveToDownloadsItem.get(), shareItem.get() ];
+}
+
+- (void)_copyImage:(id)sender
+{
+    Frame* frame = core([_webView _selectedOrMainFrame]);
+    if (!frame)
+        return;
+    frame->editor().copyImage(_hitTestResult);
+}
+
+static NSString *temporaryPhotosDirectoryPath()
+{
+    static NSString *temporaryPhotosDirectoryPath;
+
+    if (!temporaryPhotosDirectoryPath) {
+        NSString *temporaryDirectoryTemplate = [NSTemporaryDirectory() stringByAppendingPathComponent:@"WebKitPhotos-XXXXXX"];
+        CString templateRepresentation = [temporaryDirectoryTemplate fileSystemRepresentation];
+
+        if (mkdtemp(templateRepresentation.mutableData()))
+            temporaryPhotosDirectoryPath = [[[NSFileManager defaultManager] stringWithFileSystemRepresentation:templateRepresentation.data() length:templateRepresentation.length()] copy];
+    }
+
+    return temporaryPhotosDirectoryPath;
+}
+
+static NSString *pathToPhotoOnDisk(NSString *suggestedFilename)
+{
+    NSString *photoDirectoryPath = temporaryPhotosDirectoryPath();
+    if (!photoDirectoryPath) {
+        WTFLogAlways("Cannot create temporary photo download directory.");
+        return nil;
+    }
+
+    NSString *path = [photoDirectoryPath stringByAppendingPathComponent:suggestedFilename];
+
+    NSFileManager *fileManager = [NSFileManager defaultManager];
+    if ([fileManager fileExistsAtPath:path]) {
+        NSString *pathTemplatePrefix = [photoDirectoryPath stringByAppendingPathComponent:@"XXXXXX-"];
+        NSString *pathTemplate = [pathTemplatePrefix stringByAppendingString:suggestedFilename];
+        CString pathTemplateRepresentation = [pathTemplate fileSystemRepresentation];
+
+        int fd = mkstemps(pathTemplateRepresentation.mutableData(), pathTemplateRepresentation.length() - strlen([pathTemplatePrefix fileSystemRepresentation]) + 1);
+        if (fd < 0) {
+            WTFLogAlways("Cannot create photo file in the temporary directory (%@).", suggestedFilename);
+            return nil;
+        }
+
+        close(fd);
+        path = [fileManager stringWithFileSystemRepresentation:pathTemplateRepresentation.data() length:pathTemplateRepresentation.length()];
+    }
+
+    return path;
+}
+
+- (BOOL)_canAddMediaToPhotos
+{
+    return [getIKSlideshowClass() canExportToApplication:@"com.apple.Photos"];
+}
+
+- (void)_addImageToPhotos:(id)sender
+{
+    if (![self _canAddMediaToPhotos])
+        return;
+
+    Image* image = _hitTestResult.image();
+    if (!image)
+        return;
+
+    RetainPtr<CGImageRef> cgImage = image->getCGImageRef();
+
+    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+        NSString * const suggestedFilename = @"image.jpg";
+
+        NSString *filePath = pathToPhotoOnDisk(suggestedFilename);
+        if (!filePath)
+            return;
+
+        NSURL *fileURL = [NSURL fileURLWithPath:filePath];
+        auto dest = adoptCF(CGImageDestinationCreateWithURL((CFURLRef)fileURL, kUTTypeJPEG, 1, nullptr));
+        CGImageDestinationAddImage(dest.get(), cgImage.get(), nullptr);
+        CGImageDestinationFinalize(dest.get());
+
+        dispatch_async(dispatch_get_main_queue(), ^{
+            // This API provides no way to report failure, but if 18420778 is fixed so that it does, we should handle this.
+            [getIKSlideshowClass() exportSlideshowItem:filePath toApplication:@"com.apple.Photos"];
+        });
+    });
+}
+
+- (void)_saveImageToDownloads:(id)sender
+{
+    [_webView _downloadURL:_hitTestResult.absoluteImageURL()];
+}
+
 #pragma mark Text actions
 
 - (NSArray *)_defaultMenuItemsForText:(WebElementDictionary *)hitTestResult
@@ -431,6 +560,33 @@
     return @[ [NSMenuItem separatorItem], [NSMenuItem separatorItem], pasteItem.get() ];
 }
 
+#pragma mark NSSharingServicePickerDelegate implementation
+
+- (NSArray *)sharingServicePicker:(NSSharingServicePicker *)sharingServicePicker sharingServicesForItems:(NSArray *)items mask:(NSSharingServiceMask)mask proposedSharingServices:(NSArray *)proposedServices
+{
+    RetainPtr<NSMutableArray> services = adoptNS([[NSMutableArray alloc] initWithCapacity:proposedServices.count]);
+
+    for (NSSharingService *service in proposedServices) {
+        if ([service.name isEqualToString:NSSharingServiceNameAddToIPhoto])
+            continue;
+        [services addObject:service];
+    }
+
+    return services.autorelease();
+}
+
+- (id <NSSharingServiceDelegate>)sharingServicePicker:(NSSharingServicePicker *)sharingServicePicker delegateForSharingService:(NSSharingService *)sharingService
+{
+    return self;
+}
+
+#pragma mark NSSharingServiceDelegate implementation
+
+- (NSWindow *)sharingService:(NSSharingService *)sharingService sourceWindowForShareItems:(NSArray *)items sharingContentScope:(NSSharingContentScope *)sharingContentScope
+{
+    return _webView.window;
+}
+
 #pragma mark Menu Items
 
 - (RetainPtr<NSMenuItem>)_createActionMenuItemForTag:(uint32_t)tag withHitTestResult:(WebElementDictionary *)hitTestResult
@@ -485,6 +641,29 @@
         image = [NSImage imageNamed:@"NSActionMenuSpelling"];
         break;
 
+    case WebActionMenuItemTagCopyImage:
+        selector = @selector(_copyImage:);
+        title = WEB_UI_STRING_KEY("Copy", "Copy (image action menu item)", "image action menu item");
+        image = [NSImage imageNamed:@"NSActionMenuCopy"];
+        break;
+
+    case WebActionMenuItemTagAddImageToPhotos:
+        selector = @selector(_addImageToPhotos:);
+        title = WEB_UI_STRING_KEY("Add to Photos", "Add to Photos (action menu item)", "action menu item");
+        image = [NSImage imageNamed:@"NSActionMenuAddToPhotos"];
+        break;
+
+    case WebActionMenuItemTagSaveImageToDownloads:
+        selector = @selector(_saveImageToDownloads:);
+        title = WEB_UI_STRING_KEY("Save to Downloads", "Save to Downloads (image action menu item)", "image action menu item");
+        image = [NSImage imageNamed:@"NSActionMenuSaveToDownloads"];
+        break;
+
+    case WebActionMenuItemTagShareImage:
+        title = WEB_UI_STRING_KEY("Share (image action menu item)", "Share (image action menu item)", "image action menu item");
+        image = [NSImage imageNamed:@"NSActionMenuShare"];
+        break;
+
     default:
         ASSERT_NOT_REACHED();
         return nil;
@@ -511,6 +690,11 @@
         return [self _defaultMenuItemsForLink:hitTestResult];
     }
 
+    if (_hitTestResult.image() && !_hitTestResult.absoluteImageURL().isEmpty()) {
+        _type = WebActionMenuImage;
+        return [self _defaultMenuItemsForImage:hitTestResult];
+    }
+
     Node* node = _hitTestResult.innerNode();
     if (node && node->isTextNode()) {
         if (_hitTestResult.isContentEditable()) {

Modified: trunk/Source/WebKit/mac/WebView/WebUIDelegatePrivate.h (176040 => 176041)


--- trunk/Source/WebKit/mac/WebView/WebUIDelegatePrivate.h	2014-11-12 22:39:30 UTC (rev 176040)
+++ trunk/Source/WebKit/mac/WebView/WebUIDelegatePrivate.h	2014-11-12 22:52:15 UTC (rev 176041)
@@ -120,7 +120,11 @@
     WebActionMenuItemTagCopyText,
     WebActionMenuItemTagLookupText,
     WebActionMenuItemTagPaste,
-    WebActionMenuItemTagTextSuggestions
+    WebActionMenuItemTagTextSuggestions,
+    WebActionMenuItemTagCopyImage,
+    WebActionMenuItemTagAddImageToPhotos,
+    WebActionMenuItemTagSaveImageToDownloads,
+    WebActionMenuItemTagShareImage
 };
 
 typedef enum {
@@ -129,7 +133,8 @@
     WebActionMenuReadOnlyText,
     WebActionMenuEditableText,
     WebActionMenuWhitespaceInEditableArea,
-    WebActionMenuEditableTextWithSuggestions
+    WebActionMenuEditableTextWithSuggestions,
+    WebActionMenuImage
 } WebActionMenuType;
 
 // Message Sources.
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to