+2014-08-28 Tim Horton <timothy_horton@apple.com>
+
+ Occasional thread-safety-related crashes on the ServicesController queue
+ https://bugs.webkit.org/show_bug.cgi?id=136356
+ <rdar://problem/18045685>
+
+ Reviewed by Dan Bernstein.
+
+ * UIProcess/mac/ServicesController.mm:
+ (WebKit::hasCompatibleServicesForItems):
+ Added. Check directly with NSSharingService if we have any services for the given items.
+ We should eventually check Viewer and Editor services separately so the Web process can
+ be smarter about when it shows the overlay, but for now this maintains the existing behavior.
+
+ (WebKit::ServicesController::refreshExistingServices):
+ Make use of hasCompatibleServicesForItems instead of having NSSharingServicePicker construct NSMenus.
+
2014-08-28 Tim Horton <timothy_horton@apple.com>
WebKit2 doesn't support viewer services that accept image attachments
#if __has_include(<AppKit/NSSharingService_Private.h>)
#import <AppKit/NSSharingService_Private.h>
#else
-typedef enum {
+typedef NS_ENUM(NSInteger, NSSharingServicePickerStyle) {
NSSharingServicePickerStyleMenu = 0,
NSSharingServicePickerStyleRollover = 1,
NSSharingServicePickerStyleTextSelection = 2,
NSSharingServicePickerStyleDataDetector = 3
-} NSSharingServicePickerStyle;
+} NS_ENUM_AVAILABLE_MAC(10_10);
+
+typedef NS_ENUM(NSInteger, NSSharingServiceType) {
+ NSSharingServiceTypeShare = 0,
+ NSSharingServiceTypeViewer = 1,
+ NSSharingServiceTypeEditor = 2
+} NS_ENUM_AVAILABLE_MAC(10_10);
+
+typedef NS_OPTIONS(NSUInteger, NSSharingServiceMask) {
+ NSSharingServiceMaskShare = (1 << NSSharingServiceTypeShare),
+ NSSharingServiceMaskViewer = (1 << NSSharingServiceTypeViewer),
+ NSSharingServiceMaskEditor = (1 << NSSharingServiceTypeEditor),
+
+ NSSharingServiceMaskAllTypes = 0xFFFF
+} NS_ENUM_AVAILABLE_MAC(10_10);
#endif
-@interface NSSharingServicePicker (Details)
+@interface NSSharingServicePicker (WKDetails)
@property NSSharingServicePickerStyle style;
- (NSMenu *)menu;
@end
+@interface NSSharingService (WKDetails)
++ (NSArray *)sharingServicesForItems:(NSArray *)items mask:(NSSharingServiceMask)maskForFiltering;
+@end
+
#ifdef __LP64__
#if __has_include(<Foundation/NSExtension.h>)
#import <Foundation/NSExtension.h>
@end
#endif
-@interface NSExtension (Details)
+@interface NSExtension (WKDetails)
+ (id)beginMatchingExtensionsWithAttributes:(NSDictionary *)attributes completion:(void (^)(NSArray *matchingExtensions, NSError *error))handler;
@end
#endif // __LP64__
#endif // __LP64__
}
+static bool hasCompatibleServicesForItems(NSArray *items)
+{
+ return [NSSharingService sharingServicesForItems:items mask:NSSharingServiceMaskViewer | NSSharingServiceMaskEditor].count;
+}
+
void ServicesController::refreshExistingServices(bool refreshImmediately)
{
if (m_hasPendingRefresh)
auto refreshTime = dispatch_time(DISPATCH_TIME_NOW, refreshImmediately ? 0 : (int64_t)(1 * NSEC_PER_SEC));
dispatch_after(refreshTime, m_refreshQueue, ^{
static NeverDestroyed<NSImage *> image([[NSImage alloc] init]);
- RetainPtr<NSSharingServicePicker> picker = adoptNS([[NSSharingServicePicker alloc] initWithItems:@[ image ]]);
- [picker setStyle:NSSharingServicePickerStyleRollover];
-
- bool hasImageServices = picker.get().menu;
+ bool hasImageServices = hasCompatibleServicesForItems(@[ image ]);
static NeverDestroyed<NSAttributedString *> attributedString([[NSAttributedString alloc] initWithString:@"a"]);
- picker = adoptNS([[NSSharingServicePicker alloc] initWithItems:@[ attributedString ]]);
- [picker setStyle:NSSharingServicePickerStyleTextSelection];
-
- bool hasSelectionServices = picker.get().menu;
+ bool hasSelectionServices = hasCompatibleServicesForItems(@[ attributedString ]);
static NSAttributedString *attributedStringWithRichContent;
if (!attributedStringWithRichContent) {
attributedStringWithRichContent = [richString retain];
}
- picker = adoptNS([[NSSharingServicePicker alloc] initWithItems:@[ attributedStringWithRichContent ]]);
- [picker setStyle:NSSharingServicePickerStyleTextSelection];
-
- bool hasRichContentServices = picker.get().menu;
+ bool hasRichContentServices = hasCompatibleServicesForItems(@[ attributedStringWithRichContent ]);
dispatch_async(dispatch_get_main_queue(), ^{
bool availableServicesChanged = (hasImageServices != m_hasImageServices) || (hasSelectionServices != m_hasSelectionServices) || (hasRichContentServices != m_hasRichContentServices);