xref: /core/framework/source/loadenv/loadenv.cxx (revision 09e2627a83d4769983c39fb2cb260e11fce354f3)
166a17583SThorsten Behrens /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
217ff7b41SMichael Meeks /*
317ff7b41SMichael Meeks  * This file is part of the LibreOffice project.
477f6149cSKurt Zenker  *
517ff7b41SMichael Meeks  * This Source Code Form is subject to the terms of the Mozilla Public
617ff7b41SMichael Meeks  * License, v. 2.0. If a copy of the MPL was not distributed with this
717ff7b41SMichael Meeks  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8e8914d14SRüdiger Timm  *
917ff7b41SMichael Meeks  * This file incorporates work covered by the following license notice:
10e8914d14SRüdiger Timm  *
1117ff7b41SMichael Meeks  *   Licensed to the Apache Software Foundation (ASF) under one or more
1217ff7b41SMichael Meeks  *   contributor license agreements. See the NOTICE file distributed
1317ff7b41SMichael Meeks  *   with this work for additional information regarding copyright
1417ff7b41SMichael Meeks  *   ownership. The ASF licenses this file to you under the Apache
1517ff7b41SMichael Meeks  *   License, Version 2.0 (the "License"); you may not use this file
1617ff7b41SMichael Meeks  *   except in compliance with the License. You may obtain a copy of
1717ff7b41SMichael Meeks  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
1817ff7b41SMichael Meeks  */
19c24c1a18SOliver Bolte 
2077f6149cSKurt Zenker #include <loadenv/loadenv.hxx>
2177f6149cSKurt Zenker 
22e4bf92aeSGabor Kelemen #include <loadenv/loadenvexception.hxx>
2377f6149cSKurt Zenker #include <loadenv/targethelper.hxx>
244f40fd27SMathias Bauer #include <framework/framelistanalyzer.hxx>
25ffa0c246SRüdiger Timm 
26c7e172b2SJens-Heiner Rechtien #include <interaction/quietinteraction.hxx>
274543350eSVladimir Glazounov #include <properties.h>
2877f6149cSKurt Zenker #include <protocols.h>
2977f6149cSKurt Zenker #include <services.h>
30e4bf92aeSGabor Kelemen #include <targets.h>
31fd90f23fSBjoern Michaelsen #include <comphelper/interaction.hxx>
3257448212STor Lillqvist #include <comphelper/lok.hxx>
331115a60eSSamuel Mehrbrodt #include <comphelper/namedvaluecollection.hxx>
346f316707SCaolán McNamara #include <comphelper/propertysequence.hxx>
3536ea4fb1SMathias Bauer #include <framework/interaction.hxx>
369c2dfa9bSMarkus Mohrhard #include <comphelper/processfactory.hxx>
37a457c7c6SStephan Bergmann #include <officecfg/Office/Common.hxx>
38f3e0595fSJulien Nabet #include <officecfg/Setup.hxx>
397c80942cSRüdiger Timm 
402a993534SKurt Zenker #include <com/sun/star/awt/XWindow2.hpp>
41f3e0595fSJulien Nabet #include <com/sun/star/beans/XPropertySet.hpp>
42d7fa9ca7SNoel Grandin #include <com/sun/star/container/XNameAccess.hpp>
43d7fa9ca7SNoel Grandin #include <com/sun/star/container/XEnumeration.hpp>
44d7fa9ca7SNoel Grandin #include <com/sun/star/document/MacroExecMode.hpp>
45d7fa9ca7SNoel Grandin #include <com/sun/star/document/XTypeDetection.hpp>
46d7fa9ca7SNoel Grandin #include <com/sun/star/document/XActionLockable.hpp>
47d7fa9ca7SNoel Grandin #include <com/sun/star/document/UpdateDocMode.hpp>
48bb121c86SNoel Grandin #include <com/sun/star/frame/Desktop.hpp>
4930dd9b2fSNoel Grandin #include <com/sun/star/frame/OfficeFrameLoader.hpp>
5077f6149cSKurt Zenker #include <com/sun/star/frame/XModel.hpp>
5177f6149cSKurt Zenker #include <com/sun/star/frame/XFrameLoader.hpp>
5277f6149cSKurt Zenker #include <com/sun/star/frame/XSynchronousFrameLoader.hpp>
5377f6149cSKurt Zenker #include <com/sun/star/frame/XNotifyingDispatch.hpp>
54d7fa9ca7SNoel Grandin #include <com/sun/star/frame/FrameLoaderFactory.hpp>
55d7fa9ca7SNoel Grandin #include <com/sun/star/frame/ContentHandlerFactory.hpp>
56d7fa9ca7SNoel Grandin #include <com/sun/star/frame/DispatchResultState.hpp>
57d7fa9ca7SNoel Grandin #include <com/sun/star/frame/FrameSearchFlag.hpp>
5877f6149cSKurt Zenker #include <com/sun/star/frame/XDispatchProvider.hpp>
59e4bf92aeSGabor Kelemen #include <com/sun/star/lang/IllegalArgumentException.hpp>
606f316707SCaolán McNamara #include <com/sun/star/lang/XInitialization.hpp>
61d7fa9ca7SNoel Grandin #include <com/sun/star/lang/DisposedException.hpp>
6277f6149cSKurt Zenker #include <com/sun/star/io/XInputStream.hpp>
6377f6149cSKurt Zenker #include <com/sun/star/task/XInteractionHandler.hpp>
64d7fa9ca7SNoel Grandin #include <com/sun/star/task/ErrorCodeRequest.hpp>
65d7fa9ca7SNoel Grandin #include <com/sun/star/task/InteractionHandler.hpp>
66d7fa9ca7SNoel Grandin #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
67d7fa9ca7SNoel Grandin #include <com/sun/star/task/XStatusIndicator.hpp>
68d7fa9ca7SNoel Grandin #include <com/sun/star/uno/RuntimeException.hpp>
69d7fa9ca7SNoel Grandin #include <com/sun/star/ucb/UniversalContentBroker.hpp>
706dce9c67SStephan Bergmann #include <com/sun/star/util/CloseVetoException.hpp>
71d7fa9ca7SNoel Grandin #include <com/sun/star/util/URLTransformer.hpp>
72d7fa9ca7SNoel Grandin #include <com/sun/star/util/XURLTransformer.hpp>
73d7fa9ca7SNoel Grandin #include <com/sun/star/util/XCloseable.hpp>
74d7fa9ca7SNoel Grandin #include <com/sun/star/util/XModifiable.hpp>
7577f6149cSKurt Zenker 
76c60ad041SNoel Grandin #include <utility>
77965cc9c2SJens-Heiner Rechtien #include <vcl/window.hxx>
78965cc9c2SJens-Heiner Rechtien #include <vcl/wrkwin.hxx>
79965cc9c2SJens-Heiner Rechtien #include <vcl/syswin.hxx>
80965cc9c2SJens-Heiner Rechtien 
815cb2e310SThomas Arnhold #include <toolkit/helper/vclunohelper.hxx>
82bff284e2SMathias Bauer #include <unotools/moduleoptions.hxx>
837c80942cSRüdiger Timm #include <svtools/sfxecode.hxx>
8408e2fc04SMikhail Voytenko #include <unotools/ucbhelper.hxx>
854543350eSVladimir Glazounov #include <comphelper/configurationhelper.hxx>
862ce779cdSThomas Arnhold #include <rtl/bootstrap.hxx>
87bdb0775aSGabor Kelemen #include <sal/log.hxx>
88fd3888c6SNoel Grandin #include <comphelper/errcode.hxx>
8977f6149cSKurt Zenker #include <vcl/svapp.hxx>
90431f2ce8STakeshi Abe #include <cppuhelper/implbase.hxx>
9108f6f9ddSLászló Németh #include <comphelper/profilezone.hxx>
924a0f506fSMiklos Vajna #include <classes/taskcreator.hxx>
9320b1e644SMike Kaganski #include <tools/fileutil.hxx>
9477f6149cSKurt Zenker 
9564c47c92SStephan Bergmann constexpr OUString PROP_TYPES = u"Types"_ustr;
9664c47c92SStephan Bergmann constexpr OUString PROP_NAME = u"Name"_ustr;
97ae921976SCaolán McNamara 
9877f6149cSKurt Zenker namespace framework {
9977f6149cSKurt Zenker 
100a6639312SKohei Yoshida using namespace com::sun::star;
10177f6149cSKurt Zenker 
102f853ec31SStephan Bergmann namespace {
103f853ec31SStephan Bergmann 
104431f2ce8STakeshi Abe class LoadEnvListener : public ::cppu::WeakImplHelper< css::frame::XLoadEventListener      ,
10577f6149cSKurt Zenker                                                         css::frame::XDispatchResultListener >
10677f6149cSKurt Zenker {
10777f6149cSKurt Zenker     private:
10889fa0a42SNoel Grandin         std::mutex m_mutex;
1098cd21316SCaolán McNamara         bool m_bWaitingResult;
11077f6149cSKurt Zenker         LoadEnv* m_pLoadEnv;
11177f6149cSKurt Zenker 
11277f6149cSKurt Zenker     public:
11377f6149cSKurt Zenker 
LoadEnvListener(LoadEnv * pLoadEnv)114bea8a7adSCaolán McNamara         explicit LoadEnvListener(LoadEnv* pLoadEnv)
1158cd21316SCaolán McNamara             : m_bWaitingResult(true)
1168cd21316SCaolán McNamara             , m_pLoadEnv(pLoadEnv)
11777f6149cSKurt Zenker         {
11877f6149cSKurt Zenker         }
11977f6149cSKurt Zenker 
12077f6149cSKurt Zenker         // frame.XLoadEventListener
121e57ca028SStephan Bergmann         virtual void SAL_CALL loadFinished(const css::uno::Reference< css::frame::XFrameLoader >& xLoader) override;
12277f6149cSKurt Zenker 
123e57ca028SStephan Bergmann         virtual void SAL_CALL loadCancelled(const css::uno::Reference< css::frame::XFrameLoader >& xLoader) override;
12477f6149cSKurt Zenker 
12577f6149cSKurt Zenker         // frame.XDispatchResultListener
126e57ca028SStephan Bergmann         virtual void SAL_CALL dispatchFinished(const css::frame::DispatchResultEvent& aEvent) override;
12777f6149cSKurt Zenker 
12877f6149cSKurt Zenker         // lang.XEventListener
129e57ca028SStephan Bergmann         virtual void SAL_CALL disposing(const css::lang::EventObject& aEvent) override;
13077f6149cSKurt Zenker };
13177f6149cSKurt Zenker 
132f853ec31SStephan Bergmann }
133f853ec31SStephan Bergmann 
LoadEnv(css::uno::Reference<css::uno::XComponentContext> xContext)134c60ad041SNoel Grandin LoadEnv::LoadEnv(css::uno::Reference< css::uno::XComponentContext >  xContext)
135c60ad041SNoel Grandin     : m_xContext(std::move(xContext))
136cffe7a15SCaolán McNamara     , m_nSearchFlags(0)
137344957aaSNoel Grandin     , m_eFeature(LoadEnvFeatures::NONE)
138cffe7a15SCaolán McNamara     , m_eContentType(E_UNSUPPORTED_CONTENT)
139cffe7a15SCaolán McNamara     , m_bCloseFrameOnError(false)
140cffe7a15SCaolán McNamara     , m_bReactivateControllerOnError(false)
1419a57fe1aSTor Lillqvist     , m_bLoaded( false )
14277f6149cSKurt Zenker {
14377f6149cSKurt Zenker }
14477f6149cSKurt Zenker 
~LoadEnv()14577f6149cSKurt Zenker LoadEnv::~LoadEnv()
14677f6149cSKurt Zenker {
14777f6149cSKurt Zenker }
14877f6149cSKurt Zenker 
loadComponentFromURL(const css::uno::Reference<css::frame::XComponentLoader> & xLoader,const css::uno::Reference<css::uno::XComponentContext> & xContext,const OUString & sURL,const OUString & sTarget,sal_Int32 nSearchFlags,const css::uno::Sequence<css::beans::PropertyValue> & lArgs)14977f6149cSKurt Zenker css::uno::Reference< css::lang::XComponent > LoadEnv::loadComponentFromURL(const css::uno::Reference< css::frame::XComponentLoader >&    xLoader,
150fe1ac1bfSNoel Grandin                                                                            const css::uno::Reference< css::uno::XComponentContext >&     xContext  ,
1511946794aSLuboš Luňák                                                                            const OUString&                                        sURL   ,
1521946794aSLuboš Luňák                                                                            const OUString&                                        sTarget,
153c5e1c410SSamuel Mehrbrodt                                                                                  sal_Int32                                               nSearchFlags ,
15477f6149cSKurt Zenker                                                                            const css::uno::Sequence< css::beans::PropertyValue >&        lArgs  )
15577f6149cSKurt Zenker {
15677f6149cSKurt Zenker     css::uno::Reference< css::lang::XComponent > xComponent;
15727bde9a6STor Lillqvist     comphelper::ProfileZone aZone("loadComponentFromURL");
15877f6149cSKurt Zenker 
15977f6149cSKurt Zenker     try
16077f6149cSKurt Zenker     {
161fe1ac1bfSNoel Grandin         LoadEnv aEnv(xContext);
1621115a60eSSamuel Mehrbrodt         LoadEnvFeatures loadEnvFeatures = LoadEnvFeatures::WorkWithUI;
1631115a60eSSamuel Mehrbrodt         // tdf#118238 Only disable UI interaction when loading as hidden
164d03e7a8fSNoel Grandin         if (comphelper::NamedValueCollection::get(lArgs, u"Hidden") == uno::Any(true) || Application::IsHeadlessModeEnabled())
1651115a60eSSamuel Mehrbrodt             loadEnvFeatures = LoadEnvFeatures::NONE;
1661115a60eSSamuel Mehrbrodt 
1673b16dfd8SStephan Bergmann         aEnv.startLoading(sURL,
16877f6149cSKurt Zenker                                lArgs,
16977f6149cSKurt Zenker                                css::uno::Reference< css::frame::XFrame >(xLoader, css::uno::UNO_QUERY),
17077f6149cSKurt Zenker                                sTarget,
171c5e1c410SSamuel Mehrbrodt                                nSearchFlags,
1721115a60eSSamuel Mehrbrodt                                loadEnvFeatures);
17377f6149cSKurt Zenker         aEnv.waitWhileLoading(); // wait for ever!
17477f6149cSKurt Zenker 
17577f6149cSKurt Zenker         xComponent = aEnv.getTargetComponent();
17677f6149cSKurt Zenker     }
17777f6149cSKurt Zenker     catch(const LoadEnvException& ex)
17877f6149cSKurt Zenker     {
17977f6149cSKurt Zenker         switch(ex.m_nID)
18077f6149cSKurt Zenker         {
18177f6149cSKurt Zenker             case LoadEnvException::ID_INVALID_MEDIADESCRIPTOR:
18277f6149cSKurt Zenker                 throw css::lang::IllegalArgumentException(
1834f5f24a4SNoel Grandin                     u"Optional list of arguments seem to be corrupted."_ustr, xLoader, 4);
18477f6149cSKurt Zenker 
1853a54f45cSSander Vesik             case LoadEnvException::ID_UNSUPPORTED_CONTENT:
1862d2337ebSStephan Bergmann                 throw css::lang::IllegalArgumentException(
187e50ef195SStephan Bergmann                     "Unsupported URL <" + sURL + ">: \"" + ex.m_sMessage + "\"",
18880cc7728SCaolán McNamara                     xLoader, 1);
18980cc7728SCaolán McNamara 
19080cc7728SCaolán McNamara             default:
1912d2337ebSStephan Bergmann                 SAL_WARN(
1922d2337ebSStephan Bergmann                     "fwk.loadenv",
1932d2337ebSStephan Bergmann                     "caught LoadEnvException " << +ex.m_nID << " \""
1942d2337ebSStephan Bergmann                         << ex.m_sMessage << "\""
1952d2337ebSStephan Bergmann                         << (ex.m_exOriginal.has<css::uno::Exception>()
1962d2337ebSStephan Bergmann                             ? (", " + ex.m_exOriginal.getValueTypeName() + " \""
1972d2337ebSStephan Bergmann                                + (ex.m_exOriginal.get<css::uno::Exception>().
1982d2337ebSStephan Bergmann                                   Message)
1992d2337ebSStephan Bergmann                                + "\"")
2002d2337ebSStephan Bergmann                             : OUString())
2012d2337ebSStephan Bergmann                         << " while loading <" << sURL << ">");
20280cc7728SCaolán McNamara                 xComponent.clear();
20377f6149cSKurt Zenker                 break;
20477f6149cSKurt Zenker         }
20577f6149cSKurt Zenker     }
20677f6149cSKurt Zenker 
2078c6972a4SCaolán McNamara     // if AbortOnLoadFailure is set and we couldn't load the document, assert, intended for use with crashtesting to
2088c6972a4SCaolán McNamara     // detect when we export something we can't import
2098c6972a4SCaolán McNamara     assert(xComponent.is() || comphelper::NamedValueCollection::get(lArgs, u"AbortOnLoadFailure") != uno::Any(true));
2108c6972a4SCaolán McNamara 
21177f6149cSKurt Zenker     return xComponent;
21277f6149cSKurt Zenker }
21377f6149cSKurt Zenker 
214b34f0327SJan Holesovsky namespace {
215b34f0327SJan Holesovsky 
addModelArgs(const uno::Sequence<beans::PropertyValue> & rDescriptor)216b34f0327SJan Holesovsky utl::MediaDescriptor addModelArgs(const uno::Sequence<beans::PropertyValue>& rDescriptor)
217c57e8e70SVladimir Glazounov {
218b34f0327SJan Holesovsky     utl::MediaDescriptor rResult(rDescriptor);
2192ab40e9eSNoel Grandin     uno::Reference<frame::XModel> xModel(rResult.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_MODEL, uno::Reference<frame::XModel>()));
220b34f0327SJan Holesovsky 
221c57e8e70SVladimir Glazounov     if (xModel.is())
222c57e8e70SVladimir Glazounov     {
223b34f0327SJan Holesovsky         utl::MediaDescriptor aModelArgs(xModel->getArgs());
2242ab40e9eSNoel Grandin         utl::MediaDescriptor::iterator pIt = aModelArgs.find( utl::MediaDescriptor::PROP_MACROEXECUTIONMODE);
225b34f0327SJan Holesovsky         if (pIt != aModelArgs.end())
2262ab40e9eSNoel Grandin             rResult[utl::MediaDescriptor::PROP_MACROEXECUTIONMODE] = pIt->second;
227c57e8e70SVladimir Glazounov     }
228c57e8e70SVladimir Glazounov 
229b34f0327SJan Holesovsky     return rResult;
230c57e8e70SVladimir Glazounov }
231c57e8e70SVladimir Glazounov 
232b34f0327SJan Holesovsky }
233b34f0327SJan Holesovsky 
startLoading(const OUString & sURL,const uno::Sequence<beans::PropertyValue> & lMediaDescriptor,const uno::Reference<frame::XFrame> & xBaseFrame,const OUString & sTarget,sal_Int32 nSearchFlags,LoadEnvFeatures eFeature)2343b16dfd8SStephan Bergmann void LoadEnv::startLoading(const OUString& sURL, const uno::Sequence<beans::PropertyValue>& lMediaDescriptor,
235b34f0327SJan Holesovsky         const uno::Reference<frame::XFrame>& xBaseFrame, const OUString& sTarget,
236344957aaSNoel Grandin         sal_Int32 nSearchFlags, LoadEnvFeatures eFeature)
23777f6149cSKurt Zenker {
23885f7ed1cSStephan Bergmann     osl::MutexGuard g(m_mutex);
23977f6149cSKurt Zenker 
24077f6149cSKurt Zenker     // Handle still running processes!
24177f6149cSKurt Zenker     if (m_xAsynchronousJob.is())
24277f6149cSKurt Zenker         throw LoadEnvException(LoadEnvException::ID_STILL_RUNNING);
24377f6149cSKurt Zenker 
24477f6149cSKurt Zenker     // take over all new parameters.
24577f6149cSKurt Zenker     m_xTargetFrame.clear();
24677f6149cSKurt Zenker     m_xBaseFrame = xBaseFrame;
247b34f0327SJan Holesovsky     m_lMediaDescriptor = addModelArgs(lMediaDescriptor);
24877f6149cSKurt Zenker     m_sTarget = sTarget;
24977f6149cSKurt Zenker     m_nSearchFlags = nSearchFlags;
25077f6149cSKurt Zenker     m_eFeature = eFeature;
2519866efe3SNoel Grandin     m_eContentType = E_UNSUPPORTED_CONTENT;
252a6287e21SNoel Grandin     m_bCloseFrameOnError = false;
253a6287e21SNoel Grandin     m_bReactivateControllerOnError = false;
254a6287e21SNoel Grandin     m_bLoaded = false;
25577f6149cSKurt Zenker 
25620b1e644SMike Kaganski     OUString aRealURL;
257a3843f1cSMike Kaganski     if (!officecfg::Office::Common::Load::DetectWebDAVRedirection::get()
258a3843f1cSMike Kaganski         || !tools::IsMappedWebDAVPath(sURL, &aRealURL))
25920b1e644SMike Kaganski         aRealURL = sURL;
26020b1e644SMike Kaganski 
26142cfb5d0SAndrea Gelmini     // try to find out, if it's really a content, which can be loaded or must be "handled"
26277f6149cSKurt Zenker     // We use a default value for this in-parameter. Then we have to start a complex check method
263a1bc5756SJesús Corrius     // internally. But if this check was already done outside it can be suppressed to perform
26477f6149cSKurt Zenker     // the load request. We take over the result then!
26520b1e644SMike Kaganski     m_eContentType = LoadEnv::classifyContent(aRealURL, lMediaDescriptor);
26677f6149cSKurt Zenker     if (m_eContentType == E_UNSUPPORTED_CONTENT)
2674f5f24a4SNoel Grandin         throw LoadEnvException(LoadEnvException::ID_UNSUPPORTED_CONTENT, u"from LoadEnv::startLoading"_ustr);
26877f6149cSKurt Zenker 
26977f6149cSKurt Zenker     // make URL part of the MediaDescriptor
270465489d9SAndrea Gelmini     // It doesn't matter if it is already an item of it.
27177f6149cSKurt Zenker     // It must be the same value... so we can overwrite it :-)
2722ab40e9eSNoel Grandin     m_lMediaDescriptor[utl::MediaDescriptor::PROP_URL] <<= aRealURL;
27377f6149cSKurt Zenker 
27477f6149cSKurt Zenker     // parse it - because some following code require that
27520b1e644SMike Kaganski     m_aURL.Complete = aRealURL;
276b34f0327SJan Holesovsky     uno::Reference<util::XURLTransformer> xParser(util::URLTransformer::create(m_xContext));
27777f6149cSKurt Zenker     xParser->parseStrict(m_aURL);
27877f6149cSKurt Zenker 
279e2a4aa0eSKurt Zenker     // BTW: Split URL and JumpMark ...
280e2a4aa0eSKurt Zenker     // Because such mark is an explicit value of the media descriptor!
28118692cc1SOlivier Hallot     if (!m_aURL.Mark.isEmpty())
2822ab40e9eSNoel Grandin         m_lMediaDescriptor[utl::MediaDescriptor::PROP_JUMPMARK] <<= m_aURL.Mark;
283e2a4aa0eSKurt Zenker 
28477f6149cSKurt Zenker     // By the way: remove the old and deprecated value "FileName" from the descriptor!
2852ab40e9eSNoel Grandin     utl::MediaDescriptor::iterator pIt = m_lMediaDescriptor.find(utl::MediaDescriptor::PROP_FILENAME);
28677f6149cSKurt Zenker     if (pIt != m_lMediaDescriptor.end())
28777f6149cSKurt Zenker         m_lMediaDescriptor.erase(pIt);
28877f6149cSKurt Zenker 
289a1bc5756SJesús Corrius     // patch the MediaDescriptor, so it fulfil the outside requirements
2909a2d1b9cSLionel Elie Mamane     // Means especially items like e.g. UI InteractionHandler, Status Indicator,
291a1bc5756SJesús Corrius     // MacroExecutionMode, etc.
29277f6149cSKurt Zenker 
29377f6149cSKurt Zenker     /*TODO progress is bound to a frame ... How can we set it here? */
29477f6149cSKurt Zenker 
295c0899590SFrank Schoenheit [fs]     // UI mode
296c0899590SFrank Schoenheit [fs]     const bool bUIMode =
297344957aaSNoel Grandin         (m_eFeature & LoadEnvFeatures::WorkWithUI) &&
2982ab40e9eSNoel Grandin         !m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_HIDDEN, false) &&
2992ab40e9eSNoel Grandin         !m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_PREVIEW, false);
300c0899590SFrank Schoenheit [fs] 
301f43a5ec2SHenry Castro     if( comphelper::LibreOfficeKit::isActive() &&
302f43a5ec2SHenry Castro         m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_SILENT, false))
303f43a5ec2SHenry Castro     {
304f43a5ec2SHenry Castro         rtl::Reference<QuietInteraction> pQuietInteraction = new QuietInteraction();
305*09e2627aSNoel Grandin         m_lMediaDescriptor[utl::MediaDescriptor::PROP_INTERACTIONHANDLER] <<=
306*09e2627aSNoel Grandin                 uno::Reference<task::XInteractionHandler>(pQuietInteraction);
307f43a5ec2SHenry Castro     }
308f43a5ec2SHenry Castro 
309b34f0327SJan Holesovsky     initializeUIDefaults(m_xContext, m_lMediaDescriptor, bUIMode, &m_pQuietInteraction);
3103b16dfd8SStephan Bergmann 
3113b16dfd8SStephan Bergmann     start();
312c0899590SFrank Schoenheit [fs] }
313c0899590SFrank Schoenheit [fs] 
initializeUIDefaults(const css::uno::Reference<css::uno::XComponentContext> & i_rxContext,utl::MediaDescriptor & io_lMediaDescriptor,const bool i_bUIMode,rtl::Reference<QuietInteraction> * o_ppQuietInteraction)314dc00ad1eSNoel Grandin void LoadEnv::initializeUIDefaults( const css::uno::Reference< css::uno::XComponentContext >& i_rxContext,
31524cad6a6SStephan Bergmann                                     utl::MediaDescriptor& io_lMediaDescriptor, const bool i_bUIMode,
316da8bfce2SStephan Bergmann                                     rtl::Reference<QuietInteraction>* o_ppQuietInteraction )
317c0899590SFrank Schoenheit [fs] {
31877f6149cSKurt Zenker     css::uno::Reference< css::task::XInteractionHandler > xInteractionHandler;
31977f6149cSKurt Zenker     sal_Int16                                             nMacroMode;
32077f6149cSKurt Zenker     sal_Int16                                             nUpdateMode;
32177f6149cSKurt Zenker 
322c0899590SFrank Schoenheit [fs]     if ( i_bUIMode )
32377f6149cSKurt Zenker     {
32477f6149cSKurt Zenker         nMacroMode  = css::document::MacroExecMode::USE_CONFIG;
32577f6149cSKurt Zenker         nUpdateMode = css::document::UpdateDocMode::ACCORDING_TO_CONFIG;
32677f6149cSKurt Zenker         try
32777f6149cSKurt Zenker         {
3287f9b3a02SCaolán McNamara             // tdf#154308 At least for the case the document is launched from the StartCenter, put that StartCenter as the
3297f9b3a02SCaolán McNamara             // parent for any dialogs that may appear during typedetection (once load starts a permanent frame will be set
3307f9b3a02SCaolán McNamara             // anyway and used as dialog parent, which will be this one if the startcenter was running)
3317f9b3a02SCaolán McNamara             css::uno::Reference<css::frame::XFramesSupplier> xSupplier = css::frame::Desktop::create(i_rxContext);
3327f9b3a02SCaolán McNamara             FrameListAnalyzer aTasksAnalyzer(xSupplier, css::uno::Reference<css::frame::XFrame>(), FrameAnalyzerFlags::BackingComponent);
3337f9b3a02SCaolán McNamara             css::uno::Reference<css::awt::XWindow> xDialogParent(aTasksAnalyzer.m_xBackingComponent ?
3347f9b3a02SCaolán McNamara                                                                  aTasksAnalyzer.m_xBackingComponent->getContainerWindow() :
3357f9b3a02SCaolán McNamara                                                                  nullptr);
3367f9b3a02SCaolán McNamara 
3377f9b3a02SCaolán McNamara             xInteractionHandler.set( css::task::InteractionHandler::createWithParent(i_rxContext, xDialogParent), css::uno::UNO_QUERY_THROW );
33877f6149cSKurt Zenker         }
33977f6149cSKurt Zenker         catch(const css::uno::RuntimeException&) {throw;}
34077f6149cSKurt Zenker         catch(const css::uno::Exception&       ) {      }
34177f6149cSKurt Zenker     }
34277f6149cSKurt Zenker     // hidden mode
34377f6149cSKurt Zenker     else
34477f6149cSKurt Zenker     {
34577f6149cSKurt Zenker         nMacroMode  = css::document::MacroExecMode::NEVER_EXECUTE;
34677f6149cSKurt Zenker         nUpdateMode = css::document::UpdateDocMode::NO_UPDATE;
347da8bfce2SStephan Bergmann         rtl::Reference<QuietInteraction> pQuietInteraction = new QuietInteraction();
348da8bfce2SStephan Bergmann         xInteractionHandler = pQuietInteraction.get();
34906c5c630SStephan Bergmann         if ( o_ppQuietInteraction != nullptr )
350c0899590SFrank Schoenheit [fs]         {
35123d7910cSCaolán McNamara             *o_ppQuietInteraction = std::move(pQuietInteraction);
352c0899590SFrank Schoenheit [fs]         }
35377f6149cSKurt Zenker     }
35477f6149cSKurt Zenker 
355bc9a8ddbSGiuseppe Castagno     if ( xInteractionHandler.is() )
356bc9a8ddbSGiuseppe Castagno     {
3572ab40e9eSNoel Grandin         if( io_lMediaDescriptor.find(utl::MediaDescriptor::PROP_INTERACTIONHANDLER) == io_lMediaDescriptor.end() )
35877f6149cSKurt Zenker         {
3592ab40e9eSNoel Grandin             io_lMediaDescriptor[utl::MediaDescriptor::PROP_INTERACTIONHANDLER] <<= xInteractionHandler;
36077f6149cSKurt Zenker         }
3612ab40e9eSNoel Grandin         if( io_lMediaDescriptor.find(utl::MediaDescriptor::PROP_AUTHENTICATIONHANDLER) == io_lMediaDescriptor.end() )
362bc9a8ddbSGiuseppe Castagno         {
3632ab40e9eSNoel Grandin             io_lMediaDescriptor[utl::MediaDescriptor::PROP_AUTHENTICATIONHANDLER] <<= xInteractionHandler;
364bc9a8ddbSGiuseppe Castagno         }
365bc9a8ddbSGiuseppe Castagno     }
36677f6149cSKurt Zenker 
3672ab40e9eSNoel Grandin     if (io_lMediaDescriptor.find(utl::MediaDescriptor::PROP_MACROEXECUTIONMODE) == io_lMediaDescriptor.end())
3682ab40e9eSNoel Grandin         io_lMediaDescriptor[utl::MediaDescriptor::PROP_MACROEXECUTIONMODE] <<= nMacroMode;
36977f6149cSKurt Zenker 
3702ab40e9eSNoel Grandin     if (io_lMediaDescriptor.find(utl::MediaDescriptor::PROP_UPDATEDOCMODE) == io_lMediaDescriptor.end())
3712ab40e9eSNoel Grandin         io_lMediaDescriptor[utl::MediaDescriptor::PROP_UPDATEDOCMODE] <<= nUpdateMode;
37277f6149cSKurt Zenker }
37377f6149cSKurt Zenker 
start()3743b16dfd8SStephan Bergmann void LoadEnv::start()
37577f6149cSKurt Zenker {
37677f6149cSKurt Zenker     // SAFE ->
3775a824268SMike Kaganski     {
3785a824268SMike Kaganski         osl::MutexGuard aReadLock(m_mutex);
37977f6149cSKurt Zenker 
38077f6149cSKurt Zenker         // Handle still running processes!
38177f6149cSKurt Zenker         if (m_xAsynchronousJob.is())
38277f6149cSKurt Zenker             throw LoadEnvException(LoadEnvException::ID_STILL_RUNNING);
38377f6149cSKurt Zenker 
38477f6149cSKurt Zenker         // content can not be loaded or handled
38577f6149cSKurt Zenker         // check "classifyContent()" failed before ...
38677f6149cSKurt Zenker         if (m_eContentType == E_UNSUPPORTED_CONTENT)
3875a824268SMike Kaganski             throw LoadEnvException(LoadEnvException::ID_UNSUPPORTED_CONTENT,
3884f5f24a4SNoel Grandin                                    u"from LoadEnv::start"_ustr);
3895a824268SMike Kaganski     }
39077f6149cSKurt Zenker     // <- SAFE
39177f6149cSKurt Zenker 
392a1bc5756SJesús Corrius     // detect its type/filter etc.
393a179305cSAndrea Gelmini     // This information will be available by the
39477f6149cSKurt Zenker     // used descriptor member afterwards and is needed
39577f6149cSKurt Zenker     // for all following operations!
39677f6149cSKurt Zenker     // Note: An exception will be thrown, in case operation was not successfully ...
397bd32f48aSKurt Zenker     if (m_eContentType != E_CAN_BE_SET)/* Attention: special feature to set existing component on a frame must ignore type detection! */
39877f6149cSKurt Zenker         impl_detectTypeAndFilter();
39977f6149cSKurt Zenker 
40077f6149cSKurt Zenker     // start loading the content...
401a1bc5756SJesús Corrius     // Attention: Don't check m_eContentType deeper then UNSUPPORTED/SUPPORTED!
402a1bc5756SJesús Corrius     // Because it was made in the easiest way... may a flat detection was made only.
40377f6149cSKurt Zenker     // And such simple detection can fail sometimes .-)
40477f6149cSKurt Zenker     // Use another strategy here. Try it and let it run into the case "loading not possible".
405a6287e21SNoel Grandin     bool bStarted = false;
406bd32f48aSKurt Zenker     if (
407344957aaSNoel Grandin         (m_eFeature & LoadEnvFeatures::AllowContentHandler) &&
408bd32f48aSKurt Zenker         (m_eContentType                        != E_CAN_BE_SET          )   /* Attention: special feature to set existing component on a frame must ignore type detection! */
409bd32f48aSKurt Zenker        )
410bd32f48aSKurt Zenker     {
41177f6149cSKurt Zenker         bStarted = impl_handleContent();
412bd32f48aSKurt Zenker     }
41377f6149cSKurt Zenker 
41477f6149cSKurt Zenker     if (!bStarted)
41577f6149cSKurt Zenker         bStarted = impl_loadContent();
41677f6149cSKurt Zenker 
41777f6149cSKurt Zenker     // not started => general error
4189a2d1b9cSLionel Elie Mamane     // We can't say - what was the reason for.
41977f6149cSKurt Zenker     if (!bStarted)
4205a10e33fSStephan Bergmann         throw LoadEnvException(
4214f5f24a4SNoel Grandin             LoadEnvException::ID_GENERAL_ERROR, u"not started"_ustr);
42277f6149cSKurt Zenker }
42377f6149cSKurt Zenker 
42477f6149cSKurt Zenker /*-----------------------------------------------
42577f6149cSKurt Zenker     TODO
42677f6149cSKurt Zenker         First draft does not implement timeout using [ms].
42777f6149cSKurt Zenker         Current implementation counts yield calls only ...
42877f6149cSKurt Zenker -----------------------------------------------*/
waitWhileLoading(sal_uInt32 nTimeout)429a6287e21SNoel Grandin bool LoadEnv::waitWhileLoading(sal_uInt32 nTimeout)
43077f6149cSKurt Zenker {
431c7114b66SAndrea Gelmini     // Because it's not a good idea to block the main thread
4329a2d1b9cSLionel Elie Mamane     // (and we can't be sure that we are currently not used inside the
4339a2d1b9cSLionel Elie Mamane     // main thread!), we can't use conditions here really. We must yield
434a1bc5756SJesús Corrius     // in an intelligent manner :-)
43577f6149cSKurt Zenker 
43677f6149cSKurt Zenker     sal_Int32 nTime = nTimeout;
437c880d3e3SNoel Grandin     while(!Application::IsQuit())
43877f6149cSKurt Zenker     {
43977f6149cSKurt Zenker         // SAFE -> ------------------------------
4405a824268SMike Kaganski         {
4415a824268SMike Kaganski             osl::MutexGuard aReadLock1(m_mutex);
44277f6149cSKurt Zenker             if (!m_xAsynchronousJob.is())
44377f6149cSKurt Zenker                 break;
4445a824268SMike Kaganski         }
44577f6149cSKurt Zenker         // <- SAFE ------------------------------
44677f6149cSKurt Zenker 
44777f6149cSKurt Zenker         Application::Yield();
44877f6149cSKurt Zenker 
44977f6149cSKurt Zenker         // forever!
45077f6149cSKurt Zenker         if (nTimeout==0)
45177f6149cSKurt Zenker             continue;
45277f6149cSKurt Zenker 
45377f6149cSKurt Zenker         // timed out?
45477f6149cSKurt Zenker         --nTime;
45577f6149cSKurt Zenker         if (nTime<1)
45677f6149cSKurt Zenker             break;
45777f6149cSKurt Zenker     }
45877f6149cSKurt Zenker 
45985f7ed1cSStephan Bergmann     osl::MutexGuard g(m_mutex);
46077f6149cSKurt Zenker     return !m_xAsynchronousJob.is();
46177f6149cSKurt Zenker }
46277f6149cSKurt Zenker 
getTargetComponent() const46377f6149cSKurt Zenker css::uno::Reference< css::lang::XComponent > LoadEnv::getTargetComponent() const
46477f6149cSKurt Zenker {
46585f7ed1cSStephan Bergmann     osl::MutexGuard g(m_mutex);
46677f6149cSKurt Zenker 
46777f6149cSKurt Zenker     if (!m_xTargetFrame.is())
46877f6149cSKurt Zenker         return css::uno::Reference< css::lang::XComponent >();
46977f6149cSKurt Zenker 
47077f6149cSKurt Zenker     css::uno::Reference< css::frame::XController > xController = m_xTargetFrame->getController();
47177f6149cSKurt Zenker     if (!xController.is())
472952b806cSNoel Grandin         return m_xTargetFrame->getComponentWindow();
47377f6149cSKurt Zenker 
47477f6149cSKurt Zenker     css::uno::Reference< css::frame::XModel > xModel = xController->getModel();
47577f6149cSKurt Zenker     if (!xModel.is())
476952b806cSNoel Grandin         return xController;
47777f6149cSKurt Zenker 
478952b806cSNoel Grandin     return xModel;
47977f6149cSKurt Zenker }
48077f6149cSKurt Zenker 
loadFinished(const css::uno::Reference<css::frame::XFrameLoader> &)4817d144987SJens-Heiner Rechtien void SAL_CALL LoadEnvListener::loadFinished(const css::uno::Reference< css::frame::XFrameLoader >&)
48277f6149cSKurt Zenker {
48389fa0a42SNoel Grandin     std::unique_lock g(m_mutex);
4848cd21316SCaolán McNamara     if (m_bWaitingResult)
485a6287e21SNoel Grandin         m_pLoadEnv->impl_setResult(true);
4868cd21316SCaolán McNamara     m_bWaitingResult = false;
48777f6149cSKurt Zenker }
48877f6149cSKurt Zenker 
loadCancelled(const css::uno::Reference<css::frame::XFrameLoader> &)4897d144987SJens-Heiner Rechtien void SAL_CALL LoadEnvListener::loadCancelled(const css::uno::Reference< css::frame::XFrameLoader >&)
49077f6149cSKurt Zenker {
49189fa0a42SNoel Grandin     std::unique_lock g(m_mutex);
4928cd21316SCaolán McNamara     if (m_bWaitingResult)
493a6287e21SNoel Grandin         m_pLoadEnv->impl_setResult(false);
4948cd21316SCaolán McNamara     m_bWaitingResult = false;
49577f6149cSKurt Zenker }
49677f6149cSKurt Zenker 
dispatchFinished(const css::frame::DispatchResultEvent & aEvent)49777f6149cSKurt Zenker void SAL_CALL LoadEnvListener::dispatchFinished(const css::frame::DispatchResultEvent& aEvent)
49877f6149cSKurt Zenker {
49989fa0a42SNoel Grandin     std::unique_lock g(m_mutex);
50077f6149cSKurt Zenker 
5018cd21316SCaolán McNamara     if (!m_bWaitingResult)
50277f6149cSKurt Zenker         return;
50377f6149cSKurt Zenker 
50477f6149cSKurt Zenker     switch(aEvent.State)
50577f6149cSKurt Zenker     {
50677f6149cSKurt Zenker         case css::frame::DispatchResultState::FAILURE :
507a6287e21SNoel Grandin             m_pLoadEnv->impl_setResult(false);
50877f6149cSKurt Zenker             break;
50977f6149cSKurt Zenker 
51077f6149cSKurt Zenker         case css::frame::DispatchResultState::SUCCESS :
511a6287e21SNoel Grandin             m_pLoadEnv->impl_setResult(false);
51277f6149cSKurt Zenker             break;
51377f6149cSKurt Zenker 
51477f6149cSKurt Zenker         case css::frame::DispatchResultState::DONTKNOW :
515a6287e21SNoel Grandin             m_pLoadEnv->impl_setResult(false);
51677f6149cSKurt Zenker             break;
51777f6149cSKurt Zenker     }
5188cd21316SCaolán McNamara     m_bWaitingResult = false;
51977f6149cSKurt Zenker }
52077f6149cSKurt Zenker 
disposing(const css::lang::EventObject &)5217d144987SJens-Heiner Rechtien void SAL_CALL LoadEnvListener::disposing(const css::lang::EventObject&)
52277f6149cSKurt Zenker {
52389fa0a42SNoel Grandin     std::unique_lock g(m_mutex);
5248cd21316SCaolán McNamara     if (m_bWaitingResult)
525a6287e21SNoel Grandin         m_pLoadEnv->impl_setResult(false);
5268cd21316SCaolán McNamara     m_bWaitingResult = false;
52777f6149cSKurt Zenker }
52877f6149cSKurt Zenker 
impl_setResult(bool bResult)529a6287e21SNoel Grandin void LoadEnv::impl_setResult(bool bResult)
53077f6149cSKurt Zenker {
53185f7ed1cSStephan Bergmann     osl::MutexGuard g(m_mutex);
53277f6149cSKurt Zenker 
53377f6149cSKurt Zenker     m_bLoaded = bResult;
53477f6149cSKurt Zenker 
53577f6149cSKurt Zenker     impl_reactForLoadingState();
53677f6149cSKurt Zenker 
53777f6149cSKurt Zenker     // clearing of this reference will unblock waitWhileLoading()!
5389a2d1b9cSLionel Elie Mamane     // So we must be sure, that loading process was really finished.
53977f6149cSKurt Zenker     // => do it as last operation of this method ...
54077f6149cSKurt Zenker     m_xAsynchronousJob.clear();
54177f6149cSKurt Zenker }
54277f6149cSKurt Zenker 
54377f6149cSKurt Zenker /*-----------------------------------------------
54477f6149cSKurt Zenker     TODO: Is it a good idea to change Sequence<>
54577f6149cSKurt Zenker           parameter to stl-adapter?
54677f6149cSKurt Zenker -----------------------------------------------*/
classifyContent(const OUString & sURL,const css::uno::Sequence<css::beans::PropertyValue> & lMediaDescriptor)5471946794aSLuboš Luňák LoadEnv::EContentType LoadEnv::classifyContent(const OUString&                                 sURL            ,
54877f6149cSKurt Zenker                                                const css::uno::Sequence< css::beans::PropertyValue >& lMediaDescriptor)
54977f6149cSKurt Zenker {
5500ce0c369SAlexander Wilms 
55177f6149cSKurt Zenker     // (i) Filter some special well known URL protocols,
55277f6149cSKurt Zenker     //     which can not be handled or loaded in general.
55377f6149cSKurt Zenker     //     Of course an empty URL must be ignored here too.
55477f6149cSKurt Zenker     //     Note: These URL schemata are fix and well known ...
55577f6149cSKurt Zenker     //     But there can be some additional ones, which was not
55677f6149cSKurt Zenker     //     defined at implementation time of this class :-(
5579a2d1b9cSLionel Elie Mamane     //     So we have to make sure, that the following code
55877f6149cSKurt Zenker     //     can detect such protocol schemata too :-)
55977f6149cSKurt Zenker 
56077f6149cSKurt Zenker     if(
56118692cc1SOlivier Hallot         (sURL.isEmpty()                                          ) ||
562bac9a5d6SNoel Grandin         (ProtocolCheck::isProtocol(sURL,EProtocol::Uno    )) ||
563bac9a5d6SNoel Grandin         (ProtocolCheck::isProtocol(sURL,EProtocol::Slot   )) ||
564bac9a5d6SNoel Grandin         (ProtocolCheck::isProtocol(sURL,EProtocol::Macro  )) ||
565bac9a5d6SNoel Grandin         (ProtocolCheck::isProtocol(sURL,EProtocol::Service)) ||
566bac9a5d6SNoel Grandin         (ProtocolCheck::isProtocol(sURL,EProtocol::MailTo )) ||
567bac9a5d6SNoel Grandin         (ProtocolCheck::isProtocol(sURL,EProtocol::News   ))
56877f6149cSKurt Zenker       )
56977f6149cSKurt Zenker     {
57077f6149cSKurt Zenker         return E_UNSUPPORTED_CONTENT;
57177f6149cSKurt Zenker     }
57277f6149cSKurt Zenker 
57377f6149cSKurt Zenker     // (ii) Some special URLs indicates a given input stream,
57477f6149cSKurt Zenker     //      a full featured document model directly or
57577f6149cSKurt Zenker     //      specify a request for opening an empty document.
57677f6149cSKurt Zenker     //      Such contents are loadable in general.
57777f6149cSKurt Zenker     //      But we have to check, if the media descriptor contains
57877f6149cSKurt Zenker     //      all needed resources. If they are missing - the following
57977f6149cSKurt Zenker     //      load request will fail.
58077f6149cSKurt Zenker 
5819a2d1b9cSLionel Elie Mamane     /* Attention: The following code can't work on such special URLs!
582c64c4ad0SAndrea Gelmini                   It should not break the office... but it makes no sense
58377f6149cSKurt Zenker                   to start expensive object creations and complex search
584c64c4ad0SAndrea Gelmini                   algorithm if it's clear, that such URLs must be handled
58577f6149cSKurt Zenker                   in a special way .-)
58677f6149cSKurt Zenker     */
58777f6149cSKurt Zenker 
5885334ff28SAkash Jain     // creation of new documents
589bac9a5d6SNoel Grandin     if (ProtocolCheck::isProtocol(sURL,EProtocol::PrivateFactory))
5905334ff28SAkash Jain         return E_CAN_BE_LOADED;
5915334ff28SAkash Jain 
5925334ff28SAkash Jain     // using of an existing input stream
59338a3743eSTor Lillqvist     utl::MediaDescriptor                 stlMediaDescriptor(lMediaDescriptor);
59438a3743eSTor Lillqvist     utl::MediaDescriptor::const_iterator pIt;
595bac9a5d6SNoel Grandin     if (ProtocolCheck::isProtocol(sURL,EProtocol::PrivateStream))
59677f6149cSKurt Zenker     {
5972ab40e9eSNoel Grandin         pIt = stlMediaDescriptor.find(utl::MediaDescriptor::PROP_INPUTSTREAM);
59877f6149cSKurt Zenker         css::uno::Reference< css::io::XInputStream > xStream;
599965cc9c2SJens-Heiner Rechtien         if (pIt != stlMediaDescriptor.end())
60077f6149cSKurt Zenker             pIt->second >>= xStream;
60177f6149cSKurt Zenker         if (xStream.is())
60277f6149cSKurt Zenker             return E_CAN_BE_LOADED;
603d15b4e20SNoel Grandin         SAL_INFO("fwk.loadenv", "LoadEnv::classifyContent(): loading from stream with right URL but invalid stream detected");
60477f6149cSKurt Zenker         return E_UNSUPPORTED_CONTENT;
60577f6149cSKurt Zenker     }
60677f6149cSKurt Zenker 
60777f6149cSKurt Zenker     // using of a full featured document
608bac9a5d6SNoel Grandin     if (ProtocolCheck::isProtocol(sURL,EProtocol::PrivateObject))
60977f6149cSKurt Zenker     {
6102ab40e9eSNoel Grandin         pIt = stlMediaDescriptor.find(utl::MediaDescriptor::PROP_MODEL);
61177f6149cSKurt Zenker         css::uno::Reference< css::frame::XModel > xModel;
612bd32f48aSKurt Zenker         if (pIt != stlMediaDescriptor.end())
61377f6149cSKurt Zenker             pIt->second >>= xModel;
61477f6149cSKurt Zenker         if (xModel.is())
615bd32f48aSKurt Zenker             return E_CAN_BE_SET;
616d15b4e20SNoel Grandin         SAL_INFO("fwk.loadenv", "LoadEnv::classifyContent(): loading with object with right URL but invalid object detected");
61777f6149cSKurt Zenker         return E_UNSUPPORTED_CONTENT;
61877f6149cSKurt Zenker     }
61977f6149cSKurt Zenker 
62089fed427SNoel Grandin     // following operations can work on an internal type name only :-(
621ed0b12f4SNoel Grandin     const css::uno::Reference< css::uno::XComponentContext >& xContext = ::comphelper::getProcessComponentContext();
62289fed427SNoel Grandin     css::uno::Reference< css::document::XTypeDetection > xDetect(
6232d2337ebSStephan Bergmann          xContext->getServiceManager()->createInstanceWithContext(
6244f5f24a4SNoel Grandin              u"com.sun.star.document.TypeDetection"_ustr, xContext),
6252d2337ebSStephan Bergmann          css::uno::UNO_QUERY_THROW);
62677f6149cSKurt Zenker 
6271946794aSLuboš Luňák     OUString sType = xDetect->queryTypeByURL(sURL);
62877f6149cSKurt Zenker 
629d7fa9ca7SNoel Grandin     css::uno::Reference< css::frame::XLoaderFactory >      xLoaderFactory;
63077f6149cSKurt Zenker     css::uno::Reference< css::container::XEnumeration >    xSet;
63177f6149cSKurt Zenker 
63277f6149cSKurt Zenker     // (iii) If a FrameLoader service (or at least
63377f6149cSKurt Zenker     //      a Filter) can be found, which supports
63477f6149cSKurt Zenker     //      this URL - it must be a loadable content.
63577f6149cSKurt Zenker     //      Because both items are registered for types
6363c28c44aSAndrea Gelmini     //      it's enough to check for frame loaders only.
637bb73961eSJulien Nabet     //      Most of our filters are handled by our global
63877f6149cSKurt Zenker     //      default loader. But there exist some specialized
63977f6149cSKurt Zenker     //      loader, which does not work on top of filters!
640c7114b66SAndrea Gelmini     //      So it's not enough to search on the filter configuration.
641c7114b66SAndrea Gelmini     //      Further it's not enough to search for types!
64277f6149cSKurt Zenker     //      Because there exist some types, which are referenced by
643bb73961eSJulien Nabet     //      other objects... but neither by filters nor frame loaders!
644bb73961eSJulien Nabet     css::uno::Sequence< OUString > lTypesReg { sType };
645bb73961eSJulien Nabet     css::uno::Sequence< css::beans::NamedValue >           lQuery
646bb73961eSJulien Nabet     {
6476b6df07dSStephan Bergmann         css::beans::NamedValue(PROP_TYPES, css::uno::Any(lTypesReg))
648bb73961eSJulien Nabet     };
64977f6149cSKurt Zenker 
650d7fa9ca7SNoel Grandin     xLoaderFactory = css::frame::FrameLoaderFactory::create(xContext);
651d7fa9ca7SNoel Grandin     xSet       = xLoaderFactory->createSubSetEnumerationByProperties(lQuery);
65277f6149cSKurt Zenker     // at least one registered frame loader is enough!
65377f6149cSKurt Zenker     if (xSet->hasMoreElements())
65477f6149cSKurt Zenker         return E_CAN_BE_LOADED;
65577f6149cSKurt Zenker 
65677f6149cSKurt Zenker     // (iv) Some URL protocols are supported by special services.
65777f6149cSKurt Zenker     //      E.g. ContentHandler.
65877f6149cSKurt Zenker     //      Such contents can be handled ... but not loaded.
65977f6149cSKurt Zenker 
660d7fa9ca7SNoel Grandin     xLoaderFactory = css::frame::ContentHandlerFactory::create(xContext);
661d7fa9ca7SNoel Grandin     xSet       = xLoaderFactory->createSubSetEnumerationByProperties(lQuery);
66277f6149cSKurt Zenker     // at least one registered content handler is enough!
66377f6149cSKurt Zenker     if (xSet->hasMoreElements())
66477f6149cSKurt Zenker         return E_CAN_BE_HANDLED;
66577f6149cSKurt Zenker 
66677f6149cSKurt Zenker     // (v) Last but not least the UCB is used inside office to
66777f6149cSKurt Zenker     //     load contents. He has a special configuration to know
66877f6149cSKurt Zenker     //     which URL schemata can be used inside office.
66989fed427SNoel Grandin     css::uno::Reference< css::ucb::XUniversalContentBroker > xUCB(css::ucb::UniversalContentBroker::create(xContext));
67077f6149cSKurt Zenker     if (xUCB->queryContentProvider(sURL).is())
67177f6149cSKurt Zenker         return E_CAN_BE_LOADED;
67277f6149cSKurt Zenker 
67377f6149cSKurt Zenker     // (TODO) At this point, we have no idea .-)
67477f6149cSKurt Zenker     //        But it seems to be better, to break all
675a1bc5756SJesús Corrius     //        further requests for this URL. Otherwise
67677f6149cSKurt Zenker     //        we can run into some trouble.
67777f6149cSKurt Zenker     return E_UNSUPPORTED_CONTENT;
67877f6149cSKurt Zenker }
67977f6149cSKurt Zenker 
680a6639312SKohei Yoshida namespace {
681a6639312SKohei Yoshida 
queryOrcusTypeAndFilter(const uno::Sequence<beans::PropertyValue> & rDescriptor,OUString & rType,OUString & rFilter)682a6639312SKohei Yoshida bool queryOrcusTypeAndFilter(const uno::Sequence<beans::PropertyValue>& rDescriptor, OUString& rType, OUString& rFilter)
683a6639312SKohei Yoshida {
684a6639312SKohei Yoshida     OUString aURL;
685a6639312SKohei Yoshida     sal_Int32 nSize = rDescriptor.getLength();
686a6639312SKohei Yoshida     for (sal_Int32 i = 0; i < nSize; ++i)
687a6639312SKohei Yoshida     {
688a6639312SKohei Yoshida         const beans::PropertyValue& rProp = rDescriptor[i];
689a6639312SKohei Yoshida         if (rProp.Name == "URL")
690a6639312SKohei Yoshida         {
691a6639312SKohei Yoshida             rProp.Value >>= aURL;
692a6639312SKohei Yoshida             break;
693a6639312SKohei Yoshida         }
694a6639312SKohei Yoshida     }
695a6639312SKohei Yoshida 
696cbaf1fbaSNoel Grandin     if (aURL.isEmpty() || o3tl::equalsIgnoreAsciiCase(aURL.subView(0,8), u"private:"))
697a6639312SKohei Yoshida         return false;
698a6639312SKohei Yoshida 
699868ce95aSKohei Yoshida     // TODO : Type must be set to be generic_Text (or any other type that
700868ce95aSKohei Yoshida     // exists) in order to find a usable loader. Exploit it as a temporary
701868ce95aSKohei Yoshida     // hack.
702868ce95aSKohei Yoshida 
7036ae1b105SMarkus Mohrhard     // depending on the experimental mode
7044256c764SLuboš Luňák     if (!officecfg::Office::Common::Misc::ExperimentalMode::get())
7056ae1b105SMarkus Mohrhard     {
7066ae1b105SMarkus Mohrhard         return false;
7076ae1b105SMarkus Mohrhard     }
7086ae1b105SMarkus Mohrhard 
7096ae1b105SMarkus Mohrhard     OUString aUseOrcus;
7104f5f24a4SNoel Grandin     rtl::Bootstrap::get(u"LIBO_USE_ORCUS"_ustr, aUseOrcus);
7116ae1b105SMarkus Mohrhard     bool bUseOrcus = (aUseOrcus == "YES");
7126ae1b105SMarkus Mohrhard 
713644f122aSKohei Yoshida     if (!bUseOrcus)
714644f122aSKohei Yoshida         return false;
715644f122aSKohei Yoshida 
716644f122aSKohei Yoshida     if (aURL.endsWith(".xlsx"))
717a6639312SKohei Yoshida     {
718a6639312SKohei Yoshida         rType = "generic_Text";
719868ce95aSKohei Yoshida         rFilter = "xlsx";
720a6639312SKohei Yoshida         return true;
721a6639312SKohei Yoshida     }
722868ce95aSKohei Yoshida     else if (aURL.endsWith(".ods"))
723868ce95aSKohei Yoshida     {
724868ce95aSKohei Yoshida         rType = "generic_Text";
725868ce95aSKohei Yoshida         rFilter = "ods";
726868ce95aSKohei Yoshida         return true;
727868ce95aSKohei Yoshida     }
7280552a09bSKohei Yoshida     else if (aURL.endsWith(".csv"))
7290552a09bSKohei Yoshida     {
7300552a09bSKohei Yoshida         rType = "generic_Text";
7310552a09bSKohei Yoshida         rFilter = "csv";
7320552a09bSKohei Yoshida         return true;
7330552a09bSKohei Yoshida     }
734a6639312SKohei Yoshida 
735a6639312SKohei Yoshida     return false;
736a6639312SKohei Yoshida }
737a6639312SKohei Yoshida 
738a6639312SKohei Yoshida }
7391c9e7d47SXisco Fauli 
impl_detectTypeAndFilter()74077f6149cSKurt Zenker void LoadEnv::impl_detectTypeAndFilter()
74177f6149cSKurt Zenker {
74238187ec1SNoel Grandin     static const sal_Int32 FILTERFLAG_TEMPLATEPATH  = 16;
7430c917a22SKurt Zenker 
74477f6149cSKurt Zenker     // SAFE ->
74585f7ed1cSStephan Bergmann     osl::ClearableMutexGuard aReadLock(m_mutex);
746ffa0c246SRüdiger Timm 
747fbc038ccSCaolán McNamara     // Attention: Because our stl media descriptor is a copy of a uno sequence
748a1bc5756SJesús Corrius     // we can't use as an in/out parameter here. Copy it before and don't forget to
7493b2321d5SFrank Schoenheit [fs]     // update structure afterwards again!
7500c917a22SKurt Zenker     css::uno::Sequence< css::beans::PropertyValue >        lDescriptor = m_lMediaDescriptor.getAsConstPropertyValueList();
751fe1ac1bfSNoel Grandin     css::uno::Reference< css::uno::XComponentContext >     xContext = m_xContext;
752ffa0c246SRüdiger Timm 
75385f7ed1cSStephan Bergmann     aReadLock.clear();
754ffa0c246SRüdiger Timm     // <- SAFE
75577f6149cSKurt Zenker 
7561946794aSLuboš Luňák     OUString sType, sFilter;
757a6639312SKohei Yoshida 
758a6639312SKohei Yoshida     if (queryOrcusTypeAndFilter(lDescriptor, sType, sFilter) && !sType.isEmpty() && !sFilter.isEmpty())
759a6639312SKohei Yoshida     {
760e662e835SMike Kaganski         // SAFE ->
761e662e835SMike Kaganski         osl::MutexGuard aWriteLock(m_mutex);
762e662e835SMike Kaganski 
763a6639312SKohei Yoshida         // Orcus type detected.  Skip the normal type detection process.
764a6639312SKohei Yoshida         m_lMediaDescriptor << lDescriptor;
7652ab40e9eSNoel Grandin         m_lMediaDescriptor[utl::MediaDescriptor::PROP_TYPENAME] <<= sType;
7662ab40e9eSNoel Grandin         m_lMediaDescriptor[utl::MediaDescriptor::PROP_FILTERNAME] <<= sFilter;
7674f5f24a4SNoel Grandin         m_lMediaDescriptor[utl::MediaDescriptor::PROP_FILTERPROVIDER] <<= u"orcus"_ustr;
7684f5f24a4SNoel Grandin         m_lMediaDescriptor[utl::MediaDescriptor::PROP_DOCUMENTSERVICE] <<= u"com.sun.star.sheet.SpreadsheetDocument"_ustr;
769a6639312SKohei Yoshida         return;
770e662e835SMike Kaganski         // <- SAFE
771a6639312SKohei Yoshida     }
772a6639312SKohei Yoshida 
7732d2337ebSStephan Bergmann     css::uno::Reference< css::document::XTypeDetection > xDetect(
7742d2337ebSStephan Bergmann         xContext->getServiceManager()->createInstanceWithContext(
7754f5f24a4SNoel Grandin             u"com.sun.star.document.TypeDetection"_ustr, xContext),
7762d2337ebSStephan Bergmann         css::uno::UNO_QUERY_THROW);
777ed467869SStephan Bergmann     sType = xDetect->queryTypeByDescriptor(lDescriptor, true); /*TODO should deep detection be able for enable/disable it from outside? */
77877f6149cSKurt Zenker 
779ffa0c246SRüdiger Timm     // no valid content -> loading not possible
78018692cc1SOlivier Hallot     if (sType.isEmpty())
7812d2337ebSStephan Bergmann         throw LoadEnvException(
7824f5f24a4SNoel Grandin             LoadEnvException::ID_UNSUPPORTED_CONTENT, u"type detection failed"_ustr);
78377f6149cSKurt Zenker 
784ffa0c246SRüdiger Timm     // SAFE ->
78585f7ed1cSStephan Bergmann     osl::ResettableMutexGuard aWriteLock(m_mutex);
7860c917a22SKurt Zenker 
7873fce6ae2SNoel Grandin     // detection was successful => update the descriptor member of this class
788ffa0c246SRüdiger Timm     m_lMediaDescriptor << lDescriptor;
7892ab40e9eSNoel Grandin     m_lMediaDescriptor[utl::MediaDescriptor::PROP_TYPENAME] <<= sType;
7900c917a22SKurt Zenker     // Is there an already detected (may be preselected) filter?
7910c917a22SKurt Zenker     // see below ...
7922ab40e9eSNoel Grandin     sFilter = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_FILTERNAME, OUString());
7930c917a22SKurt Zenker 
79485f7ed1cSStephan Bergmann     aWriteLock.clear();
79577f6149cSKurt Zenker     // <- SAFE
7960c917a22SKurt Zenker 
797579c2de3SMaxim Monastirsky     // We do have potentially correct type, but the detection process was aborted.
7982ab40e9eSNoel Grandin     if (m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_ABORTED, false))
799579c2de3SMaxim Monastirsky         throw LoadEnvException(
8004f5f24a4SNoel Grandin             LoadEnvException::ID_UNSUPPORTED_CONTENT, u"type detection aborted"_ustr);
801579c2de3SMaxim Monastirsky 
802a1bc5756SJesús Corrius     // But the type isn't enough. For loading sometimes we need more information.
803a1bc5756SJesús Corrius     // E.g. for our "_default" feature, where we recycle any frame which contains
8040c917a22SKurt Zenker     // and "Untitled" document, we must know if the new document is based on a template!
8050c917a22SKurt Zenker     // But this information is available as a filter property only.
8060c917a22SKurt Zenker     // => We must try(!) to detect the right filter for this load request.
8070c917a22SKurt Zenker     // On the other side ... if no filter is available .. ignore it.
8080c917a22SKurt Zenker     // Then the type information must be enough.
80918692cc1SOlivier Hallot     if (sFilter.isEmpty())
8100c917a22SKurt Zenker     {
8110c917a22SKurt Zenker         // no -> try to find a preferred filter for the detected type.
812a1bc5756SJesús Corrius         // Don't forget to update the media descriptor.
8130c917a22SKurt Zenker         css::uno::Reference< css::container::XNameAccess > xTypeCont(xDetect, css::uno::UNO_QUERY_THROW);
8140c917a22SKurt Zenker         try
8150c917a22SKurt Zenker         {
8160c917a22SKurt Zenker             ::comphelper::SequenceAsHashMap lTypeProps(xTypeCont->getByName(sType));
8174f5f24a4SNoel Grandin             sFilter = lTypeProps.getUnpackedValueOrDefault(u"PreferredFilter"_ustr, OUString());
81818692cc1SOlivier Hallot             if (!sFilter.isEmpty())
8190c917a22SKurt Zenker             {
8200c917a22SKurt Zenker                 // SAFE ->
82185f7ed1cSStephan Bergmann                 aWriteLock.reset();
8222ab40e9eSNoel Grandin                 m_lMediaDescriptor[utl::MediaDescriptor::PROP_FILTERNAME] <<= sFilter;
82385f7ed1cSStephan Bergmann                 aWriteLock.clear();
8240c917a22SKurt Zenker                 // <- SAFE
8250c917a22SKurt Zenker             }
8260c917a22SKurt Zenker         }
8270c917a22SKurt Zenker         catch(const css::container::NoSuchElementException&)
8280c917a22SKurt Zenker             {}
8290c917a22SKurt Zenker     }
830f6275a04SOliver Bolte 
8310c917a22SKurt Zenker     // check if the filter (if one exists) points to a template format filter.
832f6275a04SOliver Bolte     // Then we have to add the property "AsTemplate".
833f6275a04SOliver Bolte     // We need this information to decide afterwards if we can use a "recycle frame"
834a1bc5756SJesús Corrius     // for target "_default" or has to create a new one every time.
835a1bc5756SJesús Corrius     // On the other side we have to suppress that, if this property already exists
836a1bc5756SJesús Corrius     // and should trigger a special handling. Then the outside call of this method here,
837f6275a04SOliver Bolte     // has to know, what he is doing .-)
838f6275a04SOliver Bolte 
839a6287e21SNoel Grandin     bool bIsOwnTemplate = false;
84018692cc1SOlivier Hallot     if (!sFilter.isEmpty())
8410c917a22SKurt Zenker     {
842fe1ac1bfSNoel Grandin         css::uno::Reference< css::container::XNameAccess > xFilterCont(xContext->getServiceManager()->createInstanceWithContext(SERVICENAME_FILTERFACTORY, xContext), css::uno::UNO_QUERY_THROW);
8430c917a22SKurt Zenker         try
8440c917a22SKurt Zenker         {
8450c917a22SKurt Zenker             ::comphelper::SequenceAsHashMap lFilterProps(xFilterCont->getByName(sFilter));
8464f5f24a4SNoel Grandin             sal_Int32 nFlags         = lFilterProps.getUnpackedValueOrDefault(u"Flags"_ustr, sal_Int32(0));
8470c917a22SKurt Zenker             bIsOwnTemplate = ((nFlags & FILTERFLAG_TEMPLATEPATH) == FILTERFLAG_TEMPLATEPATH);
8480c917a22SKurt Zenker         }
8490c917a22SKurt Zenker         catch(const css::container::NoSuchElementException&)
8500c917a22SKurt Zenker             {}
8510c917a22SKurt Zenker     }
8520c917a22SKurt Zenker     if (bIsOwnTemplate)
8530c917a22SKurt Zenker     {
8540c917a22SKurt Zenker         // SAFE ->
85585f7ed1cSStephan Bergmann         aWriteLock.reset();
856a1bc5756SJesús Corrius         // Don't overwrite external decisions! See comments before ...
8572ab40e9eSNoel Grandin         utl::MediaDescriptor::const_iterator pAsTemplateItem = m_lMediaDescriptor.find(utl::MediaDescriptor::PROP_ASTEMPLATE);
8585ba4567aSOliver Bolte         if (pAsTemplateItem == m_lMediaDescriptor.end())
8592ab40e9eSNoel Grandin             m_lMediaDescriptor[utl::MediaDescriptor::PROP_ASTEMPLATE] <<= true;
86085f7ed1cSStephan Bergmann         aWriteLock.clear();
8610c917a22SKurt Zenker         // <- SAFE
8620c917a22SKurt Zenker     }
86377f6149cSKurt Zenker }
86477f6149cSKurt Zenker 
impl_handleContent()865a6287e21SNoel Grandin bool LoadEnv::impl_handleContent()
86677f6149cSKurt Zenker {
86777f6149cSKurt Zenker     // SAFE -> -----------------------------------
86885f7ed1cSStephan Bergmann     osl::ClearableMutexGuard aReadLock(m_mutex);
86977f6149cSKurt Zenker 
870e2f97dccSIvan Timofeev     // the type must exist inside the descriptor ... otherwise this class is implemented wrong :-)
8712ab40e9eSNoel Grandin     OUString sType = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_TYPENAME, OUString());
87218692cc1SOlivier Hallot     if (sType.isEmpty())
87377f6149cSKurt Zenker         throw LoadEnvException(LoadEnvException::ID_INVALID_MEDIADESCRIPTOR);
87477f6149cSKurt Zenker 
87577f6149cSKurt Zenker     // convert media descriptor and URL to right format for later interface call!
87677f6149cSKurt Zenker     css::uno::Sequence< css::beans::PropertyValue > lDescriptor;
87777f6149cSKurt Zenker     m_lMediaDescriptor >> lDescriptor;
87877f6149cSKurt Zenker     css::util::URL aURL = m_aURL;
87977f6149cSKurt Zenker 
880f5ca04caSThomas Arnhold     // get necessary container to query for a handler object
881d7fa9ca7SNoel Grandin     css::uno::Reference< css::frame::XLoaderFactory > xLoaderFactory = css::frame::ContentHandlerFactory::create(m_xContext);
88277f6149cSKurt Zenker 
88385f7ed1cSStephan Bergmann     aReadLock.clear();
88477f6149cSKurt Zenker     // <- SAFE -----------------------------------
88577f6149cSKurt Zenker 
88677f6149cSKurt Zenker     // query
8878e234c5bSNoel Grandin     css::uno::Sequence< OUString > lTypeReg { sType };
88877f6149cSKurt Zenker 
8896b6df07dSStephan Bergmann     css::uno::Sequence< css::beans::NamedValue > lQuery { { PROP_TYPES, css::uno::Any(lTypeReg) } };
890ae921976SCaolán McNamara 
891d7fa9ca7SNoel Grandin     css::uno::Reference< css::container::XEnumeration > xSet = xLoaderFactory->createSubSetEnumerationByProperties(lQuery);
89277f6149cSKurt Zenker     while(xSet->hasMoreElements())
89377f6149cSKurt Zenker     {
89477f6149cSKurt Zenker         ::comphelper::SequenceAsHashMap lProps   (xSet->nextElement());
89569ef5d40SStephan Bergmann         OUString                 sHandler = lProps.getUnpackedValueOrDefault(PROP_NAME, OUString());
89677f6149cSKurt Zenker 
89777f6149cSKurt Zenker         css::uno::Reference< css::frame::XNotifyingDispatch > xHandler;
89877f6149cSKurt Zenker         try
89977f6149cSKurt Zenker         {
9005797d29eSNoel Grandin             xHandler.set(xLoaderFactory->createInstance(sHandler), css::uno::UNO_QUERY);
90177f6149cSKurt Zenker             if (!xHandler.is())
90277f6149cSKurt Zenker                 continue;
90377f6149cSKurt Zenker         }
90477f6149cSKurt Zenker         catch(const css::uno::RuntimeException&)
90577f6149cSKurt Zenker             { throw; }
90677f6149cSKurt Zenker         catch(const css::uno::Exception&)
90777f6149cSKurt Zenker             { continue; }
90877f6149cSKurt Zenker 
90977f6149cSKurt Zenker         // SAFE -> -----------------------------------
91085f7ed1cSStephan Bergmann         osl::ClearableMutexGuard aWriteLock(m_mutex);
91177f6149cSKurt Zenker         m_xAsynchronousJob = xHandler;
912897970cdSNoel         rtl::Reference<LoadEnvListener> xListener = new LoadEnvListener(this);
91385f7ed1cSStephan Bergmann         aWriteLock.clear();
91477f6149cSKurt Zenker         // <- SAFE -----------------------------------
91577f6149cSKurt Zenker 
91677f6149cSKurt Zenker         xHandler->dispatchWithNotification(aURL, lDescriptor, xListener);
91777f6149cSKurt Zenker 
918a6287e21SNoel Grandin         return true;
91977f6149cSKurt Zenker     }
92077f6149cSKurt Zenker 
921a6287e21SNoel Grandin     return false;
92277f6149cSKurt Zenker }
92377f6149cSKurt Zenker 
impl_furtherDocsAllowed()924a6287e21SNoel Grandin bool LoadEnv::impl_furtherDocsAllowed()
9257c80942cSRüdiger Timm {
9267c80942cSRüdiger Timm     // SAFE ->
92785f7ed1cSStephan Bergmann     osl::ResettableMutexGuard aReadLock(m_mutex);
928fe1ac1bfSNoel Grandin     css::uno::Reference< css::uno::XComponentContext > xContext = m_xContext;
92985f7ed1cSStephan Bergmann     aReadLock.clear();
9307c80942cSRüdiger Timm     // <- SAFE
9317c80942cSRüdiger Timm 
932a6287e21SNoel Grandin     bool bAllowed = true;
9337c80942cSRüdiger Timm 
9347c80942cSRüdiger Timm     try
9357c80942cSRüdiger Timm     {
9364256c764SLuboš Luňák         std::optional<sal_Int32> x(officecfg::Office::Common::Misc::MaxOpenDocuments::get());
9377c80942cSRüdiger Timm 
9387c80942cSRüdiger Timm         // NIL means: count of allowed documents = infinite !
939f3e0595fSJulien Nabet         //     => return true
940f3e0595fSJulien Nabet         if ( !x)
941a6287e21SNoel Grandin             bAllowed = true;
9427c80942cSRüdiger Timm         else
9437c80942cSRüdiger Timm         {
944f3e0595fSJulien Nabet             sal_Int32 nMaxOpenDocuments(*x);
9457c80942cSRüdiger Timm 
9467c80942cSRüdiger Timm             css::uno::Reference< css::frame::XFramesSupplier > xDesktop(
947fe1ac1bfSNoel Grandin                 css::frame::Desktop::create(xContext),
9487c80942cSRüdiger Timm                 css::uno::UNO_QUERY_THROW);
9497c80942cSRüdiger Timm 
9507c80942cSRüdiger Timm             FrameListAnalyzer aAnalyzer(xDesktop,
9517c80942cSRüdiger Timm                                         css::uno::Reference< css::frame::XFrame >(),
952d76d1555SNoel Grandin                                         FrameAnalyzerFlags::Help |
953d76d1555SNoel Grandin                                         FrameAnalyzerFlags::BackingComponent |
954d76d1555SNoel Grandin                                         FrameAnalyzerFlags::Hidden);
9557c80942cSRüdiger Timm 
9563f7f4971SNoel Grandin             sal_Int32 nOpenDocuments = aAnalyzer.m_lOtherVisibleFrames.size();
9577c80942cSRüdiger Timm             bAllowed       = (nOpenDocuments < nMaxOpenDocuments);
9587c80942cSRüdiger Timm         }
9597c80942cSRüdiger Timm     }
9607c80942cSRüdiger Timm     catch(const css::uno::Exception&)
961a6287e21SNoel Grandin         { bAllowed = true; } // !! internal errors are no reason to disturb the office from opening documents .-)
9627c80942cSRüdiger Timm 
9637c80942cSRüdiger Timm     if ( ! bAllowed )
9647c80942cSRüdiger Timm     {
9657c80942cSRüdiger Timm         // SAFE ->
96685f7ed1cSStephan Bergmann         aReadLock.reset();
9677c80942cSRüdiger Timm         css::uno::Reference< css::task::XInteractionHandler > xInteraction = m_lMediaDescriptor.getUnpackedValueOrDefault(
9682ab40e9eSNoel Grandin                                                                                 utl::MediaDescriptor::PROP_INTERACTIONHANDLER,
9697c80942cSRüdiger Timm                                                                                 css::uno::Reference< css::task::XInteractionHandler >());
97085f7ed1cSStephan Bergmann         aReadLock.clear();
9717c80942cSRüdiger Timm         // <- SAFE
9727c80942cSRüdiger Timm 
9737c80942cSRüdiger Timm         if (xInteraction.is())
9747c80942cSRüdiger Timm         {
9757c80942cSRüdiger Timm             css::uno::Any                                                                    aInteraction;
9767c80942cSRüdiger Timm 
977897970cdSNoel             rtl::Reference<comphelper::OInteractionAbort>   pAbort   = new comphelper::OInteractionAbort();
978897970cdSNoel             rtl::Reference<comphelper::OInteractionApprove> pApprove = new comphelper::OInteractionApprove();
9797c80942cSRüdiger Timm 
980f662ba95SMike Kaganski             css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > lContinuations{
981f662ba95SMike Kaganski                 pAbort, pApprove
982f662ba95SMike Kaganski             };
9837c80942cSRüdiger Timm 
9847c80942cSRüdiger Timm             css::task::ErrorCodeRequest aErrorCode;
98552863266SNoel Grandin             aErrorCode.ErrCode = sal_uInt32(ERRCODE_SFX_NOMOREDOCUMENTSALLOWED);
9867c80942cSRüdiger Timm             aInteraction <<= aErrorCode;
987661e2cc1SMathias Bauer             xInteraction->handle( InteractionRequest::CreateRequest(aInteraction, lContinuations) );
9887c80942cSRüdiger Timm         }
9897c80942cSRüdiger Timm     }
9907c80942cSRüdiger Timm 
9917c80942cSRüdiger Timm     return bAllowed;
9927c80942cSRüdiger Timm }
9937c80942cSRüdiger Timm 
impl_filterHasInteractiveDialog() const994754f6e2fSCaolán McNamara bool LoadEnv::impl_filterHasInteractiveDialog() const
995754f6e2fSCaolán McNamara {
996754f6e2fSCaolán McNamara     //show the frame now so it can be the parent for any message dialogs shown during import
997754f6e2fSCaolán McNamara 
998754f6e2fSCaolán McNamara     //unless (tdf#114648) an Interactive case such as the new database wizard
999754f6e2fSCaolán McNamara     if (m_aURL.Arguments == "Interactive")
1000754f6e2fSCaolán McNamara        return true;
1001754f6e2fSCaolán McNamara 
10020040076aSAndrea Gelmini     // unless (tdf#116277) it's the labels/business cards slave frame
1003754f6e2fSCaolán McNamara     if (m_aURL.Arguments.indexOf("slot=") != -1)
1004754f6e2fSCaolán McNamara         return true;
1005754f6e2fSCaolán McNamara 
10062ab40e9eSNoel Grandin     OUString sFilter = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_FILTERNAME, OUString());
1007754f6e2fSCaolán McNamara     if (sFilter.isEmpty())
1008754f6e2fSCaolán McNamara         return false;
1009754f6e2fSCaolán McNamara 
1010754f6e2fSCaolán McNamara     // unless (tdf#115683) the filter has a UIComponent
1011754f6e2fSCaolán McNamara     OUString sUIComponent;
1012754f6e2fSCaolán McNamara     css::uno::Reference<css::container::XNameAccess> xFilterCont(m_xContext->getServiceManager()->createInstanceWithContext(SERVICENAME_FILTERFACTORY, m_xContext),
1013754f6e2fSCaolán McNamara                                                                  css::uno::UNO_QUERY_THROW);
1014754f6e2fSCaolán McNamara     try
1015754f6e2fSCaolán McNamara     {
1016754f6e2fSCaolán McNamara         ::comphelper::SequenceAsHashMap lFilterProps(xFilterCont->getByName(sFilter));
10174f5f24a4SNoel Grandin         sUIComponent = lFilterProps.getUnpackedValueOrDefault(u"UIComponent"_ustr, OUString());
1018754f6e2fSCaolán McNamara     }
1019754f6e2fSCaolán McNamara     catch(const css::container::NoSuchElementException&)
1020754f6e2fSCaolán McNamara     {
1021754f6e2fSCaolán McNamara     }
1022754f6e2fSCaolán McNamara 
1023754f6e2fSCaolán McNamara     return !sUIComponent.isEmpty();
1024754f6e2fSCaolán McNamara }
1025754f6e2fSCaolán McNamara 
impl_loadContent()1026a6287e21SNoel Grandin bool LoadEnv::impl_loadContent()
102777f6149cSKurt Zenker {
102877f6149cSKurt Zenker     // SAFE -> -----------------------------------
102985f7ed1cSStephan Bergmann     osl::ClearableMutexGuard aWriteLock(m_mutex);
103077f6149cSKurt Zenker 
103177f6149cSKurt Zenker     // search or create right target frame
10321946794aSLuboš Luňák     OUString sTarget = m_sTarget;
1033bac9a5d6SNoel Grandin     if (TargetHelper::matchSpecialTarget(sTarget, TargetHelper::ESpecialTarget::Default))
103477f6149cSKurt Zenker     {
103577f6149cSKurt Zenker         m_xTargetFrame = impl_searchAlreadyLoaded();
10363a54f45cSSander Vesik         if (m_xTargetFrame.is())
10373a54f45cSSander Vesik         {
1038a6287e21SNoel Grandin             impl_setResult(true);
1039a6287e21SNoel Grandin             return true;
10403a54f45cSSander Vesik         }
104177f6149cSKurt Zenker         m_xTargetFrame = impl_searchRecycleTarget();
10427c80942cSRüdiger Timm     }
10437c80942cSRüdiger Timm 
104477f6149cSKurt Zenker     if (! m_xTargetFrame.is())
104577f6149cSKurt Zenker     {
10467c80942cSRüdiger Timm         if (
1047bac9a5d6SNoel Grandin             (TargetHelper::matchSpecialTarget(sTarget, TargetHelper::ESpecialTarget::Blank  )) ||
1048bac9a5d6SNoel Grandin             (TargetHelper::matchSpecialTarget(sTarget, TargetHelper::ESpecialTarget::Default))
10497c80942cSRüdiger Timm            )
10507c80942cSRüdiger Timm         {
10517c80942cSRüdiger Timm             if (! impl_furtherDocsAllowed())
1052a6287e21SNoel Grandin                 return false;
10534a0f506fSMiklos Vajna             TaskCreator aCreator(m_xContext);
10544a0f506fSMiklos Vajna             m_xTargetFrame = aCreator.createTask(SPECIALTARGET_BLANK, m_lMediaDescriptor);
10557c80942cSRüdiger Timm             m_bCloseFrameOnError = m_xTargetFrame.is();
10567c80942cSRüdiger Timm         }
10577c80942cSRüdiger Timm         else
10587c80942cSRüdiger Timm         {
1059c5e1c410SSamuel Mehrbrodt             sal_Int32 nSearchFlags = m_nSearchFlags & ~css::frame::FrameSearchFlag::CREATE;
1060c5e1c410SSamuel Mehrbrodt             m_xTargetFrame   = m_xBaseFrame->findFrame(sTarget, nSearchFlags);
10617c80942cSRüdiger Timm             if (! m_xTargetFrame.is())
10627c80942cSRüdiger Timm             {
10637c80942cSRüdiger Timm                 if (! impl_furtherDocsAllowed())
1064a6287e21SNoel Grandin                     return false;
10657c80942cSRüdiger Timm                 m_xTargetFrame       = m_xBaseFrame->findFrame(SPECIALTARGET_BLANK, 0);
106677f6149cSKurt Zenker                 m_bCloseFrameOnError = m_xTargetFrame.is();
106777f6149cSKurt Zenker             }
106877f6149cSKurt Zenker         }
10697c80942cSRüdiger Timm     }
107077f6149cSKurt Zenker 
1071b6ca1e97SRüdiger Timm     // If we couldn't find a valid frame or the frame has no container window
1072b6ca1e97SRüdiger Timm     // we have to throw an exception.
1073ce32bfbfSRüdiger Timm     if (
1074ce32bfbfSRüdiger Timm         ( ! m_xTargetFrame.is()                       ) ||
1075ce32bfbfSRüdiger Timm         ( ! m_xTargetFrame->getContainerWindow().is() )
1076ce32bfbfSRüdiger Timm        )
107777f6149cSKurt Zenker         throw LoadEnvException(LoadEnvException::ID_NO_TARGET_FOUND);
107877f6149cSKurt Zenker 
1079ce32bfbfSRüdiger Timm     css::uno::Reference< css::frame::XFrame > xTargetFrame = m_xTargetFrame;
108077f6149cSKurt Zenker 
10814543350eSVladimir Glazounov     // Now we have a valid frame ... and type detection was already done.
1082a1bc5756SJesús Corrius     // We should apply the module dependent window position and size to the
10834543350eSVladimir Glazounov     // frame window.
10844543350eSVladimir Glazounov     impl_applyPersistentWindowState(xTargetFrame->getContainerWindow());
10854543350eSVladimir Glazounov 
108677f6149cSKurt Zenker     // Don't forget to lock task for following load process. Otherwise it could die
108777f6149cSKurt Zenker     // during this operation runs by terminating the office or closing this task via api.
108877f6149cSKurt Zenker     // If we set this lock "close()" will return false and closing will be broken.
108977f6149cSKurt Zenker     // Attention: Don't forget to reset this lock again after finishing operation.
109077f6149cSKurt Zenker     // Otherwise task AND office couldn't die!!!
109177f6149cSKurt Zenker     // This includes gracefully handling of Exceptions (Runtime!) too ...
1092a1bc5756SJesús Corrius     // That's why we use a specialized guard, which will reset the lock
109377f6149cSKurt Zenker     // if it will be run out of scope.
109477f6149cSKurt Zenker 
109577f6149cSKurt Zenker     // Note further: ignore if this internal guard already contains a resource.
1096acd820fdSKatarina Behrens     // Might impl_searchRecycleTarget() set it before. But in case this impl-method wasn't used
109777f6149cSKurt Zenker     // and the target frame was new created ... this lock here must be set!
109877f6149cSKurt Zenker     css::uno::Reference< css::document::XActionLockable > xTargetLock(xTargetFrame, css::uno::UNO_QUERY);
109977f6149cSKurt Zenker     m_aTargetLock.setResource(xTargetLock);
110077f6149cSKurt Zenker 
11019771ab4bSAndrea Gelmini     // Add status indicator to descriptor. Loader can show a progress then.
110277f6149cSKurt Zenker     // But don't do it, if loading should be hidden or preview is used...!
110377f6149cSKurt Zenker     // So we prevent our code against wrong using. Why?
110447d9af04SAndrea Gelmini     // It could be, that using of this progress could make trouble. e.g. He makes window visible...
110577f6149cSKurt Zenker     // but shouldn't do that. But if no indicator is available... nobody has a chance to do that!
11062ab40e9eSNoel Grandin     bool bHidden    = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_HIDDEN, false);
11072ab40e9eSNoel Grandin     bool bMinimized = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_MINIMIZED, false);
11082ab40e9eSNoel Grandin     bool bPreview   = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_PREVIEW, false);
1109d239ac79STibor Nagy     bool bStartPres = m_lMediaDescriptor.contains("StartPresentation");
1110c46f0c9fSCaolán McNamara 
1111d239ac79STibor Nagy     if (!bHidden && !bMinimized && !bPreview && !bStartPres)
11126f316707SCaolán McNamara     {
111361e1e041SJan-Marek Glogowski         css::uno::Reference<css::task::XStatusIndicator> xProgress = m_lMediaDescriptor.getUnpackedValueOrDefault(
11142ab40e9eSNoel Grandin             utl::MediaDescriptor::PROP_STATUSINDICATOR, css::uno::Reference<css::task::XStatusIndicator>());
11156f316707SCaolán McNamara         if (!xProgress.is())
111677f6149cSKurt Zenker         {
1117c7114b66SAndrea Gelmini             // Note: it's an optional interface!
111877f6149cSKurt Zenker             css::uno::Reference< css::task::XStatusIndicatorFactory > xProgressFactory(xTargetFrame, css::uno::UNO_QUERY);
111977f6149cSKurt Zenker             if (xProgressFactory.is())
112077f6149cSKurt Zenker             {
112177f6149cSKurt Zenker                 xProgress = xProgressFactory->createStatusIndicator();
112277f6149cSKurt Zenker                 if (xProgress.is())
11232ab40e9eSNoel Grandin                     m_lMediaDescriptor[utl::MediaDescriptor::PROP_STATUSINDICATOR] <<= xProgress;
112477f6149cSKurt Zenker             }
112577f6149cSKurt Zenker         }
112677f6149cSKurt Zenker 
11276f316707SCaolán McNamara         // Now that we have a target window into which we can load, reinit the interaction handler to have this
11286f316707SCaolán McNamara         // window as its parent for modal dialogs and ensure the window is visible
11296f316707SCaolán McNamara         css::uno::Reference< css::task::XInteractionHandler > xInteraction = m_lMediaDescriptor.getUnpackedValueOrDefault(
11302ab40e9eSNoel Grandin                                                                                 utl::MediaDescriptor::PROP_INTERACTIONHANDLER,
11316f316707SCaolán McNamara                                                                                 css::uno::Reference< css::task::XInteractionHandler >());
11326f316707SCaolán McNamara         css::uno::Reference<css::lang::XInitialization> xHandler(xInteraction, css::uno::UNO_QUERY);
11336f316707SCaolán McNamara         if (xHandler.is())
11346f316707SCaolán McNamara         {
11356f316707SCaolán McNamara             css::uno::Reference<css::awt::XWindow> xWindow = xTargetFrame->getContainerWindow();
11366f316707SCaolán McNamara             uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
11376f316707SCaolán McNamara             {
11386f316707SCaolán McNamara                 {"Parent", uno::Any(xWindow)}
11396f316707SCaolán McNamara             }));
11406f316707SCaolán McNamara             xHandler->initialize(aArguments);
1141754f6e2fSCaolán McNamara             //show the frame as early as possible to make it the parent of any message dialogs
1142754f6e2fSCaolán McNamara             if (!impl_filterHasInteractiveDialog())
114342d197efSMike Kaganski             {
114442d197efSMike Kaganski                 impl_makeFrameWindowVisible(xWindow, shouldFocusAndToFront());
114542d197efSMike Kaganski                 m_bFocusedAndToFront = true; // no need to ask shouldFocusAndToFront second time
114642d197efSMike Kaganski             }
11476f316707SCaolán McNamara         }
11486f316707SCaolán McNamara     }
11496f316707SCaolán McNamara 
115077f6149cSKurt Zenker     // convert media descriptor and URL to right format for later interface call!
115177f6149cSKurt Zenker     css::uno::Sequence< css::beans::PropertyValue > lDescriptor;
115277f6149cSKurt Zenker     m_lMediaDescriptor >> lDescriptor;
11531946794aSLuboš Luňák     OUString sURL = m_aURL.Complete;
115477f6149cSKurt Zenker 
115577f6149cSKurt Zenker     // try to locate any interested frame loader
1156bd32f48aSKurt Zenker     css::uno::Reference< css::uno::XInterface >                xLoader     = impl_searchLoader();
115777f6149cSKurt Zenker     css::uno::Reference< css::frame::XFrameLoader >            xAsyncLoader(xLoader, css::uno::UNO_QUERY);
115877f6149cSKurt Zenker     css::uno::Reference< css::frame::XSynchronousFrameLoader > xSyncLoader (xLoader, css::uno::UNO_QUERY);
115977f6149cSKurt Zenker 
116077f6149cSKurt Zenker     if (xAsyncLoader.is())
116177f6149cSKurt Zenker     {
116277f6149cSKurt Zenker         m_xAsynchronousJob = xAsyncLoader;
1163897970cdSNoel         rtl::Reference<LoadEnvListener> xListener = new LoadEnvListener(this);
116485f7ed1cSStephan Bergmann         aWriteLock.clear();
116577f6149cSKurt Zenker         // <- SAFE -----------------------------------
116677f6149cSKurt Zenker 
116777f6149cSKurt Zenker         xAsyncLoader->load(xTargetFrame, sURL, lDescriptor, xListener);
116877f6149cSKurt Zenker 
1169a6287e21SNoel Grandin         return true;
117077f6149cSKurt Zenker     }
1171586895f8SCaolán McNamara     else if (xSyncLoader.is())
117277f6149cSKurt Zenker     {
117385467e7cSMiklos Vajna         uno::Reference<beans::XPropertySet> xTargetFrameProps(xTargetFrame, uno::UNO_QUERY);
117485467e7cSMiklos Vajna         if (xTargetFrameProps.is())
117585467e7cSMiklos Vajna         {
117685467e7cSMiklos Vajna             // Set the URL on the frame itself, for the duration of the load, when it has no
117785467e7cSMiklos Vajna             // controller.
11784f5f24a4SNoel Grandin             xTargetFrameProps->setPropertyValue(u"URL"_ustr, uno::Any(sURL));
117985467e7cSMiklos Vajna         }
1180a6287e21SNoel Grandin         bool bResult = xSyncLoader->load(lDescriptor, xTargetFrame);
118177f6149cSKurt Zenker         // react for the result here, so the outside waiting
118277f6149cSKurt Zenker         // code can ask for it later.
118377f6149cSKurt Zenker         impl_setResult(bResult);
118477f6149cSKurt Zenker         // But the return value indicates a valid started(!) operation.
1185a1bc5756SJesús Corrius         // And that's true every time we reach this line :-)
1186a6287e21SNoel Grandin         return true;
118777f6149cSKurt Zenker     }
118877f6149cSKurt Zenker 
118985f7ed1cSStephan Bergmann     aWriteLock.clear();
119077f6149cSKurt Zenker     // <- SAFE
119177f6149cSKurt Zenker 
1192a6287e21SNoel Grandin     return false;
119377f6149cSKurt Zenker }
119477f6149cSKurt Zenker 
impl_searchLoader()1195bd32f48aSKurt Zenker css::uno::Reference< css::uno::XInterface > LoadEnv::impl_searchLoader()
1196bd32f48aSKurt Zenker {
1197bd32f48aSKurt Zenker     // SAFE -> -----------------------------------
119885f7ed1cSStephan Bergmann     osl::ClearableMutexGuard aReadLock(m_mutex);
1199bd32f48aSKurt Zenker 
1200bd32f48aSKurt Zenker     // special mode to set an existing component on this frame
1201a1bc5756SJesús Corrius     // In such case the loader is fix. It must be the SFX based implementation,
1202bd32f48aSKurt Zenker     // which can create a view on top of such xModel components :-)
1203bd32f48aSKurt Zenker     if (m_eContentType == E_CAN_BE_SET)
1204bd32f48aSKurt Zenker     {
1205bd32f48aSKurt Zenker         try
1206bd32f48aSKurt Zenker         {
120730dd9b2fSNoel Grandin             return css::frame::OfficeFrameLoader::create(m_xContext);
1208bd32f48aSKurt Zenker         }
1209bd32f48aSKurt Zenker         catch(const css::uno::RuntimeException&)
1210bd32f48aSKurt Zenker             { throw; }
1211bd32f48aSKurt Zenker         catch(const css::uno::Exception&)
1212bd32f48aSKurt Zenker             {}
1213bd32f48aSKurt Zenker         throw LoadEnvException(LoadEnvException::ID_INVALID_ENVIRONMENT);
1214bd32f48aSKurt Zenker     }
1215bd32f48aSKurt Zenker 
1216a1bc5756SJesús Corrius     // Otherwise...
1217fdf032c3SAndrea Gelmini     // We need this type information to locate a registered frame loader
12189a2d1b9cSLionel Elie Mamane     // Without such information we can't work!
12192ab40e9eSNoel Grandin     OUString sType = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_TYPENAME, OUString());
122018692cc1SOlivier Hallot     if (sType.isEmpty())
1221bd32f48aSKurt Zenker         throw LoadEnvException(LoadEnvException::ID_INVALID_MEDIADESCRIPTOR);
1222bd32f48aSKurt Zenker 
1223bd32f48aSKurt Zenker     // try to locate any interested frame loader
1224d7fa9ca7SNoel Grandin     css::uno::Reference< css::frame::XLoaderFactory > xLoaderFactory = css::frame::FrameLoaderFactory::create(m_xContext);
1225bd32f48aSKurt Zenker 
122685f7ed1cSStephan Bergmann     aReadLock.clear();
1227bd32f48aSKurt Zenker     // <- SAFE -----------------------------------
1228bd32f48aSKurt Zenker 
12298e234c5bSNoel Grandin     css::uno::Sequence< OUString > lTypesReg { sType };
1230bd32f48aSKurt Zenker 
12316b6df07dSStephan Bergmann     css::uno::Sequence< css::beans::NamedValue > lQuery { { PROP_TYPES, css::uno::Any(lTypesReg) } };
1232ae921976SCaolán McNamara 
1233d7fa9ca7SNoel Grandin     css::uno::Reference< css::container::XEnumeration > xSet = xLoaderFactory->createSubSetEnumerationByProperties(lQuery);
1234bd32f48aSKurt Zenker     while(xSet->hasMoreElements())
1235bd32f48aSKurt Zenker     {
123649572624SCaolán McNamara         try
123749572624SCaolán McNamara         {
1238bd32f48aSKurt Zenker             // try everyone ...
1239bd32f48aSKurt Zenker             // Ignore any loader, which makes trouble :-)
1240bd32f48aSKurt Zenker             ::comphelper::SequenceAsHashMap             lLoaderProps(xSet->nextElement());
124169ef5d40SStephan Bergmann             OUString                             sLoader     = lLoaderProps.getUnpackedValueOrDefault(PROP_NAME, OUString());
1242bf9f0b29SNoel Grandin             css::uno::Reference< css::uno::XInterface > xLoader = xLoaderFactory->createInstance(sLoader);
1243bd32f48aSKurt Zenker             if (xLoader.is())
1244bd32f48aSKurt Zenker                 return xLoader;
1245bd32f48aSKurt Zenker         }
1246bd32f48aSKurt Zenker         catch(const css::uno::RuntimeException&)
1247bd32f48aSKurt Zenker             { throw; }
1248bd32f48aSKurt Zenker         catch(const css::uno::Exception&)
1249bd32f48aSKurt Zenker             { continue; }
1250bd32f48aSKurt Zenker     }
1251bd32f48aSKurt Zenker 
1252bd32f48aSKurt Zenker     return css::uno::Reference< css::uno::XInterface >();
1253bd32f48aSKurt Zenker }
1254bd32f48aSKurt Zenker 
impl_jumpToMark(const css::uno::Reference<css::frame::XFrame> & xFrame,const css::util::URL & aURL)1255e1b5a6d0SRüdiger Timm void LoadEnv::impl_jumpToMark(const css::uno::Reference< css::frame::XFrame >& xFrame,
1256e1b5a6d0SRüdiger Timm                               const css::util::URL&                            aURL  )
1257e1b5a6d0SRüdiger Timm {
125818692cc1SOlivier Hallot     if (aURL.Mark.isEmpty())
1259e1b5a6d0SRüdiger Timm         return;
1260e1b5a6d0SRüdiger Timm 
1261e1b5a6d0SRüdiger Timm     css::uno::Reference< css::frame::XDispatchProvider > xProvider(xFrame, css::uno::UNO_QUERY);
1262e1b5a6d0SRüdiger Timm     if (! xProvider.is())
1263e1b5a6d0SRüdiger Timm         return;
1264e1b5a6d0SRüdiger Timm 
1265e1b5a6d0SRüdiger Timm     // SAFE ->
126685f7ed1cSStephan Bergmann     osl::ClearableMutexGuard aReadLock(m_mutex);
1267fe1ac1bfSNoel Grandin     css::uno::Reference< css::uno::XComponentContext > xContext = m_xContext;
126885f7ed1cSStephan Bergmann     aReadLock.clear();
1269e1b5a6d0SRüdiger Timm     // <- SAFE
1270e1b5a6d0SRüdiger Timm 
1271e1b5a6d0SRüdiger Timm     css::util::URL aCmd;
1272e52779d2SNoel Grandin     aCmd.Complete = ".uno:JumpToMark";
1273e1b5a6d0SRüdiger Timm 
1274fe1ac1bfSNoel Grandin     css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(xContext));
1275e1b5a6d0SRüdiger Timm     xParser->parseStrict(aCmd);
1276e1b5a6d0SRüdiger Timm 
1277e1b5a6d0SRüdiger Timm     css::uno::Reference< css::frame::XDispatch > xDispatcher = xProvider->queryDispatch(aCmd, SPECIALTARGET_SELF, 0);
1278e1b5a6d0SRüdiger Timm     if (! xDispatcher.is())
1279e1b5a6d0SRüdiger Timm         return;
1280e1b5a6d0SRüdiger Timm 
1281e1b5a6d0SRüdiger Timm     ::comphelper::SequenceAsHashMap lArgs;
12824f5f24a4SNoel Grandin     lArgs[u"Bookmark"_ustr] <<= aURL.Mark;
1283e1b5a6d0SRüdiger Timm     xDispatcher->dispatch(aCmd, lArgs.getAsConstPropertyValueList());
1284e1b5a6d0SRüdiger Timm }
1285e1b5a6d0SRüdiger Timm 
impl_searchAlreadyLoaded()128677f6149cSKurt Zenker css::uno::Reference< css::frame::XFrame > LoadEnv::impl_searchAlreadyLoaded()
128777f6149cSKurt Zenker {
128885f7ed1cSStephan Bergmann     osl::MutexGuard g(m_mutex);
128977f6149cSKurt Zenker 
129077f6149cSKurt Zenker     // such search is allowed for special requests only ...
1291c7114b66SAndrea Gelmini     // or better it's not allowed for some requests in general :-)
129277f6149cSKurt Zenker     if (
1293bac9a5d6SNoel Grandin         ( ! TargetHelper::matchSpecialTarget(m_sTarget, TargetHelper::ESpecialTarget::Default)                                               ) ||
12942ab40e9eSNoel Grandin         m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_ASTEMPLATE , false) ||
1295ac113013SStephan Bergmann //      (m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_HIDDEN()     , false) == sal_True) ||
12962ab40e9eSNoel Grandin         m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_OPENNEWVIEW, false)
129777f6149cSKurt Zenker        )
129877f6149cSKurt Zenker     {
129977f6149cSKurt Zenker         return css::uno::Reference< css::frame::XFrame >();
130077f6149cSKurt Zenker     }
130177f6149cSKurt Zenker 
130277f6149cSKurt Zenker     // check URL
1303c7114b66SAndrea Gelmini     // May it's not useful to start expensive document search, if it
130477f6149cSKurt Zenker     // can fail only .. because we load from a stream or model directly!
130577f6149cSKurt Zenker     if (
1306bac9a5d6SNoel Grandin         (ProtocolCheck::isProtocol(m_aURL.Complete, EProtocol::PrivateStream )) ||
1307bac9a5d6SNoel Grandin         (ProtocolCheck::isProtocol(m_aURL.Complete, EProtocol::PrivateObject ))
130877f6149cSKurt Zenker         /*TODO should be private:factory here tested too? */
130977f6149cSKurt Zenker        )
131077f6149cSKurt Zenker     {
131177f6149cSKurt Zenker         return css::uno::Reference< css::frame::XFrame >();
131277f6149cSKurt Zenker     }
131377f6149cSKurt Zenker 
1314e2f97dccSIvan Timofeev     // otherwise - iterate through the tasks of the desktop container
131577f6149cSKurt Zenker     // to find out, which of them might contains the requested document
1316fe1ac1bfSNoel Grandin     css::uno::Reference< css::frame::XDesktop2 >  xSupplier = css::frame::Desktop::create( m_xContext );
1317952b806cSNoel Grandin     css::uno::Reference< css::container::XIndexAccess > xTaskList = xSupplier->getFrames();
131877f6149cSKurt Zenker 
131977f6149cSKurt Zenker     if (!xTaskList.is())
132077f6149cSKurt Zenker         return css::uno::Reference< css::frame::XFrame >(); // task list can be empty!
132177f6149cSKurt Zenker 
1322a1bc5756SJesús Corrius     // Note: To detect if a document was already loaded before
13239a2d1b9cSLionel Elie Mamane     // we check URLs here only. But might the existing and the required
132477f6149cSKurt Zenker     // document has different versions! Then its URLs are the same...
13252ab40e9eSNoel Grandin     sal_Int16 nNewVersion = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_VERSION, sal_Int16(-1));
132677f6149cSKurt Zenker 
1327ed2a2ab2SIvo Hinkelmann     // will be used to save the first hidden frame referring the searched model
13289a2d1b9cSLionel Elie Mamane     // Normally we are interested on visible frames... but if there is no such visible
1329a1bc5756SJesús Corrius     // frame we refer to any hidden frame also (but as fallback only).
1330ed2a2ab2SIvo Hinkelmann     css::uno::Reference< css::frame::XFrame > xHiddenTask;
1331ed2a2ab2SIvo Hinkelmann     css::uno::Reference< css::frame::XFrame > xTask;
1332ed2a2ab2SIvo Hinkelmann 
133377f6149cSKurt Zenker     sal_Int32 count = xTaskList->getCount();
133477f6149cSKurt Zenker     for (sal_Int32 i=0; i<count; ++i)
133577f6149cSKurt Zenker     {
133677f6149cSKurt Zenker         try
133777f6149cSKurt Zenker         {
133877f6149cSKurt Zenker             // locate model of task
133977f6149cSKurt Zenker             // Note: Without a model there is no chance to decide if
134077f6149cSKurt Zenker             // this task contains the searched document or not!
134177f6149cSKurt Zenker             xTaskList->getByIndex(i) >>= xTask;
134277f6149cSKurt Zenker             if (!xTask.is())
134377f6149cSKurt Zenker                 continue;
134477f6149cSKurt Zenker 
134585467e7cSMiklos Vajna             OUString sURL;
134677f6149cSKurt Zenker             css::uno::Reference< css::frame::XController > xController = xTask->getController();
134777f6149cSKurt Zenker             if (!xController.is())
1348ed2a2ab2SIvo Hinkelmann             {
134985467e7cSMiklos Vajna                 // If we have no controller, then perhaps there is a load in progress. The frame
135085467e7cSMiklos Vajna                 // itself has the URL in this case.
135185467e7cSMiklos Vajna                 uno::Reference<beans::XPropertySet> xTaskProps(xTask, uno::UNO_QUERY);
135285467e7cSMiklos Vajna                 if (xTaskProps.is())
135385467e7cSMiklos Vajna                 {
13544f5f24a4SNoel Grandin                     xTaskProps->getPropertyValue(u"URL"_ustr) >>= sURL;
135585467e7cSMiklos Vajna                 }
135685467e7cSMiklos Vajna                 if (sURL.isEmpty())
135785467e7cSMiklos Vajna                 {
1358ed2a2ab2SIvo Hinkelmann                     xTask.clear();
135977f6149cSKurt Zenker                     continue;
1360ed2a2ab2SIvo Hinkelmann                 }
136185467e7cSMiklos Vajna             }
136277f6149cSKurt Zenker 
136385467e7cSMiklos Vajna             uno::Reference<frame::XModel> xModel;
136485467e7cSMiklos Vajna             if (sURL.isEmpty())
136585467e7cSMiklos Vajna             {
136685467e7cSMiklos Vajna                 xModel = xController->getModel();
136777f6149cSKurt Zenker                 if (!xModel.is())
1368ed2a2ab2SIvo Hinkelmann                 {
1369ed2a2ab2SIvo Hinkelmann                     xTask.clear();
137077f6149cSKurt Zenker                     continue;
1371ed2a2ab2SIvo Hinkelmann                 }
137277f6149cSKurt Zenker 
137377f6149cSKurt Zenker                 // don't check the complete URL here.
137477f6149cSKurt Zenker                 // use its main part - ignore optional jumpmarks!
137585467e7cSMiklos Vajna                 sURL = xModel->getURL();
137685467e7cSMiklos Vajna             }
137708e2fc04SMikhail Voytenko             if (!::utl::UCBContentHelper::EqualURLs( m_aURL.Main, sURL ))
1378ed2a2ab2SIvo Hinkelmann             {
1379ed2a2ab2SIvo Hinkelmann                 xTask.clear ();
138077f6149cSKurt Zenker                 continue;
1381ed2a2ab2SIvo Hinkelmann             }
138277f6149cSKurt Zenker 
138377f6149cSKurt Zenker             // get the original load arguments from the current document
138442cfb5d0SAndrea Gelmini             // and decide if it's really the same then the one will be.
138577f6149cSKurt Zenker             // It must be visible and must use the same file revision ...
138677f6149cSKurt Zenker             // or must not have any file revision set (-1 == -1!)
138785467e7cSMiklos Vajna             utl::MediaDescriptor lOldDocDescriptor;
138885467e7cSMiklos Vajna             if (xModel.is())
138985467e7cSMiklos Vajna             {
139085467e7cSMiklos Vajna                 lOldDocDescriptor = xModel->getArgs();
139177f6149cSKurt Zenker 
139285467e7cSMiklos Vajna                 if (lOldDocDescriptor.getUnpackedValueOrDefault(
13932ab40e9eSNoel Grandin                         utl::MediaDescriptor::PROP_VERSION, sal_Int32(-1))
139485467e7cSMiklos Vajna                     != nNewVersion)
1395ed2a2ab2SIvo Hinkelmann                 {
1396ed2a2ab2SIvo Hinkelmann                     xTask.clear();
139777f6149cSKurt Zenker                     continue;
1398ed2a2ab2SIvo Hinkelmann                 }
139985467e7cSMiklos Vajna             }
140077f6149cSKurt Zenker 
1401ed2a2ab2SIvo Hinkelmann             // Hidden frames are special.
1402ed2a2ab2SIvo Hinkelmann             // They will be used as "last chance" if there is no visible frame pointing to the same model.
1403ed2a2ab2SIvo Hinkelmann             // Safe the result but continue with current loop might be looking for other visible frames.
14042ab40e9eSNoel Grandin             bool bIsHidden = lOldDocDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_HIDDEN, false);
14054250b25cSNoel Grandin             if ( bIsHidden && ! xHiddenTask.is() )
1406ed2a2ab2SIvo Hinkelmann             {
1407ed2a2ab2SIvo Hinkelmann                 xHiddenTask = xTask;
1408ed2a2ab2SIvo Hinkelmann                 xTask.clear ();
140977f6149cSKurt Zenker                 continue;
1410ed2a2ab2SIvo Hinkelmann             }
141177f6149cSKurt Zenker 
1412ed2a2ab2SIvo Hinkelmann             // We found a visible task pointing to the right model ...
1413ed2a2ab2SIvo Hinkelmann             // Break search.
1414ed2a2ab2SIvo Hinkelmann             break;
1415ed2a2ab2SIvo Hinkelmann         }
1416ba5a460bSPKEuS         catch(const css::uno::RuntimeException&)
1417ba5a460bSPKEuS             { throw; }
1418ed2a2ab2SIvo Hinkelmann         catch(const css::uno::Exception&)
1419ed2a2ab2SIvo Hinkelmann             { continue; }
1420ed2a2ab2SIvo Hinkelmann     }
1421ed2a2ab2SIvo Hinkelmann 
1422ed2a2ab2SIvo Hinkelmann     css::uno::Reference< css::frame::XFrame > xResult;
1423ed2a2ab2SIvo Hinkelmann     if (xTask.is())
1424ee4554b0SCaolán McNamara         xResult = std::move(xTask);
14257d044841SCaolán McNamara     else if (xHiddenTask.is())
1426ee4554b0SCaolán McNamara         xResult = std::move(xHiddenTask);
1427ed2a2ab2SIvo Hinkelmann 
1428ed2a2ab2SIvo Hinkelmann     if (xResult.is())
1429ed2a2ab2SIvo Hinkelmann     {
14309a2d1b9cSLionel Elie Mamane         // Now we are sure, that this task includes the searched document.
14319a2d1b9cSLionel Elie Mamane         // It's time to activate it. As special feature we try to jump internally
143277f6149cSKurt Zenker         // if an optional jumpmark is given too.
143318692cc1SOlivier Hallot         if (!m_aURL.Mark.isEmpty())
1434ed2a2ab2SIvo Hinkelmann             impl_jumpToMark(xResult, m_aURL);
143577f6149cSKurt Zenker     }
143677f6149cSKurt Zenker 
1437ed2a2ab2SIvo Hinkelmann     return xResult;
143877f6149cSKurt Zenker }
143977f6149cSKurt Zenker 
14408ef4dc07SNoel Grandin // static
impl_isFrameAlreadyUsedForLoading(const css::uno::Reference<css::frame::XFrame> & xFrame)14418ef4dc07SNoel Grandin bool LoadEnv::impl_isFrameAlreadyUsedForLoading(const css::uno::Reference< css::frame::XFrame >& xFrame)
14420c917a22SKurt Zenker {
14430c917a22SKurt Zenker     css::uno::Reference< css::document::XActionLockable > xLock(xFrame, css::uno::UNO_QUERY);
14440c917a22SKurt Zenker 
14450c917a22SKurt Zenker     // ? no lock interface ?
1446ad1fb1c3SAndrea Gelmini     // Maybe it's an external written frame implementation :-(
1447c7114b66SAndrea Gelmini     // Allowing using of it... but it can fail if it's not synchronized with our processes!
14480c917a22SKurt Zenker     if (!xLock.is())
1449a6287e21SNoel Grandin         return false;
14500c917a22SKurt Zenker 
14519a2d1b9cSLionel Elie Mamane     // Otherwise we have to look for any other existing lock.
14520c917a22SKurt Zenker     return xLock->isActionLocked();
14530c917a22SKurt Zenker }
14540c917a22SKurt Zenker 
impl_searchRecycleTarget()145577f6149cSKurt Zenker css::uno::Reference< css::frame::XFrame > LoadEnv::impl_searchRecycleTarget()
145677f6149cSKurt Zenker {
145777f6149cSKurt Zenker     // SAFE -> ..................................
145885f7ed1cSStephan Bergmann     osl::ClearableMutexGuard aReadLock(m_mutex);
145977f6149cSKurt Zenker 
1460ffa0c246SRüdiger Timm     // The special backing mode frame will be recycled by definition!
1461a1bc5756SJesús Corrius     // It doesn't matter if somewhere wants to create a new view
1462ffa0c246SRüdiger Timm     // or open a new untitled document...
14639771ab4bSAndrea Gelmini     // The only exception from that - hidden frames!
14642ab40e9eSNoel Grandin     if (m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_HIDDEN, false))
1465ffa0c246SRüdiger Timm         return css::uno::Reference< css::frame::XFrame >();
1466ffa0c246SRüdiger Timm 
1467952b806cSNoel Grandin     css::uno::Reference< css::frame::XFramesSupplier > xSupplier = css::frame::Desktop::create( m_xContext );
1468d76d1555SNoel Grandin     FrameListAnalyzer aTasksAnalyzer(xSupplier, css::uno::Reference< css::frame::XFrame >(), FrameAnalyzerFlags::BackingComponent);
1469ffa0c246SRüdiger Timm     if (aTasksAnalyzer.m_xBackingComponent.is())
14700c917a22SKurt Zenker     {
14710c917a22SKurt Zenker         if (!impl_isFrameAlreadyUsedForLoading(aTasksAnalyzer.m_xBackingComponent))
1472b3e80e19SRüdiger Timm         {
1473cc679439SMaxim Monastirsky             m_bReactivateControllerOnError = true;
1474ffa0c246SRüdiger Timm             return aTasksAnalyzer.m_xBackingComponent;
14750c917a22SKurt Zenker         }
1476b3e80e19SRüdiger Timm     }
1477ffa0c246SRüdiger Timm 
14789a2d1b9cSLionel Elie Mamane     // These states indicates a wish for creation of a new view in general.
147977f6149cSKurt Zenker     if (
14802ab40e9eSNoel Grandin         m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_ASTEMPLATE , false) ||
14812ab40e9eSNoel Grandin         m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_OPENNEWVIEW, false)
148277f6149cSKurt Zenker        )
148377f6149cSKurt Zenker     {
148477f6149cSKurt Zenker         return css::uno::Reference< css::frame::XFrame >();
148577f6149cSKurt Zenker     }
148677f6149cSKurt Zenker 
1487a1bc5756SJesús Corrius     // On the other side some special URLs will open a new frame every time (expecting
14882ae6c2a5SRüdiger Timm     // they can use the backing-mode frame!)
14892ae6c2a5SRüdiger Timm     if (
1490bac9a5d6SNoel Grandin         (ProtocolCheck::isProtocol(m_aURL.Complete, EProtocol::PrivateFactory )) ||
1491bac9a5d6SNoel Grandin         (ProtocolCheck::isProtocol(m_aURL.Complete, EProtocol::PrivateStream  )) ||
1492bac9a5d6SNoel Grandin         (ProtocolCheck::isProtocol(m_aURL.Complete, EProtocol::PrivateObject  ))
14932ae6c2a5SRüdiger Timm        )
14942ae6c2a5SRüdiger Timm     {
14952ae6c2a5SRüdiger Timm         return css::uno::Reference< css::frame::XFrame >();
14962ae6c2a5SRüdiger Timm     }
14972ae6c2a5SRüdiger Timm 
14982ae6c2a5SRüdiger Timm     // No backing frame! No special URL => recycle active task - if possible.
14992ae6c2a5SRüdiger Timm     // Means - if it does not already contains a modified document, or
15002ae6c2a5SRüdiger Timm     // use another office module.
150177f6149cSKurt Zenker     css::uno::Reference< css::frame::XFrame > xTask = xSupplier->getActiveFrame();
150277f6149cSKurt Zenker 
150377f6149cSKurt Zenker     // not a real error - but might a focus problem!
150477f6149cSKurt Zenker     if (!xTask.is())
150577f6149cSKurt Zenker         return css::uno::Reference< css::frame::XFrame >();
150677f6149cSKurt Zenker 
15077f436c1fSAndras Timar     // not a real error - may it's a view only
150877f6149cSKurt Zenker     css::uno::Reference< css::frame::XController > xController = xTask->getController();
150977f6149cSKurt Zenker     if (!xController.is())
151077f6149cSKurt Zenker         return css::uno::Reference< css::frame::XFrame >();
151177f6149cSKurt Zenker 
15127f436c1fSAndras Timar     // not a real error - may it's a db component instead of a full featured office document
151377f6149cSKurt Zenker     css::uno::Reference< css::frame::XModel > xModel = xController->getModel();
151477f6149cSKurt Zenker     if (!xModel.is())
151577f6149cSKurt Zenker         return css::uno::Reference< css::frame::XFrame >();
151677f6149cSKurt Zenker 
1517db7a4413SGregg King     // get some more information ...
151877f6149cSKurt Zenker 
151977f6149cSKurt Zenker     // A valid set URL means: there is already a location for this document.
152077f6149cSKurt Zenker     // => it was saved there or opened from there. Such Documents can not be used here.
152177f6149cSKurt Zenker     // We search for empty document ... created by a private:factory/ URL!
152277f6149cSKurt Zenker     if (xModel->getURL().getLength()>0)
152377f6149cSKurt Zenker         return css::uno::Reference< css::frame::XFrame >();
152477f6149cSKurt Zenker 
152577f6149cSKurt Zenker     // The old document must be unmodified ...
152677f6149cSKurt Zenker     css::uno::Reference< css::util::XModifiable > xModified(xModel, css::uno::UNO_QUERY);
152777f6149cSKurt Zenker     if (xModified->isModified())
152877f6149cSKurt Zenker         return css::uno::Reference< css::frame::XFrame >();
152977f6149cSKurt Zenker 
153078b4a1fbSNoel Grandin     VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xTask->getContainerWindow());
1531ce32bfbfSRüdiger Timm     if (pWindow && pWindow->IsInModalMode())
1532ce32bfbfSRüdiger Timm         return css::uno::Reference< css::frame::XFrame >();
1533ce32bfbfSRüdiger Timm 
153477f6149cSKurt Zenker     // find out the application type of this document
153577f6149cSKurt Zenker     // We can recycle only documents, which uses the same application
153677f6149cSKurt Zenker     // then the new one.
153777f6149cSKurt Zenker     SvtModuleOptions::EFactory eOldApp = SvtModuleOptions::ClassifyFactoryByModel(xModel);
153877f6149cSKurt Zenker     SvtModuleOptions::EFactory eNewApp = SvtModuleOptions::ClassifyFactoryByURL  (m_aURL.Complete, m_lMediaDescriptor.getAsConstPropertyValueList());
153977f6149cSKurt Zenker 
154085f7ed1cSStephan Bergmann     aReadLock.clear();
154177f6149cSKurt Zenker     // <- SAFE ..................................
154277f6149cSKurt Zenker 
154377f6149cSKurt Zenker     if (eOldApp != eNewApp)
154477f6149cSKurt Zenker         return css::uno::Reference< css::frame::XFrame >();
154577f6149cSKurt Zenker 
15466f0e7c36SJulien Nabet     // OK this task seems to be usable for recycling
154777f6149cSKurt Zenker     // But we should mark it as such - means set an action lock.
15489bac4d41STakeshi Abe     // Otherwise it would be used more than ones or will be destroyed
154977f6149cSKurt Zenker     // by a close() or terminate() request.
155077f6149cSKurt Zenker     // But if such lock already exist ... it means this task is used for
155177f6149cSKurt Zenker     // any other operation already. Don't use it then.
15520c917a22SKurt Zenker     if (impl_isFrameAlreadyUsedForLoading(xTask))
155377f6149cSKurt Zenker         return css::uno::Reference< css::frame::XFrame >();
155477f6149cSKurt Zenker 
1555ce32bfbfSRüdiger Timm     // OK - there is a valid target frame.
1556ce32bfbfSRüdiger Timm     // But may be it contains already a document.
1557a1bc5756SJesús Corrius     // Then we have to ask it, if it allows recycling of this frame .-)
1558a6287e21SNoel Grandin     bool bReactivateOldControllerOnError = false;
1559ce32bfbfSRüdiger Timm     css::uno::Reference< css::frame::XController > xOldDoc = xTask->getController();
1560ce32bfbfSRüdiger Timm     if (xOldDoc.is())
1561ce32bfbfSRüdiger Timm     {
1562acd820fdSKatarina Behrens         utl::MediaDescriptor lOldDocDescriptor(xModel->getArgs());
1563acd820fdSKatarina Behrens 
156461e1e041SJan-Marek Glogowski         // replaceable document
15652ab40e9eSNoel Grandin         if (!lOldDocDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_REPLACEABLE, false))
1566acd820fdSKatarina Behrens             return css::uno::Reference< css::frame::XFrame >();
1567acd820fdSKatarina Behrens 
1568ed467869SStephan Bergmann         bReactivateOldControllerOnError = xOldDoc->suspend(true);
1569ce32bfbfSRüdiger Timm         if (! bReactivateOldControllerOnError)
1570ce32bfbfSRüdiger Timm             return css::uno::Reference< css::frame::XFrame >();
1571ce32bfbfSRüdiger Timm     }
1572ce32bfbfSRüdiger Timm 
157377f6149cSKurt Zenker     // SAFE -> ..................................
15745a824268SMike Kaganski     {
15755a824268SMike Kaganski         osl::MutexGuard aWriteLock(m_mutex);
1576ce32bfbfSRüdiger Timm 
15770c917a22SKurt Zenker         css::uno::Reference< css::document::XActionLockable > xLock(xTask, css::uno::UNO_QUERY);
157877f6149cSKurt Zenker         if (!m_aTargetLock.setResource(xLock))
157977f6149cSKurt Zenker             return css::uno::Reference< css::frame::XFrame >();
1580ce32bfbfSRüdiger Timm 
1581ce32bfbfSRüdiger Timm         m_bReactivateControllerOnError = bReactivateOldControllerOnError;
15825a824268SMike Kaganski     }
158377f6149cSKurt Zenker     // <- SAFE ..................................
158477f6149cSKurt Zenker 
158577f6149cSKurt Zenker     return xTask;
158677f6149cSKurt Zenker }
158777f6149cSKurt Zenker 
impl_reactForLoadingState()158877f6149cSKurt Zenker void LoadEnv::impl_reactForLoadingState()
158977f6149cSKurt Zenker {
159077f6149cSKurt Zenker     /*TODO reset action locks */
159177f6149cSKurt Zenker 
159277f6149cSKurt Zenker     // SAFE -> ----------------------------------
159385f7ed1cSStephan Bergmann     osl::ClearableMutexGuard aReadLock(m_mutex);
159477f6149cSKurt Zenker 
159577f6149cSKurt Zenker     if (m_bLoaded)
159677f6149cSKurt Zenker     {
159777f6149cSKurt Zenker         // Bring the new loaded document to front (if allowed!).
159877f6149cSKurt Zenker         // Note: We show new created frames here only.
1599eab0904fSAndrea Gelmini         // We don't hide already visible frames here ...
160077f6149cSKurt Zenker         css::uno::Reference< css::awt::XWindow > xWindow      = m_xTargetFrame->getContainerWindow();
16012ab40e9eSNoel Grandin         bool                                 bHidden      = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_HIDDEN, false);
16022ab40e9eSNoel Grandin         bool                                 bMinimized = m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_MINIMIZED, false);
1603d239ac79STibor Nagy         bool                                 bStartPres = m_lMediaDescriptor.contains("StartPresentation");
1604d239ac79STibor Nagy 
1605e0b930e1SVasily Melenchuk         VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xWindow);
160677f6149cSKurt Zenker 
1607965cc9c2SJens-Heiner Rechtien         if (bMinimized)
1608965cc9c2SJens-Heiner Rechtien         {
16094bd2ed6aSNorbert Thiebaud             SolarMutexGuard aSolarGuard;
1610f5ca04caSThomas Arnhold             // check for system window is necessary to guarantee correct pointer cast!
1611965cc9c2SJens-Heiner Rechtien             if (pWindow && pWindow->IsSystemWindow())
161278b4a1fbSNoel Grandin                 static_cast<WorkWindow*>(pWindow.get())->Minimize();
1613965cc9c2SJens-Heiner Rechtien         }
1614d239ac79STibor Nagy         else if (!bHidden && !bStartPres)
161577f6149cSKurt Zenker         {
16162a993534SKurt Zenker             // show frame ... if it's not still visible ...
16172a993534SKurt Zenker             // But do nothing if it's already visible!
161842d197efSMike Kaganski             impl_makeFrameWindowVisible(xWindow, !m_bFocusedAndToFront && shouldFocusAndToFront());
161977f6149cSKurt Zenker         }
162077f6149cSKurt Zenker 
1621e0b930e1SVasily Melenchuk         if (pWindow)
1622e0b930e1SVasily Melenchuk             pWindow->FlashWindow();
1623e0b930e1SVasily Melenchuk 
1624bd32f48aSKurt Zenker         // Note: Only if an existing property "FrameName" is given by this media descriptor,
1625a1bc5756SJesús Corrius         // it should be used. Otherwise we should do nothing. May be the outside code has already
1626bd32f48aSKurt Zenker         // set a frame name on the target!
16272ab40e9eSNoel Grandin         utl::MediaDescriptor::const_iterator pFrameName = m_lMediaDescriptor.find(utl::MediaDescriptor::PROP_FRAMENAME);
1628bd32f48aSKurt Zenker         if (pFrameName != m_lMediaDescriptor.end())
1629bd32f48aSKurt Zenker         {
16301946794aSLuboš Luňák             OUString sFrameName;
1631bd32f48aSKurt Zenker             pFrameName->second >>= sFrameName;
1632a1bc5756SJesús Corrius             // Check the name again. e.g. "_default" isn't allowed.
1633bd32f48aSKurt Zenker             // On the other side "_beamer" is a valid name :-)
163477f6149cSKurt Zenker             if (TargetHelper::isValidNameForFrame(sFrameName))
163577f6149cSKurt Zenker                 m_xTargetFrame->setName(sFrameName);
163677f6149cSKurt Zenker         }
1637bd32f48aSKurt Zenker     }
1638c7e172b2SJens-Heiner Rechtien     else if (m_bReactivateControllerOnError)
163977f6149cSKurt Zenker     {
164077f6149cSKurt Zenker         // Try to reactivate the old document (if any exists!)
164177f6149cSKurt Zenker         css::uno::Reference< css::frame::XController > xOldDoc = m_xTargetFrame->getController();
164277f6149cSKurt Zenker         // clear does not depend from reactivation state of a might existing old document!
16439a2d1b9cSLionel Elie Mamane         // We must make sure, that a might following getTargetComponent() call does not return
164477f6149cSKurt Zenker         // the old document!
164577f6149cSKurt Zenker         m_xTargetFrame.clear();
164677f6149cSKurt Zenker         if (xOldDoc.is())
164777f6149cSKurt Zenker         {
1648ed467869SStephan Bergmann             bool bReactivated = xOldDoc->suspend(false);
164977f6149cSKurt Zenker             if (!bReactivated)
165077f6149cSKurt Zenker                 throw LoadEnvException(LoadEnvException::ID_COULD_NOT_REACTIVATE_CONTROLLER);
1651a6287e21SNoel Grandin             m_bReactivateControllerOnError = false;
165277f6149cSKurt Zenker         }
165377f6149cSKurt Zenker     }
1654c7e172b2SJens-Heiner Rechtien     else if (m_bCloseFrameOnError)
165577f6149cSKurt Zenker     {
165677f6149cSKurt Zenker         // close empty frames
165777f6149cSKurt Zenker         css::uno::Reference< css::util::XCloseable > xCloseable (m_xTargetFrame, css::uno::UNO_QUERY);
165877f6149cSKurt Zenker 
165977f6149cSKurt Zenker         try
166077f6149cSKurt Zenker         {
166177f6149cSKurt Zenker             if (xCloseable.is())
1662ed467869SStephan Bergmann                 xCloseable->close(true);
1663952b806cSNoel Grandin             else if (m_xTargetFrame.is())
1664952b806cSNoel Grandin                 m_xTargetFrame->dispose();
166577f6149cSKurt Zenker         }
166677f6149cSKurt Zenker         catch(const css::util::CloseVetoException&)
166777f6149cSKurt Zenker         {}
166877f6149cSKurt Zenker         catch(const css::lang::DisposedException&)
166977f6149cSKurt Zenker         {}
167077f6149cSKurt Zenker         m_xTargetFrame.clear();
167177f6149cSKurt Zenker     }
167277f6149cSKurt Zenker 
1673e2a4aa0eSKurt Zenker     // This max force an implicit closing of our target frame ...
16747799914bSXiaofei Zhang     // e.g. in case close(sal_True) was called before and the frame
1675e2a4aa0eSKurt Zenker     // kill itself if our external use-lock is released here!
1676a1bc5756SJesús Corrius     // That's why we release this lock AFTER ALL OPERATIONS on this frame
1677a1bc5756SJesús Corrius     // are finished. The frame itself must handle then
1678e2a4aa0eSKurt Zenker     // this situation gracefully.
1679e2a4aa0eSKurt Zenker     m_aTargetLock.freeResource();
1680e2a4aa0eSKurt Zenker 
1681e2a4aa0eSKurt Zenker     // Last but not least :-)
1682e2a4aa0eSKurt Zenker     // We have to clear the current media descriptor.
1683a1bc5756SJesús Corrius     // Otherwise it hold a might existing stream open!
1684e2a4aa0eSKurt Zenker     m_lMediaDescriptor.clear();
1685e2a4aa0eSKurt Zenker 
1686c7e172b2SJens-Heiner Rechtien     css::uno::Any aRequest;
1687c7e172b2SJens-Heiner Rechtien     bool bThrow = false;
1688da8bfce2SStephan Bergmann     if ( !m_bLoaded && m_pQuietInteraction.is() && m_pQuietInteraction->wasUsed() )
1689c7e172b2SJens-Heiner Rechtien     {
1690c7e172b2SJens-Heiner Rechtien         aRequest = m_pQuietInteraction->getRequest();
1691da8bfce2SStephan Bergmann         m_pQuietInteraction.clear();
1692c7e172b2SJens-Heiner Rechtien         bThrow = true;
1693c7e172b2SJens-Heiner Rechtien     }
1694c7e172b2SJens-Heiner Rechtien 
169585f7ed1cSStephan Bergmann     aReadLock.clear();
1696c7e172b2SJens-Heiner Rechtien 
1697c7e172b2SJens-Heiner Rechtien     if (bThrow)
1698c7e172b2SJens-Heiner Rechtien     {
1699d69335c9SFrank Schoenheit [fs]         if  ( aRequest.isExtractableTo( ::cppu::UnoType< css::uno::Exception >::get() ) )
17005a10e33fSStephan Bergmann             throw LoadEnvException(
17014f5f24a4SNoel Grandin                 LoadEnvException::ID_GENERAL_ERROR, u"interaction request"_ustr,
17025a10e33fSStephan Bergmann                 aRequest);
1703c7e172b2SJens-Heiner Rechtien     }
1704c7e172b2SJens-Heiner Rechtien 
170577f6149cSKurt Zenker     // <- SAFE ----------------------------------
170677f6149cSKurt Zenker }
170777f6149cSKurt Zenker 
shouldFocusAndToFront() const170842d197efSMike Kaganski bool LoadEnv::shouldFocusAndToFront() const
170942d197efSMike Kaganski {
171042d197efSMike Kaganski     bool const preview(
171142d197efSMike Kaganski         m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_PREVIEW, false));
1712e0b930e1SVasily Melenchuk     return !preview;
171342d197efSMike Kaganski }
171442d197efSMike Kaganski 
17158ef4dc07SNoel Grandin // static
impl_makeFrameWindowVisible(const css::uno::Reference<css::awt::XWindow> & xWindow,bool bForceToFront)17162a993534SKurt Zenker void LoadEnv::impl_makeFrameWindowVisible(const css::uno::Reference< css::awt::XWindow >& xWindow      ,
1717a6287e21SNoel Grandin                                                 bool bForceToFront)
17182a993534SKurt Zenker {
17194bd2ed6aSNorbert Thiebaud     SolarMutexGuard aSolarGuard;
172078b4a1fbSNoel Grandin     VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xWindow);
1721ff25a4a6SNoel Grandin     if ( !pWindow )
1722ff25a4a6SNoel Grandin         return;
1723ff25a4a6SNoel Grandin 
1724f0fbf30aSMike Kaganski     if (pWindow->IsVisible() && bForceToFront)
1725e9230b2bSMark Hung         pWindow->ToTop( ToTopFlags::RestoreWhenMin | ToTopFlags::ForegroundTask );
1726cfdbe09cSPhilipp Lohmann [pl]     else
1727f0fbf30aSMike Kaganski         pWindow->Show(true, bForceToFront ? ShowFlags::ForegroundTask : ShowFlags::NONE);
172823740dc4SVladimir Glazounov }
17292a993534SKurt Zenker 
impl_applyPersistentWindowState(const css::uno::Reference<css::awt::XWindow> & xWindow)17304543350eSVladimir Glazounov void LoadEnv::impl_applyPersistentWindowState(const css::uno::Reference< css::awt::XWindow >& xWindow)
17314543350eSVladimir Glazounov {
17324543350eSVladimir Glazounov     // no window -> action not possible
17334543350eSVladimir Glazounov     if (!xWindow.is())
17344543350eSVladimir Glazounov         return;
17354543350eSVladimir Glazounov 
17364543350eSVladimir Glazounov     // window already visible -> do nothing! If we use a "recycle frame" for loading ...
17374543350eSVladimir Glazounov     // the current position and size must be used.
17384543350eSVladimir Glazounov     css::uno::Reference< css::awt::XWindow2 > xVisibleCheck(xWindow, css::uno::UNO_QUERY);
17394543350eSVladimir Glazounov     if (
17404543350eSVladimir Glazounov         (xVisibleCheck.is()        ) &&
17414543350eSVladimir Glazounov         (xVisibleCheck->isVisible())
17424543350eSVladimir Glazounov        )
17434543350eSVladimir Glazounov        return;
17444543350eSVladimir Glazounov 
17457487c382SOliver Bolte     // SOLAR SAFE ->
17465a824268SMike Kaganski     {
17475a824268SMike Kaganski         SolarMutexGuard aSolarGuard1;
17487487c382SOliver Bolte 
174978b4a1fbSNoel Grandin         VclPtr<vcl::Window>  pWindow = VCLUnoHelper::GetWindow(xWindow);
175047cda279SCaolán McNamara         if (!pWindow)
175147cda279SCaolán McNamara             return;
175247cda279SCaolán McNamara 
1753a6287e21SNoel Grandin         bool bSystemWindow = pWindow->IsSystemWindow();
17548c00536dSNoel Grandin         bool bWorkWindow = (pWindow->GetType() == WindowType::WORKWINDOW);
17554543350eSVladimir Glazounov 
17564543350eSVladimir Glazounov         if (!bSystemWindow && !bWorkWindow)
17574543350eSVladimir Glazounov             return;
17584543350eSVladimir Glazounov 
1759eab0904fSAndrea Gelmini         // don't overwrite this special state!
176078b4a1fbSNoel Grandin         WorkWindow* pWorkWindow = static_cast<WorkWindow*>(pWindow.get());
17614543350eSVladimir Glazounov         if (pWorkWindow->IsMinimized())
17624543350eSVladimir Glazounov             return;
17635a824268SMike Kaganski     }
17647487c382SOliver Bolte     // <- SOLAR SAFE
17657487c382SOliver Bolte 
17664543350eSVladimir Glazounov     // SAFE ->
176785f7ed1cSStephan Bergmann     osl::ClearableMutexGuard aReadLock(m_mutex);
17684543350eSVladimir Glazounov 
17694543350eSVladimir Glazounov     // no filter -> no module -> no persistent window state
17701946794aSLuboš Luňák     OUString sFilter = m_lMediaDescriptor.getUnpackedValueOrDefault(
17712ab40e9eSNoel Grandin                                     utl::MediaDescriptor::PROP_FILTERNAME,
17721946794aSLuboš Luňák                                     OUString());
177318692cc1SOlivier Hallot     if (sFilter.isEmpty())
17744543350eSVladimir Glazounov         return;
17754543350eSVladimir Glazounov 
1776fe1ac1bfSNoel Grandin     css::uno::Reference< css::uno::XComponentContext > xContext = m_xContext;
17774543350eSVladimir Glazounov 
177885f7ed1cSStephan Bergmann     aReadLock.clear();
17794543350eSVladimir Glazounov     // <- SAFE
17804543350eSVladimir Glazounov 
17814543350eSVladimir Glazounov     try
17824543350eSVladimir Glazounov     {
17834543350eSVladimir Glazounov         // retrieve the module name from the filter configuration
17844543350eSVladimir Glazounov         css::uno::Reference< css::container::XNameAccess > xFilterCfg(
1785fe1ac1bfSNoel Grandin             xContext->getServiceManager()->createInstanceWithContext(SERVICENAME_FILTERFACTORY, xContext),
17864543350eSVladimir Glazounov             css::uno::UNO_QUERY_THROW);
17874543350eSVladimir Glazounov         ::comphelper::SequenceAsHashMap lProps (xFilterCfg->getByName(sFilter));
1788c5376ef6SStephan Bergmann         OUString                 sModule = lProps.getUnpackedValueOrDefault(FILTER_PROPNAME_ASCII_DOCUMENTSERVICE, OUString());
17894543350eSVladimir Glazounov 
17904543350eSVladimir Glazounov         // get access to the configuration of this office module
17914256c764SLuboš Luňák         css::uno::Reference< css::container::XNameAccess > xModuleCfg(officecfg::Setup::Office::Factories::get());
17924543350eSVladimir Glazounov 
17934543350eSVladimir Glazounov         // read window state from the configuration
17944543350eSVladimir Glazounov         // and apply it on the window.
17954543350eSVladimir Glazounov         // Do nothing, if no configuration entry exists!
17961946794aSLuboš Luňák         OUString sWindowState;
179757448212STor Lillqvist 
179857448212STor Lillqvist         // Don't look for persistent window attributes when used through LibreOfficeKit
179957448212STor Lillqvist         if( !comphelper::LibreOfficeKit::isActive() )
18004f5f24a4SNoel Grandin             comphelper::ConfigurationHelper::readRelativeKey(xModuleCfg, sModule, u"ooSetupFactoryWindowAttributes"_ustr) >>= sWindowState;
180157448212STor Lillqvist 
180218692cc1SOlivier Hallot         if (!sWindowState.isEmpty())
18037487c382SOliver Bolte         {
18047487c382SOliver Bolte             // SOLAR SAFE ->
18054bd2ed6aSNorbert Thiebaud             SolarMutexGuard aSolarGuard;
18067487c382SOliver Bolte 
18077487c382SOliver Bolte             // We have to retrieve the window pointer again. Because nobody can guarantee
18087487c382SOliver Bolte             // that the XWindow was not disposed in between .-)
18097487c382SOliver Bolte             // But if we get a valid pointer we can be sure, that it's the system window pointer
1810a1bc5756SJesús Corrius             // we already checked and used before. Because nobody recycle the same uno reference for
18117487c382SOliver Bolte             // a new internal c++ implementation ... hopefully .-))
181278b4a1fbSNoel Grandin             VclPtr<vcl::Window> pWindowCheck = VCLUnoHelper::GetWindow(xWindow);
18137487c382SOliver Bolte             if (! pWindowCheck)
18147487c382SOliver Bolte                 return;
18157487c382SOliver Bolte 
181678b4a1fbSNoel Grandin             SystemWindow* pSystemWindow = static_cast<SystemWindow*>(pWindowCheck.get());
1817116b9d6dSMike Kaganski             pSystemWindow->SetWindowState(sWindowState);
18187487c382SOliver Bolte             // <- SOLAR SAFE
18197487c382SOliver Bolte         }
18204543350eSVladimir Glazounov     }
1821ba5a460bSPKEuS     catch(const css::uno::RuntimeException&)
1822ba5a460bSPKEuS         { throw; }
18234543350eSVladimir Glazounov     catch(const css::uno::Exception&)
18244543350eSVladimir Glazounov         {}
18254543350eSVladimir Glazounov }
18264543350eSVladimir Glazounov 
182777f6149cSKurt Zenker } // namespace framework
18283d698bcaSJens-Heiner Rechtien 
18298694d2bcSSebastian Spaeth /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1830