1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #ifndef INCLUDED_FRAMEWORK_INC_SERVICES_DESKTOP_HXX
21 #define INCLUDED_FRAMEWORK_INC_SERVICES_DESKTOP_HXX
22 
23 #include <sal/config.h>
24 
25 #include <memory>
26 #include <vector>
27 
28 #include <classes/framecontainer.hxx>
29 #include <threadhelp/transactionbase.hxx>
30 
31 #include <com/sun/star/frame/XUntitledNumbers.hpp>
32 #include <com/sun/star/frame/XController.hpp>
33 #include <com/sun/star/frame/XDesktop2.hpp>
34 #include <com/sun/star/frame/XTerminateListener.hpp>
35 #include <com/sun/star/frame/XTask.hpp>
36 #include <com/sun/star/frame/XFramesSupplier.hpp>
37 #include <com/sun/star/frame/XFrames.hpp>
38 #include <com/sun/star/lang/XServiceInfo.hpp>
39 #include <com/sun/star/frame/XDispatchProvider.hpp>
40 #include <com/sun/star/frame/XTasksSupplier.hpp>
41 #include <com/sun/star/container/XEnumerationAccess.hpp>
42 #include <com/sun/star/frame/XDispatchResultListener.hpp>
43 #include <com/sun/star/lang/XEventListener.hpp>
44 #include <com/sun/star/lang/XComponent.hpp>
45 #include <com/sun/star/task/XInteractionHandler.hpp>
46 #include <com/sun/star/frame/XDispatchRecorderSupplier.hpp>
47 #include <com/sun/star/uno/XComponentContext.hpp>
48 
49 #include <cppuhelper/basemutex.hxx>
50 #include <cppuhelper/compbase.hxx>
51 #include <cppuhelper/propshlp.hxx>
52 #include <unotools/cmdoptions.hxx>
53 
54 namespace framework{
55 
56 enum ELoadState
57 {
58     E_NOTSET      ,
59     E_SUCCESSFUL  ,
60     E_FAILED      ,
61     E_INTERACTION
62 };
63 
64 /*-************************************************************************************************************
65     @short      implement the topframe of frame tree
66     @descr      This is the root of the frame tree. The desktop has no window, is not visible but he is the logical
67                 "masternode" to build the hierarchy.
68 
69     @implements XInterface
70                 XTypeProvider
71                 XServiceInfo
72                 XDesktop
73                 XComponentLoader
74                 XTasksSupplier
75                 XDispatchProvider
76                 XFramesSupplier
77                 XFrame
78                 XComponent
79                 XPropertySet
80                 XFastPropertySet
81                 XMultiPropertySet
82                 XDispatchResultListener
83                 XEventListener
84                 XInteractionHandler
85 
86     @devstatus  ready to use
87     @threadsafe yes
88 *//*-*************************************************************************************************************/
89 typedef cppu::WeakComponentImplHelper<
90            css::lang::XServiceInfo              ,
91            css::frame::XDesktop2                ,
92            css::frame::XTasksSupplier           ,
93            css::frame::XDispatchResultListener  ,   // => XEventListener
94            css::task::XInteractionHandler       ,
95            css::frame::XUntitledNumbers > Desktop_BASE;
96 
97 class Desktop : private cppu::BaseMutex,
98                 private TransactionBase,
99                 public Desktop_BASE,
100                 public cppu::OPropertySetHelper
101 {
102     // internal used types, const etcpp.
103     private:
104 
105         /** used temporary to know which listener was already called or not. */
106         typedef ::std::vector< css::uno::Reference< css::frame::XTerminateListener > > TTerminateListenerList;
107 
108     // public methods
109     public:
110 
111         //  constructor / destructor
112                  Desktop( const css::uno::Reference< css::uno::XComponentContext >& xContext );
113         virtual ~Desktop(                                                                    ) override;
114 
115         void constructorInit();
116 
117         //  XServiceInfo
118         virtual OUString SAL_CALL getImplementationName() override;
119 
120         virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override;
121 
122         virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
123 
124         // XInterface
acquire()125         virtual void SAL_CALL acquire() throw () override
126             { OWeakObject::acquire(); }
release()127         virtual void SAL_CALL release() throw () override
128             { OWeakObject::release(); }
129         virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& type) override;
130 
131         // XTypeProvider
132         virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes(  ) override;
133 
134         /**
135             @interface  XDesktop
136 
137             @short      try to shutdown these desktop environment.
138 
139             @descr      Will try to close all frames. If at least one frame could
140                         not be closed successfully termination will be stopped.
141 
142                         Registered termination listener will be taken into account
143                         also. As special feature some of our registered listener
144                         are well known by its UNO implementation name. They are handled
145                         different to all other listener.
146 
147                         Btw: Desktop.terminate() was designed in the past to be used
148                         within an UI based environment. So it's allowed e.g. to
149                         call XController.suspend() here. If UI isn't an option ... please
150                         use XCloseable.close() at these desktop implementation.
151                         ... if it will be supported in the future .-))
152 
153             @seealso    XTerminateListener
154             @seealso    XTerminateListener2
155 
156             @return     true if all open frames could be closed and no listener threw
157                         a veto exception; false otherwise.
158 
159             @onerror    False will be returned.
160             @threadsafe yes
161          */
162         virtual sal_Bool SAL_CALL terminate() override;
163 
164         /**
165             @interface  XDesktop
166 
167             @short      add a listener for termination events
168 
169             @descr      Additional to adding normal listener these method was implemented special.
170                         Every listener will be asked for its uno implementation name.
171                         Some of them are well known... and the corresponding listener won't be added
172                         to the container of "normal listener". Those listener will be set as special
173                         member.
174                         see e.g. member m_xSfxTerminator
175 
176             @seealso    terminate()
177 
178             @param      xListener
179                         the listener for registration.
180 
181             @threadsafe yes
182          */
183         virtual void SAL_CALL addTerminateListener( const css::uno::Reference< css::frame::XTerminateListener >& xListener ) override;
184 
185         /**
186             @interface  XDesktop
187 
188             @short      remove a listener from this container.
189 
190             @descr      Additional to removing normal listener these method was implemented special.
191                         Every listener will be asked for its uno implementation name.
192                         Some of them are well known... and the corresponding listener was set as special member.
193                         Now those special member will be reset also.
194                         see e.g. member m_xSfxTerminator
195 
196             @seealso    terminate()
197 
198             @param      xListener
199                         the listener for deregistration.
200 
201             @threadsafe yes
202          */
203         virtual void SAL_CALL removeTerminateListener( const css::uno::Reference< css::frame::XTerminateListener >& xListener ) override;
204 
205         virtual css::uno::Reference< css::container::XEnumerationAccess >           SAL_CALL getComponents              (                                                                                 ) override;
206         virtual css::uno::Reference< css::lang::XComponent >                        SAL_CALL getCurrentComponent        (                                                                                 ) override;
207         virtual css::uno::Reference< css::frame::XFrame >                           SAL_CALL getCurrentFrame            (                                                                                 ) override;
208 
209         //  XComponentLoader
210         virtual css::uno::Reference< css::lang::XComponent >                        SAL_CALL loadComponentFromURL       ( const OUString&                                         sURL             ,
211                                                                                                                           const OUString&                                         sTargetFrameName ,
212                                                                                                                                 sal_Int32                                                nSearchFlags     ,
213                                                                                                                           const css::uno::Sequence< css::beans::PropertyValue >&         lArguments       ) override;
214 
215         //  XTasksSupplier
216         virtual css::uno::Reference< css::container::XEnumerationAccess >           SAL_CALL getTasks                   (                                                                                 ) override;
217         virtual css::uno::Reference< css::frame::XTask >                            SAL_CALL getActiveTask              (                                                                                 ) override;
218 
219         //  XDispatchProvider
220         virtual css::uno::Reference< css::frame::XDispatch >                        SAL_CALL queryDispatch              ( const css::util::URL&                                          aURL             ,
221                                                                                                                           const OUString&                                         sTargetFrameName ,
222                                                                                                                                 sal_Int32                                                nSearchFlags     ) override;
223         virtual css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > >  SAL_CALL queryDispatches            ( const css::uno::Sequence< css::frame::DispatchDescriptor >&    lQueries         ) override;
224 
225         // XDispatchProviderInterception
226         virtual void                                                                SAL_CALL registerDispatchProviderInterceptor( const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor) override;
227         virtual void                                                                SAL_CALL releaseDispatchProviderInterceptor ( const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor) override;
228 
229         //  XFramesSupplier
230         virtual css::uno::Reference< css::frame::XFrames >                          SAL_CALL getFrames                  (                                                                                 ) override;
231         virtual css::uno::Reference< css::frame::XFrame >                           SAL_CALL getActiveFrame             (                                                                                 ) override;
232         virtual void                                                                SAL_CALL setActiveFrame             ( const css::uno::Reference< css::frame::XFrame >&               xFrame           ) override;
233 
234         //   XFrame
235         //  Attention: findFrame() is implemented only! Other methods make no sense for our desktop!
236         virtual css::uno::Reference< css::frame::XFrame >                           SAL_CALL findFrame                  ( const OUString&                                         sTargetFrameName ,
237                                                                                                                                 sal_Int32                                                nSearchFlags     ) override;
238         virtual void                                                                SAL_CALL initialize                 ( const css::uno::Reference< css::awt::XWindow >&                xWindow          ) override;
239         virtual css::uno::Reference< css::awt::XWindow >                            SAL_CALL getContainerWindow         (                                                                                 ) override;
240         virtual void                                                                SAL_CALL setCreator                 ( const css::uno::Reference< css::frame::XFramesSupplier >&      xCreator         ) override;
241         virtual css::uno::Reference< css::frame::XFramesSupplier >                  SAL_CALL getCreator                 (                                                                                 ) override;
242         virtual OUString                                                     SAL_CALL getName                    (                                                                                 ) override;
243         virtual void                                                                SAL_CALL setName                    ( const OUString&                                         sName            ) override;
244         virtual sal_Bool                                                            SAL_CALL isTop                      (                                                                                 ) override;
245         virtual void                                                                SAL_CALL activate                   (                                                                                 ) override;
246         virtual void                                                                SAL_CALL deactivate                 (                                                                                 ) override;
247         virtual sal_Bool                                                            SAL_CALL isActive                   (                                                                                 ) override;
248         virtual sal_Bool                                                            SAL_CALL setComponent               ( const css::uno::Reference< css::awt::XWindow >&                xComponentWindow ,
249                                                                                                                           const css::uno::Reference< css::frame::XController >&          xController      ) override;
250         virtual css::uno::Reference< css::awt::XWindow >                            SAL_CALL getComponentWindow         (                                                                                 ) override;
251         virtual css::uno::Reference< css::frame::XController >                      SAL_CALL getController              (                                                                                 ) override;
252         virtual void                                                                SAL_CALL contextChanged             (                                                                                 ) override;
253         virtual void                                                                SAL_CALL addFrameActionListener     ( const css::uno::Reference< css::frame::XFrameActionListener >& xListener        ) override;
254         virtual void                                                                SAL_CALL removeFrameActionListener  ( const css::uno::Reference< css::frame::XFrameActionListener >& xListener        ) override;
255 
256         //   XComponent
257         virtual void SAL_CALL disposing() override;
258         virtual void                                                                SAL_CALL addEventListener           ( const css::uno::Reference< css::lang::XEventListener >&        xListener        ) override;
259         virtual void                                                                SAL_CALL removeEventListener        ( const css::uno::Reference< css::lang::XEventListener >&        xListener        ) override;
260 
261         //   XDispatchResultListener
262         virtual void SAL_CALL dispatchFinished      ( const css::frame::DispatchResultEvent&                    aEvent     ) override;
263 
264         //   XEventListener
265         virtual void                                                                SAL_CALL disposing                  ( const css::lang::EventObject&                                  aSource          ) override;
266 
267         //   XInteractionHandler
268         virtual void                                                                SAL_CALL handle                     ( const css::uno::Reference< css::task::XInteractionRequest >&   xRequest         ) override;
269 
270         // css.frame.XUntitledNumbers
271         virtual ::sal_Int32 SAL_CALL leaseNumber( const css::uno::Reference< css::uno::XInterface >& xComponent ) override;
272 
273         // css.frame.XUntitledNumbers
274         virtual void SAL_CALL releaseNumber( ::sal_Int32 nNumber ) override;
275 
276         // css.frame.XUntitledNumbers
277         virtual void SAL_CALL releaseNumberForComponent( const css::uno::Reference< css::uno::XInterface >& xComponent ) override;
278 
279         // css.frame.XUntitledNumbers
280         virtual OUString SAL_CALL getUntitledPrefix() override;
281 
282         // we need this wrapped terminate()-call to terminate even the QuickStarter
283         // non-virtual and non-UNO for now
284         /// @throws css::uno::RuntimeException
285         bool terminateQuickstarterToo();
286 
287     //  protected methods
288 
289     protected:
290 
291         //  OPropertySetHelper
292         virtual sal_Bool                                            SAL_CALL convertFastPropertyValue        (       css::uno::Any&  aConvertedValue ,
293                                                                                                                      css::uno::Any&  aOldValue       ,
294                                                                                                                      sal_Int32       nHandle         ,
295                                                                                                                const css::uno::Any&  aValue          ) override;
296         virtual void                                                SAL_CALL setFastPropertyValue_NoBroadcast(       sal_Int32       nHandle         ,
297                                                                                                                const css::uno::Any&  aValue          ) override;
298         using cppu::OPropertySetHelper::getFastPropertyValue;
299         virtual void                                                SAL_CALL getFastPropertyValue            (       css::uno::Any&  aValue          ,
300                                                                                                                      sal_Int32       nHandle         ) const override;
301         virtual ::cppu::IPropertyArrayHelper&                       SAL_CALL getInfoHelper                   (                                       ) override;
302         virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo              (                                       ) override;
303 
304 
305     private:
306 
307         css::uno::Reference< css::lang::XComponent >            impl_getFrameComponent          ( const css::uno::Reference< css::frame::XFrame >&  xFrame          ) const;
308 
309         /** calls queryTermination() on every registered termination listener.
310          *
311          *  Note: Only normal termination listener (registered in list m_aListenerContainer
312          *        will be recognized here. Special listener like quick starter, pipe or others
313          *        has to be handled explicitly !
314          *
315          *  @param  [out] lCalledListener
316          *          every called listener will be returned here.
317          *          Those list will be used to inform all called listener
318          *          about cancel this termination request.
319          *
320          *  @param  [out] bVeto
321          *          will be true if at least one listener threw a veto exception;
322          *          false otherwise.
323          *
324          *  @see    impl_sendCancelTerminationEvent()
325          */
326         void impl_sendQueryTerminationEvent(TTerminateListenerList& lCalledListener,
327                                             bool&             bVeto          );
328 
329         /** calls cancelTermination() on every termination listener
330          *  where queryTermination() was called before.
331          *
332          *  Note: Only normal termination listener (registered in list m_aListenerContainer
333          *        will be recognized here. Special listener like quick starter, pipe or others
334          *        has to be handled explicitly !
335          *
336          *  @param  [in] lCalledListener
337          *          every listener in this list was called within its method
338          *          queryTermination() before.
339          *
340          *  @see    impl_sendQueryTerminationEvent()
341          */
342         void impl_sendCancelTerminationEvent(const TTerminateListenerList& lCalledListener);
343 
344         /** calls notifyTermination() on the clipboard listener
345          *
346          * The system clipboard may decide that it wants copies
347          * in several formats of the clipboard content requiring
348          * nearly all the services
349          *
350          */
351         void impl_sendTerminateToClipboard();
352 
353         /** calls notifyTermination() on every registered termination listener.
354          *
355          *  Note: Only normal termination listener (registered in list m_aListenerContainer
356          *        will be recognized here. Special listener like quick starter, pipe or others
357          *        has to be handled explicitly !
358          */
359         void impl_sendNotifyTerminationEvent();
360 
361         /** try to close all open frames.
362          *
363          *  Iterates over all child frames and try to close them.
364          *  Given parameter bAllowUI enable/disable showing any UI
365          *  (which mostly occur on calling XController->suspend()).
366          *
367          *  This method doesn't stop if one frame could not be closed.
368          *  It will ignore such frames and try all other ones.
369          *  But it returns false in such case - true otherwise.
370          *
371          *  @param  bAllowUI
372          *          enable/disable showing of UI.
373          *
374          *  @return true if all frames could be closed; false otherwise.
375          */
376         bool impl_closeFrames(bool bAllowUI);
377 
378     private:
379 
380         /** check flag to protect us against dispose before terminate!
381           *   see dispose() for further information!
382           */
383         bool m_bIsTerminated;
384 
385         /** when true, the call came from session manager
386           *   the method is Desktop::terminateQuickstarterToo()
387           *   this the only one place where set this to true
388           *   In this case,  when one frame break, not make
389           *   question for other, the break of shutdown or logout
390           *   can be only once.
391           *   In Desktop::impl_closeFrames would be test and break
392           *   the loop and reset to false
393           */
394         bool m_bSession;
395 
396         css::uno::Reference< css::uno::XComponentContext >              m_xContext;               /// reference to factory, which has create this instance
397         FrameContainer                                                  m_aChildTaskContainer;    /// array of child tasks (children of desktop are tasks; and tasks are also frames - But pure frames are not accepted!)
398         ::cppu::OMultiTypeInterfaceContainerHelper                      m_aListenerContainer;     /// container for ALL Listener
399         css::uno::Reference< css::frame::XFrames >                      m_xFramesHelper;          /// helper for XFrames, XIndexAccess, XElementAccess and implementation of a childcontainer!
400         css::uno::Reference< css::frame::XDispatchProvider >            m_xDispatchHelper;        /// helper to dispatch something for new tasks, created by "_blank"!
401         ELoadState                                                      m_eLoadState;             /// hold information about state of asynchron loading of component for loadComponentFromURL()!
402         bool                                                            m_bSuspendQuickstartVeto; /// don't ask quickstart for a veto
403         std::unique_ptr<SvtCommandOptions>                              m_xCommandOptions;        /// ref counted class to support disabling commands defined by configuration file
404         OUString                                                        m_sName;
405         OUString                                                        m_sTitle;
406         css::uno::Reference< css::frame::XDispatchRecorderSupplier >    m_xDispatchRecorderSupplier;
407 
408         /** special terminate listener to close pipe and block external requests
409           * during/after termination process is/was running
410           */
411         css::uno::Reference< css::frame::XTerminateListener > m_xPipeTerminator;
412 
413         /** special terminate listener shown inside system tray (quick starter)
414           * Will hinder the office on shutdown ... but wish to allow closing
415           * of open documents. And because that's different to a normal terminate listener
416           * it has to be handled special .-)
417           */
418         css::uno::Reference< css::frame::XTerminateListener > m_xQuickLauncher;
419 
420         /** special terminate listener active when a macro is executing.
421           * Because basic runs Application::Yield internally the application may quit
422           * while running inside the internal basic event loop. So all the basic
423           * infrastructure may be deleted while the call is executing, leading to
424           * a variant of crashes. So this special terminate listener will
425           * veto the current quit attempt, stop basic execution, which will
426           * cause the inner event loop to quit, and on return to the outer normal
427           * application event loop then resend the quit attempt.
428           * So these implementation must be a special terminate listener too .-(
429           */
430         css::uno::Reference< css::frame::XTerminateListener > m_xStarBasicQuitGuard;
431 
432         /** special terminate listener which loads images asynchronous for current open documents.
433           * Because internally it uses blocking system APIs... it can't be guaranteed that
434           * running jobs can be cancelled successfully if the corresponding document will be closed...
435           * it will not hinder those documents on closing. Instead it let all jobs running...
436           * but at least on terminate we have to wait for all those blocked requests.
437           * So these implementation must be a special terminate listener too .-(
438           */
439         css::uno::Reference< css::frame::XTerminateListener > m_xSWThreadManager;
440 
441         /** special terminate listener shutting down the SfxApplication.
442           * Because these desktop instance closes documents and informs listener
443           * only... it does not really shutdown the whole application.
444           *
445           * Btw: that wouldn't be possible by design... because Desktop.terminate()
446           * has to return a boolean value about success... it can't really shutdown the
447           * process .-)
448           *
449           * So we uses a trick: a special listener (exactly these one here) listen for notifyTermination()
450           * and shutdown the process asynchronous. But desktop has to make this special
451           * notification as really last one ... Otherwise it can happen that asynchronous
452           * shutdown will be faster then all other code around Desktop.terminate() .-))
453           */
454         css::uno::Reference< css::frame::XTerminateListener > m_xSfxTerminator;
455 
456         css::uno::Reference< css::frame::XUntitledNumbers > m_xTitleNumberGenerator;
457 
458         std::vector<css::uno::Reference<css::frame::XTerminateListener>> m_xComponentDllListeners;
459 
460 };      //  class Desktop
461 
462 }       //  namespace framework
463 
464 #endif // INCLUDED_FRAMEWORK_INC_SERVICES_DESKTOP_HXX
465 
466 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
467