Title: [172366] trunk/Source/WebKit2
Revision
172366
Author
[email protected]
Date
2014-08-08 16:27:25 -0700 (Fri, 08 Aug 2014)

Log Message

[mac] Dynamically update serviceability when the set of services changes
https://bugs.webkit.org/show_bug.cgi?id=135738
<rdar://problem/17533459>

Reviewed by Brady Eidson.

* UIProcess/WebContext.cpp:
(WebKit::WebContext::createNewWebProcess):
Adopt the new universal refreshExistingServices.

(WebKit::WebContext::refreshExistingServices): Deleted.
* UIProcess/WebContext.h:
Remove WebContext::refreshExistingServices; there's no need for it.

* UIProcess/mac/ServicesController.h:
* UIProcess/mac/ServicesController.mm:
Fix the build with only public headers by including NSSharingService.h itself.
Place the NSSharingServicePicker (Details) category outside the #ifdef.
Forward-declare and possibly import NSExtension SPI.

(WebKit::ServicesController::ServicesController):
Register a callback to be notified whenever the set of services changes.
When this occurs, call refreshExistingServices. We let refreshExistingServices
coalesce updates because these notifications can come in small batches.

(WebKit::ServicesController::refreshExistingServices):
Dispatch changes in service availability to all processes in all contexts.

* UIProcess/mac/WebContextMenuProxyMac.mm:
(WebKit::WebContextMenuProxyMac::setupServicesMenu):
Adjust the referenced rdar:// and call ServicesController::refreshExistingServices
instead of the now-removed WebContext:: variant. We can't remove this
yet because our services state can still be stale because NSServiceSharingPicker
can still sometimes lie about the current service state immediately after a change occurs;
once that is fixed, we should get rid of this as well as the refresh in Web Process creation.

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (172365 => 172366)


--- trunk/Source/WebKit2/ChangeLog	2014-08-08 23:24:02 UTC (rev 172365)
+++ trunk/Source/WebKit2/ChangeLog	2014-08-08 23:27:25 UTC (rev 172366)
@@ -1,3 +1,41 @@
+2014-08-08  Tim Horton  <[email protected]>
+
+        [mac] Dynamically update serviceability when the set of services changes
+        https://bugs.webkit.org/show_bug.cgi?id=135738
+        <rdar://problem/17533459>
+
+        Reviewed by Brady Eidson.
+
+        * UIProcess/WebContext.cpp:
+        (WebKit::WebContext::createNewWebProcess):
+        Adopt the new universal refreshExistingServices.
+
+        (WebKit::WebContext::refreshExistingServices): Deleted.
+        * UIProcess/WebContext.h:
+        Remove WebContext::refreshExistingServices; there's no need for it.
+
+        * UIProcess/mac/ServicesController.h:
+        * UIProcess/mac/ServicesController.mm:
+        Fix the build with only public headers by including NSSharingService.h itself.
+        Place the NSSharingServicePicker (Details) category outside the #ifdef.
+        Forward-declare and possibly import NSExtension SPI.
+
+        (WebKit::ServicesController::ServicesController):
+        Register a callback to be notified whenever the set of services changes.
+        When this occurs, call refreshExistingServices. We let refreshExistingServices
+        coalesce updates because these notifications can come in small batches.
+
+        (WebKit::ServicesController::refreshExistingServices):
+        Dispatch changes in service availability to all processes in all contexts.
+
+        * UIProcess/mac/WebContextMenuProxyMac.mm:
+        (WebKit::WebContextMenuProxyMac::setupServicesMenu):
+        Adjust the referenced rdar:// and call ServicesController::refreshExistingServices
+        instead of the now-removed WebContext:: variant. We can't remove this
+        yet because our services state can still be stale because NSServiceSharingPicker
+        can still sometimes lie about the current service state immediately after a change occurs;
+        once that is fixed, we should get rid of this as well as the refresh in Web Process creation.
+
 2014-08-08  Timothy Horton  <[email protected]>
 
         Clients that request the selection services menu after WebKit2 will get one with different metrics than otherwise

Modified: trunk/Source/WebKit2/UIProcess/WebContext.cpp (172365 => 172366)


--- trunk/Source/WebKit2/UIProcess/WebContext.cpp	2014-08-08 23:24:02 UTC (rev 172365)
+++ trunk/Source/WebKit2/UIProcess/WebContext.cpp	2014-08-08 23:27:25 UTC (rev 172366)
@@ -682,7 +682,7 @@
     parameters.hasImageServices = ServicesController::shared().hasImageServices();
     parameters.hasSelectionServices = ServicesController::shared().hasSelectionServices();
     parameters.hasRichContentServices = ServicesController::shared().hasRichContentServices();
-    ServicesController::shared().refreshExistingServices(this);
+    ServicesController::shared().refreshExistingServices();
 #endif
 
     // Add any platform specific parameters
@@ -1361,14 +1361,6 @@
     request->completedRequest(requestID, statisticsData);
 }
 
-#if ENABLE(SERVICE_CONTROLS)
-void WebContext::refreshExistingServices()
-{
-    ServicesController::shared().refreshExistingServices(this);
-}
-#endif
-
-    
 void WebContext::garbageCollectJavaScriptObjects()
 {
     sendToAllProcesses(Messages::WebProcess::GarbageCollectJavaScriptObjects());

Modified: trunk/Source/WebKit2/UIProcess/WebContext.h (172365 => 172366)


--- trunk/Source/WebKit2/UIProcess/WebContext.h	2014-08-08 23:24:02 UTC (rev 172365)
+++ trunk/Source/WebKit2/UIProcess/WebContext.h	2014-08-08 23:27:25 UTC (rev 172366)
@@ -352,10 +352,6 @@
 
     void setMemoryCacheDisabled(bool);
 
-#if ENABLE(SERVICE_CONTROLS)
-    void refreshExistingServices();
-#endif
-
 private:
     void platformInitialize();
 

Modified: trunk/Source/WebKit2/UIProcess/mac/ServicesController.h (172365 => 172366)


--- trunk/Source/WebKit2/UIProcess/mac/ServicesController.h	2014-08-08 23:24:02 UTC (rev 172365)
+++ trunk/Source/WebKit2/UIProcess/mac/ServicesController.h	2014-08-08 23:27:25 UTC (rev 172366)
@@ -28,10 +28,9 @@
 
 #if ENABLE(SERVICE_CONTROLS)
 
-#include <wtf/HashSet.h>
+#include <wtf/Forward.h>
 #include <wtf/Noncopyable.h>
-#include <wtf/RefPtr.h>
-#include <wtf/RunLoop.h>
+#include <wtf/RetainPtr.h>
 
 namespace WebKit {
 
@@ -47,21 +46,20 @@
     bool hasSelectionServices() const { return m_hasSelectionServices; }
     bool hasRichContentServices() const { return m_hasRichContentServices; }
 
-    void refreshExistingServices(WebContext*);
+    void refreshExistingServices(bool refreshImmediately = true);
 
 private:
     ServicesController();
 
-    void refreshExistingServices();
-
     dispatch_queue_t m_refreshQueue;
-    bool m_isRefreshing;
+    std::atomic_bool m_hasPendingRefresh;
 
     bool m_hasImageServices;
     bool m_hasSelectionServices;
     bool m_hasRichContentServices;
 
-    HashSet<RefPtr<WebContext>> m_contextsToNotify;
+    RetainPtr<id> m_extensionWatcher;
+    RetainPtr<id> m_uiExtensionWatcher;
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit2/UIProcess/mac/ServicesController.mm (172365 => 172366)


--- trunk/Source/WebKit2/UIProcess/mac/ServicesController.mm	2014-08-08 23:24:02 UTC (rev 172365)
+++ trunk/Source/WebKit2/UIProcess/mac/ServicesController.mm	2014-08-08 23:27:25 UTC (rev 172366)
@@ -30,6 +30,7 @@
 
 #import "WebContext.h"
 #import "WebProcessMessages.h"
+#import <AppKit/NSSharingService.h>
 #import <wtf/NeverDestroyed.h>
 
 #if __has_include(<AppKit/NSSharingService_Private.h>)
@@ -41,13 +42,24 @@
     NSSharingServicePickerStyleTextSelection = 2,
     NSSharingServicePickerStyleDataDetector = 3
 } NSSharingServicePickerStyle;
+#endif
 
 @interface NSSharingServicePicker (Details)
 @property NSSharingServicePickerStyle style;
 - (NSMenu *)menu;
 @end
+
+#if __has_include(<Foundation/NSExtension.h>)
+#import <Foundation/NSExtension.h>
+#else
+@interface NSExtension
+@end
 #endif
 
+@interface NSExtension (Details)
++ (id)beginMatchingExtensionsWithAttributes:(NSDictionary *)attributes completion:(void (^)(NSArray *matchingExtensions, NSError *error))handler;
+@end
+
 namespace WebKit {
 
 ServicesController& ServicesController::shared()
@@ -58,30 +70,33 @@
 
 ServicesController::ServicesController()
     : m_refreshQueue(dispatch_queue_create("com.apple.WebKit.ServicesController", DISPATCH_QUEUE_SERIAL))
-    , m_isRefreshing(false)
+    , m_hasPendingRefresh(false)
     , m_hasImageServices(false)
     , m_hasSelectionServices(false)
     , m_hasRichContentServices(false)
 {
     refreshExistingServices();
-}
 
-void ServicesController::refreshExistingServices(WebContext* context)
-{
-    ASSERT_ARG(context, context);
-    ASSERT([NSThread isMainThread]);
+    auto refreshCallback = [](NSArray *, NSError *) {
+        // We coalese refreshes from the notification callbacks because they can come in small batches.
+        ServicesController::shared().refreshExistingServices(false);
+    };
 
-    m_contextsToNotify.add(context);
-    refreshExistingServices();
+    auto extensionAttributes = @{ @"NSExtensionPointName" : @"com.apple.services" };
+    m_extensionWatcher = [NSExtension beginMatchingExtensionsWithAttributes:extensionAttributes completion:refreshCallback];
+    auto uiExtensionAttributes = @{ @"NSExtensionPointName" : @"com.apple.ui-services" };
+    m_uiExtensionWatcher = [NSExtension beginMatchingExtensionsWithAttributes:uiExtensionAttributes completion:refreshCallback];
 }
 
-void ServicesController::refreshExistingServices()
+void ServicesController::refreshExistingServices(bool refreshImmediately)
 {
-    if (m_isRefreshing)
+    if (m_hasPendingRefresh)
         return;
 
-    m_isRefreshing = true;
-    dispatch_async(m_refreshQueue, ^{
+    m_hasPendingRefresh = true;
+
+    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];
@@ -110,19 +125,18 @@
         bool hasRichContentServices = picker.get().menu;
         
         dispatch_async(dispatch_get_main_queue(), ^{
-            bool notifyContexts = (hasImageServices != m_hasImageServices) || (hasSelectionServices != m_hasSelectionServices) || (hasRichContentServices != m_hasRichContentServices);
+            bool availableServicesChanged = (hasImageServices != m_hasImageServices) || (hasSelectionServices != m_hasSelectionServices) || (hasRichContentServices != m_hasRichContentServices);
+
             m_hasSelectionServices = hasSelectionServices;
             m_hasImageServices = hasImageServices;
             m_hasRichContentServices = hasRichContentServices;
 
-            if (notifyContexts) {
-                for (const RefPtr<WebContext>& context : m_contextsToNotify)
+            if (availableServicesChanged) {
+                for (auto& context : WebContext::allContexts())
                     context->sendToAllProcesses(Messages::WebProcess::SetEnabledServices(m_hasImageServices, m_hasSelectionServices, m_hasRichContentServices));
             }
 
-            m_contextsToNotify.clear();
-
-            m_isRefreshing = false;
+            m_hasPendingRefresh = false;
         });
     });
 }

Modified: trunk/Source/WebKit2/UIProcess/mac/WebContextMenuProxyMac.mm (172365 => 172366)


--- trunk/Source/WebKit2/UIProcess/mac/WebContextMenuProxyMac.mm	2014-08-08 23:24:02 UTC (rev 172365)
+++ trunk/Source/WebKit2/UIProcess/mac/WebContextMenuProxyMac.mm	2014-08-08 23:27:25 UTC (rev 172366)
@@ -31,6 +31,7 @@
 #import "DataReference.h"
 #import "MenuUtilities.h"
 #import "PageClientImpl.h"
+#import "ServicesController.h"
 #import "ShareableBitmap.h"
 #import "StringUtilities.h"
 #import "WebContext.h"
@@ -412,11 +413,10 @@
         }
     }
 
-    // If there is no services menu, then the existing services on the system have changed.
-    // Ask the UIProcess to refresh that list of services.
-    // If <rdar://problem/16776831> is resolved then we can more accurately keep the list up to date without this call.
+    // If there is no services menu, then the existing services on the system have changed, so refresh that list of services.
+    // If <rdar://problem/17954709> is resolved then we can more accurately keep the list up to date without this call.
     if (!m_servicesMenu)
-        m_page->process().context().refreshExistingServices();
+        ServicesController::shared().refreshExistingServices();
 }
 
 void WebContextMenuProxyMac::clearServicesMenu()
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to