xref: /trunk/main/framework/source/loadenv/loadenv.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_framework.hxx"
26 //_______________________________________________
27 // includes of own project
28 #include <loadenv/loadenv.hxx>
29 
30 #ifndef __FRAMEWORK_LOADENV_TARGETHELPER_HXX_
31 #include <loadenv/targethelper.hxx>
32 #endif
33 #include <framework/framelistanalyzer.hxx>
34 
35 #ifndef __FRAMEWORK_CONSTANT_FRAMELOADER_HXX_
36 #include <constant/frameloader.hxx>
37 #endif
38 
39 #ifndef __FRAMEWORK_CONSTANT_CONTENTHANDLER_HXX_
40 #include <constant/contenthandler.hxx>
41 #endif
42 
43 #ifndef __FRAMEWORK_CONSTANT_CONTAINERQUERY_HXX_
44 #include <constant/containerquery.hxx>
45 #endif
46 #include <interaction/quietinteraction.hxx>
47 #include <threadhelp/writeguard.hxx>
48 #include <threadhelp/readguard.hxx>
49 #include <threadhelp/resetableguard.hxx>
50 #include <properties.h>
51 #include <protocols.h>
52 #include <services.h>
53 #include <comphelper/interaction.hxx>
54 #include <framework/interaction.hxx>
55 
56 //_______________________________________________
57 // includes of uno interface
58 #include <com/sun/star/task/ErrorCodeRequest.hpp>
59 #include <com/sun/star/uno/RuntimeException.hpp>
60 #include <com/sun/star/frame/DispatchResultState.hpp>
61 #include <com/sun/star/frame/FrameSearchFlag.hpp>
62 #include <com/sun/star/util/XURLTransformer.hpp>
63 #include <com/sun/star/ucb/XContentProviderManager.hpp>
64 #include <com/sun/star/util/XCloseable.hpp>
65 #include <com/sun/star/lang/XComponent.hpp>
66 #include <com/sun/star/lang/XServiceInfo.hpp>
67 #include <com/sun/star/lang/DisposedException.hpp>
68 #include <com/sun/star/awt/XWindow.hpp>
69 #include <com/sun/star/awt/XWindow2.hpp>
70 #include <com/sun/star/awt/XTopWindow.hpp>
71 #include <com/sun/star/frame/XModel.hpp>
72 #include <com/sun/star/frame/XFrameLoader.hpp>
73 #include <com/sun/star/frame/XSynchronousFrameLoader.hpp>
74 #include <com/sun/star/frame/XNotifyingDispatch.hpp>
75 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
76 #include <com/sun/star/task/XStatusIndicator.hpp>
77 #include <com/sun/star/util/XModifiable.hpp>
78 #include <com/sun/star/frame/XDispatchProvider.hpp>
79 #include <com/sun/star/document/XTypeDetection.hpp>
80 #include <com/sun/star/document/XActionLockable.hpp>
81 #include <com/sun/star/io/XInputStream.hpp>
82 #include <com/sun/star/task/XInteractionHandler.hpp>
83 #include <com/sun/star/container/XNameAccess.hpp>
84 #include <com/sun/star/container/XContainerQuery.hpp>
85 #include <com/sun/star/container/XEnumeration.hpp>
86 #include <com/sun/star/document/MacroExecMode.hpp>
87 #include <com/sun/star/document/UpdateDocMode.hpp>
88 
89 //_______________________________________________
90 // includes of an other project
91 #include <vcl/window.hxx>
92 #include <vcl/wrkwin.hxx>
93 #include <vcl/syswin.hxx>
94 
95 #ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_
96 #include <toolkit/helper/vclunohelper.hxx>
97 #endif
98 #include <unotools/moduleoptions.hxx>
99 #include <svtools/sfxecode.hxx>
100 #include <unotools/processfactory.hxx>
101 #include <unotools/ucbhelper.hxx>
102 #include <comphelper/configurationhelper.hxx>
103 #include <rtl/ustrbuf.hxx>
104 #include <vcl/svapp.hxx>
105 
106 //_______________________________________________
107 // namespace
108 
109 namespace framework{
110 
111 // may there exist already a define .-(
112 #ifndef css
113 namespace css = ::com::sun::star;
114 #endif
115 
116 //_______________________________________________
117 // declarations
118 
119 class LoadEnvListener : private ThreadHelpBase
120                       , public ::cppu::WeakImplHelper2< css::frame::XLoadEventListener      ,
121                                                         css::frame::XDispatchResultListener >
122 {
123     private:
124 
125         void**   m_ppCheck ;
126         LoadEnv* m_pLoadEnv;
127 
128     public:
129 
130         //_______________________________________
LoadEnvListener(void * pCheck,LoadEnv * pLoadEnv)131         LoadEnvListener(void*    pCheck  ,
132                         LoadEnv* pLoadEnv)
133         {
134             m_ppCheck  = &pCheck ;
135             m_pLoadEnv = pLoadEnv;
136         }
137 
138         //_______________________________________
139         // frame.XLoadEventListener
140         virtual void SAL_CALL loadFinished(const css::uno::Reference< css::frame::XFrameLoader >& xLoader);
141 
142         virtual void SAL_CALL loadCancelled(const css::uno::Reference< css::frame::XFrameLoader >& xLoader);
143 
144         //_______________________________________
145         // frame.XDispatchResultListener
146         virtual void SAL_CALL dispatchFinished(const css::frame::DispatchResultEvent& aEvent);
147 
148         //_______________________________________
149         // lang.XEventListener
150         virtual void SAL_CALL disposing(const css::lang::EventObject& aEvent);
151 };
152 
153 /*-----------------------------------------------
154     14.10.2003 13:43
155 -----------------------------------------------*/
LoadEnv(const css::uno::Reference<css::lang::XMultiServiceFactory> & xSMGR)156 LoadEnv::LoadEnv(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
157     : ThreadHelpBase(     )
158     , m_xSMGR       (xSMGR)
159     , m_pCheck      (this )
160     , m_pQuietInteraction( 0 )
161 {
162 }
163 
164 /*-----------------------------------------------
165     14.10.2003 13:43
166 -----------------------------------------------*/
~LoadEnv()167 LoadEnv::~LoadEnv()
168 {
169     m_pCheck = 0;
170 }
171 
172 /*-----------------------------------------------
173     10.09.2003 14:05
174 -----------------------------------------------*/
loadComponentFromURL(const css::uno::Reference<css::frame::XComponentLoader> & xLoader,const css::uno::Reference<css::lang::XMultiServiceFactory> & xSMGR,const::rtl::OUString & sURL,const::rtl::OUString & sTarget,sal_Int32 nFlags,const css::uno::Sequence<css::beans::PropertyValue> & lArgs)175 css::uno::Reference< css::lang::XComponent > LoadEnv::loadComponentFromURL(const css::uno::Reference< css::frame::XComponentLoader >&    xLoader,
176                                                                            const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR  ,
177                                                                            const ::rtl::OUString&                                        sURL   ,
178                                                                            const ::rtl::OUString&                                        sTarget,
179                                                                                  sal_Int32                                               nFlags ,
180                                                                            const css::uno::Sequence< css::beans::PropertyValue >&        lArgs  )
181 {
182 #ifdef WNT
183     CEnableAccessInterface e;
184 #endif
185     css::uno::Reference< css::lang::XComponent > xComponent;
186 
187     try
188     {
189         LoadEnv aEnv(xSMGR);
190 
191         aEnv.initializeLoading(sURL,
192                                lArgs,
193                                css::uno::Reference< css::frame::XFrame >(xLoader, css::uno::UNO_QUERY),
194                                sTarget,
195                                nFlags,
196                                LoadEnv::E_NO_FEATURE);
197         aEnv.startLoading();
198         aEnv.waitWhileLoading(); // wait for ever!
199 
200         xComponent = aEnv.getTargetComponent();
201     }
202     catch(const LoadEnvException& ex)
203     {
204         switch(ex.m_nID)
205         {
206             case LoadEnvException::ID_INVALID_MEDIADESCRIPTOR:
207                     throw css::lang::IllegalArgumentException(
208                             ::rtl::OUString::createFromAscii("Optional list of arguments seem to be corrupted."),
209                             xLoader,
210                             4);
211 
212             case LoadEnvException::ID_UNSUPPORTED_CONTENT:
213                     throw css::lang::IllegalArgumentException(
214                             ::rtl::OUString::createFromAscii("URL seems to be an unsupported one."),
215                             xLoader,
216                             1);
217 
218             default: xComponent.clear();
219                     break;
220         }
221     }
222 
223     return xComponent;
224 }
225 
226 //-----------------------------------------------
impl_mergeMediaDescriptorWithMightExistingModelArgs(const css::uno::Sequence<css::beans::PropertyValue> & lOutsideDescriptor)227 ::comphelper::MediaDescriptor impl_mergeMediaDescriptorWithMightExistingModelArgs(const css::uno::Sequence< css::beans::PropertyValue >& lOutsideDescriptor)
228 {
229     ::comphelper::MediaDescriptor lDescriptor(lOutsideDescriptor);
230     css::uno::Reference< css::frame::XModel > xModel     = lDescriptor.getUnpackedValueOrDefault(
231                                                             ::comphelper::MediaDescriptor::PROP_MODEL (),
232                                                             css::uno::Reference< css::frame::XModel > ());
233     if (xModel.is ())
234     {
235         ::comphelper::MediaDescriptor lModelDescriptor(xModel->getArgs());
236         ::comphelper::MediaDescriptor::iterator pIt = lModelDescriptor.find( ::comphelper::MediaDescriptor::PROP_MACROEXECUTIONMODE() );
237         if ( pIt != lModelDescriptor.end() )
238             lDescriptor[::comphelper::MediaDescriptor::PROP_MACROEXECUTIONMODE()] = pIt->second;
239     }
240 
241     return lDescriptor;
242 }
243 
244 /*-----------------------------------------------
245     20.08.2003 09:49
246 -----------------------------------------------*/
initializeLoading(const::rtl::OUString & sURL,const css::uno::Sequence<css::beans::PropertyValue> & lMediaDescriptor,const css::uno::Reference<css::frame::XFrame> & xBaseFrame,const::rtl::OUString & sTarget,sal_Int32 nSearchFlags,EFeature eFeature,EContentType eContentType)247 void LoadEnv::initializeLoading(const ::rtl::OUString&                                           sURL            ,
248                                 const css::uno::Sequence< css::beans::PropertyValue >&           lMediaDescriptor,
249                                 const css::uno::Reference< css::frame::XFrame >&                 xBaseFrame      ,
250                                 const ::rtl::OUString&                                           sTarget         ,
251                                       sal_Int32                                                  nSearchFlags    ,
252                                       EFeature                                                   eFeature        , // => use default ...
253                                       EContentType                                               eContentType    ) // => use default ...
254 {
255     // SAFE -> ----------------------------------
256     WriteGuard aWriteLock(m_aLock);
257 
258     // Handle still running processes!
259     if (m_xAsynchronousJob.is())
260         throw LoadEnvException(LoadEnvException::ID_STILL_RUNNING);
261 
262     // take over all new parameters.
263     m_xTargetFrame.clear();
264     m_xBaseFrame                    = xBaseFrame        ;
265     m_lMediaDescriptor              = impl_mergeMediaDescriptorWithMightExistingModelArgs(lMediaDescriptor);
266     m_sTarget                       = sTarget           ;
267     m_nSearchFlags                  = nSearchFlags      ;
268     m_eFeature                      = eFeature          ;
269     m_eContentType                  = eContentType      ;
270     m_bCloseFrameOnError            = sal_False         ;
271     m_bReactivateControllerOnError  = sal_False         ;
272     m_bLoaded                       = sal_False         ;
273 
274     // try to find out, if its really a content, which can be loaded or must be "handled"
275     // We use a default value for this in-parameter. Then we have to start a complex check method
276     // internally. But if this check was already done outside it can be suppressed to perform
277     // the load request. We take over the result then!
278     if (m_eContentType == E_UNSUPPORTED_CONTENT)
279     {
280         m_eContentType = LoadEnv::classifyContent(sURL, lMediaDescriptor);
281         if (m_eContentType == E_UNSUPPORTED_CONTENT)
282             throw LoadEnvException(LoadEnvException::ID_UNSUPPORTED_CONTENT);
283     }
284 
285     // make URL part of the MediaDescriptor
286     // It doesn't mater, if its already an item of it.
287     // It must be the same value ... so we can overwrite it :-)
288     m_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_URL()] <<= sURL;
289 
290     // parse it - because some following code require that
291     m_aURL.Complete = sURL;
292     css::uno::Reference< css::util::XURLTransformer > xParser(m_xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), css::uno::UNO_QUERY);
293     xParser->parseStrict(m_aURL);
294 
295     // BTW: Split URL and JumpMark ...
296     // Because such mark is an explicit value of the media descriptor!
297     if (m_aURL.Mark.getLength())
298         m_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_JUMPMARK()] <<= m_aURL.Mark;
299 
300     // By the way: remove the old and deprecated value "FileName" from the descriptor!
301     ::comphelper::MediaDescriptor::iterator pIt = m_lMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_FILENAME());
302     if (pIt != m_lMediaDescriptor.end())
303         m_lMediaDescriptor.erase(pIt);
304 
305     // patch the MediaDescriptor, so it fulfill the outside requirements
306     // Means especially items like e.g. UI InteractionHandler, Status Indicator,
307     // MacroExecutionMode etcpp.
308 
309     /*TODO progress is bound to a frame ... How can we set it here? */
310 
311     // UI mode
312     const bool bUIMode =
313         ( ( m_eFeature & E_WORK_WITH_UI )                                                                          == E_WORK_WITH_UI ) &&
314         ( m_lMediaDescriptor.getUnpackedValueOrDefault( ::comphelper::MediaDescriptor::PROP_HIDDEN() , sal_False ) == sal_False      ) &&
315         ( m_lMediaDescriptor.getUnpackedValueOrDefault( ::comphelper::MediaDescriptor::PROP_PREVIEW(), sal_False ) == sal_False      );
316 
317     initializeUIDefaults(
318         m_xSMGR,
319         m_lMediaDescriptor,
320         bUIMode,
321         &m_pQuietInteraction
322     );
323 
324     aWriteLock.unlock();
325     // <- SAFE ----------------------------------
326 }
327 
328 /*-----------------------------------------------
329     22.01.2010
330 -----------------------------------------------*/
initializeUIDefaults(const css::uno::Reference<css::lang::XMultiServiceFactory> & i_rSMGR,::comphelper::MediaDescriptor & io_lMediaDescriptor,const bool i_bUIMode,QuietInteraction ** o_ppQuietInteraction)331 void LoadEnv::initializeUIDefaults( const css::uno::Reference< css::lang::XMultiServiceFactory >& i_rSMGR,
332                                     ::comphelper::MediaDescriptor& io_lMediaDescriptor, const bool i_bUIMode,
333                                     QuietInteraction** o_ppQuietInteraction )
334 {
335     css::uno::Reference< css::task::XInteractionHandler > xInteractionHandler;
336     sal_Int16                                             nMacroMode         ;
337     sal_Int16                                             nUpdateMode        ;
338 
339     if ( i_bUIMode )
340     {
341         nMacroMode  = css::document::MacroExecMode::USE_CONFIG;
342         nUpdateMode = css::document::UpdateDocMode::ACCORDING_TO_CONFIG;
343         try
344         {
345             xInteractionHandler = css::uno::Reference< css::task::XInteractionHandler >(i_rSMGR->createInstance(IMPLEMENTATIONNAME_UIINTERACTIONHANDLER), css::uno::UNO_QUERY);
346         }
347         catch(const css::uno::RuntimeException&) {throw;}
348         catch(const css::uno::Exception&       ) {      }
349     }
350     // hidden mode
351     else
352     {
353         nMacroMode  = css::document::MacroExecMode::NEVER_EXECUTE;
354         nUpdateMode = css::document::UpdateDocMode::NO_UPDATE;
355         QuietInteraction* pQuietInteraction = new QuietInteraction();
356         xInteractionHandler = css::uno::Reference< css::task::XInteractionHandler >(static_cast< css::task::XInteractionHandler* >(pQuietInteraction), css::uno::UNO_QUERY);
357         if ( o_ppQuietInteraction != NULL )
358         {
359             *o_ppQuietInteraction = pQuietInteraction;
360             (*o_ppQuietInteraction)->acquire();
361         }
362     }
363 
364     if (
365         (xInteractionHandler.is()                                                                                       ) &&
366         (io_lMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER()) == io_lMediaDescriptor.end())
367        )
368     {
369         io_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER()] <<= xInteractionHandler;
370         io_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_AUTHENTICATIONHANDLER()] <<= xInteractionHandler;
371     }
372 
373     if (io_lMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_MACROEXECUTIONMODE()) == io_lMediaDescriptor.end())
374         io_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_MACROEXECUTIONMODE()] <<= nMacroMode;
375 
376     if (io_lMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_UPDATEDOCMODE()) == io_lMediaDescriptor.end())
377         io_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_UPDATEDOCMODE()] <<= nUpdateMode;
378 }
379 
380 /*-----------------------------------------------
381     15.08.2003 08:16
382 -----------------------------------------------*/
startLoading()383 void LoadEnv::startLoading()
384 {
385     // SAFE ->
386     ReadGuard aReadLock(m_aLock);
387 
388     // Handle still running processes!
389     if (m_xAsynchronousJob.is())
390         throw LoadEnvException(LoadEnvException::ID_STILL_RUNNING);
391 
392     // content can not be loaded or handled
393     // check "classifyContent()" failed before ...
394     if (m_eContentType == E_UNSUPPORTED_CONTENT)
395         throw LoadEnvException(LoadEnvException::ID_UNSUPPORTED_CONTENT);
396 
397     // <- SAFE
398     aReadLock.unlock();
399 
400     // detect its type/filter etcpp.
401     // These information will be available by the
402     // used descriptor member afterwards and is needed
403     // for all following operations!
404     // Note: An exception will be thrown, in case operation was not successfully ...
405     if (m_eContentType != E_CAN_BE_SET)/* Attention: special feature to set existing component on a frame must ignore type detection! */
406         impl_detectTypeAndFilter();
407 
408     // start loading the content ...
409     // Attention: Dont check m_eContentType deeper then UNSUPPORTED/SUPPORTED!
410     // Because it was made in th easiest way ... may a flat detection was made only.
411     // And such simple detection can fail some times .-)
412     // Use another strategy here. Try it and let it run into the case "loading not possible".
413     sal_Bool bStarted = sal_False;
414     if (
415         ((m_eFeature & E_ALLOW_CONTENTHANDLER) == E_ALLOW_CONTENTHANDLER) &&
416         (m_eContentType                        != E_CAN_BE_SET          )   /* Attention: special feature to set existing component on a frame must ignore type detection! */
417        )
418     {
419         bStarted = impl_handleContent();
420     }
421 
422     if (!bStarted)
423         bStarted = impl_loadContent();
424 
425     // not started => general error
426     // We can't say - what was the reason for.
427     if (!bStarted)
428         throw LoadEnvException(LoadEnvException::ID_GENERAL_ERROR);
429 }
430 
431 /*-----------------------------------------------
432     15.08.2003 09:50
433     TODO
434         First draft does not implement timeout using [ms].
435         Current implementation counts yield calls only ...
436 -----------------------------------------------*/
waitWhileLoading(sal_uInt32 nTimeout)437 sal_Bool LoadEnv::waitWhileLoading(sal_uInt32 nTimeout)
438 {
439     // Because its not a good idea to block the main thread
440     // (and we can't be sure that we are currently not used inside the
441     // main thread!), we can't use conditions here really. We must yield
442     // in an intellegent manner :-)
443 
444     sal_Int32 nTime = nTimeout;
445     while(true)
446     {
447         // SAFE -> ------------------------------
448         ReadGuard aReadLock1(m_aLock);
449         if (!m_xAsynchronousJob.is())
450             break;
451         aReadLock1.unlock();
452         // <- SAFE ------------------------------
453 
454         Application::Yield();
455 
456         // forever!
457         if (nTimeout==0)
458             continue;
459 
460         // timed out?
461         --nTime;
462         if (nTime<1)
463             break;
464     }
465 
466     // SAFE -> ----------------------------------
467     ReadGuard aReadLock2(m_aLock);
468     return !m_xAsynchronousJob.is();
469     // <- SAFE ----------------------------------
470 }
471 
472 /*-----------------------------------------------
473     20.08.2003 10:00
474 -----------------------------------------------*/
cancelLoading()475 void LoadEnv::cancelLoading()
476 {
477     // PARTIAL(!) SAFE -> ------------------------------
478     ReadGuard aReadLock(m_aLock);
479 
480     // Still running? Might waitWhileLoading()
481     // runned into the timeout!
482     if (m_xAsynchronousJob.is())
483     {
484         // try to cancel it ... if its an asynchronous frame loader
485         css::uno::Reference< css::frame::XFrameLoader > xAsyncLoader(m_xAsynchronousJob, css::uno::UNO_QUERY);
486         if (xAsyncLoader.is())
487         {
488             aReadLock.unlock();
489             // <- BREAK SAFE ------------------------------
490             xAsyncLoader->cancel();
491             // <- RESTART SAFE ----------------------------
492             aReadLock.lock();
493             /* Attention:
494                 After returning from any cancel/dispose call, neither the frame nor weself
495                 may be called back. Because only we can cancel this job, we already know
496                 the result! => That's why it's not useful nor necessary to wait for any
497                 asynchronous listener notification.
498             */
499             m_bLoaded = sal_False;
500             m_xAsynchronousJob.clear();
501         }
502         // or may be it's a content handler? Such handler can't be cancelled in its running
503         // operation :-( And we can't deregister us there again :-(
504         // => The only chance is an exception :-)
505         else
506             throw LoadEnvException(LoadEnvException::ID_STILL_RUNNING);
507     }
508 
509     impl_reactForLoadingState();
510 
511     aReadLock.unlock();
512     // <- PARTIAL(!) SAFE ------------------------------
513 }
514 
515 /*-----------------------------------------------
516     14.08.2003 13:33
517 -----------------------------------------------*/
getTarget() const518 css::uno::Reference< css::frame::XFrame > LoadEnv::getTarget() const
519 {
520     // SAFE ->
521     ReadGuard aReadLock(m_aLock);
522     return m_xTargetFrame;
523     // <- SAFE
524 }
525 
526 /*-----------------------------------------------
527     14.08.2003 13:35
528 -----------------------------------------------*/
getTargetComponent() const529 css::uno::Reference< css::lang::XComponent > LoadEnv::getTargetComponent() const
530 {
531     // SAFE ->
532     ReadGuard aReadLock(m_aLock);
533 
534     if (!m_xTargetFrame.is())
535         return css::uno::Reference< css::lang::XComponent >();
536 
537     css::uno::Reference< css::frame::XController > xController = m_xTargetFrame->getController();
538     if (!xController.is())
539         return css::uno::Reference< css::lang::XComponent >(m_xTargetFrame->getComponentWindow(), css::uno::UNO_QUERY);
540 
541     css::uno::Reference< css::frame::XModel > xModel = xController->getModel();
542     if (!xModel.is())
543         return css::uno::Reference< css::lang::XComponent >(xController, css::uno::UNO_QUERY);
544 
545     return css::uno::Reference< css::lang::XComponent >(xModel, css::uno::UNO_QUERY);
546     // <- SAFE
547 }
548 
549 /*-----------------------------------------------
550     15.08.2003 11:15
551 -----------------------------------------------*/
loadFinished(const css::uno::Reference<css::frame::XFrameLoader> &)552 void SAL_CALL LoadEnvListener::loadFinished(const css::uno::Reference< css::frame::XFrameLoader >&)
553 {
554     // SAFE -> ----------------------------------
555     WriteGuard aWriteLock(m_aLock);
556 
557     if (m_ppCheck && *m_ppCheck)
558         m_pLoadEnv->impl_setResult(sal_True);
559     m_ppCheck = NULL;
560 
561     aWriteLock.unlock();
562     // <- SAFE ----------------------------------
563 }
564 
565 /*-----------------------------------------------
566     14.10.2003 12:23
567 -----------------------------------------------*/
loadCancelled(const css::uno::Reference<css::frame::XFrameLoader> &)568 void SAL_CALL LoadEnvListener::loadCancelled(const css::uno::Reference< css::frame::XFrameLoader >&)
569 {
570     // SAFE -> ----------------------------------
571     WriteGuard aWriteLock(m_aLock);
572 
573     if (m_ppCheck && *m_ppCheck)
574         m_pLoadEnv->impl_setResult(sal_False);
575     m_ppCheck = NULL;
576 
577     aWriteLock.unlock();
578     // <- SAFE ----------------------------------
579 }
580 
581 /*-----------------------------------------------
582     14.10.2003 12:23
583 -----------------------------------------------*/
dispatchFinished(const css::frame::DispatchResultEvent & aEvent)584 void SAL_CALL LoadEnvListener::dispatchFinished(const css::frame::DispatchResultEvent& aEvent)
585 {
586     // SAFE -> ----------------------------------
587     WriteGuard aWriteLock(m_aLock);
588 
589     if (!m_ppCheck || !*m_ppCheck)
590         return;
591 
592     switch(aEvent.State)
593     {
594         case css::frame::DispatchResultState::FAILURE :
595             m_pLoadEnv->impl_setResult(sal_False);
596             break;
597 
598         case css::frame::DispatchResultState::SUCCESS :
599             m_pLoadEnv->impl_setResult(sal_False);
600             break;
601 
602         case css::frame::DispatchResultState::DONTKNOW :
603             m_pLoadEnv->impl_setResult(sal_False);
604             break;
605     }
606     m_ppCheck = NULL;
607 
608     aWriteLock.unlock();
609     // <- SAFE ----------------------------------
610 }
611 
612 /*-----------------------------------------------
613     14.10.2003 12:24
614 -----------------------------------------------*/
disposing(const css::lang::EventObject &)615 void SAL_CALL LoadEnvListener::disposing(const css::lang::EventObject&)
616 {
617     // SAFE -> ----------------------------------
618     WriteGuard aWriteLock(m_aLock);
619 
620     if (m_ppCheck && *m_ppCheck)
621         m_pLoadEnv->impl_setResult(sal_False);
622     m_ppCheck = NULL;
623 
624     aWriteLock.unlock();
625     // <- SAFE ----------------------------------
626 }
627 
628 /*-----------------------------------------------
629     14.10.2003 12:20
630 -----------------------------------------------*/
impl_setResult(sal_Bool bResult)631 void LoadEnv::impl_setResult(sal_Bool bResult)
632 {
633     // SAFE -> ----------------------------------
634     WriteGuard aWriteLock(m_aLock);
635 
636     m_bLoaded = bResult;
637 
638     impl_reactForLoadingState();
639 
640     // clearing of this reference will unblock waitWhileLoading()!
641     // So we must be sure, that loading process was really finished.
642     // => do it as last operation of this method ...
643     m_xAsynchronousJob.clear();
644 
645     aWriteLock.unlock();
646     // <- SAFE ----------------------------------
647 }
648 
649 /*-----------------------------------------------
650     06.02.2004 14:03
651     TODO: Is it a good idea to change Sequence<>
652           parameter to stl-adapter?
653 -----------------------------------------------*/
classifyContent(const::rtl::OUString & sURL,const css::uno::Sequence<css::beans::PropertyValue> & lMediaDescriptor)654 LoadEnv::EContentType LoadEnv::classifyContent(const ::rtl::OUString&                                 sURL            ,
655                                                const css::uno::Sequence< css::beans::PropertyValue >& lMediaDescriptor)
656 {
657     //-------------------------------------------
658     // (i) Filter some special well known URL protocols,
659     //     which can not be handled or loaded in general.
660     //     Of course an empty URL must be ignored here too.
661     //     Note: These URL schemata are fix and well known ...
662     //     But there can be some additional ones, which was not
663     //     defined at implementation time of this class :-(
664     //     So we have to make sure, that the following code
665     //     can detect such protocol schemata too :-)
666 
667     if(
668         (!sURL.getLength()                                       ) ||
669         (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_UNO    )) ||
670         (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_SLOT   )) ||
671         (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_MACRO  )) ||
672         (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_SERVICE)) ||
673         (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_MAILTO )) ||
674         (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_NEWS   ))
675       )
676     {
677         return E_UNSUPPORTED_CONTENT;
678     }
679 
680     //-------------------------------------------
681     // (ii) Some special URLs indicates a given input stream,
682     //      a full featured document model directly or
683     //      specify a request for opening an empty document.
684     //      Such contents are loadable in general.
685     //      But we have to check, if the media descriptor contains
686     //      all needed resources. If they are missing - the following
687     //      load request will fail.
688 
689     /* Attention: The following code can't work on such special URLs!
690                   It should not break the office .. but it make no sense
691                   to start expensive object creations and complex search
692                   algorithm if its clear, that such URLs must be handled
693                   in a special way .-)
694     */
695 
696     // creation of new documents
697     if (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_PRIVATE_FACTORY))
698         return E_CAN_BE_LOADED;
699 
700     // using of an existing input stream
701     ::comphelper::MediaDescriptor                 stlMediaDescriptor(lMediaDescriptor);
702     ::comphelper::MediaDescriptor::const_iterator pIt;
703     if (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_PRIVATE_STREAM))
704     {
705         pIt = stlMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_INPUTSTREAM());
706         css::uno::Reference< css::io::XInputStream > xStream;
707         if (pIt != stlMediaDescriptor.end())
708             pIt->second >>= xStream;
709         if (xStream.is())
710             return E_CAN_BE_LOADED;
711         LOG_WARNING("LoadEnv::classifyContent()", "loading from stream with right URL but invalid stream detected")
712         return E_UNSUPPORTED_CONTENT;
713     }
714 
715     // using of a full featured document
716     if (ProtocolCheck::isProtocol(sURL,ProtocolCheck::E_PRIVATE_OBJECT))
717     {
718         pIt = stlMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_MODEL());
719         css::uno::Reference< css::frame::XModel > xModel;
720         if (pIt != stlMediaDescriptor.end())
721             pIt->second >>= xModel;
722         if (xModel.is())
723             return E_CAN_BE_SET;
724         LOG_WARNING("LoadEnv::classifyContent()", "loading with object with right URL but invalid object detected")
725         return E_UNSUPPORTED_CONTENT;
726     }
727 
728     // following operations can work on an internal type name only :-(
729     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::utl::getProcessServiceFactory();
730     css::uno::Reference< css::document::XTypeDetection > xDetect(xSMGR->createInstance(SERVICENAME_TYPEDETECTION), css::uno::UNO_QUERY);
731 
732     ::rtl::OUString sType = xDetect->queryTypeByURL(sURL);
733 
734     css::uno::Sequence< css::beans::NamedValue >           lQuery(1)   ;
735     css::uno::Reference< css::container::XContainerQuery > xContainer  ;
736     css::uno::Reference< css::container::XEnumeration >    xSet        ;
737     css::uno::Sequence< ::rtl::OUString >                  lTypesReg(1);
738 
739     /*
740     //-------------------------------------------
741     lQuery[0].Name    = ::framework::constant::Filter::PROP_TYPE;
742     lQuery[0].Value <<= sType;
743 
744     xContainer = css::uno::Reference< css::container::XContainerQuery >(xSMGR->createInstance(SERVICENAME_FILTERFACTORY), css::uno::UNO_QUERY);
745     xSet       = xContainer->createSubSetEnumerationByProperties(lQuery);
746     // at least one registered frame loader is enough!
747     if (xSet->hasMoreElements())
748         return E_CAN_BE_LOADED;
749     */
750 
751     //-------------------------------------------
752     // (iii) If a FrameLoader service (or at least
753     //      a Filter) can be found, which supports
754     //      this URL - it must be a loadable content.
755     //      Because both items are registered for types
756     //      its enough to check for frame loaders only.
757     //      Mos of our filters are handled by our global
758     //      default loader. But there exist some specialized
759     //      loader, which does not work on top of filters!
760     //      So its not enough to search on the filter configuration.
761     //      Further its not enough to search for types!
762     //      Because there exist some types, which are referenced by
763     //      other objects ... but not by filters nor frame loaders!
764 
765     lTypesReg[0]      = sType;
766     lQuery[0].Name    = ::framework::constant::FrameLoader::PROP_TYPES;
767     lQuery[0].Value <<= lTypesReg;
768 
769     xContainer = css::uno::Reference< css::container::XContainerQuery >(xSMGR->createInstance(SERVICENAME_FRAMELOADERFACTORY), css::uno::UNO_QUERY);
770     xSet       = xContainer->createSubSetEnumerationByProperties(lQuery);
771     // at least one registered frame loader is enough!
772     if (xSet->hasMoreElements())
773         return E_CAN_BE_LOADED;
774 
775     //-------------------------------------------
776     // (iv) Some URL protocols are supported by special services.
777     //      E.g. ContentHandler.
778     //      Such contents can be handled ... but not loaded.
779 
780     lTypesReg[0]      = sType;
781     lQuery[0].Name    = ::framework::constant::ContentHandler::PROP_TYPES;
782     lQuery[0].Value <<= lTypesReg;
783 
784     xContainer = css::uno::Reference< css::container::XContainerQuery >(xSMGR->createInstance(SERVICENAME_CONTENTHANDLERFACTORY), css::uno::UNO_QUERY);
785     xSet       = xContainer->createSubSetEnumerationByProperties(lQuery);
786     // at least one registered content handler is enough!
787     if (xSet->hasMoreElements())
788         return E_CAN_BE_HANDLED;
789 
790     //-------------------------------------------
791     // (v) Last but not least the UCB is used inside office to
792     //     load contents. He has a special configuration to know
793     //     which URL schemata can be used inside office.
794     css::uno::Reference< css::ucb::XContentProviderManager > xUCB(xSMGR->createInstance(SERVICENAME_UCBCONTENTBROKER), css::uno::UNO_QUERY);
795     if (xUCB->queryContentProvider(sURL).is())
796         return E_CAN_BE_LOADED;
797 
798     //-------------------------------------------
799     // (TODO) At this point, we have no idea .-)
800     //        But it seems to be better, to break all
801     //        further requests for this URL. Otherwise
802     //        we can run into some trouble.
803     return E_UNSUPPORTED_CONTENT;
804 }
805 
806 /*-----------------------------------------------
807     03.11.2003 09:31
808 -----------------------------------------------*/
impl_detectTypeAndFilter()809 void LoadEnv::impl_detectTypeAndFilter()
810 {
811     static ::rtl::OUString TYPEPROP_PREFERREDFILTER = ::rtl::OUString::createFromAscii("PreferredFilter");
812     static ::rtl::OUString FILTERPROP_FLAGS         = ::rtl::OUString::createFromAscii("Flags"          );
813     static sal_Int32       FILTERFLAG_TEMPLATEPATH  = 16;
814 
815     // SAFE ->
816     ReadGuard aReadLock(m_aLock);
817 
818     // Attention: Because our stl media descriptor is a copy of an uno sequence
819     // we can't use as an in/out parameter here. Copy it before and dont forget to
820     // update structure afterwards again!
821     css::uno::Sequence< css::beans::PropertyValue >        lDescriptor = m_lMediaDescriptor.getAsConstPropertyValueList();
822     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR       = m_xSMGR;
823 
824     aReadLock.unlock();
825     // <- SAFE
826 
827     ::rtl::OUString sType;
828     css::uno::Reference< css::document::XTypeDetection > xDetect(xSMGR->createInstance(SERVICENAME_TYPEDETECTION), css::uno::UNO_QUERY);
829     if (xDetect.is())
830         sType = xDetect->queryTypeByDescriptor(lDescriptor, sal_True); /*TODO should deep detection be able for enable/disable it from outside? */
831 
832     // no valid content -> loading not possible
833     if (!sType.getLength())
834         throw LoadEnvException(LoadEnvException::ID_UNSUPPORTED_CONTENT);
835 
836     // SAFE ->
837     WriteGuard aWriteLock(m_aLock);
838 
839     // detection was successfully => update the descriptor member of this class
840     m_lMediaDescriptor << lDescriptor;
841     m_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME()] <<= sType;
842     // Is there an already detected (may be preselected) filter?
843     // see below ...
844     ::rtl::OUString sFilter = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_FILTERNAME(), ::rtl::OUString());
845 
846     aWriteLock.unlock();
847     // <- SAFE
848 
849     // But the type isn't enough. For loading sometimes we need more informations.
850     // E.g. for our "_default" feature, where we recylce any frame which contains
851     // and "Untitled" document, we must know if the new document is based on a template!
852     // But this information is available as a filter property only.
853     // => We must try(!) to detect the right filter for this load request.
854     // On the other side ... if no filter is available .. ignore it.
855     // Then the type information must be enough.
856     if (!sFilter.getLength())
857     {
858         // no -> try to find a preferred filter for the detected type.
859         // Dont forget to updatet he media descriptor.
860         css::uno::Reference< css::container::XNameAccess > xTypeCont(xDetect, css::uno::UNO_QUERY_THROW);
861         try
862         {
863             ::comphelper::SequenceAsHashMap lTypeProps(xTypeCont->getByName(sType));
864             sFilter = lTypeProps.getUnpackedValueOrDefault(TYPEPROP_PREFERREDFILTER, ::rtl::OUString());
865             if (sFilter.getLength())
866             {
867                 // SAFE ->
868                 aWriteLock.lock();
869                 m_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter;
870                 aWriteLock.unlock();
871                 // <- SAFE
872             }
873         }
874         catch(const css::container::NoSuchElementException&)
875             {}
876     }
877 
878     // check if the filter (if one exists) points to a template format filter.
879     // Then we have to add the property "AsTemplate".
880     // We need this information to decide afterwards if we can use a "recycle frame"
881     // for target "_default" or has to create a new one everytimes.
882     // On the other side we have to suppress that, if this property already exists
883     // and should trigger a special handling. Then the outside calli of this method here,
884     // has to know, what he is doing .-)
885 
886     sal_Bool bIsOwnTemplate = sal_False;
887     if (sFilter.getLength())
888     {
889         css::uno::Reference< css::container::XNameAccess > xFilterCont(xSMGR->createInstance(SERVICENAME_FILTERFACTORY), css::uno::UNO_QUERY_THROW);
890         try
891         {
892             ::comphelper::SequenceAsHashMap lFilterProps(xFilterCont->getByName(sFilter));
893             sal_Int32 nFlags         = lFilterProps.getUnpackedValueOrDefault(FILTERPROP_FLAGS, (sal_Int32)0);
894                       bIsOwnTemplate = ((nFlags & FILTERFLAG_TEMPLATEPATH) == FILTERFLAG_TEMPLATEPATH);
895         }
896         catch(const css::container::NoSuchElementException&)
897             {}
898     }
899     if (bIsOwnTemplate)
900     {
901         // SAFE ->
902         aWriteLock.lock();
903         // Dont overwrite external decisions! See comments before ...
904         ::comphelper::MediaDescriptor::const_iterator pAsTemplateItem = m_lMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_ASTEMPLATE());
905         if (pAsTemplateItem == m_lMediaDescriptor.end())
906             m_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_ASTEMPLATE()] <<= sal_True;
907         aWriteLock.unlock();
908         // <- SAFE
909     }
910 }
911 
912 /*-----------------------------------------------
913     15.08.2003 09:38
914 -----------------------------------------------*/
impl_handleContent()915 sal_Bool LoadEnv::impl_handleContent()
916 {
917     // SAFE -> -----------------------------------
918     ReadGuard aReadLock(m_aLock);
919 
920     // the type must exist inside the descriptor ... otherwise this class is implemented wrong :-)
921     ::rtl::OUString sType = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_TYPENAME(), ::rtl::OUString());
922     if (!sType.getLength())
923         throw LoadEnvException(LoadEnvException::ID_INVALID_MEDIADESCRIPTOR);
924 
925     // convert media descriptor and URL to right format for later interface call!
926     css::uno::Sequence< css::beans::PropertyValue > lDescriptor;
927     m_lMediaDescriptor >> lDescriptor;
928     css::util::URL aURL = m_aURL;
929 
930     // get necessary container to query for a handler object
931     css::uno::Reference< css::lang::XMultiServiceFactory > xFactory(m_xSMGR->createInstance(SERVICENAME_CONTENTHANDLERFACTORY), css::uno::UNO_QUERY);
932     css::uno::Reference< css::container::XContainerQuery > xQuery  (xFactory                                                  , css::uno::UNO_QUERY);
933 
934     aReadLock.unlock();
935     // <- SAFE -----------------------------------
936 
937     // query
938     css::uno::Sequence< ::rtl::OUString > lTypeReg(1);
939     lTypeReg[0] = sType;
940 
941     css::uno::Sequence< css::beans::NamedValue > lQuery(1);
942     lQuery[0].Name    = ::framework::constant::ContentHandler::PROP_TYPES;
943     lQuery[0].Value <<= lTypeReg;
944 
945     css::uno::Reference< css::container::XEnumeration > xSet = xQuery->createSubSetEnumerationByProperties(lQuery);
946     while(xSet->hasMoreElements())
947     {
948         ::comphelper::SequenceAsHashMap lProps   (xSet->nextElement());
949         ::rtl::OUString                 sHandler = lProps.getUnpackedValueOrDefault(::framework::constant::ContentHandler::PROP_NAME, ::rtl::OUString());
950 
951         css::uno::Reference< css::frame::XNotifyingDispatch > xHandler;
952         try
953         {
954             xHandler = css::uno::Reference< css::frame::XNotifyingDispatch >(xFactory->createInstance(sHandler), css::uno::UNO_QUERY);
955             if (!xHandler.is())
956                 continue;
957         }
958         catch(const css::uno::RuntimeException&)
959             { throw; }
960         catch(const css::uno::Exception&)
961             { continue; }
962 
963         // SAFE -> -----------------------------------
964         WriteGuard aWriteLock(m_aLock);
965         m_xAsynchronousJob = xHandler;
966         m_pCheck           = this;
967         LoadEnvListener* pListener = new LoadEnvListener(m_pCheck, this);
968         aWriteLock.unlock();
969         // <- SAFE -----------------------------------
970 
971         css::uno::Reference< css::frame::XDispatchResultListener > xListener(static_cast< css::frame::XDispatchResultListener* >(pListener), css::uno::UNO_QUERY);
972         xHandler->dispatchWithNotification(aURL, lDescriptor, xListener);
973 
974         return sal_True;
975     }
976 
977     return sal_False;
978 }
979 
980 //-----------------------------------------------
impl_furtherDocsAllowed()981 sal_Bool LoadEnv::impl_furtherDocsAllowed()
982 {
983     // SAFE ->
984     ReadGuard aReadLock(m_aLock);
985     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
986     aReadLock.unlock();
987     // <- SAFE
988 
989     sal_Bool bAllowed = sal_True;
990 
991     try
992     {
993         css::uno::Any aVal = ::comphelper::ConfigurationHelper::readDirectKey(
994                                 xSMGR,
995                                 ::rtl::OUString::createFromAscii("org.openoffice.Office.Common/"),
996                                 ::rtl::OUString::createFromAscii("Misc"),
997                                 ::rtl::OUString::createFromAscii("MaxOpenDocuments"),
998                                 ::comphelper::ConfigurationHelper::E_READONLY);
999 
1000         // NIL means: count of allowed documents = infinite !
1001         //     => return sal_True
1002         if ( ! aVal.hasValue())
1003             bAllowed = sal_True;
1004         else
1005         {
1006             sal_Int32 nMaxOpenDocuments = 0;
1007             aVal >>= nMaxOpenDocuments;
1008 
1009             css::uno::Reference< css::frame::XFramesSupplier > xDesktop(
1010                 xSMGR->createInstance(SERVICENAME_DESKTOP),
1011                 css::uno::UNO_QUERY_THROW);
1012 
1013             FrameListAnalyzer aAnalyzer(xDesktop,
1014                                         css::uno::Reference< css::frame::XFrame >(),
1015                                         FrameListAnalyzer::E_HELP |
1016                                         FrameListAnalyzer::E_BACKINGCOMPONENT |
1017                                         FrameListAnalyzer::E_HIDDEN);
1018 
1019             sal_Int32 nOpenDocuments = aAnalyzer.m_lOtherVisibleFrames.getLength();
1020                       bAllowed       = (nOpenDocuments < nMaxOpenDocuments);
1021         }
1022     }
1023     catch(const css::uno::Exception&)
1024         { bAllowed = sal_True; } // !! internal errors are no reason to disturb the office from opening documents .-)
1025 
1026     if ( ! bAllowed )
1027     {
1028         // SAFE ->
1029         aReadLock.lock();
1030         css::uno::Reference< css::task::XInteractionHandler > xInteraction = m_lMediaDescriptor.getUnpackedValueOrDefault(
1031                                                                                 ::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER(),
1032                                                                                 css::uno::Reference< css::task::XInteractionHandler >());
1033         aReadLock.unlock();
1034         // <- SAFE
1035 
1036         if (xInteraction.is())
1037         {
1038             css::uno::Any                                                                    aInteraction;
1039             css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > lContinuations(2);
1040 
1041             comphelper::OInteractionAbort*   pAbort   = new comphelper::OInteractionAbort();
1042             comphelper::OInteractionApprove* pApprove = new comphelper::OInteractionApprove();
1043 
1044             lContinuations[0] = css::uno::Reference< css::task::XInteractionContinuation >(
1045                                     static_cast< css::task::XInteractionContinuation* >(pAbort),
1046                                     css::uno::UNO_QUERY_THROW);
1047             lContinuations[1] = css::uno::Reference< css::task::XInteractionContinuation >(
1048                                     static_cast< css::task::XInteractionContinuation* >(pApprove),
1049                                     css::uno::UNO_QUERY_THROW);
1050 
1051             css::task::ErrorCodeRequest aErrorCode;
1052             aErrorCode.ErrCode = ERRCODE_SFX_NOMOREDOCUMENTSALLOWED;
1053             aInteraction <<= aErrorCode;
1054             xInteraction->handle( InteractionRequest::CreateRequest(aInteraction, lContinuations) );
1055         }
1056     }
1057 
1058     return bAllowed;
1059 }
1060 
1061 //-----------------------------------------------
impl_loadContent()1062 sal_Bool LoadEnv::impl_loadContent()
1063 {
1064     // SAFE -> -----------------------------------
1065     WriteGuard aWriteLock(m_aLock);
1066 
1067     // search or create right target frame
1068     ::rtl::OUString sTarget = m_sTarget;
1069     if (TargetHelper::matchSpecialTarget(sTarget, TargetHelper::E_DEFAULT))
1070     {
1071         m_xTargetFrame = impl_searchAlreadyLoaded();
1072         if (m_xTargetFrame.is())
1073         {
1074             impl_setResult(sal_True);
1075             return sal_True;
1076         }
1077         m_xTargetFrame = impl_searchRecycleTarget();
1078     }
1079 
1080     if (! m_xTargetFrame.is())
1081     {
1082         if (
1083             (TargetHelper::matchSpecialTarget(sTarget, TargetHelper::E_BLANK  )) ||
1084             (TargetHelper::matchSpecialTarget(sTarget, TargetHelper::E_DEFAULT))
1085            )
1086         {
1087             if (! impl_furtherDocsAllowed())
1088                 return sal_False;
1089             m_xTargetFrame       = m_xBaseFrame->findFrame(SPECIALTARGET_BLANK, 0);
1090             m_bCloseFrameOnError = m_xTargetFrame.is();
1091         }
1092         else
1093         {
1094             sal_Int32 nFlags = m_nSearchFlags & ~css::frame::FrameSearchFlag::CREATE;
1095             m_xTargetFrame   = m_xBaseFrame->findFrame(sTarget, nFlags);
1096             if (! m_xTargetFrame.is())
1097             {
1098                 if (! impl_furtherDocsAllowed())
1099                     return sal_False;
1100                 m_xTargetFrame       = m_xBaseFrame->findFrame(SPECIALTARGET_BLANK, 0);
1101                 m_bCloseFrameOnError = m_xTargetFrame.is();
1102             }
1103         }
1104     }
1105 
1106     // If we couldn't find a valid frame or the frame has no container window
1107     // we have to throw an exception.
1108     if (
1109         ( ! m_xTargetFrame.is()                       ) ||
1110         ( ! m_xTargetFrame->getContainerWindow().is() )
1111        )
1112         throw LoadEnvException(LoadEnvException::ID_NO_TARGET_FOUND);
1113 
1114     css::uno::Reference< css::frame::XFrame > xTargetFrame = m_xTargetFrame;
1115 
1116     // Now we have a valid frame ... and type detection was already done.
1117     // We should apply the module dependend window position and size to the
1118     // frame window.
1119     impl_applyPersistentWindowState(xTargetFrame->getContainerWindow());
1120 
1121     // Don't forget to lock task for following load process. Otherwise it could die
1122     // during this operation runs by terminating the office or closing this task via api.
1123     // If we set this lock "close()" will return false and closing will be broken.
1124     // Attention: Don't forget to reset this lock again after finishing operation.
1125     // Otherwise task AND office couldn't die!!!
1126     // This includes gracefully handling of Exceptions (Runtime!) too ...
1127     // That's why we use a specialized guard, which will reset the lock
1128     // if it will be run out of scope.
1129 
1130     // Note further: ignore if this internal guard already contains a resource.
1131     // Might impl_searchRecylcTarget() set it before. But incase this impl-method wasn't used
1132     // and the target frame was new created ... this lock here must be set!
1133     css::uno::Reference< css::document::XActionLockable > xTargetLock(xTargetFrame, css::uno::UNO_QUERY);
1134     m_aTargetLock.setResource(xTargetLock);
1135 
1136     // Add status indicator to descriptor. Loader can show an progresses then.
1137     // But don't do it, if loading should be hidden or preview is used ...!
1138     // So we prevent our code against wrong using. Why?
1139     // It could be, that using of this progress could make trouble. e.g. He make window visible ...
1140     // but shouldn't do that. But if no indicator is available ... nobody has a chance to do that!
1141     sal_Bool                                           bHidden    = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_HIDDEN()         , sal_False                                           );
1142     sal_Bool                                           bMinimized = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_MINIMIZED()      , sal_False                                           );
1143     sal_Bool                                           bPreview   = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_PREVIEW()        , sal_False                                           );
1144     css::uno::Reference< css::task::XStatusIndicator > xProgress  = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_STATUSINDICATOR(), css::uno::Reference< css::task::XStatusIndicator >());
1145 
1146     if (!bHidden && !bMinimized && !bPreview && !xProgress.is())
1147     {
1148         // Note: its an optional interface!
1149         css::uno::Reference< css::task::XStatusIndicatorFactory > xProgressFactory(xTargetFrame, css::uno::UNO_QUERY);
1150         if (xProgressFactory.is())
1151         {
1152             xProgress = xProgressFactory->createStatusIndicator();
1153             if (xProgress.is())
1154                 m_lMediaDescriptor[::comphelper::MediaDescriptor::PROP_STATUSINDICATOR()] <<= xProgress;
1155         }
1156     }
1157 
1158     // convert media descriptor and URL to right format for later interface call!
1159     css::uno::Sequence< css::beans::PropertyValue > lDescriptor;
1160     m_lMediaDescriptor >> lDescriptor;
1161     ::rtl::OUString sURL = m_aURL.Complete;
1162 
1163     // try to locate any interested frame loader
1164     css::uno::Reference< css::uno::XInterface >                xLoader     = impl_searchLoader();
1165     css::uno::Reference< css::frame::XFrameLoader >            xAsyncLoader(xLoader, css::uno::UNO_QUERY);
1166     css::uno::Reference< css::frame::XSynchronousFrameLoader > xSyncLoader (xLoader, css::uno::UNO_QUERY);
1167 
1168     if (xAsyncLoader.is())
1169     {
1170         // SAFE -> -----------------------------------
1171         aWriteLock.lock();
1172         m_xAsynchronousJob = xAsyncLoader;
1173         m_pCheck           = this;
1174         LoadEnvListener* pListener = new LoadEnvListener(m_pCheck, this);
1175         aWriteLock.unlock();
1176         // <- SAFE -----------------------------------
1177 
1178         css::uno::Reference< css::frame::XLoadEventListener > xListener(static_cast< css::frame::XLoadEventListener* >(pListener), css::uno::UNO_QUERY);
1179         xAsyncLoader->load(xTargetFrame, sURL, lDescriptor, xListener);
1180 
1181         return sal_True;
1182     }
1183     else
1184     if (xSyncLoader.is())
1185     {
1186         sal_Bool bResult = xSyncLoader->load(lDescriptor, xTargetFrame);
1187         // react for the result here, so the outside waiting
1188         // code can ask for it later.
1189         impl_setResult(bResult);
1190         // But the return value indicates a valid started(!) operation.
1191         // And that's true every time we reach this line :-)
1192         return sal_True;
1193     }
1194 
1195     aWriteLock.unlock();
1196     // <- SAFE
1197 
1198     return sal_False;
1199 }
1200 
1201 /*-----------------------------------------------
1202     06.02.2004 14:40
1203 -----------------------------------------------*/
impl_searchLoader()1204 css::uno::Reference< css::uno::XInterface > LoadEnv::impl_searchLoader()
1205 {
1206     // SAFE -> -----------------------------------
1207     ReadGuard aReadLock(m_aLock);
1208 
1209     // special mode to set an existing component on this frame
1210     // In such case the laoder is fix. It must be the SFX based implementation,
1211     // which can create a view on top of such xModel components :-)
1212     if (m_eContentType == E_CAN_BE_SET)
1213     {
1214         try
1215         {
1216             return m_xSMGR->createInstance(IMPLEMENTATIONNAME_GENERICFRAMELOADER);
1217         }
1218         catch(const css::uno::RuntimeException&)
1219             { throw; }
1220         catch(const css::uno::Exception&)
1221             {}
1222         throw LoadEnvException(LoadEnvException::ID_INVALID_ENVIRONMENT);
1223     }
1224 
1225     // Otherwise ...
1226     // We need this type information to locate an registered frame loader
1227     // Without such information we can't work!
1228     ::rtl::OUString sType = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_TYPENAME(), ::rtl::OUString());
1229     if (!sType.getLength())
1230         throw LoadEnvException(LoadEnvException::ID_INVALID_MEDIADESCRIPTOR);
1231 
1232     // try to locate any interested frame loader
1233     css::uno::Reference< css::lang::XMultiServiceFactory > xLoaderFactory(m_xSMGR->createInstance(SERVICENAME_FRAMELOADERFACTORY), css::uno::UNO_QUERY);
1234     css::uno::Reference< css::container::XContainerQuery > xQuery        (xLoaderFactory                                         , css::uno::UNO_QUERY);
1235 
1236     aReadLock.unlock();
1237     // <- SAFE -----------------------------------
1238 
1239     css::uno::Sequence< ::rtl::OUString > lTypesReg(1);
1240     lTypesReg[0] = sType;
1241 
1242     css::uno::Sequence< css::beans::NamedValue > lQuery(1);
1243     lQuery[0].Name    = ::framework::constant::FrameLoader::PROP_TYPES;
1244     lQuery[0].Value <<= lTypesReg;
1245 
1246     css::uno::Reference< css::container::XEnumeration > xSet = xQuery->createSubSetEnumerationByProperties(lQuery);
1247     while(xSet->hasMoreElements())
1248     {
1249         // try everyone ...
1250         // Ignore any loader, which makes trouble :-)
1251         ::comphelper::SequenceAsHashMap             lLoaderProps(xSet->nextElement());
1252         ::rtl::OUString                             sLoader     = lLoaderProps.getUnpackedValueOrDefault(::framework::constant::FrameLoader::PROP_NAME, ::rtl::OUString());
1253         css::uno::Reference< css::uno::XInterface > xLoader     ;
1254         try
1255         {
1256             xLoader = xLoaderFactory->createInstance(sLoader);
1257             if (xLoader.is())
1258                 return xLoader;
1259         }
1260         catch(const css::uno::RuntimeException&)
1261             { throw; }
1262         catch(const css::uno::Exception&)
1263             { continue; }
1264     }
1265 
1266     return css::uno::Reference< css::uno::XInterface >();
1267 }
1268 
1269 /*-----------------------------------------------
1270     24.01.2006 15:11
1271 -----------------------------------------------*/
impl_jumpToMark(const css::uno::Reference<css::frame::XFrame> & xFrame,const css::util::URL & aURL)1272 void LoadEnv::impl_jumpToMark(const css::uno::Reference< css::frame::XFrame >& xFrame,
1273                               const css::util::URL&                            aURL  )
1274 {
1275     if (! aURL.Mark.getLength())
1276         return;
1277 
1278     css::uno::Reference< css::frame::XDispatchProvider > xProvider(xFrame, css::uno::UNO_QUERY);
1279     if (! xProvider.is())
1280         return;
1281 
1282     // SAFE ->
1283     ReadGuard aReadLock(m_aLock);
1284     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
1285     aReadLock.unlock();
1286     // <- SAFE
1287 
1288     css::util::URL aCmd;
1289     aCmd.Complete = ::rtl::OUString::createFromAscii(".uno:JumpToMark");
1290 
1291     css::uno::Reference< css::util::XURLTransformer > xParser(xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), css::uno::UNO_QUERY_THROW);
1292     xParser->parseStrict(aCmd);
1293 
1294     css::uno::Reference< css::frame::XDispatch > xDispatcher = xProvider->queryDispatch(aCmd, SPECIALTARGET_SELF, 0);
1295     if (! xDispatcher.is())
1296         return;
1297 
1298     ::comphelper::SequenceAsHashMap lArgs;
1299     lArgs[::rtl::OUString::createFromAscii("Bookmark")] <<= aURL.Mark;
1300     xDispatcher->dispatch(aCmd, lArgs.getAsConstPropertyValueList());
1301 }
1302 
1303 /*-----------------------------------------------
1304     31.07.2003 09:02
1305 -----------------------------------------------*/
impl_searchAlreadyLoaded()1306 css::uno::Reference< css::frame::XFrame > LoadEnv::impl_searchAlreadyLoaded()
1307 {
1308     // SAFE ->
1309     ReadGuard aReadLock(m_aLock);
1310 
1311     // such search is allowed for special requests only ...
1312     // or better its not allowed for some requests in general :-)
1313     if (
1314         ( ! TargetHelper::matchSpecialTarget(m_sTarget, TargetHelper::E_DEFAULT)                                               ) ||
1315         (m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_ASTEMPLATE() , sal_False) == sal_True) ||
1316 //      (m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_HIDDEN()     , sal_False) == sal_True) ||
1317         (m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_OPENNEWVIEW(), sal_False) == sal_True)
1318        )
1319     {
1320         return css::uno::Reference< css::frame::XFrame >();
1321     }
1322 
1323     // check URL
1324     // May its not useful to start expensive document search, if it
1325     // can fail only .. because we load from a stream or model directly!
1326     if (
1327         (ProtocolCheck::isProtocol(m_aURL.Complete, ProtocolCheck::E_PRIVATE_STREAM )) ||
1328         (ProtocolCheck::isProtocol(m_aURL.Complete, ProtocolCheck::E_PRIVATE_OBJECT ))
1329         /*TODO should be private:factory here tested too? */
1330        )
1331     {
1332         return css::uno::Reference< css::frame::XFrame >();
1333     }
1334 
1335     // otherwise - iterate through the tasks of the desktop container
1336     // to find out, which of them might contain the requested document
1337     css::uno::Reference< css::frame::XFramesSupplier >  xSupplier(m_xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY);
1338     css::uno::Reference< css::container::XIndexAccess > xTaskList(xSupplier->getFrames()                      , css::uno::UNO_QUERY);
1339 
1340     if (!xTaskList.is())
1341         return css::uno::Reference< css::frame::XFrame >(); // task list can be empty!
1342 
1343     // Note: To detect if a document was already loaded before
1344     // we check URLs here only. But might the existing and the required
1345     // document has different versions! Then its URLs are the same ...
1346     sal_Int16 nNewVersion = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_VERSION(), (sal_Int16)(-1));
1347 
1348     // will be used to save the first hidden frame referring the searched model
1349     // Normally we are interested in visible frames ... but if there is no such visible
1350     // frame we refer to any hidden frame also (but as fallback only).
1351     css::uno::Reference< css::frame::XFrame > xHiddenTask;
1352     css::uno::Reference< css::frame::XFrame > xTask;
1353 
1354     sal_Int32 count = xTaskList->getCount();
1355     for (sal_Int32 i=0; i<count; ++i)
1356     {
1357         try
1358         {
1359             // locate model of task
1360             // Note: Without a model there is no chance to decide if
1361             // this task contains the searched document or not!
1362             xTaskList->getByIndex(i) >>= xTask;
1363             if (!xTask.is())
1364                 continue;
1365 
1366             css::uno::Reference< css::frame::XController > xController = xTask->getController();
1367             if (!xController.is())
1368             {
1369                 xTask.clear ();
1370                 continue;
1371             }
1372 
1373             css::uno::Reference< css::frame::XModel > xModel = xController->getModel();
1374             if (!xModel.is())
1375             {
1376                 xTask.clear ();
1377                 continue;
1378             }
1379 
1380             // don't check the complete URL here.
1381             // use its main part - ignore optional jumpmarks!
1382             const ::rtl::OUString sURL = xModel->getURL();
1383             if (!::utl::UCBContentHelper::EqualURLs( m_aURL.Main, sURL ))
1384             {
1385                 xTask.clear ();
1386                 continue;
1387             }
1388 
1389             // get the original load arguments from the current document
1390             // and decide if its really the same then the one will be.
1391             // It must be visible and must use the same file revision ...
1392             // or must not have any file revision set (-1 == -1!)
1393             ::comphelper::MediaDescriptor lOldDocDescriptor(xModel->getArgs());
1394 
1395             if (lOldDocDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_VERSION(), (sal_Int32)(-1)) != nNewVersion)
1396             {
1397                 xTask.clear ();
1398                 continue;
1399             }
1400 
1401             // Hidden frames are special.
1402             // They will be used as "last chance" if there is no visible frame pointing to the same model.
1403             // Safe the result but continue with current loop might be looking for other visible frames.
1404             ::sal_Bool bIsHidden = lOldDocDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_HIDDEN(), sal_False);
1405             if (
1406                 (   bIsHidden       ) &&
1407                 ( ! xHiddenTask.is())
1408                )
1409             {
1410                 xHiddenTask = xTask;
1411                 xTask.clear ();
1412                 continue;
1413             }
1414 
1415             // We found a visible task pointing to the right model ...
1416             // Break search.
1417             break;
1418         }
1419         catch(const css::uno::RuntimeException& exRun)
1420             { throw exRun; }
1421         catch(const css::uno::Exception&)
1422             { continue; }
1423     }
1424 
1425     css::uno::Reference< css::frame::XFrame > xResult;
1426     if (xTask.is())
1427         xResult = xTask;
1428     else
1429     if (xHiddenTask.is())
1430         xResult = xHiddenTask;
1431 
1432     if (xResult.is())
1433     {
1434         // Now we are sure, that this task includes the searched document.
1435         // It's time to activate it. As special feature we try to jump internally
1436         // if an optional jumpmark is given too.
1437         if (m_aURL.Mark.getLength())
1438             impl_jumpToMark(xResult, m_aURL);
1439 
1440         // bring it to front and make sure it's visible...
1441         impl_makeFrameWindowVisible(xResult->getContainerWindow(), sal_True);
1442     }
1443 
1444     aReadLock.unlock();
1445     // <- SAFE
1446 
1447     return xResult;
1448 }
1449 
1450 /*-----------------------------------------------
1451     30.03.2004 09:12
1452 -----------------------------------------------*/
impl_isFrameAlreadyUsedForLoading(const css::uno::Reference<css::frame::XFrame> & xFrame) const1453 sal_Bool LoadEnv::impl_isFrameAlreadyUsedForLoading(const css::uno::Reference< css::frame::XFrame >& xFrame) const
1454 {
1455     css::uno::Reference< css::document::XActionLockable > xLock(xFrame, css::uno::UNO_QUERY);
1456 
1457     // ? no lock interface ?
1458     // Might its an external written frame implementation :-(
1459     // Allowing using of it ... but it can fail if its not synchronized with our processes !
1460     if (!xLock.is())
1461         return sal_False;
1462 
1463     // Otherwise we have to look for any other existing lock.
1464     return xLock->isActionLocked();
1465 }
1466 
1467 /*-----------------------------------------------
1468     30.03.2004 09:12
1469 -----------------------------------------------*/
impl_searchRecycleTarget()1470 css::uno::Reference< css::frame::XFrame > LoadEnv::impl_searchRecycleTarget()
1471 {
1472     // SAFE -> ..................................
1473     ReadGuard aReadLock(m_aLock);
1474 
1475     // The special backing mode frame will be recycled by definition!
1476     // It doesn't matter if somewhere wishes to create a new view
1477     // or open a new untitled document ...
1478     // The only exception form that - hidden frames!
1479     if (m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_HIDDEN(), sal_False) == sal_True)
1480         return css::uno::Reference< css::frame::XFrame >();
1481 
1482     css::uno::Reference< css::frame::XFramesSupplier > xSupplier(m_xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY);
1483     FrameListAnalyzer aTasksAnalyzer(xSupplier, css::uno::Reference< css::frame::XFrame >(), FrameListAnalyzer::E_BACKINGCOMPONENT);
1484     if (aTasksAnalyzer.m_xBackingComponent.is())
1485     {
1486         if (!impl_isFrameAlreadyUsedForLoading(aTasksAnalyzer.m_xBackingComponent))
1487         {
1488             // bring it to front ...
1489             impl_makeFrameWindowVisible(aTasksAnalyzer.m_xBackingComponent->getContainerWindow(), sal_True);
1490             return aTasksAnalyzer.m_xBackingComponent;
1491         }
1492     }
1493 
1494     // These states indicates the wishing for creation of a new view in general.
1495     if (
1496         (m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_ASTEMPLATE() , sal_False) == sal_True) ||
1497         (m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_OPENNEWVIEW(), sal_False) == sal_True)
1498        )
1499     {
1500         return css::uno::Reference< css::frame::XFrame >();
1501     }
1502 
1503     // On the other side some special URLs will open a new frame everytimes (expecting
1504     // they can use the backing-mode frame!)
1505     if (
1506         (ProtocolCheck::isProtocol(m_aURL.Complete, ProtocolCheck::E_PRIVATE_FACTORY )) ||
1507         (ProtocolCheck::isProtocol(m_aURL.Complete, ProtocolCheck::E_PRIVATE_STREAM  )) ||
1508         (ProtocolCheck::isProtocol(m_aURL.Complete, ProtocolCheck::E_PRIVATE_OBJECT  ))
1509        )
1510     {
1511         return css::uno::Reference< css::frame::XFrame >();
1512     }
1513 
1514     // No backing frame! No special URL => recycle active task - if possible.
1515     // Means - if it does not already contains a modified document, or
1516     // use another office module.
1517     css::uno::Reference< css::frame::XFrame > xTask = xSupplier->getActiveFrame();
1518 
1519     // not a real error - but might a focus problem!
1520     if (!xTask.is())
1521         return css::uno::Reference< css::frame::XFrame >();
1522 
1523     // not a real error - may its a view only
1524     css::uno::Reference< css::frame::XController > xController = xTask->getController();
1525     if (!xController.is())
1526         return css::uno::Reference< css::frame::XFrame >();
1527 
1528     // not a real error - may its a db component instead of a full feartured office document
1529     css::uno::Reference< css::frame::XModel > xModel = xController->getModel();
1530     if (!xModel.is())
1531         return css::uno::Reference< css::frame::XFrame >();
1532 
1533     // get some more informations ...
1534 
1535     // A valid set URL means: there is already a location for this document.
1536     // => it was saved there or opened from there. Such Documents can not be used here.
1537     // We search for empty document ... created by a private:factory/ URL!
1538     if (xModel->getURL().getLength()>0)
1539         return css::uno::Reference< css::frame::XFrame >();
1540 
1541     // The old document must be unmodified ...
1542     css::uno::Reference< css::util::XModifiable > xModified(xModel, css::uno::UNO_QUERY);
1543     if (xModified->isModified())
1544         return css::uno::Reference< css::frame::XFrame >();
1545 
1546     Window* pWindow = VCLUnoHelper::GetWindow(xTask->getContainerWindow());
1547     if (pWindow && pWindow->IsInModalMode())
1548         return css::uno::Reference< css::frame::XFrame >();
1549 
1550     // find out the application type of this document
1551     // We can recycle only documents, which uses the same application
1552     // then the new one.
1553     SvtModuleOptions::EFactory eOldApp = SvtModuleOptions::ClassifyFactoryByModel(xModel);
1554     SvtModuleOptions::EFactory eNewApp = SvtModuleOptions::ClassifyFactoryByURL  (m_aURL.Complete, m_lMediaDescriptor.getAsConstPropertyValueList());
1555 
1556     aReadLock.unlock();
1557     // <- SAFE ..................................
1558 
1559     if (eOldApp != eNewApp)
1560         return css::uno::Reference< css::frame::XFrame >();
1561 
1562     // OK this task seems to be useable for recycling
1563     // But we should mark it as such - means set an action lock.
1564     // Otherwise it would be used more than once or will be destroyed
1565     // by a close() or terminate() request.
1566     // But if such lock already exists ... it means this task is used for
1567     // any other operation already. Don't use it then.
1568     if (impl_isFrameAlreadyUsedForLoading(xTask))
1569         return css::uno::Reference< css::frame::XFrame >();
1570 
1571     // OK - there is a valid target frame.
1572     // But may be it contains already a document.
1573     // Then we have to ask it, if it allows recylcing of this frame .-)
1574     sal_Bool bReactivateOldControllerOnError = sal_False;
1575     css::uno::Reference< css::frame::XController > xOldDoc = xTask->getController();
1576     if (xOldDoc.is())
1577     {
1578         bReactivateOldControllerOnError = xOldDoc->suspend(sal_True);
1579         if (! bReactivateOldControllerOnError)
1580             return css::uno::Reference< css::frame::XFrame >();
1581     }
1582 
1583     // SAFE -> ..................................
1584     WriteGuard aWriteLock(m_aLock);
1585 
1586     css::uno::Reference< css::document::XActionLockable > xLock(xTask, css::uno::UNO_QUERY);
1587     if (!m_aTargetLock.setResource(xLock))
1588         return css::uno::Reference< css::frame::XFrame >();
1589 
1590     m_bReactivateControllerOnError = bReactivateOldControllerOnError;
1591     aWriteLock.unlock();
1592     // <- SAFE ..................................
1593 
1594     // bring it to front ...
1595     impl_makeFrameWindowVisible(xTask->getContainerWindow(), sal_True);
1596 
1597     return xTask;
1598 }
1599 
1600 /*-----------------------------------------------
1601     15.08.2003 12:39
1602 -----------------------------------------------*/
impl_reactForLoadingState()1603 void LoadEnv::impl_reactForLoadingState()
1604 {
1605     /*TODO reset action locks */
1606 
1607     // SAFE -> ----------------------------------
1608     ReadGuard aReadLock(m_aLock);
1609 
1610     if (m_bLoaded)
1611     {
1612         // Bring the new loaded document to front (if allowed!).
1613         // Note: We show new created frames here only.
1614         // We dont hide already visible frames here ...
1615         css::uno::Reference< css::awt::XWindow > xWindow      = m_xTargetFrame->getContainerWindow();
1616         sal_Bool                                 bHidden      = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_HIDDEN(), sal_False);
1617         sal_Bool                                 bMinimized = m_lMediaDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_MINIMIZED(), sal_False);
1618 
1619         if (bMinimized)
1620         {
1621             ::vos::OClearableGuard aSolarGuard(Application::GetSolarMutex());
1622             Window* pWindow = VCLUnoHelper::GetWindow(xWindow);
1623             // check for system window is necessary to guarantee correct pointer cast!
1624             if (pWindow && pWindow->IsSystemWindow())
1625                 ((WorkWindow*)pWindow)->Minimize();
1626         }
1627         else
1628         if (!bHidden)
1629         {
1630             // show frame ... if it's not still visible ...
1631             // But do nothing if it's already visible!
1632             impl_makeFrameWindowVisible(xWindow, sal_False);
1633         }
1634 
1635         // Note: Only if an existing property "FrameName" is given by this media descriptor,
1636         // it should be used. Otherwise we should do nothing. Maybe the outside code has already
1637         // set a frame name on the target!
1638         ::comphelper::MediaDescriptor::const_iterator pFrameName = m_lMediaDescriptor.find(::comphelper::MediaDescriptor::PROP_FRAMENAME());
1639         if (pFrameName != m_lMediaDescriptor.end())
1640         {
1641             ::rtl::OUString sFrameName;
1642             pFrameName->second >>= sFrameName;
1643             // Check the name again. e.g. "_default" isn't allowed.
1644             // On the other side "_beamer" is a valid name :-)
1645             if (TargetHelper::isValidNameForFrame(sFrameName))
1646                 m_xTargetFrame->setName(sFrameName);
1647         }
1648     }
1649     else if (m_bReactivateControllerOnError)
1650     {
1651         // Try to reactivate the old document (if any exists!)
1652         css::uno::Reference< css::frame::XController > xOldDoc = m_xTargetFrame->getController();
1653         // clear does not depend from reactivation state of a might existing old document!
1654         // We must make sure, that a might following getTargetComponent() call does not return
1655         // the old document!
1656         m_xTargetFrame.clear();
1657         if (xOldDoc.is())
1658         {
1659             sal_Bool bReactivated = xOldDoc->suspend(sal_False);
1660             if (!bReactivated)
1661                 throw LoadEnvException(LoadEnvException::ID_COULD_NOT_REACTIVATE_CONTROLLER);
1662             m_bReactivateControllerOnError = sal_False;
1663         }
1664     }
1665     else if (m_bCloseFrameOnError)
1666     {
1667         // close empty frames
1668         css::uno::Reference< css::util::XCloseable > xCloseable (m_xTargetFrame, css::uno::UNO_QUERY);
1669         css::uno::Reference< css::lang::XComponent > xDisposable(m_xTargetFrame, css::uno::UNO_QUERY);
1670 
1671         try
1672         {
1673             if (xCloseable.is())
1674                 xCloseable->close(sal_True);
1675             else
1676             if (xDisposable.is())
1677                 xDisposable->dispose();
1678         }
1679         catch(const css::util::CloseVetoException&)
1680         {}
1681         catch(const css::lang::DisposedException&)
1682         {}
1683         m_xTargetFrame.clear();
1684     }
1685 
1686     // This max force an implicit closing of our target frame ...
1687     // e.g. in case close(sal_True) was called before and the frame
1688     // kill itself if our external use-lock is released here!
1689     // That's why we release this lock AFTER ALL OPERATIONS on this frame
1690     // are finished. The frame itself must handle then
1691     // this situation gracefully.
1692     m_aTargetLock.freeResource();
1693 
1694     // Last but not least :-)
1695     // We have to clear the current media descriptor.
1696     // Otherwise it hold a might existing stream open!
1697     m_lMediaDescriptor.clear();
1698 
1699     css::uno::Any aRequest;
1700     bool bThrow = false;
1701     if ( !m_bLoaded && m_pQuietInteraction && m_pQuietInteraction->wasUsed() )
1702     {
1703         aRequest = m_pQuietInteraction->getRequest();
1704         m_pQuietInteraction->release();
1705         m_pQuietInteraction = 0;
1706         bThrow = true;
1707     }
1708 
1709     aReadLock.unlock();
1710 
1711     if (bThrow)
1712     {
1713         if  ( aRequest.isExtractableTo( ::cppu::UnoType< css::uno::Exception >::get() ) )
1714             throw LoadEnvException( LoadEnvException::ID_GENERAL_ERROR, aRequest );
1715     }
1716 
1717     // <- SAFE ----------------------------------
1718 }
1719 
1720 /*-----------------------------------------------
1721     16.01.2005 13:04
1722 -----------------------------------------------*/
impl_makeFrameWindowVisible(const css::uno::Reference<css::awt::XWindow> & xWindow,sal_Bool bForceToFront)1723 void LoadEnv::impl_makeFrameWindowVisible(const css::uno::Reference< css::awt::XWindow >& xWindow      ,
1724                                                 sal_Bool bForceToFront)
1725 {
1726     // SAFE -> ----------------------------------
1727     ReadGuard aReadLock(m_aLock);
1728     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR( m_xSMGR.get(), css::uno::UNO_QUERY );
1729     aReadLock.unlock();
1730     // <- SAFE ----------------------------------
1731 
1732     ::vos::OClearableGuard aSolarGuard(Application::GetSolarMutex());
1733     Window* pWindow = VCLUnoHelper::GetWindow(xWindow);
1734     if ( pWindow )
1735     {
1736         bool bForceFrontAndFocus(false);
1737         css::uno::Any a = ::comphelper::ConfigurationHelper::readDirectKey(
1738             xSMGR,
1739             ::rtl::OUString::createFromAscii("org.openoffice.Office.Common/View"),
1740             ::rtl::OUString::createFromAscii("NewDocumentHandling"),
1741             ::rtl::OUString::createFromAscii("ForceFocusAndToFront"),
1742             ::comphelper::ConfigurationHelper::E_READONLY);
1743         a >>= bForceFrontAndFocus;
1744 
1745         if( pWindow->IsVisible() && (bForceFrontAndFocus || bForceToFront) )
1746             pWindow->ToTop();
1747         else
1748             pWindow->Show(sal_True, (bForceFrontAndFocus || bForceToFront) ? SHOW_FOREGROUNDTASK : 0 );
1749     }
1750 
1751 /* #i19976#
1752     We tried to prevent a toFront() call in case the user putted the
1753     loading document into the background ..
1754     But we had several errors trying that. So we decided to
1755     rollback these changes and bring the new loaded document to front hardly !
1756 
1757     css::uno::Reference< css::awt::XWindow2 > xWindow2(xWindow, css::uno::UNO_QUERY);
1758 
1759     sal_Bool bIsVisible = sal_False;
1760     if (xWindow2.is())
1761         bIsVisible = xWindow2->isVisible(); // TODO is parent visible too ? .-)
1762 
1763     if (!bIsVisible)
1764     {
1765         xWindow->setVisible(sal_True);
1766         bForceToFront = sal_True;
1767     }
1768 
1769     if (
1770         (bForceToFront  ) &&
1771         (xTopWindow.is())
1772        )
1773     {
1774         xTopWindow->toFront();
1775     }
1776 */
1777 }
1778 
1779 /*-----------------------------------------------
1780     15.03.2005 11:12
1781 -----------------------------------------------*/
impl_applyPersistentWindowState(const css::uno::Reference<css::awt::XWindow> & xWindow)1782 void LoadEnv::impl_applyPersistentWindowState(const css::uno::Reference< css::awt::XWindow >& xWindow)
1783 {
1784     static ::rtl::OUString PACKAGE_SETUP_MODULES = ::rtl::OUString::createFromAscii("/org.openoffice.Setup/Office/Factories");
1785 
1786     // no window -> action not possible
1787     if (!xWindow.is())
1788         return;
1789 
1790     // window already visible -> do nothing! If we use a "recycle frame" for loading ...
1791     // the current position and size must be used.
1792     css::uno::Reference< css::awt::XWindow2 > xVisibleCheck(xWindow, css::uno::UNO_QUERY);
1793     if (
1794         (xVisibleCheck.is()        ) &&
1795         (xVisibleCheck->isVisible())
1796        )
1797        return;
1798 
1799     // SOLAR SAFE ->
1800     ::vos::OClearableGuard aSolarLock1(Application::GetSolarMutex());
1801 
1802     Window*  pWindow       = VCLUnoHelper::GetWindow(xWindow);
1803     sal_Bool bSystemWindow = pWindow->IsSystemWindow();
1804     sal_Bool bWorkWindow   = (pWindow->GetType() == WINDOW_WORKWINDOW);
1805 
1806     if (!bSystemWindow && !bWorkWindow)
1807         return;
1808 
1809     // dont overwrite this special state!
1810     WorkWindow* pWorkWindow = (WorkWindow*)pWindow;
1811     if (pWorkWindow->IsMinimized())
1812         return;
1813 
1814     aSolarLock1.clear();
1815     // <- SOLAR SAFE
1816 
1817     // SAFE ->
1818     ReadGuard aReadLock(m_aLock);
1819 
1820     // no filter -> no module -> no persistent window state
1821     ::rtl::OUString sFilter = m_lMediaDescriptor.getUnpackedValueOrDefault(
1822                                     ::comphelper::MediaDescriptor::PROP_FILTERNAME(),
1823                                     ::rtl::OUString());
1824     if (!sFilter.getLength())
1825         return;
1826 
1827     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
1828 
1829     aReadLock.unlock();
1830     // <- SAFE
1831 
1832     try
1833     {
1834         // retrieve the module name from the filter configuration
1835         css::uno::Reference< css::container::XNameAccess > xFilterCfg(
1836             xSMGR->createInstance(SERVICENAME_FILTERFACTORY),
1837             css::uno::UNO_QUERY_THROW);
1838         ::comphelper::SequenceAsHashMap lProps (xFilterCfg->getByName(sFilter));
1839         ::rtl::OUString                 sModule = lProps.getUnpackedValueOrDefault(FILTER_PROPNAME_DOCUMENTSERVICE, ::rtl::OUString());
1840 
1841         // get access to the configuration of this office module
1842         css::uno::Reference< css::container::XNameAccess > xModuleCfg(::comphelper::ConfigurationHelper::openConfig(
1843                                                                         xSMGR,
1844                                                                         PACKAGE_SETUP_MODULES,
1845                                                                         ::comphelper::ConfigurationHelper::E_READONLY),
1846                                                                       css::uno::UNO_QUERY_THROW);
1847 
1848         // read window state from the configuration
1849         // and apply it on the window.
1850         // Do nothing, if no configuration entry exists!
1851         ::rtl::OUString sWindowState ;
1852         ::comphelper::ConfigurationHelper::readRelativeKey(xModuleCfg, sModule, OFFICEFACTORY_PROPNAME_WINDOWATTRIBUTES) >>= sWindowState;
1853         if (sWindowState.getLength())
1854         {
1855             // SOLAR SAFE ->
1856             ::vos::OClearableGuard aSolarLock2(Application::GetSolarMutex());
1857 
1858             // We have to retrieve the window pointer again. Because nobody can guarantee
1859             // that the XWindow was not disposed inbetween .-)
1860             // But if we get a valid pointer we can be sure, that it's the system window pointer
1861             // we already checked and used before. Because nobody recylce the same uno reference for
1862             // a new internal c++ implementation ... hopefully .-))
1863             Window* pWindowCheck  = VCLUnoHelper::GetWindow(xWindow);
1864             if (! pWindowCheck)
1865                 return;
1866 
1867             SystemWindow* pSystemWindow = (SystemWindow*)pWindowCheck;
1868             pSystemWindow->SetWindowState(U2B_ENC(sWindowState,RTL_TEXTENCODING_UTF8));
1869 
1870             aSolarLock2.clear();
1871             // <- SOLAR SAFE
1872         }
1873     }
1874     catch(const css::uno::RuntimeException& exRun)
1875         { throw exRun; }
1876     catch(const css::uno::Exception&)
1877         {}
1878 }
1879 
1880 } // namespace framework
1881