Occasional thread-safety-related crashes on the ServicesController queue
authortimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 28 Aug 2014 23:58:20 +0000 (23:58 +0000)
committertimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 28 Aug 2014 23:58:20 +0000 (23:58 +0000)
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.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@173092 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/mac/ServicesController.mm

index 171602d2960ff191a5697d14f802d8e2e2218888..eab77c85bcd92707945d48d2883ba7af673ee912 100644 (file)
@@ -1,3 +1,20 @@
+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
index 0d36f44f6b5feb3c69165c9f6ada7aa284f83238..39859aab62e7a04e80c32a71705053076ee2b397 100644 (file)
 #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>
@@ -57,7 +75,7 @@ typedef enum {
 @end
 #endif
 
-@interface NSExtension (Details)
+@interface NSExtension (WKDetails)
 + (id)beginMatchingExtensionsWithAttributes:(NSDictionary *)attributes completion:(void (^)(NSArray *matchingExtensions, NSError *error))handler;
 @end
 #endif // __LP64__
@@ -92,6 +110,11 @@ ServicesController::ServicesController()
 #endif // __LP64__
 }
 
+static bool hasCompatibleServicesForItems(NSArray *items)
+{
+    return [NSSharingService sharingServicesForItems:items mask:NSSharingServiceMaskViewer | NSSharingServiceMaskEditor].count;
+}
+
 void ServicesController::refreshExistingServices(bool refreshImmediately)
 {
     if (m_hasPendingRefresh)
@@ -102,16 +125,10 @@ void ServicesController::refreshExistingServices(bool refreshImmediately)
     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) {
@@ -123,10 +140,7 @@ void ServicesController::refreshExistingServices(bool refreshImmediately)
             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);