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