xref: /core/desktop/source/app/appinit.cxx (revision 9422879a)
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 
21 #include <algorithm>
22 
23 #include <app.hxx>
24 #include <dp_shared.hxx>
25 #include "cmdlineargs.hxx"
26 #include <strings.hrc>
27 #include <com/sun/star/lang/XInitialization.hpp>
28 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
29 #include <com/sun/star/uno/Exception.hpp>
30 #include <com/sun/star/ucb/UniversalContentBroker.hpp>
31 #include <cppuhelper/bootstrap.hxx>
32 #include <officecfg/Setup.hxx>
33 #include <osl/file.hxx>
34 #include <rtl/bootstrap.hxx>
35 #include <sal/log.hxx>
36 #include <comphelper/diagnose_ex.hxx>
37 
38 #include <comphelper/processfactory.hxx>
39 #include <unotools/ucbhelper.hxx>
40 #include <unotools/tempfile.hxx>
41 #include <vcl/svapp.hxx>
42 #include <unotools/pathoptions.hxx>
43 
44 #include <iostream>
45 #include <map>
46 
47 #if defined EMSCRIPTEN
48 #include <bindings_uno.hxx>
49 #endif
50 
51 using namespace ::com::sun::star::uno;
52 using namespace ::com::sun::star::lang;
53 using namespace ::com::sun::star::ucb;
54 
55 namespace desktop
56 {
57 
58 
configureUcb()59 static void configureUcb()
60 {
61     // For backwards compatibility, in case some code still uses plain
62     // createInstance w/o args directly to obtain an instance:
63     UniversalContentBroker::create(comphelper::getProcessComponentContext());
64 }
65 
InitApplicationServiceManager()66 void Desktop::InitApplicationServiceManager()
67 {
68     Reference<XMultiServiceFactory> sm;
69 #ifdef ANDROID
70     OUString aUnoRc( "file:///assets/program/unorc" );
71     sm.set(
72         cppu::defaultBootstrap_InitialComponentContext( aUnoRc )->getServiceManager(),
73         UNO_QUERY_THROW);
74 #elif defined(IOS)
75     OUString uri( "$APP_DATA_DIR" );
76     rtl_bootstrap_expandMacros( &uri.pData );
77     OUString aUnoRc("file://" + uri  + "/unorc");
78     sm.set(
79            cppu::defaultBootstrap_InitialComponentContext( aUnoRc )->getServiceManager(),
80            UNO_QUERY_THROW);
81 #else
82     sm.set(
83         cppu::defaultBootstrap_InitialComponentContext()->getServiceManager(),
84         UNO_QUERY_THROW);
85 #endif
86     comphelper::setProcessServiceFactory(sm);
87 #if defined EMSCRIPTEN
88     init_unoembind_uno();
89 #endif
90 }
91 
RegisterServices()92 void Desktop::RegisterServices()
93 {
94     if( m_bServicesRegistered )
95         return;
96 
97     // interpret command line arguments
98     CommandLineArgs& rCmdLine = GetCommandLineArgs();
99 
100     // Headless mode for FAT Office, auto cancels any dialogs that popup
101     if (rCmdLine.IsHeadless())
102         Application::EnableHeadlessMode(false);
103 
104     // read accept string from configuration
105     OUString conDcpCfg(
106         officecfg::Setup::Office::ooSetupConnectionURL::get());
107     if (!conDcpCfg.isEmpty()) {
108         createAcceptor(conDcpCfg);
109     }
110 
111     std::vector< OUString > const & conDcp = rCmdLine.GetAccept();
112     for (auto const& elem : conDcp)
113     {
114         createAcceptor(elem);
115     }
116 
117     configureUcb();
118 
119     CreateTemporaryDirectory();
120     m_bServicesRegistered = true;
121 }
122 
123 typedef std::map< OUString, css::uno::Reference<css::lang::XInitialization> > AcceptorMap;
124 
125 namespace
126 {
acceptorMap()127     AcceptorMap& acceptorMap()
128     {
129         static AcceptorMap SINGLETON;
130         return SINGLETON;
131     }
CurrentTempURL()132     OUString& CurrentTempURL()
133     {
134         static OUString SINGLETON;
135         return SINGLETON;
136     }
137 }
138 
139 static bool bAccept = false;
140 
createAcceptor(const OUString & aAcceptString)141 void Desktop::createAcceptor(const OUString& aAcceptString)
142 {
143     // check whether the requested acceptor already exists
144     AcceptorMap &rMap = acceptorMap();
145     AcceptorMap::const_iterator pIter = rMap.find(aAcceptString);
146     if (pIter != rMap.end() )
147     {
148         // there is already an acceptor with this description
149         SAL_WARN( "desktop.app", "Acceptor already exists.");
150         return;
151     }
152 
153     Sequence< Any > aSeq{ Any(aAcceptString), Any(bAccept) };
154     Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
155     Reference<XInitialization> rAcceptor(
156         xContext->getServiceManager()->createInstanceWithContext(u"com.sun.star.office.Acceptor"_ustr, xContext),
157         UNO_QUERY );
158     if ( rAcceptor.is() )
159     {
160         try
161         {
162             rAcceptor->initialize( aSeq );
163             rMap.emplace(aAcceptString, rAcceptor);
164         }
165         catch (const css::uno::Exception&)
166         {
167             // no error handling needed...
168             // acceptor just won't come up
169             TOOLS_WARN_EXCEPTION( "desktop.app", "Acceptor could not be created");
170         }
171     }
172     else
173     {
174         ::std::cerr << "UNO Remote Protocol acceptor could not be created, presumably because it has been disabled in configuration." << ::std::endl;
175     }
176 }
177 
178 namespace {
179 
180 class enable
181 {
182     private:
183     Sequence<Any> m_aSeq{ Any(true) };
184     public:
185     enable() = default;
operator ()(const AcceptorMap::value_type & val)186     void operator() (const AcceptorMap::value_type& val) {
187         if (val.second.is()) {
188             val.second->initialize(m_aSeq);
189         }
190     }
191 };
192 
193 }
194 
195 // enable acceptors
IMPL_STATIC_LINK_NOARG(Desktop,EnableAcceptors_Impl,void *,void)196 IMPL_STATIC_LINK_NOARG(Desktop, EnableAcceptors_Impl, void*, void)
197 {
198     if (!bAccept)
199     {
200         // from now on, all new acceptors are enabled
201         bAccept = true;
202         // enable existing acceptors by calling initialize(true)
203         // on all existing acceptors
204         AcceptorMap &rMap = acceptorMap();
205         std::for_each(rMap.begin(), rMap.end(), enable());
206     }
207 }
208 
destroyAcceptor(const OUString & aAcceptString)209 void Desktop::destroyAcceptor(const OUString& aAcceptString)
210 {
211     // special case stop all acceptors
212     AcceptorMap &rMap = acceptorMap();
213     if (aAcceptString == "all") {
214         rMap.clear();
215 
216     } else {
217         // try to remove acceptor from map
218         AcceptorMap::const_iterator pIter = rMap.find(aAcceptString);
219         if (pIter != rMap.end() ) {
220             // remove reference from map
221             // this is the last reference and the acceptor will be destructed
222             rMap.erase(aAcceptString);
223         } else {
224             SAL_WARN( "desktop.app", "Found no acceptor to remove");
225         }
226     }
227 }
228 
229 
DeregisterServices()230 void Desktop::DeregisterServices()
231 {
232     // stop all acceptors by clearing the map
233     acceptorMap().clear();
234 }
235 
CreateTemporaryDirectory()236 void Desktop::CreateTemporaryDirectory()
237 {
238     OUString aTempBaseURL;
239     try
240     {
241         SvtPathOptions aOpt;
242         aTempBaseURL = aOpt.GetTempPath();
243     }
244     catch (RuntimeException& e)
245     {
246         // Catch runtime exception here: We have to add language dependent info
247         // to the exception message. Fallback solution uses hard coded string.
248         OUString aMsg = DpResId(STR_BOOTSTRAP_ERR_NO_PATHSET_SERVICE);
249         e.Message = aMsg + e.Message;
250         throw;
251     }
252 
253     // create new current temporary directory
254     OUString aTempPath = ::utl::SetTempNameBaseDirectory( aTempBaseURL );
255     if ( aTempPath.isEmpty()
256          && ::osl::File::getTempDirURL( aTempBaseURL ) == osl::FileBase::E_None )
257     {
258         aTempPath = ::utl::SetTempNameBaseDirectory( aTempBaseURL );
259     }
260 
261     // set new current temporary directory
262     OUString aRet;
263     if (osl::FileBase::getFileURLFromSystemPath( aTempPath, aRet )
264         != osl::FileBase::E_None)
265     {
266         aRet.clear();
267     }
268     CurrentTempURL() = aRet;
269 }
270 
RemoveTemporaryDirectory()271 void Desktop::RemoveTemporaryDirectory()
272 {
273     // remove current temporary directory
274     OUString &rCurrentTempURL = CurrentTempURL();
275     if ( !rCurrentTempURL.isEmpty() )
276     {
277         ::utl::UCBContentHelper::Kill( rCurrentTempURL );
278     }
279 }
280 
281 } // namespace desktop
282 
283 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
284