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