cid#1607171 Data race condition
[LibreOffice.git] / framework / source / dispatch / popupmenudispatcher.cxx
blob1379d7ee7e81d04fc5901c4cb82383a7a7284d6d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <dispatch/popupmenudispatcher.hxx>
21 #include <services.h>
22 #include <properties.h>
24 #include <com/sun/star/frame/XLayoutManager2.hpp>
25 #include <com/sun/star/beans/XPropertySet.hpp>
26 #include <com/sun/star/uri/UriReferenceFactory.hpp>
27 #include <com/sun/star/ui/XUIElement.hpp>
29 #include <cppuhelper/supportsservice.hxx>
30 #include <sal/log.hxx>
31 #include <utility>
32 #include <vcl/svapp.hxx>
34 namespace framework{
36 using namespace ::com::sun::star;
37 using namespace ::com::sun::star::awt;
38 using namespace ::com::sun::star::beans;
39 using namespace ::com::sun::star::container;
40 using namespace ::com::sun::star::frame;
41 using namespace ::com::sun::star::lang;
42 using namespace ::com::sun::star::uno;
43 using namespace ::com::sun::star::util;
44 using namespace ::cppu;
45 using namespace ::osl;
47 PopupMenuDispatcher::PopupMenuDispatcher(
48 uno::Reference< XComponentContext > xContext )
49 : m_xContext (std::move( xContext ))
50 , m_bAlreadyDisposed ( false )
51 , m_bActivateListener ( false )
55 PopupMenuDispatcher::~PopupMenuDispatcher()
57 // Warn programmer if he forgot to dispose this instance.
58 // We must release all our references ...
59 // and a dtor isn't the best place to do that!
62 OUString SAL_CALL PopupMenuDispatcher::getImplementationName()
64 return u"com.sun.star.comp.framework.PopupMenuControllerDispatcher"_ustr;
67 sal_Bool SAL_CALL PopupMenuDispatcher::supportsService( const OUString& sServiceName )
69 return cppu::supportsService(this, sServiceName);
72 css::uno::Sequence< OUString > SAL_CALL PopupMenuDispatcher::getSupportedServiceNames()
74 return { SERVICENAME_PROTOCOLHANDLER };
77 void SAL_CALL PopupMenuDispatcher::initialize( const css::uno::Sequence< css::uno::Any >& lArguments )
79 css::uno::Reference< css::frame::XFrame > xFrame;
81 SolarMutexGuard g;
82 for (int a=0; a<lArguments.getLength(); ++a)
84 if (a==0)
86 lArguments[a] >>= xFrame;
87 m_xWeakFrame = xFrame;
89 m_bActivateListener = true;
90 uno::Reference< css::frame::XFrameActionListener > xFrameActionListener(this);
91 xFrame->addFrameActionListener( xFrameActionListener );
96 css::uno::Reference< css::frame::XDispatch >
97 SAL_CALL PopupMenuDispatcher::queryDispatch(
98 const css::util::URL& rURL ,
99 const OUString& sTarget ,
100 sal_Int32 nFlags )
102 if ( !rURL.Complete.startsWith( "vnd.sun.star.popup:" ) )
103 return {};
105 // --- SAFE ---
106 SolarMutexClearableGuard aGuard;
107 impl_RetrievePopupControllerQuery();
108 if ( !m_xUriRefFactory.is() )
109 m_xUriRefFactory = css::uri::UriReferenceFactory::create( m_xContext );
111 css::uno::Reference< css::container::XNameAccess > xPopupCtrlQuery( m_xPopupCtrlQuery );
112 aGuard.clear();
113 // --- SAFE ---
115 if ( !xPopupCtrlQuery.is() )
116 return {};
118 css::uno::Reference< css::frame::XDispatch > xDispatch;
122 // Just use the main part of the URL for popup menu controllers
123 sal_Int32 nSchemePart( 0 );
124 OUString aBaseURL( u"vnd.sun.star.popup:"_ustr );
125 OUString aURL( rURL.Complete );
127 nSchemePart = aURL.indexOf( ':' );
128 if (( nSchemePart > 0 ) &&
129 ( aURL.getLength() > ( nSchemePart+1 )))
131 sal_Int32 nQueryPart = aURL.indexOf( '?', nSchemePart );
132 if ( nQueryPart > 0 )
133 aBaseURL += aURL.subView( nSchemePart+1, nQueryPart-(nSchemePart+1) );
134 else if ( nQueryPart == -1 )
135 aBaseURL += aURL.subView( nSchemePart+1 );
138 css::uno::Reference< css::frame::XDispatchProvider > xDispatchProvider;
140 // Find popup menu controller using the base URL
141 xPopupCtrlQuery->getByName( aBaseURL ) >>= xDispatchProvider;
143 // Ask popup menu dispatch provider for dispatch object
144 if ( xDispatchProvider.is() )
145 xDispatch = xDispatchProvider->queryDispatch( rURL, sTarget, nFlags );
147 catch ( const RuntimeException& )
149 throw;
151 catch ( const Exception& )
154 return xDispatch;
157 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL
158 PopupMenuDispatcher::queryDispatches(
159 const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor )
161 sal_Int32 nCount = lDescriptor.getLength();
162 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatcher( nCount );
163 auto lDispatcherRange = asNonConstRange(lDispatcher);
164 for( sal_Int32 i=0; i<nCount; ++i )
166 lDispatcherRange[i] = queryDispatch(
167 lDescriptor[i].FeatureURL,
168 lDescriptor[i].FrameName,
169 lDescriptor[i].SearchFlags);
171 return lDispatcher;
174 void SAL_CALL PopupMenuDispatcher::dispatch( const URL& /*aURL*/, const Sequence< PropertyValue >& /*seqProperties*/ )
178 void SAL_CALL PopupMenuDispatcher::addStatusListener( const uno::Reference< XStatusListener >& /*xControl*/,
179 const URL& /*aURL*/ )
183 void SAL_CALL PopupMenuDispatcher::removeStatusListener( const uno::Reference< XStatusListener >& /*xControl*/,
184 const URL& /*aURL*/ )
188 void SAL_CALL PopupMenuDispatcher::frameAction( const FrameActionEvent& aEvent )
190 SolarMutexGuard g;
191 if (( aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING ) ||
192 ( aEvent.Action == css::frame::FrameAction_COMPONENT_ATTACHED ))
194 // Reset query reference to requery it again next time
195 m_xPopupCtrlQuery.clear();
199 void SAL_CALL PopupMenuDispatcher::disposing( const EventObject& )
201 SolarMutexGuard g;
202 // Safe impossible cases
203 SAL_WARN_IF( m_bAlreadyDisposed, "fwk", "MenuDispatcher::disposing(): Object already disposed .. don't call it again!" );
205 if( m_bAlreadyDisposed )
206 return;
208 m_bAlreadyDisposed = true;
210 if ( m_bActivateListener )
212 uno::Reference< XFrame > xFrame( m_xWeakFrame.get(), UNO_QUERY );
213 if ( xFrame.is() )
215 xFrame->removeFrameActionListener( uno::Reference< XFrameActionListener >(this) );
216 m_bActivateListener = false;
220 // Forget our factory.
221 m_xContext.clear();
224 void PopupMenuDispatcher::impl_RetrievePopupControllerQuery()
226 if ( m_xPopupCtrlQuery.is() )
227 return;
229 css::uno::Reference< css::frame::XLayoutManager2 > xLayoutManager;
230 css::uno::Reference< css::frame::XFrame > xFrame( m_xWeakFrame );
232 if ( !xFrame.is() )
233 return;
235 css::uno::Reference< css::beans::XPropertySet > xPropSet( xFrame, css::uno::UNO_QUERY );
236 if ( !xPropSet.is() )
237 return;
241 xPropSet->getPropertyValue( FRAME_PROPNAME_ASCII_LAYOUTMANAGER ) >>= xLayoutManager;
243 if ( xLayoutManager.is() )
245 css::uno::Reference< css::ui::XUIElement > xMenuBar = xLayoutManager->getElement( u"private:resource/menubar/menubar"_ustr );
247 m_xPopupCtrlQuery.set( xMenuBar, css::uno::UNO_QUERY );
250 catch ( const css::uno::RuntimeException& )
252 throw;
254 catch ( const css::uno::Exception& )
259 } // namespace framework
262 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
263 framework_PopupMenuDispatcher_get_implementation(
264 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
266 return cppu::acquire(new framework::PopupMenuDispatcher(context));
269 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */