framework/inc/dispatch/dispatchprovider.hxx    |    2 ++
 framework/source/dispatch/dispatchprovider.cxx |   22 +++++++++++++++++-----
 2 files changed, 19 insertions(+), 5 deletions(-)

New commits:
commit cc012114572b4871fbfa8059c0bde332830a6e63
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Mon May 2 16:25:31 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Tue May 3 09:41:10 2022 +0200

    framework: avoid re-creating protocol handler instances all the time
    
    Once you install an extension that adds its own protocol handlers (e.g.
    <https://github.com/niocs/ProtocolHandlerExtension>), DispatchProvider
    re-creates this protocol handler every time the custom menu gets opened
    or a command gets dispatched.
    
    This allows the dispatch provider to avoid managing the lifecycle of
    those protocol handler instances, but in case the constructor of those
    handlers is expensive, this leads to performance problems.
    
    Introduce a map of handler instances in DispatchProvider to avoid
    unnecessary re-creation and re-initialization: these instances get the
    same XFrame anyway (the DispatchProvider is owned by the frame), so this
    is meant to be safe.
    
    No testcase for this -- the problem is only visible if you have an UNO
    service registered in the global UNO service registry, but by the time
    our cppunit tests run, that is already a fixed list, so this would be
    hard to test from code.
    
    (cherry picked from commit 3f768cddd28a2f04eb1ffa30bed4474deb6fbfc4)
    
    Change-Id: I6d69906a795a2d5a67706002d635b6cb3091b856

diff --git a/framework/inc/dispatch/dispatchprovider.hxx 
b/framework/inc/dispatch/dispatchprovider.hxx
index d94b53c45340..5062149580a7 100644
--- a/framework/inc/dispatch/dispatchprovider.hxx
+++ b/framework/inc/dispatch/dispatchprovider.hxx
@@ -75,6 +75,8 @@ class DispatchProvider final : public ::cppu::WeakImplHelper< 
css::frame::XDispa
         css::uno::WeakReference< css::frame::XFrame > m_xFrame;
         /// cache of some other dispatch provider which are registered inside 
configuration to handle special URL protocols
         HandlerCache m_aProtocolHandlerCache;
+        std::unordered_map<OUString, 
css::uno::Reference<css::frame::XDispatchProvider>>
+            m_aProtocolHandlers;
 
     /* interface */
     public:
diff --git a/framework/source/dispatch/dispatchprovider.cxx 
b/framework/source/dispatch/dispatchprovider.cxx
index 9d86254061a7..1c6a56c1263e 100644
--- a/framework/source/dispatch/dispatchprovider.cxx
+++ b/framework/source/dispatch/dispatchprovider.cxx
@@ -440,18 +440,30 @@ css::uno::Reference< css::frame::XDispatch > 
DispatchProvider::implts_searchProt
             SolarMutexGuard g;
 
             // create it
+            bool bInitialize = true;
             try
             {
-                xHandler.set(
-                    
css::uno::Reference<css::lang::XMultiServiceFactory>(m_xContext->getServiceManager(),
 css::uno::UNO_QUERY_THROW)
-                      ->createInstance(aHandler.m_sUNOName),
-                    css::uno::UNO_QUERY);
+                // Only create the protocol handler instance once, the 
creation is expensive.
+                auto it = m_aProtocolHandlers.find(aHandler.m_sUNOName);
+                if (it == m_aProtocolHandlers.end())
+                {
+                    xHandler.set(
+                        
css::uno::Reference<css::lang::XMultiServiceFactory>(m_xContext->getServiceManager(),
 css::uno::UNO_QUERY_THROW)
+                          ->createInstance(aHandler.m_sUNOName),
+                        css::uno::UNO_QUERY);
+                    m_aProtocolHandlers.emplace(aHandler.m_sUNOName, xHandler);
+                }
+                else
+                {
+                    xHandler = it->second;
+                    bInitialize = false;
+                }
             }
             catch(const css::uno::Exception&) {}
 
             // look if initialization is necessary
             css::uno::Reference< css::lang::XInitialization > xInit( xHandler, 
css::uno::UNO_QUERY );
-            if (xInit.is())
+            if (xInit.is() && bInitialize)
             {
                 css::uno::Reference< css::frame::XFrame > xOwner( 
m_xFrame.get(), css::uno::UNO_QUERY );
                 SAL_WARN_IF(!xOwner.is(), "fwk", 
"DispatchProvider::implts_searchProtocolHandler(): Couldn't get reference to my 
owner frame. So I can't set may needed context information for this protocol 
handler.");

Reply via email to