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