LCOV - code coverage report
Current view: top level - framework/source/loadenv - loadenv.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 747 0.0 %
Date: 2014-04-14 Functions: 0 31 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10