calc: on editing invalidation of view with different zoom is wrong
[LibreOffice.git] / framework / source / loadenv / loadenv.cxx
blob3cf0c85962230dba8ad8799fc1ef8cfa540719d6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <loadenv/loadenv.hxx>
22 #include <loadenv/loadenvexception.hxx>
23 #include <loadenv/targethelper.hxx>
24 #include <framework/framelistanalyzer.hxx>
26 #include <interaction/quietinteraction.hxx>
27 #include <properties.h>
28 #include <protocols.h>
29 #include <services.h>
30 #include <targets.h>
31 #include <comphelper/interaction.hxx>
32 #include <comphelper/lok.hxx>
33 #include <comphelper/namedvaluecollection.hxx>
34 #include <comphelper/propertysequence.hxx>
35 #include <framework/interaction.hxx>
36 #include <comphelper/processfactory.hxx>
37 #include <officecfg/Office/Common.hxx>
38 #include <officecfg/Setup.hxx>
40 #include <com/sun/star/awt/XWindow2.hpp>
41 #include <com/sun/star/beans/XPropertySet.hpp>
42 #include <com/sun/star/container/XNameAccess.hpp>
43 #include <com/sun/star/container/XEnumeration.hpp>
44 #include <com/sun/star/document/MacroExecMode.hpp>
45 #include <com/sun/star/document/XTypeDetection.hpp>
46 #include <com/sun/star/document/XActionLockable.hpp>
47 #include <com/sun/star/document/UpdateDocMode.hpp>
48 #include <com/sun/star/frame/Desktop.hpp>
49 #include <com/sun/star/frame/OfficeFrameLoader.hpp>
50 #include <com/sun/star/frame/XModel.hpp>
51 #include <com/sun/star/frame/XFrameLoader.hpp>
52 #include <com/sun/star/frame/XSynchronousFrameLoader.hpp>
53 #include <com/sun/star/frame/XNotifyingDispatch.hpp>
54 #include <com/sun/star/frame/FrameLoaderFactory.hpp>
55 #include <com/sun/star/frame/ContentHandlerFactory.hpp>
56 #include <com/sun/star/frame/DispatchResultState.hpp>
57 #include <com/sun/star/frame/FrameSearchFlag.hpp>
58 #include <com/sun/star/frame/XDispatchProvider.hpp>
59 #include <com/sun/star/lang/IllegalArgumentException.hpp>
60 #include <com/sun/star/lang/XInitialization.hpp>
61 #include <com/sun/star/lang/DisposedException.hpp>
62 #include <com/sun/star/io/XInputStream.hpp>
63 #include <com/sun/star/task/XInteractionHandler.hpp>
64 #include <com/sun/star/task/ErrorCodeRequest.hpp>
65 #include <com/sun/star/task/InteractionHandler.hpp>
66 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
67 #include <com/sun/star/task/XStatusIndicator.hpp>
68 #include <com/sun/star/uno/RuntimeException.hpp>
69 #include <com/sun/star/ucb/UniversalContentBroker.hpp>
70 #include <com/sun/star/util/CloseVetoException.hpp>
71 #include <com/sun/star/util/URLTransformer.hpp>
72 #include <com/sun/star/util/XURLTransformer.hpp>
73 #include <com/sun/star/util/XCloseable.hpp>
74 #include <com/sun/star/util/XModifiable.hpp>
76 #include <utility>
77 #include <vcl/window.hxx>
78 #include <vcl/wrkwin.hxx>
79 #include <vcl/syswin.hxx>
81 #include <toolkit/helper/vclunohelper.hxx>
82 #include <unotools/moduleoptions.hxx>
83 #include <svtools/sfxecode.hxx>
84 #include <unotools/ucbhelper.hxx>
85 #include <comphelper/configurationhelper.hxx>
86 #include <rtl/bootstrap.hxx>
87 #include <sal/log.hxx>
88 #include <comphelper/errcode.hxx>
89 #include <vcl/svapp.hxx>
90 #include <cppuhelper/implbase.hxx>
91 #include <comphelper/profilezone.hxx>
92 #include <classes/taskcreator.hxx>
93 #include <tools/fileutil.hxx>
95 constexpr OUStringLiteral PROP_TYPES = u"Types";
96 constexpr OUStringLiteral PROP_NAME = u"Name";
98 namespace framework {
100 using namespace com::sun::star;
102 namespace {
104 class LoadEnvListener : public ::cppu::WeakImplHelper< css::frame::XLoadEventListener ,
105 css::frame::XDispatchResultListener >
107 private:
108 osl::Mutex m_mutex;
109 bool m_bWaitingResult;
110 LoadEnv* m_pLoadEnv;
112 public:
114 explicit LoadEnvListener(LoadEnv* pLoadEnv)
115 : m_bWaitingResult(true)
116 , m_pLoadEnv(pLoadEnv)
120 // frame.XLoadEventListener
121 virtual void SAL_CALL loadFinished(const css::uno::Reference< css::frame::XFrameLoader >& xLoader) override;
123 virtual void SAL_CALL loadCancelled(const css::uno::Reference< css::frame::XFrameLoader >& xLoader) override;
125 // frame.XDispatchResultListener
126 virtual void SAL_CALL dispatchFinished(const css::frame::DispatchResultEvent& aEvent) override;
128 // lang.XEventListener
129 virtual void SAL_CALL disposing(const css::lang::EventObject& aEvent) override;
134 LoadEnv::LoadEnv(css::uno::Reference< css::uno::XComponentContext > xContext)
135 : m_xContext(std::move(xContext))
136 , m_nSearchFlags(0)
137 , m_eFeature(LoadEnvFeatures::NONE)
138 , m_eContentType(E_UNSUPPORTED_CONTENT)
139 , m_bCloseFrameOnError(false)
140 , m_bReactivateControllerOnError(false)
141 , m_bLoaded( false )
145 LoadEnv::~LoadEnv()
149 css::uno::Reference< css::lang::XComponent > LoadEnv::loadComponentFromURL(const css::uno::Reference< css::frame::XComponentLoader >& xLoader,
150 const css::uno::Reference< css::uno::XComponentContext >& xContext ,
151 const OUString& sURL ,
152 const OUString& sTarget,
153 sal_Int32 nSearchFlags ,
154 const css::uno::Sequence< css::beans::PropertyValue >& lArgs )
156 css::uno::Reference< css::lang::XComponent > xComponent;
157 comphelper::ProfileZone aZone("loadComponentFromURL");
161 LoadEnv aEnv(xContext);
163 LoadEnvFeatures loadEnvFeatures = LoadEnvFeatures::WorkWithUI;
164 // tdf#118238 Only disable UI interaction when loading as hidden
165 if (comphelper::NamedValueCollection::get(lArgs, u"Hidden") == uno::Any(true) || Application::IsHeadlessModeEnabled())
166 loadEnvFeatures = LoadEnvFeatures::NONE;
168 aEnv.startLoading(sURL,
169 lArgs,
170 css::uno::Reference< css::frame::XFrame >(xLoader, css::uno::UNO_QUERY),
171 sTarget,
172 nSearchFlags,
173 loadEnvFeatures);
174 aEnv.waitWhileLoading(); // wait for ever!
176 xComponent = aEnv.getTargetComponent();
178 catch(const LoadEnvException& ex)
180 switch(ex.m_nID)
182 case LoadEnvException::ID_INVALID_MEDIADESCRIPTOR:
183 throw css::lang::IllegalArgumentException(
184 "Optional list of arguments seem to be corrupted.", xLoader, 4);
186 case LoadEnvException::ID_UNSUPPORTED_CONTENT:
187 throw css::lang::IllegalArgumentException(
188 "Unsupported URL <" + sURL + ">: \"" + ex.m_sMessage + "\"",
189 xLoader, 1);
191 default:
192 SAL_WARN(
193 "fwk.loadenv",
194 "caught LoadEnvException " << +ex.m_nID << " \""
195 << ex.m_sMessage << "\""
196 << (ex.m_exOriginal.has<css::uno::Exception>()
197 ? (", " + ex.m_exOriginal.getValueTypeName() + " \""
198 + (ex.m_exOriginal.get<css::uno::Exception>().
199 Message)
200 + "\"")
201 : OUString())
202 << " while loading <" << sURL << ">");
203 xComponent.clear();
204 break;
208 return xComponent;
211 namespace {
213 utl::MediaDescriptor addModelArgs(const uno::Sequence<beans::PropertyValue>& rDescriptor)
215 utl::MediaDescriptor rResult(rDescriptor);
216 uno::Reference<frame::XModel> xModel(rResult.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_MODEL, uno::Reference<frame::XModel>()));
218 if (xModel.is())
220 utl::MediaDescriptor aModelArgs(xModel->getArgs());
221 utl::MediaDescriptor::iterator pIt = aModelArgs.find( utl::MediaDescriptor::PROP_MACROEXECUTIONMODE);
222 if (pIt != aModelArgs.end())
223 rResult[utl::MediaDescriptor::PROP_MACROEXECUTIONMODE] = pIt->second;
226 return rResult;
231 void LoadEnv::startLoading(const OUString& sURL, const uno::Sequence<beans::PropertyValue>& lMediaDescriptor,
232 const uno::Reference<frame::XFrame>& xBaseFrame, const OUString& sTarget,
233 sal_Int32 nSearchFlags, LoadEnvFeatures eFeature)
235 osl::MutexGuard g(m_mutex);
237 // Handle still running processes!
238 if (m_xAsynchronousJob.is())
239 throw LoadEnvException(LoadEnvException::ID_STILL_RUNNING);
241 // take over all new parameters.
242 m_xTargetFrame.clear();
243 m_xBaseFrame = xBaseFrame;
244 m_lMediaDescriptor = addModelArgs(lMediaDescriptor);
245 m_sTarget = sTarget;
246 m_nSearchFlags = nSearchFlags;
247 m_eFeature = eFeature;
248 m_eContentType = E_UNSUPPORTED_CONTENT;
249 m_bCloseFrameOnError = false;
250 m_bReactivateControllerOnError = false;
251 m_bLoaded = false;
253 OUString aRealURL;
254 if (!officecfg::Office::Common::Load::DetectWebDAVRedirection::get()
255 || !tools::IsMappedWebDAVPath(sURL, &aRealURL))
256 aRealURL = sURL;
258 // try to find out, if it's really a content, which can be loaded or must be "handled"
259 // We use a default value for this in-parameter. Then we have to start a complex check method
260 // internally. But if this check was already done outside it can be suppressed to perform
261 // the load request. We take over the result then!
262 m_eContentType = LoadEnv::classifyContent(aRealURL, lMediaDescriptor);
263 if (m_eContentType == E_UNSUPPORTED_CONTENT)
264 throw LoadEnvException(LoadEnvException::ID_UNSUPPORTED_CONTENT, "from LoadEnv::startLoading");
266 // make URL part of the MediaDescriptor
267 // It doesn't matter if it is already an item of it.
268 // It must be the same value... so we can overwrite it :-)
269 m_lMediaDescriptor[utl::MediaDescriptor::PROP_URL] <<= aRealURL;
271 // parse it - because some following code require that
272 m_aURL.Complete = aRealURL;
273 uno::Reference<util::XURLTransformer> xParser(util::URLTransformer::create(m_xContext));
274 xParser->parseStrict(m_aURL);
276 // BTW: Split URL and JumpMark ...
277 // Because such mark is an explicit value of the media descriptor!
278 if (!m_aURL.Mark.isEmpty())
279 m_lMediaDescriptor[utl::MediaDescriptor::PROP_JUMPMARK] <<= m_aURL.Mark;
281 // By the way: remove the old and deprecated value "FileName" from the descriptor!
282 utl::MediaDescriptor::iterator pIt = m_lMediaDescriptor.find(utl::MediaDescriptor::PROP_FILENAME);
283 if (pIt != m_lMediaDescriptor.end())
284 m_lMediaDescriptor.erase(pIt);
286 // patch the MediaDescriptor, so it fulfil the outside requirements
287 // Means especially items like e.g. UI InteractionHandler, Status Indicator,
288 // MacroExecutionMode, etc.
290 /*TODO progress is bound to a frame ... How can we set it here? */
292 // UI mode
293 const bool bUIMode =
294 (m_eFeature & LoadEnvFeatures::WorkWithUI) &&
295 !m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_HIDDEN, false) &&
296 !m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_PREVIEW, false);
298 if( comphelper::LibreOfficeKit::isActive() &&
299 m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_SILENT, false))
301 rtl::Reference<QuietInteraction> pQuietInteraction = new QuietInteraction();
302 uno::Reference<task::XInteractionHandler> xInteractionHandler(pQuietInteraction);
303 m_lMediaDescriptor[utl::MediaDescriptor::PROP_INTERACTIONHANDLER] <<= xInteractionHandler;
306 initializeUIDefaults(m_xContext, m_lMediaDescriptor, bUIMode, &m_pQuietInteraction);
308 start();
311 void LoadEnv::initializeUIDefaults( const css::uno::Reference< css::uno::XComponentContext >& i_rxContext,
312 utl::MediaDescriptor& io_lMediaDescriptor, const bool i_bUIMode,
313 rtl::Reference<QuietInteraction>* o_ppQuietInteraction )
315 css::uno::Reference< css::task::XInteractionHandler > xInteractionHandler;
316 sal_Int16 nMacroMode;
317 sal_Int16 nUpdateMode;
319 if ( i_bUIMode )
321 nMacroMode = css::document::MacroExecMode::USE_CONFIG;
322 nUpdateMode = css::document::UpdateDocMode::ACCORDING_TO_CONFIG;
325 // tdf#154308 At least for the case the document is launched from the StartCenter, put that StartCenter as the
326 // parent for any dialogs that may appear during typedetection (once load starts a permanent frame will be set
327 // anyway and used as dialog parent, which will be this one if the startcenter was running)
328 css::uno::Reference<css::frame::XFramesSupplier> xSupplier = css::frame::Desktop::create(i_rxContext);
329 FrameListAnalyzer aTasksAnalyzer(xSupplier, css::uno::Reference<css::frame::XFrame>(), FrameAnalyzerFlags::BackingComponent);
330 css::uno::Reference<css::awt::XWindow> xDialogParent(aTasksAnalyzer.m_xBackingComponent ?
331 aTasksAnalyzer.m_xBackingComponent->getContainerWindow() :
332 nullptr);
334 xInteractionHandler.set( css::task::InteractionHandler::createWithParent(i_rxContext, xDialogParent), css::uno::UNO_QUERY_THROW );
336 catch(const css::uno::RuntimeException&) {throw;}
337 catch(const css::uno::Exception& ) { }
339 // hidden mode
340 else
342 nMacroMode = css::document::MacroExecMode::NEVER_EXECUTE;
343 nUpdateMode = css::document::UpdateDocMode::NO_UPDATE;
344 rtl::Reference<QuietInteraction> pQuietInteraction = new QuietInteraction();
345 xInteractionHandler = pQuietInteraction.get();
346 if ( o_ppQuietInteraction != nullptr )
348 *o_ppQuietInteraction = pQuietInteraction;
352 if ( xInteractionHandler.is() )
354 if( io_lMediaDescriptor.find(utl::MediaDescriptor::PROP_INTERACTIONHANDLER) == io_lMediaDescriptor.end() )
356 io_lMediaDescriptor[utl::MediaDescriptor::PROP_INTERACTIONHANDLER] <<= xInteractionHandler;
358 if( io_lMediaDescriptor.find(utl::MediaDescriptor::PROP_AUTHENTICATIONHANDLER) == io_lMediaDescriptor.end() )
360 io_lMediaDescriptor[utl::MediaDescriptor::PROP_AUTHENTICATIONHANDLER] <<= xInteractionHandler;
364 if (io_lMediaDescriptor.find(utl::MediaDescriptor::PROP_MACROEXECUTIONMODE) == io_lMediaDescriptor.end())
365 io_lMediaDescriptor[utl::MediaDescriptor::PROP_MACROEXECUTIONMODE] <<= nMacroMode;
367 if (io_lMediaDescriptor.find(utl::MediaDescriptor::PROP_UPDATEDOCMODE) == io_lMediaDescriptor.end())
368 io_lMediaDescriptor[utl::MediaDescriptor::PROP_UPDATEDOCMODE] <<= nUpdateMode;
371 void LoadEnv::start()
373 // SAFE ->
375 osl::MutexGuard aReadLock(m_mutex);
377 // Handle still running processes!
378 if (m_xAsynchronousJob.is())
379 throw LoadEnvException(LoadEnvException::ID_STILL_RUNNING);
381 // content can not be loaded or handled
382 // check "classifyContent()" failed before ...
383 if (m_eContentType == E_UNSUPPORTED_CONTENT)
384 throw LoadEnvException(LoadEnvException::ID_UNSUPPORTED_CONTENT,
385 "from LoadEnv::start");
387 // <- SAFE
389 // detect its type/filter etc.
390 // This information will be available by the
391 // used descriptor member afterwards and is needed
392 // for all following operations!
393 // Note: An exception will be thrown, in case operation was not successfully ...
394 if (m_eContentType != E_CAN_BE_SET)/* Attention: special feature to set existing component on a frame must ignore type detection! */
395 impl_detectTypeAndFilter();
397 // start loading the content...
398 // Attention: Don't check m_eContentType deeper then UNSUPPORTED/SUPPORTED!
399 // Because it was made in the easiest way... may a flat detection was made only.
400 // And such simple detection can fail sometimes .-)
401 // Use another strategy here. Try it and let it run into the case "loading not possible".
402 bool bStarted = false;
403 if (
404 (m_eFeature & LoadEnvFeatures::AllowContentHandler) &&
405 (m_eContentType != E_CAN_BE_SET ) /* Attention: special feature to set existing component on a frame must ignore type detection! */
408 bStarted = impl_handleContent();
411 if (!bStarted)
412 bStarted = impl_loadContent();
414 // not started => general error
415 // We can't say - what was the reason for.
416 if (!bStarted)
417 throw LoadEnvException(
418 LoadEnvException::ID_GENERAL_ERROR, "not started");
421 /*-----------------------------------------------
422 TODO
423 First draft does not implement timeout using [ms].
424 Current implementation counts yield calls only ...
425 -----------------------------------------------*/
426 bool LoadEnv::waitWhileLoading(sal_uInt32 nTimeout)
428 // Because it's not a good idea to block the main thread
429 // (and we can't be sure that we are currently not used inside the
430 // main thread!), we can't use conditions here really. We must yield
431 // in an intelligent manner :-)
433 sal_Int32 nTime = nTimeout;
434 while(!Application::IsQuit())
436 // SAFE -> ------------------------------
438 osl::MutexGuard aReadLock1(m_mutex);
439 if (!m_xAsynchronousJob.is())
440 break;
442 // <- SAFE ------------------------------
444 Application::Yield();
446 // forever!
447 if (nTimeout==0)
448 continue;
450 // timed out?
451 --nTime;
452 if (nTime<1)
453 break;
456 osl::MutexGuard g(m_mutex);
457 return !m_xAsynchronousJob.is();
460 css::uno::Reference< css::lang::XComponent > LoadEnv::getTargetComponent() const
462 osl::MutexGuard g(m_mutex);
464 if (!m_xTargetFrame.is())
465 return css::uno::Reference< css::lang::XComponent >();
467 css::uno::Reference< css::frame::XController > xController = m_xTargetFrame->getController();
468 if (!xController.is())
469 return m_xTargetFrame->getComponentWindow();
471 css::uno::Reference< css::frame::XModel > xModel = xController->getModel();
472 if (!xModel.is())
473 return xController;
475 return xModel;
478 void SAL_CALL LoadEnvListener::loadFinished(const css::uno::Reference< css::frame::XFrameLoader >&)
480 osl::MutexGuard g(m_mutex);
481 if (m_bWaitingResult)
482 m_pLoadEnv->impl_setResult(true);
483 m_bWaitingResult = false;
486 void SAL_CALL LoadEnvListener::loadCancelled(const css::uno::Reference< css::frame::XFrameLoader >&)
488 osl::MutexGuard g(m_mutex);
489 if (m_bWaitingResult)
490 m_pLoadEnv->impl_setResult(false);
491 m_bWaitingResult = false;
494 void SAL_CALL LoadEnvListener::dispatchFinished(const css::frame::DispatchResultEvent& aEvent)
496 osl::MutexGuard g(m_mutex);
498 if (!m_bWaitingResult)
499 return;
501 switch(aEvent.State)
503 case css::frame::DispatchResultState::FAILURE :
504 m_pLoadEnv->impl_setResult(false);
505 break;
507 case css::frame::DispatchResultState::SUCCESS :
508 m_pLoadEnv->impl_setResult(false);
509 break;
511 case css::frame::DispatchResultState::DONTKNOW :
512 m_pLoadEnv->impl_setResult(false);
513 break;
515 m_bWaitingResult = false;
518 void SAL_CALL LoadEnvListener::disposing(const css::lang::EventObject&)
520 osl::MutexGuard g(m_mutex);
521 if (m_bWaitingResult)
522 m_pLoadEnv->impl_setResult(false);
523 m_bWaitingResult = false;
526 void LoadEnv::impl_setResult(bool bResult)
528 osl::MutexGuard g(m_mutex);
530 m_bLoaded = bResult;
532 impl_reactForLoadingState();
534 // clearing of this reference will unblock waitWhileLoading()!
535 // So we must be sure, that loading process was really finished.
536 // => do it as last operation of this method ...
537 m_xAsynchronousJob.clear();
540 /*-----------------------------------------------
541 TODO: Is it a good idea to change Sequence<>
542 parameter to stl-adapter?
543 -----------------------------------------------*/
544 LoadEnv::EContentType LoadEnv::classifyContent(const OUString& sURL ,
545 const css::uno::Sequence< css::beans::PropertyValue >& lMediaDescriptor)
548 // (i) Filter some special well known URL protocols,
549 // which can not be handled or loaded in general.
550 // Of course an empty URL must be ignored here too.
551 // Note: These URL schemata are fix and well known ...
552 // But there can be some additional ones, which was not
553 // defined at implementation time of this class :-(
554 // So we have to make sure, that the following code
555 // can detect such protocol schemata too :-)
558 (sURL.isEmpty() ) ||
559 (ProtocolCheck::isProtocol(sURL,EProtocol::Uno )) ||
560 (ProtocolCheck::isProtocol(sURL,EProtocol::Slot )) ||
561 (ProtocolCheck::isProtocol(sURL,EProtocol::Macro )) ||
562 (ProtocolCheck::isProtocol(sURL,EProtocol::Service)) ||
563 (ProtocolCheck::isProtocol(sURL,EProtocol::MailTo )) ||
564 (ProtocolCheck::isProtocol(sURL,EProtocol::News ))
567 return E_UNSUPPORTED_CONTENT;
570 // (ii) Some special URLs indicates a given input stream,
571 // a full featured document model directly or
572 // specify a request for opening an empty document.
573 // Such contents are loadable in general.
574 // But we have to check, if the media descriptor contains
575 // all needed resources. If they are missing - the following
576 // load request will fail.
578 /* Attention: The following code can't work on such special URLs!
579 It should not break the office... but it makes no sense
580 to start expensive object creations and complex search
581 algorithm if it's clear, that such URLs must be handled
582 in a special way .-)
585 // creation of new documents
586 if (ProtocolCheck::isProtocol(sURL,EProtocol::PrivateFactory))
587 return E_CAN_BE_LOADED;
589 // using of an existing input stream
590 utl::MediaDescriptor stlMediaDescriptor(lMediaDescriptor);
591 utl::MediaDescriptor::const_iterator pIt;
592 if (ProtocolCheck::isProtocol(sURL,EProtocol::PrivateStream))
594 pIt = stlMediaDescriptor.find(utl::MediaDescriptor::PROP_INPUTSTREAM);
595 css::uno::Reference< css::io::XInputStream > xStream;
596 if (pIt != stlMediaDescriptor.end())
597 pIt->second >>= xStream;
598 if (xStream.is())
599 return E_CAN_BE_LOADED;
600 SAL_INFO("fwk.loadenv", "LoadEnv::classifyContent(): loading from stream with right URL but invalid stream detected");
601 return E_UNSUPPORTED_CONTENT;
604 // using of a full featured document
605 if (ProtocolCheck::isProtocol(sURL,EProtocol::PrivateObject))
607 pIt = stlMediaDescriptor.find(utl::MediaDescriptor::PROP_MODEL);
608 css::uno::Reference< css::frame::XModel > xModel;
609 if (pIt != stlMediaDescriptor.end())
610 pIt->second >>= xModel;
611 if (xModel.is())
612 return E_CAN_BE_SET;
613 SAL_INFO("fwk.loadenv", "LoadEnv::classifyContent(): loading with object with right URL but invalid object detected");
614 return E_UNSUPPORTED_CONTENT;
617 // following operations can work on an internal type name only :-(
618 css::uno::Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
619 css::uno::Reference< css::document::XTypeDetection > xDetect(
620 xContext->getServiceManager()->createInstanceWithContext(
621 "com.sun.star.document.TypeDetection", xContext),
622 css::uno::UNO_QUERY_THROW);
624 OUString sType = xDetect->queryTypeByURL(sURL);
626 css::uno::Reference< css::frame::XLoaderFactory > xLoaderFactory;
627 css::uno::Reference< css::container::XEnumeration > xSet;
629 // (iii) If a FrameLoader service (or at least
630 // a Filter) can be found, which supports
631 // this URL - it must be a loadable content.
632 // Because both items are registered for types
633 // it's enough to check for frame loaders only.
634 // Most of our filters are handled by our global
635 // default loader. But there exist some specialized
636 // loader, which does not work on top of filters!
637 // So it's not enough to search on the filter configuration.
638 // Further it's not enough to search for types!
639 // Because there exist some types, which are referenced by
640 // other objects... but neither by filters nor frame loaders!
641 css::uno::Sequence< OUString > lTypesReg { sType };
642 css::uno::Sequence< css::beans::NamedValue > lQuery
644 css::beans::NamedValue(PROP_TYPES, css::uno::Any(lTypesReg))
647 xLoaderFactory = css::frame::FrameLoaderFactory::create(xContext);
648 xSet = xLoaderFactory->createSubSetEnumerationByProperties(lQuery);
649 // at least one registered frame loader is enough!
650 if (xSet->hasMoreElements())
651 return E_CAN_BE_LOADED;
653 // (iv) Some URL protocols are supported by special services.
654 // E.g. ContentHandler.
655 // Such contents can be handled ... but not loaded.
657 xLoaderFactory = css::frame::ContentHandlerFactory::create(xContext);
658 xSet = xLoaderFactory->createSubSetEnumerationByProperties(lQuery);
659 // at least one registered content handler is enough!
660 if (xSet->hasMoreElements())
661 return E_CAN_BE_HANDLED;
663 // (v) Last but not least the UCB is used inside office to
664 // load contents. He has a special configuration to know
665 // which URL schemata can be used inside office.
666 css::uno::Reference< css::ucb::XUniversalContentBroker > xUCB(css::ucb::UniversalContentBroker::create(xContext));
667 if (xUCB->queryContentProvider(sURL).is())
668 return E_CAN_BE_LOADED;
670 // (TODO) At this point, we have no idea .-)
671 // But it seems to be better, to break all
672 // further requests for this URL. Otherwise
673 // we can run into some trouble.
674 return E_UNSUPPORTED_CONTENT;
677 namespace {
679 bool queryOrcusTypeAndFilter(const uno::Sequence<beans::PropertyValue>& rDescriptor, OUString& rType, OUString& rFilter)
681 OUString aURL;
682 sal_Int32 nSize = rDescriptor.getLength();
683 for (sal_Int32 i = 0; i < nSize; ++i)
685 const beans::PropertyValue& rProp = rDescriptor[i];
686 if (rProp.Name == "URL")
688 rProp.Value >>= aURL;
689 break;
693 if (aURL.isEmpty() || o3tl::equalsIgnoreAsciiCase(aURL.subView(0,8), u"private:"))
694 return false;
696 // TODO : Type must be set to be generic_Text (or any other type that
697 // exists) in order to find a usable loader. Exploit it as a temporary
698 // hack.
700 // depending on the experimental mode
701 if (!officecfg::Office::Common::Misc::ExperimentalMode::get())
703 return false;
706 OUString aUseOrcus;
707 rtl::Bootstrap::get("LIBO_USE_ORCUS", aUseOrcus);
708 bool bUseOrcus = (aUseOrcus == "YES");
710 if (!bUseOrcus)
711 return false;
713 if (aURL.endsWith(".xlsx"))
715 rType = "generic_Text";
716 rFilter = "xlsx";
717 return true;
719 else if (aURL.endsWith(".ods"))
721 rType = "generic_Text";
722 rFilter = "ods";
723 return true;
725 else if (aURL.endsWith(".csv"))
727 rType = "generic_Text";
728 rFilter = "csv";
729 return true;
732 return false;
737 void LoadEnv::impl_detectTypeAndFilter()
739 static const sal_Int32 FILTERFLAG_TEMPLATEPATH = 16;
741 // SAFE ->
742 osl::ClearableMutexGuard aReadLock(m_mutex);
744 // Attention: Because our stl media descriptor is a copy of a uno sequence
745 // we can't use as an in/out parameter here. Copy it before and don't forget to
746 // update structure afterwards again!
747 css::uno::Sequence< css::beans::PropertyValue > lDescriptor = m_lMediaDescriptor.getAsConstPropertyValueList();
748 css::uno::Reference< css::uno::XComponentContext > xContext = m_xContext;
750 aReadLock.clear();
751 // <- SAFE
753 OUString sType, sFilter;
755 if (queryOrcusTypeAndFilter(lDescriptor, sType, sFilter) && !sType.isEmpty() && !sFilter.isEmpty())
757 // SAFE ->
758 osl::MutexGuard aWriteLock(m_mutex);
760 // Orcus type detected. Skip the normal type detection process.
761 m_lMediaDescriptor << lDescriptor;
762 m_lMediaDescriptor[utl::MediaDescriptor::PROP_TYPENAME] <<= sType;
763 m_lMediaDescriptor[utl::MediaDescriptor::PROP_FILTERNAME] <<= sFilter;
764 m_lMediaDescriptor[utl::MediaDescriptor::PROP_FILTERPROVIDER] <<= OUString("orcus");
765 m_lMediaDescriptor[utl::MediaDescriptor::PROP_DOCUMENTSERVICE] <<= OUString("com.sun.star.sheet.SpreadsheetDocument");
766 return;
767 // <- SAFE
770 css::uno::Reference< css::document::XTypeDetection > xDetect(
771 xContext->getServiceManager()->createInstanceWithContext(
772 "com.sun.star.document.TypeDetection", xContext),
773 css::uno::UNO_QUERY_THROW);
774 sType = xDetect->queryTypeByDescriptor(lDescriptor, true); /*TODO should deep detection be able for enable/disable it from outside? */
776 // no valid content -> loading not possible
777 if (sType.isEmpty())
778 throw LoadEnvException(
779 LoadEnvException::ID_UNSUPPORTED_CONTENT, "type detection failed");
781 // SAFE ->
782 osl::ResettableMutexGuard aWriteLock(m_mutex);
784 // detection was successful => update the descriptor member of this class
785 m_lMediaDescriptor << lDescriptor;
786 m_lMediaDescriptor[utl::MediaDescriptor::PROP_TYPENAME] <<= sType;
787 // Is there an already detected (may be preselected) filter?
788 // see below ...
789 sFilter = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_FILTERNAME, OUString());
791 aWriteLock.clear();
792 // <- SAFE
794 // We do have potentially correct type, but the detection process was aborted.
795 if (m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_ABORTED, false))
796 throw LoadEnvException(
797 LoadEnvException::ID_UNSUPPORTED_CONTENT, "type detection aborted");
799 // But the type isn't enough. For loading sometimes we need more information.
800 // E.g. for our "_default" feature, where we recycle any frame which contains
801 // and "Untitled" document, we must know if the new document is based on a template!
802 // But this information is available as a filter property only.
803 // => We must try(!) to detect the right filter for this load request.
804 // On the other side ... if no filter is available .. ignore it.
805 // Then the type information must be enough.
806 if (sFilter.isEmpty())
808 // no -> try to find a preferred filter for the detected type.
809 // Don't forget to update the media descriptor.
810 css::uno::Reference< css::container::XNameAccess > xTypeCont(xDetect, css::uno::UNO_QUERY_THROW);
813 ::comphelper::SequenceAsHashMap lTypeProps(xTypeCont->getByName(sType));
814 sFilter = lTypeProps.getUnpackedValueOrDefault("PreferredFilter", OUString());
815 if (!sFilter.isEmpty())
817 // SAFE ->
818 aWriteLock.reset();
819 m_lMediaDescriptor[utl::MediaDescriptor::PROP_FILTERNAME] <<= sFilter;
820 aWriteLock.clear();
821 // <- SAFE
824 catch(const css::container::NoSuchElementException&)
828 // check if the filter (if one exists) points to a template format filter.
829 // Then we have to add the property "AsTemplate".
830 // We need this information to decide afterwards if we can use a "recycle frame"
831 // for target "_default" or has to create a new one every time.
832 // On the other side we have to suppress that, if this property already exists
833 // and should trigger a special handling. Then the outside call of this method here,
834 // has to know, what he is doing .-)
836 bool bIsOwnTemplate = false;
837 if (!sFilter.isEmpty())
839 css::uno::Reference< css::container::XNameAccess > xFilterCont(xContext->getServiceManager()->createInstanceWithContext(SERVICENAME_FILTERFACTORY, xContext), css::uno::UNO_QUERY_THROW);
842 ::comphelper::SequenceAsHashMap lFilterProps(xFilterCont->getByName(sFilter));
843 sal_Int32 nFlags = lFilterProps.getUnpackedValueOrDefault("Flags", sal_Int32(0));
844 bIsOwnTemplate = ((nFlags & FILTERFLAG_TEMPLATEPATH) == FILTERFLAG_TEMPLATEPATH);
846 catch(const css::container::NoSuchElementException&)
849 if (bIsOwnTemplate)
851 // SAFE ->
852 aWriteLock.reset();
853 // Don't overwrite external decisions! See comments before ...
854 utl::MediaDescriptor::const_iterator pAsTemplateItem = m_lMediaDescriptor.find(utl::MediaDescriptor::PROP_ASTEMPLATE);
855 if (pAsTemplateItem == m_lMediaDescriptor.end())
856 m_lMediaDescriptor[utl::MediaDescriptor::PROP_ASTEMPLATE] <<= true;
857 aWriteLock.clear();
858 // <- SAFE
862 bool LoadEnv::impl_handleContent()
864 // SAFE -> -----------------------------------
865 osl::ClearableMutexGuard aReadLock(m_mutex);
867 // the type must exist inside the descriptor ... otherwise this class is implemented wrong :-)
868 OUString sType = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_TYPENAME, OUString());
869 if (sType.isEmpty())
870 throw LoadEnvException(LoadEnvException::ID_INVALID_MEDIADESCRIPTOR);
872 // convert media descriptor and URL to right format for later interface call!
873 css::uno::Sequence< css::beans::PropertyValue > lDescriptor;
874 m_lMediaDescriptor >> lDescriptor;
875 css::util::URL aURL = m_aURL;
877 // get necessary container to query for a handler object
878 css::uno::Reference< css::frame::XLoaderFactory > xLoaderFactory = css::frame::ContentHandlerFactory::create(m_xContext);
880 aReadLock.clear();
881 // <- SAFE -----------------------------------
883 // query
884 css::uno::Sequence< OUString > lTypeReg { sType };
886 css::uno::Sequence< css::beans::NamedValue > lQuery { { PROP_TYPES, css::uno::Any(lTypeReg) } };
888 css::uno::Reference< css::container::XEnumeration > xSet = xLoaderFactory->createSubSetEnumerationByProperties(lQuery);
889 while(xSet->hasMoreElements())
891 ::comphelper::SequenceAsHashMap lProps (xSet->nextElement());
892 OUString sHandler = lProps.getUnpackedValueOrDefault(PROP_NAME, OUString());
894 css::uno::Reference< css::frame::XNotifyingDispatch > xHandler;
897 xHandler.set(xLoaderFactory->createInstance(sHandler), css::uno::UNO_QUERY);
898 if (!xHandler.is())
899 continue;
901 catch(const css::uno::RuntimeException&)
902 { throw; }
903 catch(const css::uno::Exception&)
904 { continue; }
906 // SAFE -> -----------------------------------
907 osl::ClearableMutexGuard aWriteLock(m_mutex);
908 m_xAsynchronousJob = xHandler;
909 rtl::Reference<LoadEnvListener> xListener = new LoadEnvListener(this);
910 aWriteLock.clear();
911 // <- SAFE -----------------------------------
913 xHandler->dispatchWithNotification(aURL, lDescriptor, xListener);
915 return true;
918 return false;
921 bool LoadEnv::impl_furtherDocsAllowed()
923 // SAFE ->
924 osl::ResettableMutexGuard aReadLock(m_mutex);
925 css::uno::Reference< css::uno::XComponentContext > xContext = m_xContext;
926 aReadLock.clear();
927 // <- SAFE
929 bool bAllowed = true;
933 std::optional<sal_Int32> x(officecfg::Office::Common::Misc::MaxOpenDocuments::get());
935 // NIL means: count of allowed documents = infinite !
936 // => return true
937 if ( !x)
938 bAllowed = true;
939 else
941 sal_Int32 nMaxOpenDocuments(*x);
943 css::uno::Reference< css::frame::XFramesSupplier > xDesktop(
944 css::frame::Desktop::create(xContext),
945 css::uno::UNO_QUERY_THROW);
947 FrameListAnalyzer aAnalyzer(xDesktop,
948 css::uno::Reference< css::frame::XFrame >(),
949 FrameAnalyzerFlags::Help |
950 FrameAnalyzerFlags::BackingComponent |
951 FrameAnalyzerFlags::Hidden);
953 sal_Int32 nOpenDocuments = aAnalyzer.m_lOtherVisibleFrames.size();
954 bAllowed = (nOpenDocuments < nMaxOpenDocuments);
957 catch(const css::uno::Exception&)
958 { bAllowed = true; } // !! internal errors are no reason to disturb the office from opening documents .-)
960 if ( ! bAllowed )
962 // SAFE ->
963 aReadLock.reset();
964 css::uno::Reference< css::task::XInteractionHandler > xInteraction = m_lMediaDescriptor.getUnpackedValueOrDefault(
965 utl::MediaDescriptor::PROP_INTERACTIONHANDLER,
966 css::uno::Reference< css::task::XInteractionHandler >());
967 aReadLock.clear();
968 // <- SAFE
970 if (xInteraction.is())
972 css::uno::Any aInteraction;
974 rtl::Reference<comphelper::OInteractionAbort> pAbort = new comphelper::OInteractionAbort();
975 rtl::Reference<comphelper::OInteractionApprove> pApprove = new comphelper::OInteractionApprove();
977 css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > lContinuations{
978 pAbort, pApprove
981 css::task::ErrorCodeRequest aErrorCode;
982 aErrorCode.ErrCode = sal_uInt32(ERRCODE_SFX_NOMOREDOCUMENTSALLOWED);
983 aInteraction <<= aErrorCode;
984 xInteraction->handle( InteractionRequest::CreateRequest(aInteraction, lContinuations) );
988 return bAllowed;
991 bool LoadEnv::impl_filterHasInteractiveDialog() const
993 //show the frame now so it can be the parent for any message dialogs shown during import
995 //unless (tdf#114648) an Interactive case such as the new database wizard
996 if (m_aURL.Arguments == "Interactive")
997 return true;
999 // unless (tdf#116277) it's the labels/business cards slave frame
1000 if (m_aURL.Arguments.indexOf("slot=") != -1)
1001 return true;
1003 OUString sFilter = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_FILTERNAME, OUString());
1004 if (sFilter.isEmpty())
1005 return false;
1007 // unless (tdf#115683) the filter has a UIComponent
1008 OUString sUIComponent;
1009 css::uno::Reference<css::container::XNameAccess> xFilterCont(m_xContext->getServiceManager()->createInstanceWithContext(SERVICENAME_FILTERFACTORY, m_xContext),
1010 css::uno::UNO_QUERY_THROW);
1013 ::comphelper::SequenceAsHashMap lFilterProps(xFilterCont->getByName(sFilter));
1014 sUIComponent = lFilterProps.getUnpackedValueOrDefault("UIComponent", OUString());
1016 catch(const css::container::NoSuchElementException&)
1020 return !sUIComponent.isEmpty();
1023 bool LoadEnv::impl_loadContent()
1025 // SAFE -> -----------------------------------
1026 osl::ClearableMutexGuard aWriteLock(m_mutex);
1028 // search or create right target frame
1029 OUString sTarget = m_sTarget;
1030 if (TargetHelper::matchSpecialTarget(sTarget, TargetHelper::ESpecialTarget::Default))
1032 m_xTargetFrame = impl_searchAlreadyLoaded();
1033 if (m_xTargetFrame.is())
1035 impl_setResult(true);
1036 return true;
1038 m_xTargetFrame = impl_searchRecycleTarget();
1041 if (! m_xTargetFrame.is())
1043 if (
1044 (TargetHelper::matchSpecialTarget(sTarget, TargetHelper::ESpecialTarget::Blank )) ||
1045 (TargetHelper::matchSpecialTarget(sTarget, TargetHelper::ESpecialTarget::Default))
1048 if (! impl_furtherDocsAllowed())
1049 return false;
1050 TaskCreator aCreator(m_xContext);
1051 m_xTargetFrame = aCreator.createTask(SPECIALTARGET_BLANK, m_lMediaDescriptor);
1052 m_bCloseFrameOnError = m_xTargetFrame.is();
1054 else
1056 sal_Int32 nSearchFlags = m_nSearchFlags & ~css::frame::FrameSearchFlag::CREATE;
1057 m_xTargetFrame = m_xBaseFrame->findFrame(sTarget, nSearchFlags);
1058 if (! m_xTargetFrame.is())
1060 if (! impl_furtherDocsAllowed())
1061 return false;
1062 m_xTargetFrame = m_xBaseFrame->findFrame(SPECIALTARGET_BLANK, 0);
1063 m_bCloseFrameOnError = m_xTargetFrame.is();
1068 // If we couldn't find a valid frame or the frame has no container window
1069 // we have to throw an exception.
1070 if (
1071 ( ! m_xTargetFrame.is() ) ||
1072 ( ! m_xTargetFrame->getContainerWindow().is() )
1074 throw LoadEnvException(LoadEnvException::ID_NO_TARGET_FOUND);
1076 css::uno::Reference< css::frame::XFrame > xTargetFrame = m_xTargetFrame;
1078 // Now we have a valid frame ... and type detection was already done.
1079 // We should apply the module dependent window position and size to the
1080 // frame window.
1081 impl_applyPersistentWindowState(xTargetFrame->getContainerWindow());
1083 // Don't forget to lock task for following load process. Otherwise it could die
1084 // during this operation runs by terminating the office or closing this task via api.
1085 // If we set this lock "close()" will return false and closing will be broken.
1086 // Attention: Don't forget to reset this lock again after finishing operation.
1087 // Otherwise task AND office couldn't die!!!
1088 // This includes gracefully handling of Exceptions (Runtime!) too ...
1089 // That's why we use a specialized guard, which will reset the lock
1090 // if it will be run out of scope.
1092 // Note further: ignore if this internal guard already contains a resource.
1093 // Might impl_searchRecycleTarget() set it before. But in case this impl-method wasn't used
1094 // and the target frame was new created ... this lock here must be set!
1095 css::uno::Reference< css::document::XActionLockable > xTargetLock(xTargetFrame, css::uno::UNO_QUERY);
1096 m_aTargetLock.setResource(xTargetLock);
1098 // Add status indicator to descriptor. Loader can show a progress then.
1099 // But don't do it, if loading should be hidden or preview is used...!
1100 // So we prevent our code against wrong using. Why?
1101 // It could be, that using of this progress could make trouble. e.g. He makes window visible...
1102 // but shouldn't do that. But if no indicator is available... nobody has a chance to do that!
1103 bool bHidden = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_HIDDEN, false);
1104 bool bMinimized = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_MINIMIZED, false);
1105 bool bPreview = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_PREVIEW, false);
1107 if (!bHidden && !bMinimized && !bPreview)
1109 css::uno::Reference<css::task::XStatusIndicator> xProgress = m_lMediaDescriptor.getUnpackedValueOrDefault(
1110 utl::MediaDescriptor::PROP_STATUSINDICATOR, css::uno::Reference<css::task::XStatusIndicator>());
1111 if (!xProgress.is())
1113 // Note: it's an optional interface!
1114 css::uno::Reference< css::task::XStatusIndicatorFactory > xProgressFactory(xTargetFrame, css::uno::UNO_QUERY);
1115 if (xProgressFactory.is())
1117 xProgress = xProgressFactory->createStatusIndicator();
1118 if (xProgress.is())
1119 m_lMediaDescriptor[utl::MediaDescriptor::PROP_STATUSINDICATOR] <<= xProgress;
1123 // Now that we have a target window into which we can load, reinit the interaction handler to have this
1124 // window as its parent for modal dialogs and ensure the window is visible
1125 css::uno::Reference< css::task::XInteractionHandler > xInteraction = m_lMediaDescriptor.getUnpackedValueOrDefault(
1126 utl::MediaDescriptor::PROP_INTERACTIONHANDLER,
1127 css::uno::Reference< css::task::XInteractionHandler >());
1128 css::uno::Reference<css::lang::XInitialization> xHandler(xInteraction, css::uno::UNO_QUERY);
1129 if (xHandler.is())
1131 css::uno::Reference<css::awt::XWindow> xWindow = xTargetFrame->getContainerWindow();
1132 uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
1134 {"Parent", uno::Any(xWindow)}
1135 }));
1136 xHandler->initialize(aArguments);
1137 //show the frame as early as possible to make it the parent of any message dialogs
1138 if (!impl_filterHasInteractiveDialog())
1140 impl_makeFrameWindowVisible(xWindow, shouldFocusAndToFront());
1141 m_bFocusedAndToFront = true; // no need to ask shouldFocusAndToFront second time
1146 // convert media descriptor and URL to right format for later interface call!
1147 css::uno::Sequence< css::beans::PropertyValue > lDescriptor;
1148 m_lMediaDescriptor >> lDescriptor;
1149 OUString sURL = m_aURL.Complete;
1151 // try to locate any interested frame loader
1152 css::uno::Reference< css::uno::XInterface > xLoader = impl_searchLoader();
1153 css::uno::Reference< css::frame::XFrameLoader > xAsyncLoader(xLoader, css::uno::UNO_QUERY);
1154 css::uno::Reference< css::frame::XSynchronousFrameLoader > xSyncLoader (xLoader, css::uno::UNO_QUERY);
1156 if (xAsyncLoader.is())
1158 m_xAsynchronousJob = xAsyncLoader;
1159 rtl::Reference<LoadEnvListener> xListener = new LoadEnvListener(this);
1160 aWriteLock.clear();
1161 // <- SAFE -----------------------------------
1163 xAsyncLoader->load(xTargetFrame, sURL, lDescriptor, xListener);
1165 return true;
1167 else if (xSyncLoader.is())
1169 uno::Reference<beans::XPropertySet> xTargetFrameProps(xTargetFrame, uno::UNO_QUERY);
1170 if (xTargetFrameProps.is())
1172 // Set the URL on the frame itself, for the duration of the load, when it has no
1173 // controller.
1174 xTargetFrameProps->setPropertyValue("URL", uno::Any(sURL));
1176 bool bResult = xSyncLoader->load(lDescriptor, xTargetFrame);
1177 // react for the result here, so the outside waiting
1178 // code can ask for it later.
1179 impl_setResult(bResult);
1180 // But the return value indicates a valid started(!) operation.
1181 // And that's true every time we reach this line :-)
1182 return true;
1185 aWriteLock.clear();
1186 // <- SAFE
1188 return false;
1191 css::uno::Reference< css::uno::XInterface > LoadEnv::impl_searchLoader()
1193 // SAFE -> -----------------------------------
1194 osl::ClearableMutexGuard aReadLock(m_mutex);
1196 // special mode to set an existing component on this frame
1197 // In such case the loader is fix. It must be the SFX based implementation,
1198 // which can create a view on top of such xModel components :-)
1199 if (m_eContentType == E_CAN_BE_SET)
1203 return css::frame::OfficeFrameLoader::create(m_xContext);
1205 catch(const css::uno::RuntimeException&)
1206 { throw; }
1207 catch(const css::uno::Exception&)
1209 throw LoadEnvException(LoadEnvException::ID_INVALID_ENVIRONMENT);
1212 // Otherwise...
1213 // We need this type information to locate a registered frame loader
1214 // Without such information we can't work!
1215 OUString sType = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_TYPENAME, OUString());
1216 if (sType.isEmpty())
1217 throw LoadEnvException(LoadEnvException::ID_INVALID_MEDIADESCRIPTOR);
1219 // try to locate any interested frame loader
1220 css::uno::Reference< css::frame::XLoaderFactory > xLoaderFactory = css::frame::FrameLoaderFactory::create(m_xContext);
1222 aReadLock.clear();
1223 // <- SAFE -----------------------------------
1225 css::uno::Sequence< OUString > lTypesReg { sType };
1227 css::uno::Sequence< css::beans::NamedValue > lQuery { { PROP_TYPES, css::uno::Any(lTypesReg) } };
1229 css::uno::Reference< css::container::XEnumeration > xSet = xLoaderFactory->createSubSetEnumerationByProperties(lQuery);
1230 while(xSet->hasMoreElements())
1234 // try everyone ...
1235 // Ignore any loader, which makes trouble :-)
1236 ::comphelper::SequenceAsHashMap lLoaderProps(xSet->nextElement());
1237 OUString sLoader = lLoaderProps.getUnpackedValueOrDefault(PROP_NAME, OUString());
1238 css::uno::Reference< css::uno::XInterface > xLoader = xLoaderFactory->createInstance(sLoader);
1239 if (xLoader.is())
1240 return xLoader;
1242 catch(const css::uno::RuntimeException&)
1243 { throw; }
1244 catch(const css::uno::Exception&)
1245 { continue; }
1248 return css::uno::Reference< css::uno::XInterface >();
1251 void LoadEnv::impl_jumpToMark(const css::uno::Reference< css::frame::XFrame >& xFrame,
1252 const css::util::URL& aURL )
1254 if (aURL.Mark.isEmpty())
1255 return;
1257 css::uno::Reference< css::frame::XDispatchProvider > xProvider(xFrame, css::uno::UNO_QUERY);
1258 if (! xProvider.is())
1259 return;
1261 // SAFE ->
1262 osl::ClearableMutexGuard aReadLock(m_mutex);
1263 css::uno::Reference< css::uno::XComponentContext > xContext = m_xContext;
1264 aReadLock.clear();
1265 // <- SAFE
1267 css::util::URL aCmd;
1268 aCmd.Complete = ".uno:JumpToMark";
1270 css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(xContext));
1271 xParser->parseStrict(aCmd);
1273 css::uno::Reference< css::frame::XDispatch > xDispatcher = xProvider->queryDispatch(aCmd, SPECIALTARGET_SELF, 0);
1274 if (! xDispatcher.is())
1275 return;
1277 ::comphelper::SequenceAsHashMap lArgs;
1278 lArgs[OUString("Bookmark")] <<= aURL.Mark;
1279 xDispatcher->dispatch(aCmd, lArgs.getAsConstPropertyValueList());
1282 css::uno::Reference< css::frame::XFrame > LoadEnv::impl_searchAlreadyLoaded()
1284 osl::MutexGuard g(m_mutex);
1286 // such search is allowed for special requests only ...
1287 // or better it's not allowed for some requests in general :-)
1288 if (
1289 ( ! TargetHelper::matchSpecialTarget(m_sTarget, TargetHelper::ESpecialTarget::Default) ) ||
1290 m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_ASTEMPLATE , false) ||
1291 // (m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_HIDDEN() , false) == sal_True) ||
1292 m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_OPENNEWVIEW, false)
1295 return css::uno::Reference< css::frame::XFrame >();
1298 // check URL
1299 // May it's not useful to start expensive document search, if it
1300 // can fail only .. because we load from a stream or model directly!
1301 if (
1302 (ProtocolCheck::isProtocol(m_aURL.Complete, EProtocol::PrivateStream )) ||
1303 (ProtocolCheck::isProtocol(m_aURL.Complete, EProtocol::PrivateObject ))
1304 /*TODO should be private:factory here tested too? */
1307 return css::uno::Reference< css::frame::XFrame >();
1310 // otherwise - iterate through the tasks of the desktop container
1311 // to find out, which of them might contains the requested document
1312 css::uno::Reference< css::frame::XDesktop2 > xSupplier = css::frame::Desktop::create( m_xContext );
1313 css::uno::Reference< css::container::XIndexAccess > xTaskList = xSupplier->getFrames();
1315 if (!xTaskList.is())
1316 return css::uno::Reference< css::frame::XFrame >(); // task list can be empty!
1318 // Note: To detect if a document was already loaded before
1319 // we check URLs here only. But might the existing and the required
1320 // document has different versions! Then its URLs are the same...
1321 sal_Int16 nNewVersion = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_VERSION, sal_Int16(-1));
1323 // will be used to save the first hidden frame referring the searched model
1324 // Normally we are interested on visible frames... but if there is no such visible
1325 // frame we refer to any hidden frame also (but as fallback only).
1326 css::uno::Reference< css::frame::XFrame > xHiddenTask;
1327 css::uno::Reference< css::frame::XFrame > xTask;
1329 sal_Int32 count = xTaskList->getCount();
1330 for (sal_Int32 i=0; i<count; ++i)
1334 // locate model of task
1335 // Note: Without a model there is no chance to decide if
1336 // this task contains the searched document or not!
1337 xTaskList->getByIndex(i) >>= xTask;
1338 if (!xTask.is())
1339 continue;
1341 OUString sURL;
1342 css::uno::Reference< css::frame::XController > xController = xTask->getController();
1343 if (!xController.is())
1345 // If we have no controller, then perhaps there is a load in progress. The frame
1346 // itself has the URL in this case.
1347 uno::Reference<beans::XPropertySet> xTaskProps(xTask, uno::UNO_QUERY);
1348 if (xTaskProps.is())
1350 xTaskProps->getPropertyValue("URL") >>= sURL;
1352 if (sURL.isEmpty())
1354 xTask.clear();
1355 continue;
1359 uno::Reference<frame::XModel> xModel;
1360 if (sURL.isEmpty())
1362 xModel = xController->getModel();
1363 if (!xModel.is())
1365 xTask.clear();
1366 continue;
1369 // don't check the complete URL here.
1370 // use its main part - ignore optional jumpmarks!
1371 sURL = xModel->getURL();
1373 if (!::utl::UCBContentHelper::EqualURLs( m_aURL.Main, sURL ))
1375 xTask.clear ();
1376 continue;
1379 // get the original load arguments from the current document
1380 // and decide if it's really the same then the one will be.
1381 // It must be visible and must use the same file revision ...
1382 // or must not have any file revision set (-1 == -1!)
1383 utl::MediaDescriptor lOldDocDescriptor;
1384 if (xModel.is())
1386 lOldDocDescriptor = xModel->getArgs();
1388 if (lOldDocDescriptor.getUnpackedValueOrDefault(
1389 utl::MediaDescriptor::PROP_VERSION, sal_Int32(-1))
1390 != nNewVersion)
1392 xTask.clear();
1393 continue;
1397 // Hidden frames are special.
1398 // They will be used as "last chance" if there is no visible frame pointing to the same model.
1399 // Safe the result but continue with current loop might be looking for other visible frames.
1400 bool bIsHidden = lOldDocDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_HIDDEN, false);
1401 if ( bIsHidden && ! xHiddenTask.is() )
1403 xHiddenTask = xTask;
1404 xTask.clear ();
1405 continue;
1408 // We found a visible task pointing to the right model ...
1409 // Break search.
1410 break;
1412 catch(const css::uno::RuntimeException&)
1413 { throw; }
1414 catch(const css::uno::Exception&)
1415 { continue; }
1418 css::uno::Reference< css::frame::XFrame > xResult;
1419 if (xTask.is())
1420 xResult = xTask;
1421 else if (xHiddenTask.is())
1422 xResult = xHiddenTask;
1424 if (xResult.is())
1426 // Now we are sure, that this task includes the searched document.
1427 // It's time to activate it. As special feature we try to jump internally
1428 // if an optional jumpmark is given too.
1429 if (!m_aURL.Mark.isEmpty())
1430 impl_jumpToMark(xResult, m_aURL);
1433 return xResult;
1436 bool LoadEnv::impl_isFrameAlreadyUsedForLoading(const css::uno::Reference< css::frame::XFrame >& xFrame) const
1438 css::uno::Reference< css::document::XActionLockable > xLock(xFrame, css::uno::UNO_QUERY);
1440 // ? no lock interface ?
1441 // Maybe it's an external written frame implementation :-(
1442 // Allowing using of it... but it can fail if it's not synchronized with our processes!
1443 if (!xLock.is())
1444 return false;
1446 // Otherwise we have to look for any other existing lock.
1447 return xLock->isActionLocked();
1450 css::uno::Reference< css::frame::XFrame > LoadEnv::impl_searchRecycleTarget()
1452 // SAFE -> ..................................
1453 osl::ClearableMutexGuard aReadLock(m_mutex);
1455 // The special backing mode frame will be recycled by definition!
1456 // It doesn't matter if somewhere wants to create a new view
1457 // or open a new untitled document...
1458 // The only exception from that - hidden frames!
1459 if (m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_HIDDEN, false))
1460 return css::uno::Reference< css::frame::XFrame >();
1462 css::uno::Reference< css::frame::XFramesSupplier > xSupplier = css::frame::Desktop::create( m_xContext );
1463 FrameListAnalyzer aTasksAnalyzer(xSupplier, css::uno::Reference< css::frame::XFrame >(), FrameAnalyzerFlags::BackingComponent);
1464 if (aTasksAnalyzer.m_xBackingComponent.is())
1466 if (!impl_isFrameAlreadyUsedForLoading(aTasksAnalyzer.m_xBackingComponent))
1468 m_bReactivateControllerOnError = true;
1469 return aTasksAnalyzer.m_xBackingComponent;
1473 // These states indicates a wish for creation of a new view in general.
1474 if (
1475 m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_ASTEMPLATE , false) ||
1476 m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_OPENNEWVIEW, false)
1479 return css::uno::Reference< css::frame::XFrame >();
1482 // On the other side some special URLs will open a new frame every time (expecting
1483 // they can use the backing-mode frame!)
1484 if (
1485 (ProtocolCheck::isProtocol(m_aURL.Complete, EProtocol::PrivateFactory )) ||
1486 (ProtocolCheck::isProtocol(m_aURL.Complete, EProtocol::PrivateStream )) ||
1487 (ProtocolCheck::isProtocol(m_aURL.Complete, EProtocol::PrivateObject ))
1490 return css::uno::Reference< css::frame::XFrame >();
1493 // No backing frame! No special URL => recycle active task - if possible.
1494 // Means - if it does not already contains a modified document, or
1495 // use another office module.
1496 css::uno::Reference< css::frame::XFrame > xTask = xSupplier->getActiveFrame();
1498 // not a real error - but might a focus problem!
1499 if (!xTask.is())
1500 return css::uno::Reference< css::frame::XFrame >();
1502 // not a real error - may it's a view only
1503 css::uno::Reference< css::frame::XController > xController = xTask->getController();
1504 if (!xController.is())
1505 return css::uno::Reference< css::frame::XFrame >();
1507 // not a real error - may it's a db component instead of a full featured office document
1508 css::uno::Reference< css::frame::XModel > xModel = xController->getModel();
1509 if (!xModel.is())
1510 return css::uno::Reference< css::frame::XFrame >();
1512 // get some more information ...
1514 // A valid set URL means: there is already a location for this document.
1515 // => it was saved there or opened from there. Such Documents can not be used here.
1516 // We search for empty document ... created by a private:factory/ URL!
1517 if (xModel->getURL().getLength()>0)
1518 return css::uno::Reference< css::frame::XFrame >();
1520 // The old document must be unmodified ...
1521 css::uno::Reference< css::util::XModifiable > xModified(xModel, css::uno::UNO_QUERY);
1522 if (xModified->isModified())
1523 return css::uno::Reference< css::frame::XFrame >();
1525 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xTask->getContainerWindow());
1526 if (pWindow && pWindow->IsInModalMode())
1527 return css::uno::Reference< css::frame::XFrame >();
1529 // find out the application type of this document
1530 // We can recycle only documents, which uses the same application
1531 // then the new one.
1532 SvtModuleOptions::EFactory eOldApp = SvtModuleOptions::ClassifyFactoryByModel(xModel);
1533 SvtModuleOptions::EFactory eNewApp = SvtModuleOptions::ClassifyFactoryByURL (m_aURL.Complete, m_lMediaDescriptor.getAsConstPropertyValueList());
1535 aReadLock.clear();
1536 // <- SAFE ..................................
1538 if (eOldApp != eNewApp)
1539 return css::uno::Reference< css::frame::XFrame >();
1541 // OK this task seems to be usable for recycling
1542 // But we should mark it as such - means set an action lock.
1543 // Otherwise it would be used more than ones or will be destroyed
1544 // by a close() or terminate() request.
1545 // But if such lock already exist ... it means this task is used for
1546 // any other operation already. Don't use it then.
1547 if (impl_isFrameAlreadyUsedForLoading(xTask))
1548 return css::uno::Reference< css::frame::XFrame >();
1550 // OK - there is a valid target frame.
1551 // But may be it contains already a document.
1552 // Then we have to ask it, if it allows recycling of this frame .-)
1553 bool bReactivateOldControllerOnError = false;
1554 css::uno::Reference< css::frame::XController > xOldDoc = xTask->getController();
1555 if (xOldDoc.is())
1557 utl::MediaDescriptor lOldDocDescriptor(xModel->getArgs());
1559 // replaceable document
1560 if (!lOldDocDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_REPLACEABLE, false))
1561 return css::uno::Reference< css::frame::XFrame >();
1563 bReactivateOldControllerOnError = xOldDoc->suspend(true);
1564 if (! bReactivateOldControllerOnError)
1565 return css::uno::Reference< css::frame::XFrame >();
1568 // SAFE -> ..................................
1570 osl::MutexGuard aWriteLock(m_mutex);
1572 css::uno::Reference< css::document::XActionLockable > xLock(xTask, css::uno::UNO_QUERY);
1573 if (!m_aTargetLock.setResource(xLock))
1574 return css::uno::Reference< css::frame::XFrame >();
1576 m_bReactivateControllerOnError = bReactivateOldControllerOnError;
1578 // <- SAFE ..................................
1580 return xTask;
1583 void LoadEnv::impl_reactForLoadingState()
1585 /*TODO reset action locks */
1587 // SAFE -> ----------------------------------
1588 osl::ClearableMutexGuard aReadLock(m_mutex);
1590 if (m_bLoaded)
1592 // Bring the new loaded document to front (if allowed!).
1593 // Note: We show new created frames here only.
1594 // We don't hide already visible frames here ...
1595 css::uno::Reference< css::awt::XWindow > xWindow = m_xTargetFrame->getContainerWindow();
1596 bool bHidden = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_HIDDEN, false);
1597 bool bMinimized = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_MINIMIZED, false);
1599 if (bMinimized)
1601 SolarMutexGuard aSolarGuard;
1602 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xWindow);
1603 // check for system window is necessary to guarantee correct pointer cast!
1604 if (pWindow && pWindow->IsSystemWindow())
1605 static_cast<WorkWindow*>(pWindow.get())->Minimize();
1607 else if (!bHidden)
1609 // show frame ... if it's not still visible ...
1610 // But do nothing if it's already visible!
1611 impl_makeFrameWindowVisible(xWindow, !m_bFocusedAndToFront && shouldFocusAndToFront());
1614 // Note: Only if an existing property "FrameName" is given by this media descriptor,
1615 // it should be used. Otherwise we should do nothing. May be the outside code has already
1616 // set a frame name on the target!
1617 utl::MediaDescriptor::const_iterator pFrameName = m_lMediaDescriptor.find(utl::MediaDescriptor::PROP_FRAMENAME);
1618 if (pFrameName != m_lMediaDescriptor.end())
1620 OUString sFrameName;
1621 pFrameName->second >>= sFrameName;
1622 // Check the name again. e.g. "_default" isn't allowed.
1623 // On the other side "_beamer" is a valid name :-)
1624 if (TargetHelper::isValidNameForFrame(sFrameName))
1625 m_xTargetFrame->setName(sFrameName);
1628 else if (m_bReactivateControllerOnError)
1630 // Try to reactivate the old document (if any exists!)
1631 css::uno::Reference< css::frame::XController > xOldDoc = m_xTargetFrame->getController();
1632 // clear does not depend from reactivation state of a might existing old document!
1633 // We must make sure, that a might following getTargetComponent() call does not return
1634 // the old document!
1635 m_xTargetFrame.clear();
1636 if (xOldDoc.is())
1638 bool bReactivated = xOldDoc->suspend(false);
1639 if (!bReactivated)
1640 throw LoadEnvException(LoadEnvException::ID_COULD_NOT_REACTIVATE_CONTROLLER);
1641 m_bReactivateControllerOnError = false;
1644 else if (m_bCloseFrameOnError)
1646 // close empty frames
1647 css::uno::Reference< css::util::XCloseable > xCloseable (m_xTargetFrame, css::uno::UNO_QUERY);
1651 if (xCloseable.is())
1652 xCloseable->close(true);
1653 else if (m_xTargetFrame.is())
1654 m_xTargetFrame->dispose();
1656 catch(const css::util::CloseVetoException&)
1658 catch(const css::lang::DisposedException&)
1660 m_xTargetFrame.clear();
1663 // This max force an implicit closing of our target frame ...
1664 // e.g. in case close(sal_True) was called before and the frame
1665 // kill itself if our external use-lock is released here!
1666 // That's why we release this lock AFTER ALL OPERATIONS on this frame
1667 // are finished. The frame itself must handle then
1668 // this situation gracefully.
1669 m_aTargetLock.freeResource();
1671 // Last but not least :-)
1672 // We have to clear the current media descriptor.
1673 // Otherwise it hold a might existing stream open!
1674 m_lMediaDescriptor.clear();
1676 css::uno::Any aRequest;
1677 bool bThrow = false;
1678 if ( !m_bLoaded && m_pQuietInteraction.is() && m_pQuietInteraction->wasUsed() )
1680 aRequest = m_pQuietInteraction->getRequest();
1681 m_pQuietInteraction.clear();
1682 bThrow = true;
1685 aReadLock.clear();
1687 if (bThrow)
1689 if ( aRequest.isExtractableTo( ::cppu::UnoType< css::uno::Exception >::get() ) )
1690 throw LoadEnvException(
1691 LoadEnvException::ID_GENERAL_ERROR, "interaction request",
1692 aRequest);
1695 // <- SAFE ----------------------------------
1698 bool LoadEnv::shouldFocusAndToFront() const
1700 bool const preview(
1701 m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_PREVIEW, false));
1702 return !preview
1703 && officecfg::Office::Common::View::NewDocumentHandling::ForceFocusAndToFront::get();
1706 void LoadEnv::impl_makeFrameWindowVisible(const css::uno::Reference< css::awt::XWindow >& xWindow ,
1707 bool bForceToFront)
1709 SolarMutexGuard aSolarGuard;
1710 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xWindow);
1711 if ( !pWindow )
1712 return;
1714 if (pWindow->IsVisible() && bForceToFront)
1715 pWindow->ToTop( ToTopFlags::RestoreWhenMin | ToTopFlags::ForegroundTask );
1716 else
1717 pWindow->Show(true, bForceToFront ? ShowFlags::ForegroundTask : ShowFlags::NONE);
1720 void LoadEnv::impl_applyPersistentWindowState(const css::uno::Reference< css::awt::XWindow >& xWindow)
1722 // no window -> action not possible
1723 if (!xWindow.is())
1724 return;
1726 // window already visible -> do nothing! If we use a "recycle frame" for loading ...
1727 // the current position and size must be used.
1728 css::uno::Reference< css::awt::XWindow2 > xVisibleCheck(xWindow, css::uno::UNO_QUERY);
1729 if (
1730 (xVisibleCheck.is() ) &&
1731 (xVisibleCheck->isVisible())
1733 return;
1735 // SOLAR SAFE ->
1737 SolarMutexGuard aSolarGuard1;
1739 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xWindow);
1740 if (!pWindow)
1741 return;
1743 bool bSystemWindow = pWindow->IsSystemWindow();
1744 bool bWorkWindow = (pWindow->GetType() == WindowType::WORKWINDOW);
1746 if (!bSystemWindow && !bWorkWindow)
1747 return;
1749 // don't overwrite this special state!
1750 WorkWindow* pWorkWindow = static_cast<WorkWindow*>(pWindow.get());
1751 if (pWorkWindow->IsMinimized())
1752 return;
1754 // <- SOLAR SAFE
1756 // SAFE ->
1757 osl::ClearableMutexGuard aReadLock(m_mutex);
1759 // no filter -> no module -> no persistent window state
1760 OUString sFilter = m_lMediaDescriptor.getUnpackedValueOrDefault(
1761 utl::MediaDescriptor::PROP_FILTERNAME,
1762 OUString());
1763 if (sFilter.isEmpty())
1764 return;
1766 css::uno::Reference< css::uno::XComponentContext > xContext = m_xContext;
1768 aReadLock.clear();
1769 // <- SAFE
1773 // retrieve the module name from the filter configuration
1774 css::uno::Reference< css::container::XNameAccess > xFilterCfg(
1775 xContext->getServiceManager()->createInstanceWithContext(SERVICENAME_FILTERFACTORY, xContext),
1776 css::uno::UNO_QUERY_THROW);
1777 ::comphelper::SequenceAsHashMap lProps (xFilterCfg->getByName(sFilter));
1778 OUString sModule = lProps.getUnpackedValueOrDefault(FILTER_PROPNAME_ASCII_DOCUMENTSERVICE, OUString());
1780 // get access to the configuration of this office module
1781 css::uno::Reference< css::container::XNameAccess > xModuleCfg(officecfg::Setup::Office::Factories::get());
1783 // read window state from the configuration
1784 // and apply it on the window.
1785 // Do nothing, if no configuration entry exists!
1786 OUString sWindowState;
1788 // Don't look for persistent window attributes when used through LibreOfficeKit
1789 if( !comphelper::LibreOfficeKit::isActive() )
1790 comphelper::ConfigurationHelper::readRelativeKey(xModuleCfg, sModule, "ooSetupFactoryWindowAttributes") >>= sWindowState;
1792 if (!sWindowState.isEmpty())
1794 // SOLAR SAFE ->
1795 SolarMutexGuard aSolarGuard;
1797 // We have to retrieve the window pointer again. Because nobody can guarantee
1798 // that the XWindow was not disposed in between .-)
1799 // But if we get a valid pointer we can be sure, that it's the system window pointer
1800 // we already checked and used before. Because nobody recycle the same uno reference for
1801 // a new internal c++ implementation ... hopefully .-))
1802 VclPtr<vcl::Window> pWindowCheck = VCLUnoHelper::GetWindow(xWindow);
1803 if (! pWindowCheck)
1804 return;
1806 SystemWindow* pSystemWindow = static_cast<SystemWindow*>(pWindowCheck.get());
1807 pSystemWindow->SetWindowState(OUStringToOString(sWindowState,RTL_TEXTENCODING_UTF8));
1808 // <- SOLAR SAFE
1811 catch(const css::uno::RuntimeException&)
1812 { throw; }
1813 catch(const css::uno::Exception&)
1817 } // namespace framework
1819 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */