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 <config_features.h>
21 : #include <config_folders.h>
22 :
23 : #include <sal/config.h>
24 :
25 : #include <iostream>
26 :
27 : #include "app.hxx"
28 : #include "desktop.hrc"
29 : #include "cmdlineargs.hxx"
30 : #include "cmdlinehelp.hxx"
31 : #include "dispatchwatcher.hxx"
32 : #include "configinit.hxx"
33 : #include "lockfile.hxx"
34 : #include "userinstall.hxx"
35 : #include "desktopcontext.hxx"
36 : #include "exithelper.h"
37 : #include "migration.hxx"
38 :
39 : #include <svl/languageoptions.hxx>
40 : #include <svtools/javacontext.hxx>
41 : #include <com/sun/star/beans/XPropertySet.hpp>
42 : #include <com/sun/star/frame/theAutoRecovery.hpp>
43 : #include <com/sun/star/frame/theGlobalEventBroadcaster.hpp>
44 : #include <com/sun/star/frame/SessionListener.hpp>
45 : #include <com/sun/star/frame/XSessionManagerListener.hpp>
46 : #include <com/sun/star/frame/XSynchronousDispatch.hpp>
47 : #include <com/sun/star/document/CorruptedFilterConfigurationException.hpp>
48 : #include <com/sun/star/configuration/CorruptedConfigurationException.hpp>
49 : #include <com/sun/star/configuration/theDefaultProvider.hpp>
50 : #include <com/sun/star/util/XFlushable.hpp>
51 : #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
52 : #include <com/sun/star/frame/Desktop.hpp>
53 : #include <com/sun/star/frame/StartModule.hpp>
54 : #include <com/sun/star/frame/XComponentLoader.hpp>
55 : #include <com/sun/star/view/XPrintable.hpp>
56 : #include <com/sun/star/awt/XTopWindow.hpp>
57 : #include <com/sun/star/util/URLTransformer.hpp>
58 : #include <com/sun/star/util/XURLTransformer.hpp>
59 : #include <com/sun/star/util/XCloseable.hpp>
60 : #include <com/sun/star/frame/XDispatchProvider.hpp>
61 : #include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
62 : #include <com/sun/star/configuration/MissingBootstrapFileException.hpp>
63 : #include <com/sun/star/configuration/InvalidBootstrapFileException.hpp>
64 : #include <com/sun/star/configuration/InstallationIncompleteException.hpp>
65 : #include <com/sun/star/configuration/backend/BackendSetupException.hpp>
66 : #include <com/sun/star/configuration/backend/BackendAccessException.hpp>
67 : #include <com/sun/star/task/theJobExecutor.hpp>
68 : #include <com/sun/star/task/OfficeRestartManager.hpp>
69 : #include <com/sun/star/task/XRestartManager.hpp>
70 : #include <com/sun/star/document/XDocumentEventListener.hpp>
71 : #include <com/sun/star/frame/theUICommandDescription.hpp>
72 : #include <com/sun/star/ui/theUIElementFactoryManager.hpp>
73 : #include <com/sun/star/ui/theWindowStateConfiguration.hpp>
74 : #include <com/sun/star/frame/XUIControllerRegistration.hpp>
75 : #include <com/sun/star/frame/thePopupMenuControllerFactory.hpp>
76 : #include <com/sun/star/office/Quickstart.hpp>
77 :
78 : #include <sal/log.hxx>
79 : #include <toolkit/helper/vclunohelper.hxx>
80 : #include <comphelper/configuration.hxx>
81 : #include <comphelper/processfactory.hxx>
82 : #include <unotools/bootstrap.hxx>
83 : #include <unotools/configmgr.hxx>
84 : #include <unotools/moduleoptions.hxx>
85 : #include <unotools/localfilehelper.hxx>
86 : #include <officecfg/Office/Common.hxx>
87 : #include <officecfg/Office/Recovery.hxx>
88 : #include <officecfg/Setup.hxx>
89 : #include <osl/file.hxx>
90 : #include <osl/process.h>
91 : #include <rtl/uri.hxx>
92 : #include <unotools/pathoptions.hxx>
93 : #include <svtools/miscopt.hxx>
94 : #include <svtools/menuoptions.hxx>
95 : #include <rtl/bootstrap.hxx>
96 : #include <vcl/help.hxx>
97 : #include <vcl/layout.hxx>
98 : #include <vcl/settings.hxx>
99 : #include <sfx2/sfx.hrc>
100 : #include <sfx2/app.hxx>
101 : #include <svl/itemset.hxx>
102 : #include <svl/eitem.hxx>
103 : #include <basic/sbstar.hxx>
104 :
105 : #include <svtools/fontsubstconfig.hxx>
106 : #include <svtools/accessibilityoptions.hxx>
107 : #include <svtools/apearcfg.hxx>
108 : #include <vcl/graphicfilter.hxx>
109 :
110 : #include "langselect.hxx"
111 :
112 : #include <config_telepathy.h>
113 :
114 : #if ENABLE_TELEPATHY
115 : #include <tubes/manager.hxx>
116 : #endif
117 :
118 : #if defined MACOSX
119 : #include <errno.h>
120 : #include <sys/wait.h>
121 : #endif
122 :
123 : #ifdef WNT
124 : #ifdef _MSC_VER
125 : #pragma warning(push, 1) /* disable warnings within system headers */
126 : #pragma warning (disable: 4005)
127 : #endif
128 : #define WIN32_LEAN_AND_MEAN
129 : #include <windows.h>
130 : #ifdef _MSC_VER
131 : #pragma warning(pop)
132 : #endif
133 : #endif //WNT
134 :
135 : #if defined WNT
136 : #include <process.h>
137 : #define GETPID _getpid
138 : #else
139 : #include <unistd.h>
140 : #define GETPID getpid
141 : #endif
142 :
143 : using namespace ::com::sun::star::awt;
144 : using namespace ::com::sun::star::uno;
145 : using namespace ::com::sun::star::util;
146 : using namespace ::com::sun::star::lang;
147 : using namespace ::com::sun::star::beans;
148 : using namespace ::com::sun::star::frame;
149 : using namespace ::com::sun::star::document;
150 : using namespace ::com::sun::star::view;
151 : using namespace ::com::sun::star::task;
152 : using namespace ::com::sun::star::system;
153 : using namespace ::com::sun::star::ui;
154 : using namespace ::com::sun::star::ui::dialogs;
155 : using namespace ::com::sun::star::container;
156 :
157 : ResMgr* desktop::Desktop::pResMgr = 0;
158 :
159 : namespace desktop
160 : {
161 :
162 : static oslSignalHandler pSignalHandler = 0;
163 :
164 : namespace {
165 :
166 : #if HAVE_FEATURE_EXTENSIONS
167 :
168 : // Remove any existing UserInstallation's extensions cache data remaining from
169 : // old installations. This addresses at least two problems:
170 : //
171 : // For one, apparently due to the old share/prereg/bundled mechanism (disabled
172 : // since 5c47e5f63a79a9e72ec4a100786b1bbf65137ed4 "fdo#51252 Disable copying
173 : // share/prereg/bundled to avoid startup crashes"), the user/extensions/bundled
174 : // cache could contain corrupted information (like a UNO component registered
175 : // twice, which got changed from active to passive registration in one LO
176 : // version, but the version of the corresponding bundled extension only
177 : // incremented in a later LO version).
178 : //
179 : // For another, UserInstallations have been seen in the wild where no extensions
180 : // were installed per-user (any longer), but user/uno_packages/cache/registry/
181 : // com.sun.star.comp.deployment.component.PackageRegistryBackend/*.rdb files
182 : // contained data nevertheless.
183 : //
184 : // When a LO upgrade is detected (i.e., no user/extensions/buildid or one
185 : // containing an old build ID), then user/extensions and
186 : // user/uno_packages/cache/registry/
187 : // com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc are
188 : // removed. That should prevent any problems starting the service manager due
189 : // to old junk. Later on in Desktop::SynchronizeExtensionRepositories, the
190 : // removed cache data is recreated.
191 : //
192 : // Multiple instances of soffice.bin can execute this code in parallel for a
193 : // single UserInstallation, as it is called before OfficeIPCThread is set up.
194 : // Therefore, any errors here only lead to SAL_WARNs.
195 : //
196 : // At least in theory, this function could be removed again once no
197 : // UserInstallation can be poisoned by old junk any more.
198 116 : bool cleanExtensionCache() {
199 : OUString buildId(
200 116 : "${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("version") ":buildid}");
201 116 : rtl::Bootstrap::expandMacros(buildId); //TODO: detect failure
202 : OUString extDir(
203 : "${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap")
204 232 : ":UserInstallation}/user/extensions");
205 116 : rtl::Bootstrap::expandMacros(extDir); //TODO: detect failure
206 232 : OUString buildIdFile(extDir + "/buildid");
207 232 : osl::File fr(buildIdFile);
208 116 : osl::FileBase::RC rc = fr.open(osl_File_OpenFlag_Read);
209 116 : switch (rc) {
210 : case osl::FileBase::E_None:
211 : {
212 63 : rtl::ByteSequence s1;
213 63 : rc = fr.readLine(s1);
214 63 : osl::FileBase::RC rc2 = fr.close();
215 : SAL_WARN_IF(
216 : rc2 != osl::FileBase::E_None, "desktop.app",
217 : "cannot close " << fr.getURL() << " after reading: " << +rc2);
218 : // readLine returns E_AGAIN for a zero-size file:
219 63 : if (rc != osl::FileBase::E_None && rc != osl::FileBase::E_AGAIN) {
220 : SAL_WARN( "desktop.app", "cannot read from " << fr.getURL() << ": " << +rc);
221 0 : break;
222 : }
223 : OUString s2(
224 63 : reinterpret_cast< char const * >(s1.getConstArray()),
225 126 : s1.getLength(), RTL_TEXTENCODING_ISO_8859_1);
226 : // using ISO 8859-1 avoids any and all conversion errors; the
227 : // content should only be a subset of ASCII, anyway
228 63 : if (s2 == buildId) {
229 63 : return false;
230 : }
231 0 : break;
232 : }
233 : case osl::FileBase::E_NOENT:
234 53 : break;
235 : default:
236 : SAL_WARN( "desktop.app", "cannot open " << fr.getURL() << " for reading: " << +rc);
237 0 : break;
238 : }
239 53 : utl::removeTree(extDir);
240 : OUString userRcFile(
241 : "$UNO_USER_PACKAGES_CACHE/registry/"
242 53 : "com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc");
243 53 : rtl::Bootstrap::expandMacros(userRcFile); //TODO: detect failure
244 53 : rc = osl::File::remove(userRcFile);
245 : SAL_WARN_IF(
246 : rc != osl::FileBase::E_None && rc != osl::FileBase::E_NOENT, "desktop.app",
247 : "cannot remove file " << userRcFile << ": " << +rc);
248 53 : rc = osl::Directory::createPath(extDir);
249 : SAL_WARN_IF(
250 : rc != osl::FileBase::E_None && rc != osl::FileBase::E_EXIST, "desktop.app",
251 : "cannot create path " << extDir << ": " << +rc);
252 106 : osl::File fw(buildIdFile);
253 53 : rc = fw.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Create);
254 53 : if (rc != osl::FileBase::E_None) {
255 : SAL_WARN( "desktop.app", "cannot open " << fw.getURL() << " for writing: " << +rc);
256 0 : return true;
257 : }
258 106 : OString buf(OUStringToOString(buildId, RTL_TEXTENCODING_UTF8));
259 : // using UTF-8 avoids almost all conversion errors (and buildid
260 : // containing single surrogate halves should never happen, anyway); the
261 : // content should only be a subset of ASCII, anyway
262 53 : sal_uInt64 n = 0;
263 53 : rc = fw.write(buf.getStr(), buf.getLength(), n);
264 : SAL_WARN_IF(
265 : (rc != osl::FileBase::E_None
266 : || n != static_cast< sal_uInt32 >(buf.getLength())),
267 : "desktop.app",
268 : "cannot write to " << fw.getURL() << ": " << +rc << ", " << n);
269 53 : rc = fw.close();
270 : SAL_WARN_IF(
271 : rc != osl::FileBase::E_None, "desktop.app",
272 : "cannot close " << fw.getURL() << " after writing: " << +rc);
273 222 : return true;
274 : }
275 :
276 : #endif
277 :
278 0 : bool shouldLaunchQuickstart()
279 : {
280 0 : bool bQuickstart = Desktop::GetCommandLineArgs().IsQuickstart();
281 0 : if (!bQuickstart)
282 : {
283 0 : const SfxPoolItem* pItem=0;
284 0 : SfxItemSet aQLSet(SfxGetpApp()->GetPool(), SID_ATTR_QUICKLAUNCHER, SID_ATTR_QUICKLAUNCHER);
285 0 : SfxGetpApp()->GetOptions(aQLSet);
286 0 : SfxItemState eState = aQLSet.GetItemState(SID_ATTR_QUICKLAUNCHER, false, &pItem);
287 0 : if (SfxItemState::SET == eState)
288 0 : bQuickstart = static_cast<const SfxBoolItem*>(pItem)->GetValue();
289 : }
290 0 : return bQuickstart;
291 : }
292 :
293 52 : void SetRestartState() {
294 : try {
295 : std::shared_ptr< comphelper::ConfigurationChanges > batch(
296 52 : comphelper::ConfigurationChanges::create());
297 52 : officecfg::Setup::Office::OfficeRestartInProgress::set(true, batch);
298 52 : batch->commit();
299 0 : } catch (css::uno::Exception & e) {
300 : SAL_WARN("desktop.app", "ignoring Exception \"" << e.Message << "\"");
301 : }
302 52 : }
303 :
304 64 : void DoRestartActionsIfNecessary(bool quickstart) {
305 64 : if (quickstart) {
306 : try {
307 0 : if (officecfg::Setup::Office::OfficeRestartInProgress::get()) {
308 : std::shared_ptr< comphelper::ConfigurationChanges > batch(
309 0 : comphelper::ConfigurationChanges::create());
310 : officecfg::Setup::Office::OfficeRestartInProgress::set(
311 0 : false, batch);
312 0 : batch->commit();
313 : css::office::Quickstart::createStart(
314 : comphelper::getProcessComponentContext(),
315 0 : shouldLaunchQuickstart());
316 : }
317 0 : } catch (css::uno::Exception & e) {
318 : SAL_WARN(
319 : "desktop.app", "ignoring Exception \"" << e.Message << "\"");
320 : }
321 : }
322 64 : }
323 :
324 : }
325 :
326 :
327 :
328 116 : ResMgr* Desktop::GetDesktopResManager()
329 : {
330 116 : if ( !Desktop::pResMgr )
331 : {
332 : // Create desktop resource manager and bootstrap process
333 : // was successful. Use default way to get language specific message.
334 116 : if ( Application::IsInExecute() )
335 0 : Desktop::pResMgr = ResMgr::CreateResMgr("dkt");
336 :
337 116 : if ( !Desktop::pResMgr )
338 : {
339 : // Use VCL to get the correct language specific message as we
340 : // are in the bootstrap process and not able to get the installed
341 : // language!!
342 116 : OUString aUILocaleString = langselect::getEmergencyLocale();
343 232 : LanguageTag aLanguageTag( aUILocaleString);
344 : //! ResMgr may modify the Locale for fallback!
345 232 : Desktop::pResMgr = ResMgr::SearchCreateResMgr( "dkt", aLanguageTag);
346 : }
347 : }
348 :
349 116 : return Desktop::pResMgr;
350 : }
351 :
352 : namespace {
353 :
354 :
355 : // Get a message string securely. There is a fallback string if the resource
356 : // is not available.
357 :
358 0 : OUString GetMsgString(
359 : sal_uInt16 nId, const OUString& aFallbackMsg,
360 : bool bAlwaysUseFallbackMsg = false )
361 : {
362 0 : if ( !bAlwaysUseFallbackMsg )
363 : {
364 0 : ResMgr* resMgr = Desktop::GetDesktopResManager();
365 0 : if ( resMgr )
366 0 : return ResId(nId, *resMgr).toString();
367 : }
368 0 : return aFallbackMsg;
369 : }
370 :
371 0 : OUString MakeStartupErrorMessage(
372 : OUString const & aErrorMessage, bool bAlwaysUseFallbackMsg = false )
373 : {
374 0 : OUStringBuffer aDiagnosticMessage( 100 );
375 :
376 : aDiagnosticMessage.append(
377 : GetMsgString(
378 : STR_BOOTSTRAP_ERR_CANNOT_START, "The program cannot be started.",
379 0 : bAlwaysUseFallbackMsg ) );
380 :
381 0 : aDiagnosticMessage.appendAscii( "\n" );
382 :
383 0 : aDiagnosticMessage.append( aErrorMessage );
384 :
385 0 : return aDiagnosticMessage.makeStringAndClear();
386 : }
387 :
388 0 : OUString MakeStartupConfigAccessErrorMessage( OUString const & aInternalErrMsg )
389 : {
390 0 : OUStringBuffer aDiagnosticMessage( 200 );
391 :
392 0 : ResMgr* pResMgr = Desktop::GetDesktopResManager();
393 0 : if ( pResMgr )
394 0 : aDiagnosticMessage.append( ResId(STR_BOOTSTRAP_ERR_CFG_DATAACCESS, *pResMgr).toString() );
395 : else
396 0 : aDiagnosticMessage.appendAscii( "The program cannot be started." );
397 :
398 0 : if ( !aInternalErrMsg.isEmpty() )
399 : {
400 0 : aDiagnosticMessage.appendAscii( "\n\n" );
401 0 : if ( pResMgr )
402 0 : aDiagnosticMessage.append( ResId(STR_INTERNAL_ERRMSG, *pResMgr).toString() );
403 : else
404 0 : aDiagnosticMessage.appendAscii( "The following internal error has occurred:\n\n" );
405 0 : aDiagnosticMessage.append( aInternalErrMsg );
406 : }
407 :
408 0 : return aDiagnosticMessage.makeStringAndClear();
409 : }
410 :
411 :
412 : // shows a simple error box with the given message ... but exits from these process !
413 : // Fatal errors can't be solved by the process ... nor any recovery can help.
414 : // Mostly the installation was damaged and must be repaired manually .. or by calling
415 : // setup again.
416 : // On the other side we must make sure that no further actions will be possible within
417 : // the current office process ! No pipe requests, no menu/toolbar/shortuct actions
418 : // are allowed. Otherwise we will force a "crash inside a crash".
419 : // Thats why we have to use a special native message box here which does not use yield :-)
420 :
421 0 : void FatalError(const OUString& sMessage)
422 : {
423 0 : OUString sProductKey = ::utl::Bootstrap::getProductKey();
424 0 : if ( sProductKey.isEmpty())
425 : {
426 0 : osl_getExecutableFile( &sProductKey.pData );
427 :
428 0 : ::sal_uInt32 nLastIndex = sProductKey.lastIndexOf('/');
429 0 : if ( nLastIndex > 0 )
430 0 : sProductKey = sProductKey.copy( nLastIndex+1 );
431 : }
432 :
433 0 : OUStringBuffer sTitle (128);
434 0 : sTitle.append (sProductKey );
435 0 : sTitle.appendAscii (" - Fatal Error");
436 :
437 0 : Application::ShowNativeErrorBox (sTitle.makeStringAndClear (), sMessage);
438 0 : _exit(EXITHELPER_FATAL_ERROR);
439 : }
440 :
441 116 : static bool ShouldSuppressUI(const CommandLineArgs& rCmdLine)
442 : {
443 116 : return rCmdLine.IsInvisible() ||
444 116 : rCmdLine.IsHeadless() ||
445 116 : rCmdLine.IsQuickstart();
446 : }
447 :
448 : struct theCommandLineArgs : public rtl::Static< CommandLineArgs, theCommandLineArgs > {};
449 :
450 : }
451 :
452 877 : CommandLineArgs& Desktop::GetCommandLineArgs()
453 : {
454 877 : return theCommandLineArgs::get();
455 : }
456 :
457 : namespace
458 : {
459 : struct BrandName
460 : : public rtl::Static< OUString, BrandName > {};
461 : struct Version
462 : : public rtl::Static< OUString, Version > {};
463 : struct AboutBoxVersion
464 : : public rtl::Static< OUString, AboutBoxVersion > {};
465 : struct AboutBoxVersionSuffix
466 : : public rtl::Static< OUString, AboutBoxVersionSuffix > {};
467 : struct OOOVendor
468 : : public rtl::Static< OUString, OOOVendor > {};
469 : struct Extension
470 : : public rtl::Static< OUString, Extension > {};
471 : }
472 :
473 680630 : OUString ReplaceStringHookProc( const OUString& rStr )
474 : {
475 680630 : OUString sRet(rStr);
476 :
477 680630 : if (sRet.indexOf("%PRODUCT") != -1 || sRet.indexOf("%ABOUTBOX") != -1)
478 : {
479 941 : OUString sBrandName = BrandName::get();
480 1882 : OUString sVersion = Version::get();
481 1882 : OUString sBuildId = utl::Bootstrap::getBuildIdData("development");
482 1882 : OUString sAboutBoxVersion = AboutBoxVersion::get();
483 1882 : OUString sAboutBoxVersionSuffix = AboutBoxVersionSuffix::get();
484 1882 : OUString sExtension = Extension::get();
485 :
486 941 : if ( sBrandName.isEmpty() )
487 : {
488 941 : sBrandName = utl::ConfigManager::getProductName();
489 941 : sVersion = utl::ConfigManager::getProductVersion();
490 941 : sAboutBoxVersion = utl::ConfigManager::getAboutBoxProductVersion();
491 941 : sAboutBoxVersionSuffix = utl::ConfigManager::getAboutBoxProductVersionSuffix();
492 941 : if ( sExtension.isEmpty() )
493 : {
494 941 : sExtension = utl::ConfigManager::getProductExtension();
495 : }
496 : }
497 :
498 941 : sRet = sRet.replaceAll( "%PRODUCTNAME", sBrandName );
499 941 : sRet = sRet.replaceAll( "%PRODUCTVERSION", sVersion );
500 941 : sRet = sRet.replaceAll( "%BUILDID", sBuildId );
501 941 : sRet = sRet.replaceAll( "%ABOUTBOXPRODUCTVERSIONSUFFIX", sAboutBoxVersionSuffix );
502 941 : sRet = sRet.replaceAll( "%ABOUTBOXPRODUCTVERSION", sAboutBoxVersion );
503 1882 : sRet = sRet.replaceAll( "%PRODUCTEXTENSION", sExtension );
504 : }
505 :
506 680630 : if ( sRet.indexOf( "%OOOVENDOR" ) != -1 )
507 : {
508 0 : OUString sOOOVendor = OOOVendor::get();
509 :
510 0 : if ( sOOOVendor.isEmpty() )
511 : {
512 0 : sOOOVendor = utl::ConfigManager::getVendor();
513 : }
514 :
515 0 : sRet = sRet.replaceAll( "%OOOVENDOR", sOOOVendor );
516 : }
517 :
518 680630 : return sRet;
519 : }
520 :
521 116 : Desktop::Desktop()
522 : : m_bCleanedExtensionCache(false)
523 : , m_bServicesRegistered(false)
524 : , m_aBootstrapError(BE_OK)
525 116 : , m_aBootstrapStatus(BS_OK)
526 : {
527 116 : }
528 :
529 116 : Desktop::~Desktop()
530 : {
531 : #if ENABLE_TELEPATHY
532 : TeleManager::finalize();
533 : #endif
534 116 : }
535 :
536 116 : void Desktop::Init()
537 : {
538 116 : SetBootstrapStatus(BS_OK);
539 :
540 : #if HAVE_FEATURE_EXTENSIONS
541 116 : m_bCleanedExtensionCache = cleanExtensionCache();
542 : #endif
543 :
544 : // We need to have service factory before going further, but see fdo#37195.
545 : // Doing this will mmap common.rdb, making it not overwritable on windows,
546 : // so this can't happen before the synchronization above. Lets rework this
547 : // so that the above is called *from* CreateApplicationServiceManager or
548 : // something to enforce this gotcha
549 : try
550 : {
551 116 : InitApplicationServiceManager();
552 : }
553 0 : catch (css::uno::Exception & e)
554 : {
555 0 : SetBootstrapError( BE_UNO_SERVICEMANAGER, e.Message );
556 : }
557 :
558 116 : if ( m_aBootstrapError == BE_OK )
559 : {
560 : try
561 : {
562 116 : if (!langselect::prepareLocale())
563 : {
564 0 : SetBootstrapError( BE_LANGUAGE_MISSING, OUString() );
565 : }
566 : }
567 0 : catch (css::uno::Exception & e)
568 : {
569 0 : SetBootstrapError( BE_OFFICECONFIG_BROKEN, e.Message );
570 : }
571 : }
572 :
573 : if ( true )
574 : {
575 116 : const CommandLineArgs& rCmdLineArgs = GetCommandLineArgs();
576 :
577 : // start ipc thread only for non-remote offices
578 116 : OfficeIPCThread::Status aStatus = OfficeIPCThread::EnableOfficeIPCThread();
579 116 : if ( aStatus == OfficeIPCThread::IPC_STATUS_PIPE_ERROR )
580 : {
581 : #if HAVE_FEATURE_MACOSX_SANDBOX
582 : // In a sandboxed LO, on 10.8.2 at least, creating the
583 : // Unix domain socket fails. Ignore that as hopefully
584 : // people running a sandboxed LO won't attempt starting it
585 : // from the command-line or otherwise in tricky ways, so
586 : // the normal OS X mechanism that prevents multiple
587 : // instances of an app from being started should work
588 : // fine. I hope.
589 : #elif defined ANDROID
590 : // Ignore crack pipe errors on Android, too
591 : #else
592 : // Keep using this oddly named BE_PATHINFO_MISSING value
593 : // for pipe-related errors on other platforms. Of course
594 : // this crack with two (if not more) levels of our own
595 : // error codes hiding the actual system error code is
596 : // broken, but that is done all over the code, let's leave
597 : // re-enginering that to another year.
598 0 : SetBootstrapError( BE_PATHINFO_MISSING, OUString() );
599 : #endif
600 : }
601 116 : else if ( aStatus == OfficeIPCThread::IPC_STATUS_BOOTSTRAP_ERROR )
602 : {
603 0 : SetBootstrapError( BE_PATHINFO_MISSING, OUString() );
604 : }
605 116 : else if ( aStatus == OfficeIPCThread::IPC_STATUS_2ND_OFFICE )
606 : {
607 : // 2nd office startup should terminate after sending cmdlineargs through pipe
608 0 : SetBootstrapStatus(BS_TERMINATE);
609 : }
610 348 : else if ( !rCmdLineArgs.GetUnknown().isEmpty()
611 348 : || rCmdLineArgs.IsHelp() || rCmdLineArgs.IsVersion() )
612 : {
613 : // disable IPC thread in an instance that is just showing a help message
614 0 : OfficeIPCThread::DisableOfficeIPCThread();
615 : }
616 116 : pSignalHandler = osl_addSignalHandler(SalMainPipeExchangeSignal_impl, NULL);
617 : }
618 116 : }
619 :
620 611 : void Desktop::InitFinished()
621 : {
622 611 : CloseSplashScreen();
623 611 : }
624 :
625 116 : void Desktop::DeInit()
626 : {
627 : try {
628 : // instead of removing of the configManager just let it commit all the changes
629 116 : utl::ConfigManager::storeConfigItems();
630 116 : FlushConfiguration();
631 :
632 : // close splashscreen if it's still open
633 116 : CloseSplashScreen();
634 : Reference< XComponent >(
635 232 : comphelper::getProcessComponentContext(), UNO_QUERY_THROW )->
636 116 : dispose();
637 : // nobody should get a destroyed service factory...
638 116 : ::comphelper::setProcessServiceFactory( NULL );
639 :
640 : // clear lockfile
641 116 : m_xLockfile.reset();
642 :
643 116 : OfficeIPCThread::DisableOfficeIPCThread();
644 116 : if( pSignalHandler )
645 116 : osl_removeSignalHandler( pSignalHandler );
646 0 : } catch (const RuntimeException&) {
647 : // someone threw an exception during shutdown
648 : // this will leave some garbage behind..
649 : }
650 116 : }
651 :
652 0 : bool Desktop::QueryExit()
653 : {
654 : try
655 : {
656 0 : utl::ConfigManager::storeConfigItems();
657 : }
658 0 : catch ( const RuntimeException& )
659 : {
660 : }
661 :
662 0 : const sal_Char SUSPEND_QUICKSTARTVETO[] = "SuspendQuickstartVeto";
663 :
664 0 : Reference< XDesktop2 > xDesktop = css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
665 0 : Reference< XPropertySet > xPropertySet(xDesktop, UNO_QUERY_THROW);
666 0 : xPropertySet->setPropertyValue( OUString(SUSPEND_QUICKSTARTVETO ), Any(true) );
667 :
668 0 : bool bExit = xDesktop->terminate();
669 :
670 0 : if ( !bExit )
671 : {
672 0 : xPropertySet->setPropertyValue( OUString(SUSPEND_QUICKSTARTVETO ), Any(false) );
673 : }
674 : else
675 : {
676 0 : FlushConfiguration();
677 : try
678 : {
679 : // it is no problem to call DisableOfficeIPCThread() more than once
680 : // it also looks to be threadsafe
681 0 : OfficeIPCThread::DisableOfficeIPCThread();
682 : }
683 0 : catch ( const RuntimeException& )
684 : {
685 : }
686 :
687 0 : m_xLockfile.reset();
688 :
689 : }
690 :
691 0 : return bExit;
692 : }
693 :
694 0 : void Desktop::HandleBootstrapPathErrors( ::utl::Bootstrap::Status aBootstrapStatus, const OUString& aDiagnosticMessage )
695 : {
696 0 : if ( aBootstrapStatus != ::utl::Bootstrap::DATA_OK )
697 : {
698 0 : OUString aProductKey;
699 0 : OUString aTemp;
700 :
701 0 : osl_getExecutableFile( &aProductKey.pData );
702 0 : sal_uInt32 lastIndex = aProductKey.lastIndexOf('/');
703 0 : if ( lastIndex > 0 )
704 0 : aProductKey = aProductKey.copy( lastIndex+1 );
705 :
706 0 : aTemp = ::utl::Bootstrap::getProductKey( aProductKey );
707 0 : if ( !aTemp.isEmpty() )
708 0 : aProductKey = aTemp;
709 :
710 0 : OUString const aMessage(aDiagnosticMessage + "\n");
711 :
712 0 : ScopedVclPtrInstance< MessageDialog > aBootstrapFailedBox(nullptr, aMessage);
713 0 : aBootstrapFailedBox->SetText( aProductKey );
714 0 : aBootstrapFailedBox->Execute();
715 : }
716 0 : }
717 :
718 : // Create a error message depending on bootstrap failure code and an optional file url
719 0 : OUString Desktop::CreateErrorMsgString(
720 : utl::Bootstrap::FailureCode nFailureCode,
721 : const OUString& aFileURL )
722 : {
723 0 : OUString aMsg;
724 0 : OUString aFilePath;
725 0 : bool bFileInfo = true;
726 :
727 0 : switch ( nFailureCode )
728 : {
729 : /// the shared installation directory could not be located
730 : case ::utl::Bootstrap::MISSING_INSTALL_DIRECTORY:
731 : {
732 0 : aMsg = GetMsgString( STR_BOOTSTRAP_ERR_PATH_INVALID,
733 0 : OUString( "The installation path is not available." ) );
734 0 : bFileInfo = false;
735 : }
736 0 : break;
737 :
738 : /// the bootstrap INI file could not be found or read
739 : case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE:
740 : {
741 0 : aMsg = GetMsgString( STR_BOOTSTRAP_ERR_FILE_MISSING,
742 0 : OUString( "The configuration file \"$1\" is missing." ) );
743 : }
744 0 : break;
745 :
746 : /// the bootstrap INI is missing a required entry
747 : /// the bootstrap INI contains invalid data
748 : case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE_ENTRY:
749 : case ::utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY:
750 : {
751 0 : aMsg = GetMsgString( STR_BOOTSTRAP_ERR_FILE_CORRUPT,
752 0 : OUString( "The configuration file \"$1\" is corrupt." ) );
753 : }
754 0 : break;
755 :
756 : /// the version locator INI file could not be found or read
757 : case ::utl::Bootstrap::MISSING_VERSION_FILE:
758 : {
759 0 : aMsg = GetMsgString( STR_BOOTSTRAP_ERR_FILE_MISSING,
760 0 : OUString( "The configuration file \"$1\" is missing." ) );
761 : }
762 0 : break;
763 :
764 : /// the version locator INI has no entry for this version
765 : case ::utl::Bootstrap::MISSING_VERSION_FILE_ENTRY:
766 : {
767 0 : aMsg = GetMsgString( STR_BOOTSTRAP_ERR_NO_SUPPORT,
768 0 : OUString( "The main configuration file \"$1\" does not support the current version." ) );
769 : }
770 0 : break;
771 :
772 : /// the user installation directory does not exist
773 : case ::utl::Bootstrap::MISSING_USER_DIRECTORY:
774 : {
775 0 : aMsg = GetMsgString( STR_BOOTSTRAP_ERR_DIR_MISSING,
776 0 : OUString( "The configuration directory \"$1\" is missing." ) );
777 : }
778 0 : break;
779 :
780 : /// some bootstrap data was invalid in unexpected ways
781 : case ::utl::Bootstrap::INVALID_BOOTSTRAP_DATA:
782 : {
783 0 : aMsg = GetMsgString( STR_BOOTSTRAP_ERR_INTERNAL,
784 0 : OUString( "An internal failure occurred." ) );
785 0 : bFileInfo = false;
786 : }
787 0 : break;
788 :
789 : case ::utl::Bootstrap::INVALID_VERSION_FILE_ENTRY:
790 : {
791 : // This needs to be improved, see #i67575#:
792 0 : aMsg = "Invalid version file entry";
793 0 : bFileInfo = false;
794 : }
795 0 : break;
796 :
797 : case ::utl::Bootstrap::NO_FAILURE:
798 : {
799 : OSL_ASSERT(false);
800 : }
801 0 : break;
802 : }
803 :
804 0 : if ( bFileInfo )
805 : {
806 0 : OUString aMsgString( aMsg );
807 :
808 0 : osl::File::getSystemPathFromFileURL( aFileURL, aFilePath );
809 :
810 0 : aMsgString = aMsgString.replaceFirst( "$1", aFilePath );
811 0 : aMsg = aMsgString;
812 : }
813 :
814 0 : return MakeStartupErrorMessage( aMsg );
815 : }
816 :
817 0 : void Desktop::HandleBootstrapErrors(
818 : BootstrapError aBootstrapError, OUString const & aErrorMessage )
819 : {
820 0 : if ( aBootstrapError == BE_PATHINFO_MISSING )
821 : {
822 0 : OUString aErrorMsg;
823 0 : OUString aBuffer;
824 : utl::Bootstrap::Status aBootstrapStatus;
825 : utl::Bootstrap::FailureCode nFailureCode;
826 :
827 0 : aBootstrapStatus = ::utl::Bootstrap::checkBootstrapStatus( aBuffer, nFailureCode );
828 0 : if ( aBootstrapStatus != ::utl::Bootstrap::DATA_OK )
829 : {
830 0 : switch ( nFailureCode )
831 : {
832 : case ::utl::Bootstrap::MISSING_INSTALL_DIRECTORY:
833 : case ::utl::Bootstrap::INVALID_BOOTSTRAP_DATA:
834 : {
835 0 : aErrorMsg = CreateErrorMsgString( nFailureCode, OUString() );
836 : }
837 0 : break;
838 :
839 : /// the bootstrap INI file could not be found or read
840 : /// the bootstrap INI is missing a required entry
841 : /// the bootstrap INI contains invalid data
842 : case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE_ENTRY:
843 : case ::utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY:
844 : case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE:
845 : {
846 0 : OUString aBootstrapFileURL;
847 :
848 0 : utl::Bootstrap::locateBootstrapFile( aBootstrapFileURL );
849 0 : aErrorMsg = CreateErrorMsgString( nFailureCode, aBootstrapFileURL );
850 : }
851 0 : break;
852 :
853 : /// the version locator INI file could not be found or read
854 : /// the version locator INI has no entry for this version
855 : /// the version locator INI entry is not a valid directory URL
856 : case ::utl::Bootstrap::INVALID_VERSION_FILE_ENTRY:
857 : case ::utl::Bootstrap::MISSING_VERSION_FILE_ENTRY:
858 : case ::utl::Bootstrap::MISSING_VERSION_FILE:
859 : {
860 0 : OUString aVersionFileURL;
861 :
862 0 : utl::Bootstrap::locateVersionFile( aVersionFileURL );
863 0 : aErrorMsg = CreateErrorMsgString( nFailureCode, aVersionFileURL );
864 : }
865 0 : break;
866 :
867 : /// the user installation directory does not exist
868 : case ::utl::Bootstrap::MISSING_USER_DIRECTORY:
869 : {
870 0 : OUString aUserInstallationURL;
871 :
872 0 : utl::Bootstrap::locateUserInstallation( aUserInstallationURL );
873 0 : aErrorMsg = CreateErrorMsgString( nFailureCode, aUserInstallationURL );
874 : }
875 0 : break;
876 :
877 : case ::utl::Bootstrap::NO_FAILURE:
878 : {
879 : OSL_ASSERT(false);
880 : }
881 0 : break;
882 : }
883 :
884 0 : HandleBootstrapPathErrors( aBootstrapStatus, aErrorMsg );
885 0 : }
886 : }
887 0 : else if ( aBootstrapError == BE_UNO_SERVICEMANAGER || aBootstrapError == BE_UNO_SERVICE_CONFIG_MISSING )
888 : {
889 : // Uno service manager is not available. VCL needs a uno service manager to display a message box!!!
890 : // Currently we are not able to display a message box with a service manager due to this limitations inside VCL.
891 :
892 : // When UNO is not properly initialized, all kinds of things can fail
893 : // and cause the process to crash (e.g., a call to GetMsgString may
894 : // crash when somewhere deep within that call Any::operator <= is used
895 : // with a PropertyValue, and no binary UNO type description for
896 : // PropertyValue is available). To give the user a hint even if
897 : // generating and displaying a message box below crashes, print a
898 : // hard-coded message on stderr first:
899 : std::cerr
900 0 : << "The application cannot be started.\n"
901 : // STR_BOOTSTRAP_ERR_CANNOT_START
902 : << (aBootstrapError == BE_UNO_SERVICEMANAGER
903 : ? "The component manager is not available.\n"
904 : // STR_BOOTSTRAP_ERR_NO_SERVICE
905 0 : : "The configuration service is not available.\n");
906 : // STR_BOOTSTRAP_ERR_NO_CFG_SERVICE
907 0 : if ( !aErrorMessage.isEmpty() )
908 : {
909 0 : std::cerr << "(\"" << aErrorMessage << "\")\n";
910 : }
911 :
912 : // First sentence. We cannot bootstrap office further!
913 0 : OUString aMessage;
914 0 : OUStringBuffer aDiagnosticMessage( 100 );
915 :
916 0 : OUString aErrorMsg;
917 :
918 0 : if ( aBootstrapError == BE_UNO_SERVICEMANAGER )
919 0 : aErrorMsg = "The service manager is not available.";
920 : else
921 0 : aErrorMsg = GetMsgString( STR_BOOTSTRAP_ERR_NO_CFG_SERVICE,
922 0 : OUString( "The configuration service is not available." ) );
923 :
924 0 : aDiagnosticMessage.append( aErrorMsg );
925 0 : aDiagnosticMessage.appendAscii( "\n" );
926 0 : if ( !aErrorMessage.isEmpty() )
927 : {
928 0 : aDiagnosticMessage.appendAscii( "(\"" );
929 0 : aDiagnosticMessage.append( aErrorMessage );
930 0 : aDiagnosticMessage.appendAscii( "\")\n" );
931 : }
932 :
933 : // Due to the fact the we haven't a backup applicat.rdb file anymore it is not possible to
934 : // repair the installation with the setup executable besides the office executable. Now
935 : // we have to ask the user to start the setup on CD/installation directory manually!!
936 : OUString aStartSetupManually( GetMsgString(
937 : STR_ASK_START_SETUP_MANUALLY,
938 : OUString( "Start setup application to repair the installation from CD, or the folder containing the installation packages." ),
939 0 : aBootstrapError == BE_UNO_SERVICEMANAGER ) );
940 :
941 0 : aDiagnosticMessage.append( aStartSetupManually );
942 0 : aMessage = MakeStartupErrorMessage(
943 : aDiagnosticMessage.makeStringAndClear(),
944 0 : aBootstrapError == BE_UNO_SERVICEMANAGER );
945 :
946 0 : FatalError( aMessage);
947 : }
948 0 : else if ( aBootstrapError == BE_OFFICECONFIG_BROKEN )
949 : {
950 : OUString msg(
951 : GetMsgString(
952 : STR_CONFIG_ERR_ACCESS_GENERAL,
953 : ("A general error occurred while accessing your central"
954 0 : " configuration.")));
955 0 : if (!aErrorMessage.isEmpty()) {
956 0 : msg += "\n(\"" + aErrorMessage + "\")";
957 : }
958 0 : FatalError(MakeStartupErrorMessage(msg));
959 : }
960 0 : else if ( aBootstrapError == BE_USERINSTALL_FAILED )
961 : {
962 0 : OUString aMessage;
963 0 : OUStringBuffer aDiagnosticMessage( 100 );
964 0 : OUString aErrorMsg;
965 0 : aErrorMsg = GetMsgString( STR_BOOTSTRAP_ERR_USERINSTALL_FAILED,
966 0 : OUString( "User installation could not be completed" ) );
967 0 : aDiagnosticMessage.append( aErrorMsg );
968 0 : aMessage = MakeStartupErrorMessage( aDiagnosticMessage.makeStringAndClear() );
969 0 : FatalError(aMessage);
970 : }
971 0 : else if ( aBootstrapError == BE_LANGUAGE_MISSING )
972 : {
973 0 : OUString aMessage;
974 0 : OUStringBuffer aDiagnosticMessage( 100 );
975 0 : OUString aErrorMsg;
976 0 : aErrorMsg = GetMsgString(
977 : //@@@ FIXME: should use an own resource string => #i36213#
978 : STR_BOOTSTRAP_ERR_LANGUAGE_MISSING,
979 0 : OUString( "Language could not be determined." ) );
980 0 : aDiagnosticMessage.append( aErrorMsg );
981 0 : aMessage = MakeStartupErrorMessage(
982 0 : aDiagnosticMessage.makeStringAndClear() );
983 0 : FatalError(aMessage);
984 : }
985 0 : else if (( aBootstrapError == BE_USERINSTALL_NOTENOUGHDISKSPACE ) ||
986 : ( aBootstrapError == BE_USERINSTALL_NOWRITEACCESS ))
987 : {
988 0 : OUString aUserInstallationURL;
989 0 : OUString aUserInstallationPath;
990 0 : OUString aMessage;
991 0 : OUString aErrorMsg;
992 0 : OUStringBuffer aDiagnosticMessage( 100 );
993 :
994 0 : utl::Bootstrap::locateUserInstallation( aUserInstallationURL );
995 :
996 0 : if ( aBootstrapError == BE_USERINSTALL_NOTENOUGHDISKSPACE )
997 0 : aErrorMsg = GetMsgString(
998 : STR_BOOSTRAP_ERR_NOTENOUGHDISKSPACE,
999 0 : OUString( "User installation could not be completed due to insufficient free disk space." ) );
1000 : else
1001 0 : aErrorMsg = GetMsgString(
1002 : STR_BOOSTRAP_ERR_NOACCESSRIGHTS,
1003 0 : OUString( "User installation could not be processed due to missing access rights." ) );
1004 :
1005 0 : osl::File::getSystemPathFromFileURL( aUserInstallationURL, aUserInstallationPath );
1006 :
1007 0 : aDiagnosticMessage.append( aErrorMsg );
1008 0 : aDiagnosticMessage.append( aUserInstallationPath );
1009 0 : aMessage = MakeStartupErrorMessage(
1010 0 : aDiagnosticMessage.makeStringAndClear() );
1011 0 : FatalError(aMessage);
1012 : }
1013 :
1014 0 : return;
1015 : }
1016 :
1017 :
1018 0 : bool Desktop::isUIOnSessionShutdownAllowed()
1019 : {
1020 : return officecfg::Office::Recovery::SessionShutdown::DocumentStoreUIEnabled
1021 0 : ::get();
1022 : }
1023 :
1024 :
1025 : /** @short check if recovery must be started or not.
1026 :
1027 : @param bCrashed [boolean ... out!]
1028 : the office crashed last times.
1029 : But may be there are no recovery data.
1030 : Useful to trigger the error report tool without
1031 : showing the recovery UI.
1032 :
1033 : @param bRecoveryDataExists [boolean ... out!]
1034 : there exists some recovery data.
1035 :
1036 : @param bSessionDataExists [boolean ... out!]
1037 : there exists some session data.
1038 : Because the user may be logged out last time from it's
1039 : unix session...
1040 : */
1041 116 : void impl_checkRecoveryState(bool& bCrashed ,
1042 : bool& bRecoveryDataExists,
1043 : bool& bSessionDataExists )
1044 : {
1045 116 : bCrashed = officecfg::Office::Recovery::RecoveryInfo::Crashed::get();
1046 232 : bool elements = officecfg::Office::Recovery::RecoveryList::get()->
1047 116 : hasElements();
1048 : bool session
1049 116 : = officecfg::Office::Recovery::RecoveryInfo::SessionData::get();
1050 116 : bRecoveryDataExists = elements && !session;
1051 116 : bSessionDataExists = elements && session;
1052 116 : }
1053 :
1054 :
1055 : /* @short start the recovery wizard.
1056 :
1057 : @param bEmergencySave
1058 : differs between EMERGENCY_SAVE and RECOVERY
1059 : */
1060 0 : bool impl_callRecoveryUI(bool bEmergencySave ,
1061 : bool bExistsRecoveryData)
1062 : {
1063 : static const char SERVICENAME_RECOVERYUI[] = "com.sun.star.comp.svx.RecoveryUI";
1064 : static const char COMMAND_EMERGENCYSAVE[] = "vnd.sun.star.autorecovery:/doEmergencySave";
1065 : static const char COMMAND_RECOVERY[] = "vnd.sun.star.autorecovery:/doAutoRecovery";
1066 :
1067 0 : css::uno::Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
1068 :
1069 : Reference< css::frame::XSynchronousDispatch > xRecoveryUI(
1070 0 : xContext->getServiceManager()->createInstanceWithContext(SERVICENAME_RECOVERYUI, xContext),
1071 0 : css::uno::UNO_QUERY_THROW);
1072 :
1073 : Reference< css::util::XURLTransformer > xURLParser =
1074 0 : css::util::URLTransformer::create(::comphelper::getProcessComponentContext());
1075 :
1076 0 : css::util::URL aURL;
1077 0 : if (bEmergencySave)
1078 0 : aURL.Complete = COMMAND_EMERGENCYSAVE;
1079 0 : else if (bExistsRecoveryData)
1080 0 : aURL.Complete = COMMAND_RECOVERY;
1081 : else
1082 0 : return false;
1083 :
1084 0 : xURLParser->parseStrict(aURL);
1085 :
1086 0 : css::uno::Any aRet = xRecoveryUI->dispatchWithReturnValue(aURL, css::uno::Sequence< css::beans::PropertyValue >());
1087 0 : bool bRet = false;
1088 0 : aRet >>= bRet;
1089 0 : return !bEmergencySave || bRet;
1090 : }
1091 :
1092 : /*
1093 : * Save all open documents so they will be reopened
1094 : * the next time the application is started
1095 : *
1096 : * returns sal_True if at least one document could be saved...
1097 : *
1098 : */
1099 :
1100 0 : bool Desktop::SaveTasks()
1101 : {
1102 : return impl_callRecoveryUI(
1103 : true , // sal_True => force emergency save
1104 0 : false);
1105 : }
1106 :
1107 : namespace {
1108 :
1109 52 : void restartOnMac(bool passArguments) {
1110 : #if defined MACOSX
1111 : OfficeIPCThread::DisableOfficeIPCThread();
1112 : #if HAVE_FEATURE_MACOSX_SANDBOX
1113 : (void) passArguments; // avoid warnings
1114 : ResMgr *resMgr = Desktop::GetDesktopResManager();
1115 : OUString aMessage = ResId(STR_LO_MUST_BE_RESTARTED, *resMgr).toString();
1116 :
1117 : MessageDialog aRestartBox(NULL, aMessage);
1118 : aRestartBox.Execute();
1119 : #else
1120 : OUString execUrl;
1121 : OSL_VERIFY(osl_getExecutableFile(&execUrl.pData) == osl_Process_E_None);
1122 : OUString execPath;
1123 : OString execPath8;
1124 : if ((osl::FileBase::getSystemPathFromFileURL(execUrl, execPath)
1125 : != osl::FileBase::E_None) ||
1126 : !execPath.convertToString(
1127 : &execPath8, osl_getThreadTextEncoding(),
1128 : (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
1129 : RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
1130 : {
1131 : std::abort();
1132 : }
1133 : std::vector< OString > args;
1134 : args.push_back(execPath8);
1135 : bool wait = false;
1136 : if (passArguments) {
1137 : sal_uInt32 n = osl_getCommandArgCount();
1138 : for (sal_uInt32 i = 0; i < n; ++i) {
1139 : OUString arg;
1140 : osl_getCommandArg(i, &arg.pData);
1141 : if (arg.match("--accept=")) {
1142 : wait = true;
1143 : }
1144 : OString arg8;
1145 : if (!arg.convertToString(
1146 : &arg8, osl_getThreadTextEncoding(),
1147 : (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
1148 : RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
1149 : {
1150 : std::abort();
1151 : }
1152 : args.push_back(arg8);
1153 : }
1154 : }
1155 : std::vector< char const * > argPtrs;
1156 : for (std::vector< OString >::iterator i(args.begin()); i != args.end();
1157 : ++i)
1158 : {
1159 : argPtrs.push_back(i->getStr());
1160 : }
1161 : argPtrs.push_back(0);
1162 : execv(execPath8.getStr(), const_cast< char ** >(&argPtrs[0]));
1163 : if (errno == ENOTSUP) { // happens when multithreaded on OS X < 10.6
1164 : pid_t pid = fork();
1165 : if (pid == 0) {
1166 : execv(execPath8.getStr(), const_cast< char ** >(&argPtrs[0]));
1167 : } else if (pid > 0) {
1168 : // Two simultaneously running soffice processes lead to two dock
1169 : // icons, so avoid waiting here unless it must be assumed that the
1170 : // process invoking soffice itself wants to wait for soffice to
1171 : // finish:
1172 : if (!wait) {
1173 : return;
1174 : }
1175 : int stat;
1176 : if (waitpid(pid, &stat, 0) == pid && WIFEXITED(stat)) {
1177 : _exit(WEXITSTATUS(stat));
1178 : }
1179 : }
1180 : }
1181 : std::abort();
1182 : #endif
1183 : #else
1184 : (void) passArguments; // avoid warnings
1185 : #endif
1186 52 : }
1187 :
1188 : }
1189 :
1190 0 : sal_uInt16 Desktop::Exception(sal_uInt16 nError)
1191 : {
1192 : // protect against recursive calls
1193 : static bool bInException = false;
1194 :
1195 0 : SystemWindowFlags nOldMode = Application::GetSystemWindowMode();
1196 0 : Application::SetSystemWindowMode( nOldMode & ~SystemWindowFlags::NOAUTOMODE );
1197 0 : Application::SetDefDialogParent( NULL );
1198 :
1199 0 : if ( bInException )
1200 : {
1201 0 : OUString aDoubleExceptionString;
1202 0 : Application::Abort( aDoubleExceptionString );
1203 : }
1204 :
1205 0 : bInException = true;
1206 0 : const CommandLineArgs& rArgs = GetCommandLineArgs();
1207 :
1208 : // save all modified documents ... if it's allowed doing so.
1209 0 : bool bRestart = false;
1210 : bool bAllowRecoveryAndSessionManagement = (
1211 0 : ( !rArgs.IsNoRestore() ) && // some use cases of office must work without recovery
1212 0 : ( !rArgs.IsHeadless() ) &&
1213 0 : (( nError & EXC_MAJORTYPE ) != EXC_DISPLAY ) && // recovery can't work without UI ... but UI layer seems to be the reason for this crash
1214 0 : ( Application::IsInExecute() ) // crashes during startup and shutdown should be ignored (they indicates a corrupt installation ...)
1215 0 : );
1216 0 : if ( bAllowRecoveryAndSessionManagement )
1217 0 : bRestart = SaveTasks();
1218 :
1219 0 : FlushConfiguration();
1220 :
1221 0 : switch( nError & EXC_MAJORTYPE )
1222 : {
1223 : case EXC_RSCNOTLOADED:
1224 : {
1225 0 : OUString aResExceptionString;
1226 0 : Application::Abort( aResExceptionString );
1227 0 : break;
1228 : }
1229 :
1230 : default:
1231 : {
1232 0 : m_xLockfile.reset();
1233 :
1234 0 : if( bRestart )
1235 : {
1236 0 : OfficeIPCThread::DisableOfficeIPCThread();
1237 0 : if( pSignalHandler )
1238 0 : osl_removeSignalHandler( pSignalHandler );
1239 :
1240 0 : restartOnMac(false);
1241 0 : if ( m_rSplashScreen.is() )
1242 0 : m_rSplashScreen->reset();
1243 :
1244 0 : _exit( EXITHELPER_CRASH_WITH_RESTART );
1245 : }
1246 : else
1247 : {
1248 0 : Application::Abort( OUString() );
1249 : }
1250 :
1251 0 : break;
1252 : }
1253 : }
1254 :
1255 : OSL_ASSERT(false); // unreachable
1256 0 : return 0;
1257 : }
1258 :
1259 0 : void Desktop::AppEvent( const ApplicationEvent& rAppEvent )
1260 : {
1261 0 : HandleAppEvent( rAppEvent );
1262 0 : }
1263 :
1264 :
1265 116 : struct ExecuteGlobals
1266 : {
1267 : Reference < css::document::XDocumentEventListener > xGlobalBroadcaster;
1268 : bool bRestartRequested;
1269 : bool bUseSystemFileDialog;
1270 : std::unique_ptr<SvtLanguageOptions> pLanguageOptions;
1271 : std::unique_ptr<SvtPathOptions> pPathOptions;
1272 :
1273 116 : ExecuteGlobals()
1274 : : bRestartRequested( false )
1275 116 : , bUseSystemFileDialog( true )
1276 116 : {}
1277 : };
1278 :
1279 : static ExecuteGlobals* pExecGlobals = NULL;
1280 :
1281 116 : int Desktop::Main()
1282 : {
1283 116 : pExecGlobals = new ExecuteGlobals();
1284 :
1285 : // Remember current context object
1286 : com::sun::star::uno::ContextLayer layer(
1287 116 : com::sun::star::uno::getCurrentContext() );
1288 :
1289 116 : if ( m_aBootstrapError != BE_OK )
1290 : {
1291 0 : HandleBootstrapErrors( m_aBootstrapError, m_aBootstrapErrorMessage );
1292 0 : return EXIT_FAILURE;
1293 : }
1294 :
1295 116 : BootstrapStatus eStatus = GetBootstrapStatus();
1296 116 : if (eStatus == BS_TERMINATE) {
1297 0 : return EXIT_SUCCESS;
1298 : }
1299 :
1300 : // Detect desktop environment - need to do this as early as possible
1301 : com::sun::star::uno::setCurrentContext(
1302 116 : new DesktopContext( com::sun::star::uno::getCurrentContext() ) );
1303 :
1304 116 : CommandLineArgs& rCmdLineArgs = GetCommandLineArgs();
1305 :
1306 : #if HAVE_FEATURE_DESKTOP
1307 232 : OUString aUnknown( rCmdLineArgs.GetUnknown() );
1308 116 : if ( !aUnknown.isEmpty() )
1309 : {
1310 0 : displayCmdlineHelp( aUnknown );
1311 0 : return EXIT_FAILURE;
1312 : }
1313 116 : if ( rCmdLineArgs.IsHelp() )
1314 : {
1315 0 : displayCmdlineHelp( OUString() );
1316 0 : return EXIT_SUCCESS;
1317 : }
1318 116 : if ( rCmdLineArgs.IsVersion() )
1319 : {
1320 0 : displayVersion();
1321 0 : return EXIT_SUCCESS;
1322 : }
1323 : #endif
1324 : // setup configuration error handling
1325 232 : ConfigurationErrorHandler aConfigErrHandler;
1326 116 : if (!ShouldSuppressUI(rCmdLineArgs))
1327 0 : aConfigErrHandler.activate();
1328 :
1329 116 : ResMgr::SetReadStringHook( ReplaceStringHookProc );
1330 :
1331 : // Startup screen
1332 116 : OpenSplashScreen();
1333 :
1334 116 : SetSplashScreenProgress(10);
1335 :
1336 116 : userinstall::Status inst_fin = userinstall::finalize();
1337 116 : if (inst_fin != userinstall::EXISTED && inst_fin != userinstall::CREATED)
1338 : {
1339 : SAL_WARN( "desktop.app", "userinstall failed");
1340 0 : if ( inst_fin == userinstall::ERROR_NO_SPACE )
1341 : HandleBootstrapErrors(
1342 0 : BE_USERINSTALL_NOTENOUGHDISKSPACE, OUString() );
1343 0 : else if ( inst_fin == userinstall::ERROR_CANT_WRITE )
1344 0 : HandleBootstrapErrors( BE_USERINSTALL_NOWRITEACCESS, OUString() );
1345 : else
1346 0 : HandleBootstrapErrors( BE_USERINSTALL_FAILED, OUString() );
1347 0 : return EXIT_FAILURE;
1348 : }
1349 : // refresh path information
1350 116 : utl::Bootstrap::reloadData();
1351 116 : SetSplashScreenProgress(20);
1352 :
1353 232 : Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
1354 :
1355 232 : Reference< XRestartManager > xRestartManager( OfficeRestartManager::get(xContext) );
1356 :
1357 232 : Reference< XDesktop2 > xDesktop;
1358 : try
1359 : {
1360 116 : RegisterServices(xContext);
1361 :
1362 116 : SetSplashScreenProgress(25);
1363 :
1364 : #if HAVE_FEATURE_DESKTOP
1365 : // check user installation directory for lockfile so we can be sure
1366 : // there is no other instance using our data files from a remote host
1367 116 : m_xLockfile.reset(new Lockfile);
1368 :
1369 232 : if ( !rCmdLineArgs.IsHeadless() && !rCmdLineArgs.IsInvisible() &&
1370 116 : !rCmdLineArgs.IsNoLockcheck() && !m_xLockfile->check( Lockfile_execWarning ))
1371 : {
1372 : // Lockfile exists, and user clicked 'no'
1373 0 : return EXIT_FAILURE;
1374 : }
1375 :
1376 : // check if accessibility is enabled but not working and allow to quit
1377 116 : if( Application::GetSettings().GetMiscSettings().GetEnableATToolSupport() )
1378 : {
1379 0 : if( !InitAccessBridge() )
1380 0 : return EXIT_FAILURE;
1381 : }
1382 : #endif
1383 :
1384 : // terminate if requested...
1385 116 : if( rCmdLineArgs.IsTerminateAfterInit() )
1386 0 : return EXIT_SUCCESS;
1387 :
1388 : // Read the common configuration items for optimization purpose
1389 116 : if ( !InitializeConfiguration() )
1390 0 : return EXIT_FAILURE;
1391 :
1392 116 : SetSplashScreenProgress(30);
1393 :
1394 : // set static variable to disable crash reporting
1395 116 : osl_setErrorReporting( false );
1396 :
1397 : // create title string
1398 116 : LanguageTag aLocale( LANGUAGE_SYSTEM);
1399 116 : ResMgr* pLabelResMgr = GetDesktopResManager();
1400 232 : OUString aTitle = pLabelResMgr ? ResId(RID_APPTITLE, *pLabelResMgr).toString() : OUString();
1401 :
1402 : #ifdef DBG_UTIL
1403 : //include buildid in non product builds
1404 : OUString aDefault("development");
1405 : aTitle += " [";
1406 : aTitle += utl::Bootstrap::getBuildIdData(aDefault);
1407 : aTitle += "]";
1408 : #endif
1409 :
1410 116 : SetDisplayName( aTitle );
1411 116 : SetSplashScreenProgress(35);
1412 116 : pExecGlobals->pPathOptions.reset( new SvtPathOptions);
1413 116 : SetSplashScreenProgress(40);
1414 :
1415 116 : xDesktop = css::frame::Desktop::create( xContext );
1416 :
1417 : // create service for loadin SFX (still needed in startup)
1418 232 : pExecGlobals->xGlobalBroadcaster = Reference < css::document::XDocumentEventListener >
1419 116 : ( css::frame::theGlobalEventBroadcaster::get(xContext), UNO_SET_THROW );
1420 :
1421 : /* ensure existence of a default window that messages can be dispatched to
1422 : This is for the benefit of testtool which uses PostUserEvent extensively
1423 : and else can deadlock while creating this window from another tread while
1424 : the main thread is not yet in the event loop.
1425 : */
1426 116 : Application::GetDefaultDevice();
1427 :
1428 : #if HAVE_FEATURE_EXTENSIONS
1429 : // Check if bundled or shared extensions were added /removed
1430 : // and process those extensions (has to be done before checking
1431 : // the extension dependencies!
1432 116 : SynchronizeExtensionRepositories();
1433 116 : bool bAbort = CheckExtensionDependencies();
1434 116 : if ( bAbort )
1435 0 : return EXIT_FAILURE;
1436 :
1437 116 : if (inst_fin == userinstall::CREATED)
1438 : {
1439 53 : Migration::migrateSettingsIfNecessary();
1440 : }
1441 : #endif
1442 :
1443 : // keep a language options instance...
1444 116 : pExecGlobals->pLanguageOptions.reset( new SvtLanguageOptions(true));
1445 :
1446 232 : css::document::DocumentEvent aEvent;
1447 116 : aEvent.EventName = "OnStartApp";
1448 116 : pExecGlobals->xGlobalBroadcaster->documentEventOccured(aEvent);
1449 :
1450 116 : SetSplashScreenProgress(50);
1451 :
1452 : // Backing Component
1453 116 : bool bCrashed = false;
1454 116 : bool bExistsRecoveryData = false;
1455 116 : bool bExistsSessionData = false;
1456 :
1457 116 : impl_checkRecoveryState(bCrashed, bExistsRecoveryData, bExistsSessionData);
1458 :
1459 232 : OUString pidfileName = rCmdLineArgs.GetPidfileName();
1460 116 : if ( !pidfileName.isEmpty() )
1461 : {
1462 0 : OUString pidfileURL;
1463 :
1464 0 : if ( osl_getFileURLFromSystemPath(pidfileName.pData, &pidfileURL.pData) == osl_File_E_None )
1465 : {
1466 0 : osl::File pidfile( pidfileURL );
1467 : osl::FileBase::RC rc;
1468 :
1469 0 : osl::File::remove( pidfileURL );
1470 0 : if ( (rc = pidfile.open( osl_File_OpenFlag_Write | osl_File_OpenFlag_Create ) ) == osl::File::E_None )
1471 : {
1472 0 : OString pid( OString::number( GETPID() ) );
1473 0 : sal_uInt64 written = 0;
1474 0 : if ( pidfile.write(pid.getStr(), pid.getLength(), written) != osl::File::E_None )
1475 : {
1476 : SAL_WARN("desktop.app", "cannot write pidfile " << pidfile.getURL());
1477 : }
1478 0 : pidfile.close();
1479 : }
1480 : else
1481 : {
1482 : SAL_WARN("desktop.app", "cannot open pidfile " << pidfile.getURL() << osl::FileBase::RC(rc));
1483 0 : }
1484 : }
1485 : else
1486 : {
1487 : SAL_WARN("desktop.app", "cannot get pidfile URL from path" << pidfileName);
1488 0 : }
1489 : }
1490 :
1491 116 : if ( rCmdLineArgs.IsHeadless() )
1492 : {
1493 : // Ensure that we use not the system file dialogs as
1494 : // headless mode relies on Application::EnableHeadlessMode()
1495 : // which does only work for VCL dialogs!!
1496 116 : SvtMiscOptions aMiscOptions;
1497 116 : pExecGlobals->bUseSystemFileDialog = aMiscOptions.UseSystemFileDialog();
1498 116 : aMiscOptions.SetUseSystemFileDialog( false );
1499 : }
1500 :
1501 116 : pExecGlobals->bRestartRequested = xRestartManager->isRestartRequested(
1502 232 : true);
1503 116 : if ( !pExecGlobals->bRestartRequested )
1504 : {
1505 319 : if ((!rCmdLineArgs.WantsToLoadDocument() && !rCmdLineArgs.IsInvisible() && !rCmdLineArgs.IsHeadless() && !rCmdLineArgs.IsQuickstart()) &&
1506 64 : (SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::EModule::STARTMODULE)) &&
1507 0 : (!bExistsRecoveryData ) &&
1508 128 : (!bExistsSessionData ) &&
1509 0 : (!Application::AnyInput( VclInputFlags::APPEVENT ) ))
1510 : {
1511 0 : ShowBackingComponent(this);
1512 : }
1513 116 : }
1514 : }
1515 0 : catch ( const com::sun::star::lang::WrappedTargetException& wte )
1516 : {
1517 0 : com::sun::star::uno::Exception te;
1518 0 : wte.TargetException >>= te;
1519 0 : FatalError( MakeStartupConfigAccessErrorMessage(wte.Message + te.Message) );
1520 : }
1521 0 : catch ( const com::sun::star::uno::Exception& e )
1522 : {
1523 0 : FatalError( MakeStartupErrorMessage(e.Message) );
1524 : }
1525 116 : SetSplashScreenProgress(55);
1526 :
1527 116 : SvtFontSubstConfig().Apply();
1528 :
1529 232 : SvtTabAppearanceCfg aAppearanceCfg;
1530 116 : SvtTabAppearanceCfg::SetInitialized();
1531 116 : aAppearanceCfg.SetApplicationDefaults( this );
1532 232 : SvtAccessibilityOptions aOptions;
1533 116 : aOptions.SetVCLSettings();
1534 116 : SetSplashScreenProgress(60);
1535 :
1536 : #if ENABLE_TELEPATHY
1537 : bool bListen = rCmdLineArgs.IsInvisible();
1538 : TeleManager::init( bListen );
1539 : #endif
1540 :
1541 116 : if ( !pExecGlobals->bRestartRequested )
1542 : {
1543 64 : Application::SetFilterHdl( LINK( this, Desktop, ImplInitFilterHdl ) );
1544 64 : bool bTerminateRequested = false;
1545 :
1546 : // Preload function depends on an initialized sfx application!
1547 64 : SetSplashScreenProgress(75);
1548 :
1549 : // use system window dialogs
1550 64 : Application::SetSystemWindowMode( SystemWindowFlags::DIALOG );
1551 :
1552 64 : SetSplashScreenProgress(80);
1553 :
1554 64 : if ( !bTerminateRequested && !rCmdLineArgs.IsInvisible() &&
1555 0 : !rCmdLineArgs.IsNoQuickstart() )
1556 0 : InitializeQuickstartMode( xContext );
1557 :
1558 : try
1559 : {
1560 64 : if ( xDesktop.is() )
1561 64 : xDesktop->addTerminateListener( new OfficeIPCThreadController );
1562 64 : SetSplashScreenProgress(100);
1563 : }
1564 0 : catch ( const com::sun::star::uno::Exception& e )
1565 : {
1566 0 : FatalError( MakeStartupErrorMessage(e.Message) );
1567 : }
1568 :
1569 : // Release solar mutex just before we wait for our client to connect
1570 : {
1571 64 : SolarMutexReleaser aReleaser;
1572 :
1573 : // Post user event to startup first application component window
1574 : // We have to send this OpenClients message short before execute() to
1575 : // minimize the risk that this message overtakes type detection construction!!
1576 64 : Application::PostUserEvent( LINK( this, Desktop, OpenClients_Impl ) );
1577 :
1578 : // Post event to enable acceptors
1579 64 : Application::PostUserEvent( LINK( this, Desktop, EnableAcceptors_Impl) );
1580 :
1581 : // The configuration error handler currently is only for startup
1582 64 : aConfigErrHandler.deactivate();
1583 :
1584 : // Acquire solar mutex just before we enter our message loop
1585 : }
1586 :
1587 : // call Application::Execute to process messages in vcl message loop
1588 : try
1589 : {
1590 : #if HAVE_FEATURE_JAVA
1591 : // The JavaContext contains an interaction handler which is used when
1592 : // the creation of a Java Virtual Machine fails
1593 : com::sun::star::uno::ContextLayer layer2(
1594 64 : new svt::JavaContext( com::sun::star::uno::getCurrentContext() ) );
1595 : #endif
1596 : // check whether the shutdown is caused by restart just before entering the Execute
1597 128 : pExecGlobals->bRestartRequested = pExecGlobals->bRestartRequested ||
1598 192 : xRestartManager->isRestartRequested(true);
1599 :
1600 64 : if ( !pExecGlobals->bRestartRequested )
1601 : {
1602 : // if this run of the office is triggered by restart, some additional actions should be done
1603 64 : DoRestartActionsIfNecessary( !rCmdLineArgs.IsInvisible() && !rCmdLineArgs.IsNoQuickstart() );
1604 :
1605 64 : Execute();
1606 64 : }
1607 : }
1608 0 : catch(const com::sun::star::document::CorruptedFilterConfigurationException& exFilterCfg)
1609 : {
1610 0 : OfficeIPCThread::SetDowning();
1611 0 : FatalError( MakeStartupErrorMessage(exFilterCfg.Message) );
1612 : }
1613 0 : catch(const com::sun::star::configuration::CorruptedConfigurationException& exAnyCfg)
1614 : {
1615 0 : OfficeIPCThread::SetDowning();
1616 0 : FatalError( MakeStartupErrorMessage(exAnyCfg.Message) );
1617 : }
1618 0 : catch( const ::com::sun::star::uno::Exception& exUNO)
1619 : {
1620 0 : OfficeIPCThread::SetDowning();
1621 0 : FatalError( exUNO.Message);
1622 : }
1623 0 : catch( const std::exception& exSTD)
1624 : {
1625 0 : OfficeIPCThread::SetDowning();
1626 0 : FatalError( OUString::createFromAscii( exSTD.what()));
1627 : }
1628 0 : catch( ...)
1629 : {
1630 0 : OfficeIPCThread::SetDowning();
1631 0 : FatalError( OUString( "Caught Unknown Exception: Aborting!"));
1632 : }
1633 : }
1634 : else
1635 : {
1636 52 : if (xDesktop.is())
1637 52 : xDesktop->terminate();
1638 : }
1639 : // CAUTION: you do not necessarily get here e.g. on the Mac.
1640 : // please put all deinitialization code into doShutdown
1641 232 : return doShutdown();
1642 : }
1643 :
1644 116 : int Desktop::doShutdown()
1645 : {
1646 116 : if( ! pExecGlobals )
1647 0 : return EXIT_SUCCESS;
1648 :
1649 244 : pExecGlobals->bRestartRequested = pExecGlobals->bRestartRequested ||
1650 308 : OfficeRestartManager::get(comphelper::getProcessComponentContext())->
1651 348 : isRestartRequested(true);
1652 116 : if ( pExecGlobals->bRestartRequested )
1653 52 : SetRestartState();
1654 :
1655 116 : if (pExecGlobals->xGlobalBroadcaster.is())
1656 : {
1657 116 : css::document::DocumentEvent aEvent;
1658 116 : aEvent.EventName = "OnCloseApp";
1659 116 : pExecGlobals->xGlobalBroadcaster->documentEventOccured(aEvent);
1660 : }
1661 :
1662 116 : delete pResMgr, pResMgr = NULL;
1663 : // Restore old value
1664 116 : const CommandLineArgs& rCmdLineArgs = GetCommandLineArgs();
1665 116 : if ( rCmdLineArgs.IsHeadless() )
1666 116 : SvtMiscOptions().SetUseSystemFileDialog( pExecGlobals->bUseSystemFileDialog );
1667 :
1668 116 : OUString pidfileName = rCmdLineArgs.GetPidfileName();
1669 116 : if ( !pidfileName.isEmpty() )
1670 : {
1671 0 : OUString pidfileURL;
1672 :
1673 0 : if ( osl_getFileURLFromSystemPath(pidfileName.pData, &pidfileURL.pData) == osl_File_E_None )
1674 : {
1675 0 : if ( osl::File::remove( pidfileURL ) != osl::FileBase::E_None )
1676 : {
1677 : SAL_WARN("desktop.app", "shutdown: cannot remove pidfile " << pidfileURL);
1678 : }
1679 : }
1680 : else
1681 : {
1682 : SAL_WARN("desktop.app", "shutdown: cannot get pidfile URL from path" << pidfileName);
1683 0 : }
1684 : }
1685 :
1686 : // remove temp directory
1687 116 : RemoveTemporaryDirectory();
1688 116 : FlushConfiguration();
1689 : // The acceptors in the AcceptorMap must be released (in DeregisterServices)
1690 : // with the solar mutex unlocked, to avoid deadlock:
1691 : {
1692 116 : SolarMutexReleaser aReleaser;
1693 116 : DeregisterServices();
1694 : #if HAVE_FEATURE_SCRIPTING
1695 116 : StarBASIC::DetachAllDocBasicItems();
1696 : #endif
1697 : }
1698 : // be sure that path/language options gets destroyed before
1699 : // UCB is deinitialized
1700 116 : pExecGlobals->pLanguageOptions.reset( 0 );
1701 116 : pExecGlobals->pPathOptions.reset( 0 );
1702 :
1703 116 : bool bRR = pExecGlobals->bRestartRequested;
1704 116 : delete pExecGlobals, pExecGlobals = NULL;
1705 :
1706 116 : if ( bRR )
1707 : {
1708 52 : restartOnMac(true);
1709 52 : if ( m_rSplashScreen.is() )
1710 0 : m_rSplashScreen->reset();
1711 :
1712 52 : return EXITHELPER_NORMAL_RESTART;
1713 : }
1714 64 : return EXIT_SUCCESS;
1715 : }
1716 :
1717 14 : IMPL_STATIC_LINK( Desktop, ImplInitFilterHdl, ConvertData*, pData )
1718 : {
1719 7 : return GraphicFilter::GetGraphicFilter().GetFilterCallback().Call( pData );
1720 : }
1721 :
1722 116 : bool Desktop::InitializeConfiguration()
1723 : {
1724 : try
1725 : {
1726 : css::configuration::theDefaultProvider::get(
1727 116 : comphelper::getProcessComponentContext() );
1728 116 : return true;
1729 : }
1730 0 : catch( ::com::sun::star::lang::ServiceNotRegisteredException & e )
1731 : {
1732 : HandleBootstrapErrors(
1733 0 : Desktop::BE_UNO_SERVICE_CONFIG_MISSING, e.Message );
1734 : }
1735 0 : catch( const ::com::sun::star::configuration::MissingBootstrapFileException& e )
1736 : {
1737 : OUString aMsg( CreateErrorMsgString( utl::Bootstrap::MISSING_BOOTSTRAP_FILE,
1738 0 : e.BootstrapFileURL ));
1739 0 : HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_USER_INSTALL, aMsg );
1740 : }
1741 0 : catch( const ::com::sun::star::configuration::InvalidBootstrapFileException& e )
1742 : {
1743 : OUString aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY,
1744 0 : e.BootstrapFileURL ));
1745 0 : HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL, aMsg );
1746 : }
1747 0 : catch( const ::com::sun::star::configuration::InstallationIncompleteException& )
1748 : {
1749 0 : OUString aVersionFileURL;
1750 0 : OUString aMsg;
1751 0 : utl::Bootstrap::PathStatus aPathStatus = utl::Bootstrap::locateVersionFile( aVersionFileURL );
1752 0 : if ( aPathStatus == utl::Bootstrap::PATH_EXISTS )
1753 0 : aMsg = CreateErrorMsgString( utl::Bootstrap::MISSING_VERSION_FILE_ENTRY, aVersionFileURL );
1754 : else
1755 0 : aMsg = CreateErrorMsgString( utl::Bootstrap::MISSING_VERSION_FILE, aVersionFileURL );
1756 :
1757 0 : HandleBootstrapPathErrors( ::utl::Bootstrap::MISSING_USER_INSTALL, aMsg );
1758 : }
1759 0 : catch ( const com::sun::star::configuration::backend::BackendAccessException& exception)
1760 : {
1761 : // [cm122549] It is assumed in this case that the message
1762 : // coming from InitConfiguration (in fact CreateApplicationConf...)
1763 : // is suitable for display directly.
1764 0 : FatalError( MakeStartupErrorMessage( exception.Message ) );
1765 : }
1766 0 : catch ( const com::sun::star::configuration::backend::BackendSetupException& exception)
1767 : {
1768 : // [cm122549] It is assumed in this case that the message
1769 : // coming from InitConfiguration (in fact CreateApplicationConf...)
1770 : // is suitable for display directly.
1771 0 : FatalError( MakeStartupErrorMessage( exception.Message ) );
1772 : }
1773 0 : catch ( const ::com::sun::star::configuration::CannotLoadConfigurationException& )
1774 : {
1775 : OUString aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_DATA,
1776 0 : OUString() ));
1777 0 : HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL, aMsg );
1778 : }
1779 0 : catch( const ::com::sun::star::uno::Exception& )
1780 : {
1781 : OUString aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_DATA,
1782 0 : OUString() ));
1783 0 : HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL, aMsg );
1784 : }
1785 0 : return false;
1786 : }
1787 :
1788 232 : void Desktop::FlushConfiguration()
1789 : {
1790 : css::uno::Reference< css::util::XFlushable >(
1791 : css::configuration::theDefaultProvider::get(
1792 : comphelper::getProcessComponentContext()),
1793 232 : css::uno::UNO_QUERY_THROW)->flush();
1794 232 : }
1795 :
1796 0 : bool Desktop::InitializeQuickstartMode( const Reference< XComponentContext >& rxContext )
1797 : {
1798 : try
1799 : {
1800 : // the shutdown icon sits in the systray and allows the user to keep
1801 : // the office instance running for quicker restart
1802 : // this will only be activated if --quickstart was specified on cmdline
1803 :
1804 0 : bool bQuickstart = shouldLaunchQuickstart();
1805 :
1806 : // Try to instantiate quickstart service. This service is not mandatory, so
1807 : // do nothing if service is not available
1808 :
1809 : // #i105753# the following if was invented for performance
1810 : // unfortunately this broke the Mac behavior which is to always run
1811 : // in quickstart mode since Mac applications do not usually quit
1812 : // when the last document closes.
1813 : // Note that this claim that on OS X we "always run in quickstart mode"
1814 : // has nothing to do with (quick) *starting* (i.e. starting automatically
1815 : // when the user logs in), though, but with not quitting when no documents
1816 : // are open.
1817 : #ifndef MACOSX
1818 0 : if ( bQuickstart )
1819 : #endif
1820 : {
1821 0 : css::office::Quickstart::createStart(rxContext, bQuickstart);
1822 : }
1823 0 : return true;
1824 : }
1825 0 : catch( const ::com::sun::star::uno::Exception& )
1826 : {
1827 0 : return false;
1828 : }
1829 : }
1830 :
1831 232 : void Desktop::OverrideSystemSettings( AllSettings& rSettings )
1832 : {
1833 232 : if ( !SvtTabAppearanceCfg::IsInitialized () )
1834 348 : return;
1835 :
1836 116 : StyleSettings hStyleSettings = rSettings.GetStyleSettings();
1837 232 : MouseSettings hMouseSettings = rSettings.GetMouseSettings();
1838 :
1839 116 : DragFullOptions nDragFullOptions = hStyleSettings.GetDragFullOptions();
1840 :
1841 232 : SvtTabAppearanceCfg aAppearanceCfg;
1842 116 : sal_uInt16 nDragMode = aAppearanceCfg.GetDragMode();
1843 116 : switch ( nDragMode )
1844 : {
1845 : case DragFullWindow:
1846 0 : nDragFullOptions |= DragFullOptions::All;
1847 0 : break;
1848 : case DragFrame:
1849 0 : nDragFullOptions &= ~DragFullOptions::All;
1850 0 : break;
1851 : case DragSystemDep:
1852 : default:
1853 116 : break;
1854 : }
1855 :
1856 116 : MouseFollowFlags nFollow = hMouseSettings.GetFollow();
1857 116 : hMouseSettings.SetFollow( aAppearanceCfg.IsMenuMouseFollow() ? (nFollow|MouseFollowFlags::Menu) : (nFollow&~MouseFollowFlags::Menu));
1858 116 : rSettings.SetMouseSettings(hMouseSettings);
1859 :
1860 116 : SvtMenuOptions aMenuOpt;
1861 116 : hStyleSettings.SetUseImagesInMenus(aMenuOpt.GetMenuIconsState());
1862 116 : hStyleSettings.SetDragFullOptions( nDragFullOptions );
1863 232 : rSettings.SetStyleSettings ( hStyleSettings );
1864 : }
1865 :
1866 :
1867 76 : IMPL_STATIC_LINK_TYPED(Desktop, AsyncInitFirstRun, Timer *, /*unused*/, void)
1868 : {
1869 38 : DoFirstRunInitializations();
1870 38 : }
1871 :
1872 :
1873 :
1874 0 : class ExitTimer : public Timer
1875 : {
1876 : public:
1877 0 : ExitTimer()
1878 0 : {
1879 0 : SetTimeout(500);
1880 0 : Start();
1881 0 : }
1882 0 : virtual void Invoke() SAL_OVERRIDE
1883 : {
1884 0 : exit(42);
1885 : }
1886 : };
1887 :
1888 128 : IMPL_LINK_NOARG(Desktop, OpenClients_Impl)
1889 : {
1890 : try {
1891 64 : OpenClients();
1892 :
1893 64 : OfficeIPCThread::SetReady();
1894 :
1895 64 : CloseSplashScreen();
1896 64 : CheckFirstRun( );
1897 : #ifdef WNT
1898 : // Registers a COM class factory of the service manager with the windows operating system.
1899 : Reference< XMultiServiceFactory > xSMgr= comphelper::getProcessServiceFactory();
1900 : xSMgr->createInstance("com.sun.star.bridge.OleApplicationRegistration");
1901 : xSMgr->createInstance("com.sun.star.comp.ole.EmbedServer");
1902 : #endif
1903 64 : const char *pExitPostStartup = getenv ("OOO_EXIT_POST_STARTUP");
1904 64 : if (pExitPostStartup && *pExitPostStartup)
1905 0 : new ExitTimer();
1906 0 : } catch (const ::com::sun::star::uno::Exception &e) {
1907 0 : OUString a( "UNO exception during client open:\n" );
1908 0 : Application::Abort( a + e.Message );
1909 : }
1910 64 : return 0;
1911 : }
1912 :
1913 : // enable acceptos
1914 128 : IMPL_STATIC_LINK_NOARG(Desktop, EnableAcceptors_Impl)
1915 : {
1916 64 : enableAcceptors();
1917 64 : return 0;
1918 : }
1919 :
1920 :
1921 0 : void Desktop::PreloadModuleData( const CommandLineArgs& rArgs )
1922 : {
1923 0 : Sequence < com::sun::star::beans::PropertyValue > args(1);
1924 0 : args[0].Name = "Hidden";
1925 0 : args[0].Value <<= sal_True;
1926 0 : Reference < XDesktop2 > xDesktop = css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
1927 :
1928 0 : if ( rArgs.IsWriter() )
1929 : {
1930 : try
1931 : {
1932 0 : Reference < ::com::sun::star::util::XCloseable > xDoc( xDesktop->loadComponentFromURL( OUString("private:factory/swriter"),
1933 0 : OUString("_blank"), 0, args ), UNO_QUERY_THROW );
1934 0 : xDoc->close( sal_False );
1935 : }
1936 0 : catch ( const com::sun::star::uno::Exception& )
1937 : {
1938 : }
1939 : }
1940 0 : if ( rArgs.IsCalc() )
1941 : {
1942 : try
1943 : {
1944 0 : Reference < ::com::sun::star::util::XCloseable > xDoc( xDesktop->loadComponentFromURL( OUString("private:factory/scalc"),
1945 0 : OUString("_blank"), 0, args ), UNO_QUERY_THROW );
1946 0 : xDoc->close( sal_False );
1947 : }
1948 0 : catch ( const com::sun::star::uno::Exception& )
1949 : {
1950 : }
1951 : }
1952 0 : if ( rArgs.IsDraw() )
1953 : {
1954 : try
1955 : {
1956 0 : Reference < ::com::sun::star::util::XCloseable > xDoc( xDesktop->loadComponentFromURL( OUString("private:factory/sdraw"),
1957 0 : OUString("_blank"), 0, args ), UNO_QUERY_THROW );
1958 0 : xDoc->close( sal_False );
1959 : }
1960 0 : catch ( const com::sun::star::uno::Exception& )
1961 : {
1962 : }
1963 : }
1964 0 : if ( rArgs.IsImpress() )
1965 : {
1966 : try
1967 : {
1968 0 : Reference < ::com::sun::star::util::XCloseable > xDoc( xDesktop->loadComponentFromURL( OUString("private:factory/simpress"),
1969 0 : OUString("_blank"), 0, args ), UNO_QUERY_THROW );
1970 0 : xDoc->close( sal_False );
1971 : }
1972 0 : catch ( const com::sun::star::uno::Exception& )
1973 : {
1974 : }
1975 0 : }
1976 0 : }
1977 :
1978 0 : void Desktop::PreloadConfigurationData()
1979 : {
1980 0 : Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
1981 0 : Reference< XNameAccess > xNameAccess = css::frame::theUICommandDescription::get(xContext);
1982 :
1983 0 : OUString aWriterDoc( "com.sun.star.text.TextDocument" );
1984 0 : OUString aCalcDoc( "com.sun.star.sheet.SpreadsheetDocument" );
1985 0 : OUString aDrawDoc( "com.sun.star.drawing.DrawingDocument" );
1986 0 : OUString aImpressDoc( "com.sun.star.presentation.PresentationDocument" );
1987 :
1988 : // preload commands configuration
1989 0 : Any a;
1990 0 : Reference< XNameAccess > xCmdAccess;
1991 :
1992 : try
1993 : {
1994 0 : a = xNameAccess->getByName( aWriterDoc );
1995 0 : a >>= xCmdAccess;
1996 0 : if ( xCmdAccess.is() )
1997 : {
1998 0 : xCmdAccess->getByName(".uno:BasicShapes");
1999 0 : xCmdAccess->getByName(".uno:EditGlossary");
2000 : }
2001 : }
2002 0 : catch ( const ::com::sun::star::uno::Exception& )
2003 : {
2004 : }
2005 :
2006 : try
2007 : {
2008 0 : a = xNameAccess->getByName( aCalcDoc );
2009 0 : a >>= xCmdAccess;
2010 0 : if ( xCmdAccess.is() )
2011 0 : xCmdAccess->getByName(".uno:InsertObjectStarMath");
2012 : }
2013 0 : catch ( const ::com::sun::star::uno::Exception& )
2014 : {
2015 : }
2016 :
2017 : try
2018 : {
2019 : // draw and impress share the same configuration file (DrawImpressCommands.xcu)
2020 0 : a = xNameAccess->getByName( aDrawDoc );
2021 0 : a >>= xCmdAccess;
2022 0 : if ( xCmdAccess.is() )
2023 0 : xCmdAccess->getByName(".uno:Polygon");
2024 : }
2025 0 : catch ( const ::com::sun::star::uno::Exception& )
2026 : {
2027 : }
2028 :
2029 : // preload window state configuration
2030 0 : xNameAccess = theWindowStateConfiguration::get( xContext );
2031 0 : Reference< XNameAccess > xWindowAccess;
2032 : try
2033 : {
2034 0 : a = xNameAccess->getByName( aWriterDoc );
2035 0 : a >>= xWindowAccess;
2036 0 : if ( xWindowAccess.is() )
2037 0 : xWindowAccess->getByName("private:resource/toolbar/standardbar");
2038 : }
2039 0 : catch ( const ::com::sun::star::uno::Exception& )
2040 : {
2041 : }
2042 : try
2043 : {
2044 0 : a = xNameAccess->getByName( aCalcDoc );
2045 0 : a >>= xWindowAccess;
2046 0 : if ( xWindowAccess.is() )
2047 0 : xWindowAccess->getByName("private:resource/toolbar/standardbar");
2048 : }
2049 0 : catch ( const ::com::sun::star::uno::Exception& )
2050 : {
2051 : }
2052 : try
2053 : {
2054 0 : a = xNameAccess->getByName( aDrawDoc );
2055 0 : a >>= xWindowAccess;
2056 0 : if ( xWindowAccess.is() )
2057 0 : xWindowAccess->getByName("private:resource/toolbar/standardbar");
2058 : }
2059 0 : catch ( const ::com::sun::star::uno::Exception& )
2060 : {
2061 : }
2062 : try
2063 : {
2064 0 : a = xNameAccess->getByName( aImpressDoc );
2065 0 : a >>= xWindowAccess;
2066 0 : if ( xWindowAccess.is() )
2067 0 : xWindowAccess->getByName("private:resource/toolbar/standardbar");
2068 : }
2069 0 : catch ( const ::com::sun::star::uno::Exception& )
2070 : {
2071 : }
2072 :
2073 : // preload user interface element factories
2074 0 : Reference< XUIElementFactoryManager > xUIElementFactory = theUIElementFactoryManager::get( xContext );
2075 : try
2076 : {
2077 0 : xUIElementFactory->getRegisteredFactories();
2078 : }
2079 0 : catch ( const ::com::sun::star::uno::Exception& )
2080 : {
2081 : }
2082 :
2083 : // preload popup menu controller factories. As all controllers are in the same
2084 : // configuration file they also get preloaded!
2085 :
2086 : Reference< css::frame::XUIControllerRegistration > xPopupMenuControllerFactory =
2087 0 : css::frame::thePopupMenuControllerFactory::get( xContext );
2088 : try
2089 : {
2090 0 : (void)xPopupMenuControllerFactory->hasController(
2091 : OUString( ".uno:CharFontName" ),
2092 0 : OUString() );
2093 : }
2094 0 : catch ( const ::com::sun::star::uno::Exception& )
2095 : {
2096 : }
2097 :
2098 : // preload filter configuration
2099 0 : xNameAccess = Reference< XNameAccess >(
2100 0 : xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.FilterFactory", xContext),
2101 0 : UNO_QUERY );
2102 0 : if ( xNameAccess.is() )
2103 : {
2104 : try
2105 : {
2106 0 : xNameAccess->getElementNames();
2107 : }
2108 0 : catch ( const ::com::sun::star::uno::Exception& )
2109 : {
2110 : }
2111 : }
2112 :
2113 : // preload type detection configuration
2114 0 : xNameAccess = Reference< XNameAccess >(
2115 0 : xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", xContext),
2116 0 : UNO_QUERY );
2117 0 : if ( xNameAccess.is() )
2118 : {
2119 : try
2120 : {
2121 0 : xNameAccess->getElementNames();
2122 : }
2123 0 : catch ( const ::com::sun::star::uno::Exception& )
2124 : {
2125 : }
2126 0 : }
2127 0 : }
2128 :
2129 64 : void Desktop::OpenClients()
2130 : {
2131 :
2132 : // check if a document has been recovered - if there is one of if a document was loaded by cmdline, no default document
2133 : // should be created
2134 64 : Reference < XComponent > xFirst;
2135 64 : bool bRecovery = false;
2136 :
2137 64 : const CommandLineArgs& rArgs = GetCommandLineArgs();
2138 :
2139 64 : if (!rArgs.IsQuickstart())
2140 : {
2141 64 : bool bShowHelp = false;
2142 64 : OUStringBuffer aHelpURLBuffer;
2143 64 : if (rArgs.IsHelpWriter()) {
2144 0 : bShowHelp = true;
2145 0 : aHelpURLBuffer.appendAscii("vnd.sun.star.help://swriter/start");
2146 64 : } else if (rArgs.IsHelpCalc()) {
2147 0 : bShowHelp = true;
2148 0 : aHelpURLBuffer.appendAscii("vnd.sun.star.help://scalc/start");
2149 64 : } else if (rArgs.IsHelpDraw()) {
2150 0 : bShowHelp = true;
2151 0 : aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdraw/start");
2152 64 : } else if (rArgs.IsHelpImpress()) {
2153 0 : bShowHelp = true;
2154 0 : aHelpURLBuffer.appendAscii("vnd.sun.star.help://simpress/start");
2155 64 : } else if (rArgs.IsHelpBase()) {
2156 0 : bShowHelp = true;
2157 0 : aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdatabase/start");
2158 64 : } else if (rArgs.IsHelpBasic()) {
2159 0 : bShowHelp = true;
2160 0 : aHelpURLBuffer.appendAscii("vnd.sun.star.help://sbasic/start");
2161 64 : } else if (rArgs.IsHelpMath()) {
2162 0 : bShowHelp = true;
2163 0 : aHelpURLBuffer.appendAscii("vnd.sun.star.help://smath/start");
2164 : }
2165 64 : if (bShowHelp) {
2166 0 : aHelpURLBuffer.appendAscii("?Language=");
2167 0 : aHelpURLBuffer.append(utl::ConfigManager::getLocale());
2168 : #if defined UNX
2169 0 : aHelpURLBuffer.appendAscii("&System=UNX");
2170 : #elif defined WNT
2171 : aHelpURLBuffer.appendAscii("&System=WIN");
2172 : #endif
2173 0 : Application::GetHelp()->Start(
2174 0 : aHelpURLBuffer.makeStringAndClear(), NULL);
2175 0 : return;
2176 64 : }
2177 : }
2178 : else
2179 : {
2180 0 : OUString aIniName;
2181 :
2182 0 : osl_getExecutableFile( &aIniName.pData );
2183 0 : sal_uInt32 lastIndex = aIniName.lastIndexOf('/');
2184 0 : if ( lastIndex > 0 )
2185 : {
2186 0 : aIniName = aIniName.copy( 0, lastIndex+1 );
2187 0 : aIniName += "perftune";
2188 : #if defined(WNT)
2189 : aIniName += ".ini";
2190 : #else
2191 0 : aIniName += "rc";
2192 : #endif
2193 : }
2194 :
2195 0 : rtl::Bootstrap aPerfTuneIniFile( aIniName );
2196 :
2197 0 : OUString aDefault( "0" );
2198 0 : OUString aPreloadData;
2199 :
2200 0 : aPerfTuneIniFile.getFrom( OUString( "QuickstartPreloadConfiguration" ), aPreloadData, aDefault );
2201 0 : if ( aPreloadData == "1" )
2202 : {
2203 0 : if ( rArgs.IsWriter() ||
2204 0 : rArgs.IsCalc() ||
2205 0 : rArgs.IsDraw() ||
2206 0 : rArgs.IsImpress() )
2207 : {
2208 0 : PreloadModuleData( rArgs );
2209 : }
2210 :
2211 0 : PreloadConfigurationData();
2212 0 : }
2213 : }
2214 :
2215 : // Disable AutoSave feature in case "--norestore" or a similar command line switch is set on the command line.
2216 : // The reason behind: AutoSave/EmergencySave/AutoRecovery share the same data.
2217 : // But the require that all documents, which are saved as backup should exists inside
2218 : // memory. May be this mechanism will be inconsistent if the configuration exists ...
2219 : // but no document inside memory corrspond to this data.
2220 : // Furter it's not acceptable to recover such documents without any UI. It can
2221 : // need some time, where the user wont see any results and wait for finishing the office startup ...
2222 64 : bool bAllowRecoveryAndSessionManagement = ( !rArgs.IsNoRestore() ) && ( !rArgs.IsHeadless() );
2223 :
2224 64 : if ( ! bAllowRecoveryAndSessionManagement )
2225 : {
2226 : try
2227 : {
2228 64 : Reference< XDispatch > xRecovery = css::frame::theAutoRecovery::get( ::comphelper::getProcessComponentContext() );
2229 128 : Reference< css::util::XURLTransformer > xParser = css::util::URLTransformer::create( ::comphelper::getProcessComponentContext() );
2230 :
2231 128 : css::util::URL aCmd;
2232 64 : aCmd.Complete = "vnd.sun.star.autorecovery:/disableRecovery";
2233 64 : xParser->parseStrict(aCmd);
2234 :
2235 128 : xRecovery->dispatch(aCmd, css::uno::Sequence< css::beans::PropertyValue >());
2236 : }
2237 0 : catch(const css::uno::Exception& e)
2238 : {
2239 : SAL_WARN( "desktop.app", "Could not disable AutoRecovery." << e.Message);
2240 : }
2241 : }
2242 : else
2243 : {
2244 0 : bool bCrashed = false;
2245 0 : bool bExistsRecoveryData = false;
2246 0 : bool bExistsSessionData = false;
2247 0 : bool const bDisableRecovery = getenv("OOO_DISABLE_RECOVERY") != nullptr;
2248 :
2249 0 : impl_checkRecoveryState(bCrashed, bExistsRecoveryData, bExistsSessionData);
2250 :
2251 0 : if ( !bDisableRecovery &&
2252 : (
2253 0 : ( bExistsRecoveryData ) || // => crash with files => recovery
2254 : ( bCrashed ) // => crash without files => error report
2255 : )
2256 : )
2257 : {
2258 : try
2259 : {
2260 : bRecovery = impl_callRecoveryUI(
2261 : false , // false => force recovery instead of emergency save
2262 0 : bExistsRecoveryData);
2263 : }
2264 0 : catch(const css::uno::Exception& e)
2265 : {
2266 : SAL_WARN( "desktop.app", "Error during recovery" << e.Message);
2267 0 : }
2268 : }
2269 0 : else if (bExistsRecoveryData && bDisableRecovery)
2270 : // prevent new Writer doc
2271 0 : bRecovery = true;
2272 :
2273 0 : Reference< XSessionManagerListener2 > xSessionListener;
2274 : try
2275 : {
2276 : // specifies whether the UI-interaction on Session shutdown is allowed
2277 0 : xSessionListener = SessionListener::createWithOnQuitFlag(
2278 0 : ::comphelper::getProcessComponentContext(), isUIOnSessionShutdownAllowed());
2279 : }
2280 0 : catch(const com::sun::star::uno::Exception& e)
2281 : {
2282 : SAL_WARN( "desktop.app", "Registration of session listener failed" << e.Message);
2283 : }
2284 :
2285 0 : if ( !bExistsRecoveryData && xSessionListener.is() )
2286 : {
2287 : // session management
2288 : try
2289 : {
2290 0 : xSessionListener->doRestore();
2291 : }
2292 0 : catch(const com::sun::star::uno::Exception& e)
2293 : {
2294 : SAL_WARN( "desktop.app", "Error in session management" << e.Message);
2295 : }
2296 0 : }
2297 : }
2298 :
2299 64 : OfficeIPCThread::EnableRequests();
2300 :
2301 64 : ProcessDocumentsRequest aRequest(rArgs.getCwdUrl());
2302 64 : aRequest.pcProcessed = NULL;
2303 :
2304 64 : aRequest.aOpenList = rArgs.GetOpenList();
2305 64 : aRequest.aViewList = rArgs.GetViewList();
2306 64 : aRequest.aStartList = rArgs.GetStartList();
2307 64 : aRequest.aPrintList = rArgs.GetPrintList();
2308 64 : aRequest.aPrintToList = rArgs.GetPrintToList();
2309 64 : aRequest.aPrinterName = rArgs.GetPrinterName();
2310 64 : aRequest.aForceOpenList = rArgs.GetForceOpenList();
2311 64 : aRequest.aForceNewList = rArgs.GetForceNewList();
2312 64 : aRequest.aConversionList = rArgs.GetConversionList();
2313 64 : aRequest.aConversionParams = rArgs.GetConversionParams();
2314 64 : aRequest.aConversionOut = rArgs.GetConversionOut();
2315 64 : aRequest.aInFilter = rArgs.GetInFilter();
2316 64 : aRequest.bTextCat = rArgs.IsTextCat();
2317 :
2318 191 : if ( !aRequest.aOpenList.empty() ||
2319 126 : !aRequest.aViewList.empty() ||
2320 126 : !aRequest.aStartList.empty() ||
2321 126 : !aRequest.aPrintList.empty() ||
2322 126 : !aRequest.aForceOpenList.empty() ||
2323 126 : !aRequest.aForceNewList.empty() ||
2324 190 : ( !aRequest.aPrintToList.empty() && !aRequest.aPrinterName.isEmpty() ) ||
2325 63 : !aRequest.aConversionList.empty() )
2326 : {
2327 1 : if ( rArgs.HasModuleParam() )
2328 : {
2329 0 : SvtModuleOptions aOpt;
2330 :
2331 : // Support command line parameters to start a module (as preselection)
2332 0 : if ( rArgs.IsWriter() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::WRITER ) )
2333 0 : aRequest.aModule = aOpt.GetFactoryName( SvtModuleOptions::EFactory::WRITER );
2334 0 : else if ( rArgs.IsCalc() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::CALC ) )
2335 0 : aRequest.aModule = aOpt.GetFactoryName( SvtModuleOptions::EFactory::CALC );
2336 0 : else if ( rArgs.IsImpress() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::IMPRESS ) )
2337 0 : aRequest.aModule= aOpt.GetFactoryName( SvtModuleOptions::EFactory::IMPRESS );
2338 0 : else if ( rArgs.IsDraw() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::DRAW ) )
2339 0 : aRequest.aModule= aOpt.GetFactoryName( SvtModuleOptions::EFactory::DRAW );
2340 : }
2341 :
2342 : // check for printing disabled
2343 3 : if( ( !(aRequest.aPrintList.empty() && aRequest.aPrintToList.empty()) )
2344 1 : && Application::GetSettings().GetMiscSettings().GetDisablePrinting() )
2345 : {
2346 0 : aRequest.aPrintList.clear();
2347 0 : aRequest.aPrintToList.clear();
2348 0 : ResMgr* pDtResMgr = GetDesktopResManager();
2349 0 : if( pDtResMgr )
2350 : {
2351 0 : ScopedVclPtrInstance< MessageDialog > aBox(nullptr, ResId(STR_ERR_PRINTDISABLED, *pDtResMgr));
2352 0 : aBox->Execute();
2353 : }
2354 : }
2355 :
2356 : // Process request
2357 1 : if ( OfficeIPCThread::ExecuteCmdLineRequests( aRequest ) )
2358 : {
2359 : // Don't do anything if we have successfully called terminate at desktop:
2360 0 : return;
2361 : }
2362 : }
2363 :
2364 : // no default document if a document was loaded by recovery or by command line or if soffice is used as server
2365 64 : Reference< XDesktop2 > xDesktop = css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
2366 64 : Reference< XElementAccess > xList( xDesktop->getFrames(), UNO_QUERY_THROW );
2367 64 : if ( xList->hasElements() )
2368 1 : return;
2369 :
2370 63 : if ( rArgs.IsQuickstart() || rArgs.IsInvisible() || Application::AnyInput( VclInputFlags::APPEVENT ) )
2371 : // soffice was started as tray icon ...
2372 63 : return;
2373 :
2374 0 : if ( bRecovery )
2375 : {
2376 0 : ShowBackingComponent(0);
2377 : }
2378 : else
2379 : {
2380 0 : OpenDefault();
2381 0 : }
2382 : }
2383 :
2384 0 : void Desktop::OpenDefault()
2385 : {
2386 0 : OUString aName;
2387 0 : SvtModuleOptions aOpt;
2388 :
2389 0 : const CommandLineArgs& rArgs = GetCommandLineArgs();
2390 0 : if ( rArgs.IsNoDefault() ) return;
2391 0 : if ( rArgs.HasModuleParam() )
2392 : {
2393 : // Support new command line parameters to start a module
2394 0 : if ( rArgs.IsWriter() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::WRITER ) )
2395 0 : aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::EFactory::WRITER );
2396 0 : else if ( rArgs.IsCalc() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::CALC ) )
2397 0 : aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::EFactory::CALC );
2398 0 : else if ( rArgs.IsImpress() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::IMPRESS ) )
2399 0 : aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::EFactory::IMPRESS );
2400 0 : else if ( rArgs.IsBase() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::DATABASE ) )
2401 0 : aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::EFactory::DATABASE );
2402 0 : else if ( rArgs.IsDraw() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::DRAW ) )
2403 0 : aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::EFactory::DRAW );
2404 0 : else if ( rArgs.IsMath() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::MATH ) )
2405 0 : aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::EFactory::MATH );
2406 0 : else if ( rArgs.IsGlobal() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::WRITER ) )
2407 0 : aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::EFactory::WRITERGLOBAL );
2408 0 : else if ( rArgs.IsWeb() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::WRITER ) )
2409 0 : aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::EFactory::WRITERWEB );
2410 : }
2411 :
2412 0 : if ( aName.isEmpty() )
2413 : {
2414 : // Old way to create a default document
2415 0 : if ( aOpt.IsModuleInstalled( SvtModuleOptions::EModule::WRITER ) )
2416 0 : aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::EFactory::WRITER );
2417 0 : else if ( aOpt.IsModuleInstalled( SvtModuleOptions::EModule::CALC ) )
2418 0 : aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::EFactory::CALC );
2419 0 : else if ( aOpt.IsModuleInstalled( SvtModuleOptions::EModule::IMPRESS ) )
2420 0 : aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::EFactory::IMPRESS );
2421 0 : else if ( aOpt.IsModuleInstalled( SvtModuleOptions::EModule::DATABASE ) )
2422 0 : aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::EFactory::DATABASE );
2423 0 : else if ( aOpt.IsModuleInstalled( SvtModuleOptions::EModule::DRAW ) )
2424 0 : aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::EFactory::DRAW );
2425 : else
2426 0 : return;
2427 : }
2428 :
2429 0 : ProcessDocumentsRequest aRequest(rArgs.getCwdUrl());
2430 0 : aRequest.pcProcessed = NULL;
2431 0 : aRequest.aOpenList.push_back(aName);
2432 0 : OfficeIPCThread::ExecuteCmdLineRequests( aRequest );
2433 : }
2434 :
2435 :
2436 1 : OUString GetURL_Impl(
2437 : const OUString& rName, boost::optional< OUString > const & cwdUrl )
2438 : {
2439 : // if rName is a vnd.sun.star.script URL do not attempt to parse it
2440 : // as INetURLObj does not handle handle there URLs
2441 1 : if (rName.startsWith("vnd.sun.star.script"))
2442 : {
2443 0 : return rName;
2444 : }
2445 :
2446 : // dont touch file urls, those should already be in internal form
2447 : // they won't get better here (#112849#)
2448 1 : if (rName.startsWith("file:"))
2449 : {
2450 0 : return rName;
2451 : }
2452 :
2453 1 : if ( rName.startsWith("service:"))
2454 : {
2455 0 : return rName;
2456 : }
2457 :
2458 : // Add path separator to these directory and make given URL (rName) absolute by using of current working directory
2459 : // Attention: "setFinalSlash()" is necessary for calling "smartRel2Abs()"!!!
2460 : // Otherwhise last part will be ignored and wrong result will be returned!!!
2461 : // "smartRel2Abs()" interpret given URL as file not as path. So he truncate last element to get the base path ...
2462 : // But if we add a separator - he doesn't do it anymore.
2463 1 : INetURLObject aObj;
2464 1 : if (cwdUrl) {
2465 1 : aObj.SetURL(*cwdUrl);
2466 1 : aObj.setFinalSlash();
2467 : }
2468 :
2469 : // Use the provided parameters for smartRel2Abs to support the usage of '%' in system paths.
2470 : // Otherwise this char won't get encoded and we are not able to load such files later,
2471 : bool bWasAbsolute;
2472 : INetURLObject aURL = aObj.smartRel2Abs( rName, bWasAbsolute, false, INetURLObject::WAS_ENCODED,
2473 2 : RTL_TEXTENCODING_UTF8, true );
2474 2 : OUString aFileURL = aURL.GetMainURL(INetURLObject::NO_DECODE);
2475 :
2476 2 : ::osl::FileStatus aStatus( osl_FileStatus_Mask_FileURL );
2477 2 : ::osl::DirectoryItem aItem;
2478 2 : if( ::osl::FileBase::E_None == ::osl::DirectoryItem::get( aFileURL, aItem ) &&
2479 1 : ::osl::FileBase::E_None == aItem.getFileStatus( aStatus ) )
2480 1 : aFileURL = aStatus.getFileURL();
2481 :
2482 2 : return aFileURL;
2483 : }
2484 :
2485 0 : void Desktop::HandleAppEvent( const ApplicationEvent& rAppEvent )
2486 : {
2487 0 : switch ( rAppEvent.GetEvent() )
2488 : {
2489 : case ApplicationEvent::TYPE_ACCEPT:
2490 : // every time an accept parameter is used we create an acceptor
2491 : // with the corresponding accept-string
2492 0 : createAcceptor(rAppEvent.GetStringData());
2493 0 : break;
2494 : case ApplicationEvent::TYPE_APPEAR:
2495 0 : if ( !GetCommandLineArgs().IsInvisible() )
2496 : {
2497 0 : Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
2498 :
2499 : // find active task - the active task is always a visible task
2500 0 : Reference< css::frame::XDesktop2 > xDesktop = css::frame::Desktop::create( xContext );
2501 0 : Reference< css::frame::XFrame > xTask = xDesktop->getActiveFrame();
2502 0 : if ( !xTask.is() )
2503 : {
2504 : // get any task if there is no active one
2505 0 : Reference< css::container::XIndexAccess > xList( xDesktop->getFrames(), ::com::sun::star::uno::UNO_QUERY );
2506 0 : if ( xList->getCount() > 0 )
2507 0 : xList->getByIndex(0) >>= xTask;
2508 : }
2509 :
2510 0 : if ( xTask.is() )
2511 : {
2512 0 : Reference< com::sun::star::awt::XTopWindow > xTop( xTask->getContainerWindow(), UNO_QUERY );
2513 0 : xTop->toFront();
2514 : }
2515 : else
2516 : {
2517 : // no visible task that could be activated found
2518 0 : Reference< ::com::sun::star::awt::XWindow > xContainerWindow;
2519 0 : Reference< XFrame > xBackingFrame = xDesktop->findFrame(OUString( "_blank" ), 0);
2520 0 : if (xBackingFrame.is())
2521 0 : xContainerWindow = xBackingFrame->getContainerWindow();
2522 0 : if (xContainerWindow.is())
2523 : {
2524 0 : Reference< XController > xStartModule = StartModule::createWithParentWindow(xContext, xContainerWindow);
2525 0 : Reference< ::com::sun::star::awt::XWindow > xBackingWin(xStartModule, UNO_QUERY);
2526 : // Attention: You MUST(!) call setComponent() before you call attachFrame().
2527 : // Because the backing component set the property "IsBackingMode" of the frame
2528 : // to true inside attachFrame(). But setComponent() reset this state every time ...
2529 0 : xBackingFrame->setComponent(xBackingWin, xStartModule);
2530 0 : xStartModule->attachFrame(xBackingFrame);
2531 0 : xContainerWindow->setVisible(sal_True);
2532 :
2533 0 : vcl::Window* pCompWindow = VCLUnoHelper::GetWindow(xBackingFrame->getComponentWindow());
2534 0 : if (pCompWindow)
2535 0 : pCompWindow->Update();
2536 0 : }
2537 0 : }
2538 : }
2539 0 : break;
2540 : case ApplicationEvent::TYPE_HELP:
2541 0 : displayCmdlineHelp(rAppEvent.GetStringData());
2542 0 : break;
2543 : case ApplicationEvent::TYPE_VERSION:
2544 0 : displayVersion();
2545 0 : break;
2546 : case ApplicationEvent::TYPE_OPEN:
2547 : {
2548 0 : const CommandLineArgs& rCmdLine = GetCommandLineArgs();
2549 0 : if ( !rCmdLine.IsInvisible() && !rCmdLine.IsTerminateAfterInit() )
2550 : {
2551 : ProcessDocumentsRequest* pDocsRequest = new ProcessDocumentsRequest(
2552 0 : rCmdLine.getCwdUrl());
2553 0 : std::vector<OUString> const & data(rAppEvent.GetStringsData());
2554 : pDocsRequest->aOpenList.insert(
2555 0 : pDocsRequest->aOpenList.end(), data.begin(), data.end());
2556 0 : pDocsRequest->pcProcessed = NULL;
2557 :
2558 0 : OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest );
2559 0 : delete pDocsRequest;
2560 : }
2561 : }
2562 0 : break;
2563 : case ApplicationEvent::TYPE_OPENHELPURL:
2564 : // start help for a specific URL
2565 0 : Application::GetHelp()->Start(rAppEvent.GetStringData(), NULL);
2566 0 : break;
2567 : case ApplicationEvent::TYPE_PRINT:
2568 : {
2569 0 : const CommandLineArgs& rCmdLine = GetCommandLineArgs();
2570 0 : if ( !rCmdLine.IsInvisible() && !rCmdLine.IsTerminateAfterInit() )
2571 : {
2572 : ProcessDocumentsRequest* pDocsRequest = new ProcessDocumentsRequest(
2573 0 : rCmdLine.getCwdUrl());
2574 0 : std::vector<OUString> const & data(rAppEvent.GetStringsData());
2575 : pDocsRequest->aPrintList.insert(
2576 0 : pDocsRequest->aPrintList.end(), data.begin(), data.end());
2577 0 : pDocsRequest->pcProcessed = NULL;
2578 :
2579 0 : OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest );
2580 0 : delete pDocsRequest;
2581 : }
2582 : }
2583 0 : break;
2584 : case ApplicationEvent::TYPE_PRIVATE_DOSHUTDOWN:
2585 : {
2586 0 : Desktop* pD = dynamic_cast<Desktop*>(GetpApp());
2587 : OSL_ENSURE( pD, "no desktop ?!?" );
2588 0 : if( pD )
2589 0 : pD->doShutdown();
2590 : }
2591 0 : break;
2592 : case ApplicationEvent::TYPE_QUICKSTART:
2593 0 : if ( !GetCommandLineArgs().IsInvisible() )
2594 : {
2595 : // If the office has been started the second time its command line arguments are sent through a pipe
2596 : // connection to the first office. We want to reuse the quickstart option for the first office.
2597 : // NOTICE: The quickstart service must be initialized inside the "main thread", so we use the
2598 : // application events to do this (they are executed inside main thread)!!!
2599 : // Don't start quickstart service if the user specified "--invisible" on the command line!
2600 0 : Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
2601 0 : css::office::Quickstart::createStart(xContext, true/*Quickstart*/);
2602 : }
2603 0 : break;
2604 : case ApplicationEvent::TYPE_SHOWDIALOG:
2605 : // ignore all errors here. It's clicking a menu entry only ...
2606 : // The user will try it again, in case nothing happens .-)
2607 : try
2608 : {
2609 0 : Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
2610 :
2611 0 : Reference< css::frame::XDesktop2 > xDesktop = css::frame::Desktop::create( xContext );
2612 :
2613 0 : Reference< css::util::XURLTransformer > xParser = css::util::URLTransformer::create(xContext);
2614 0 : css::util::URL aCommand;
2615 0 : if( rAppEvent.GetStringData() == "PREFERENCES" )
2616 0 : aCommand.Complete = ".uno:OptionsTreeDialog";
2617 0 : else if( rAppEvent.GetStringData() == "ABOUT" )
2618 0 : aCommand.Complete = ".uno:About";
2619 0 : if( !aCommand.Complete.isEmpty() )
2620 : {
2621 0 : xParser->parseStrict(aCommand);
2622 :
2623 0 : css::uno::Reference< css::frame::XDispatch > xDispatch = xDesktop->queryDispatch(aCommand, OUString(), 0);
2624 0 : if (xDispatch.is())
2625 0 : xDispatch->dispatch(aCommand, css::uno::Sequence< css::beans::PropertyValue >());
2626 0 : }
2627 : }
2628 0 : catch(const css::uno::Exception&)
2629 : {}
2630 0 : break;
2631 : case ApplicationEvent::TYPE_UNACCEPT:
2632 : // try to remove corresponding acceptor
2633 0 : destroyAcceptor(rAppEvent.GetStringData());
2634 0 : break;
2635 : default:
2636 : SAL_WARN( "desktop.app", "this cannot happen");
2637 0 : break;
2638 : }
2639 0 : }
2640 :
2641 116 : void Desktop::OpenSplashScreen()
2642 : {
2643 116 : const CommandLineArgs &rCmdLine = GetCommandLineArgs();
2644 : // Show intro only if this is normal start (e.g. no server, no quickstart, no printing )
2645 464 : if ( !rCmdLine.IsInvisible() &&
2646 0 : !rCmdLine.IsHeadless() &&
2647 0 : !rCmdLine.IsQuickstart() &&
2648 0 : !rCmdLine.IsMinimized() &&
2649 0 : !rCmdLine.IsNoLogo() &&
2650 0 : !rCmdLine.IsTerminateAfterInit() &&
2651 116 : rCmdLine.GetPrintList().empty() &&
2652 348 : rCmdLine.GetPrintToList().empty() &&
2653 116 : rCmdLine.GetConversionList().empty() )
2654 : {
2655 : // Determine application name from command line parameters
2656 0 : OUString aAppName;
2657 0 : if ( rCmdLine.IsWriter() )
2658 0 : aAppName = "writer";
2659 0 : else if ( rCmdLine.IsCalc() )
2660 0 : aAppName = "calc";
2661 0 : else if ( rCmdLine.IsDraw() )
2662 0 : aAppName = "draw";
2663 0 : else if ( rCmdLine.IsImpress() )
2664 0 : aAppName = "impress";
2665 0 : else if ( rCmdLine.IsBase() )
2666 0 : aAppName = "base";
2667 0 : else if ( rCmdLine.IsGlobal() )
2668 0 : aAppName = "global";
2669 0 : else if ( rCmdLine.IsMath() )
2670 0 : aAppName = "math";
2671 0 : else if ( rCmdLine.IsWeb() )
2672 0 : aAppName = "web";
2673 :
2674 : // Which splash to use
2675 0 : OUString aSplashService( "com.sun.star.office.SplashScreen" );
2676 0 : if ( rCmdLine.HasSplashPipe() )
2677 0 : aSplashService = "com.sun.star.office.PipeSplashScreen";
2678 :
2679 0 : bool bVisible = true;
2680 0 : Sequence< Any > aSeq( 2 );
2681 0 : aSeq[0] <<= bVisible;
2682 0 : aSeq[1] <<= aAppName;
2683 0 : css::uno::Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
2684 0 : m_rSplashScreen = Reference<XStatusIndicator>(
2685 0 : xContext->getServiceManager()->createInstanceWithArgumentsAndContext(aSplashService, aSeq, xContext),
2686 0 : UNO_QUERY);
2687 :
2688 0 : if(m_rSplashScreen.is())
2689 0 : m_rSplashScreen->start(OUString("SplashScreen"), 100);
2690 : }
2691 :
2692 116 : }
2693 :
2694 1236 : void Desktop::SetSplashScreenProgress(sal_Int32 iProgress)
2695 : {
2696 1236 : if(m_rSplashScreen.is())
2697 : {
2698 0 : m_rSplashScreen->setValue(iProgress);
2699 : }
2700 1236 : }
2701 :
2702 381 : void Desktop::SetSplashScreenText( const OUString& rText )
2703 : {
2704 381 : if( m_rSplashScreen.is() )
2705 : {
2706 0 : m_rSplashScreen->setText( rText );
2707 : }
2708 381 : }
2709 :
2710 791 : void Desktop::CloseSplashScreen()
2711 : {
2712 791 : if(m_rSplashScreen.is())
2713 : {
2714 0 : m_rSplashScreen->end();
2715 0 : m_rSplashScreen = NULL;
2716 : }
2717 791 : }
2718 :
2719 :
2720 38 : void Desktop::DoFirstRunInitializations()
2721 : {
2722 : try
2723 : {
2724 38 : Reference< XJobExecutor > xExecutor = theJobExecutor::get( ::comphelper::getProcessComponentContext() );
2725 38 : xExecutor->trigger( OUString("onFirstRunInitialization") );
2726 : }
2727 0 : catch(const ::com::sun::star::uno::Exception&)
2728 : {
2729 : SAL_WARN( "desktop.app", "Desktop::DoFirstRunInitializations: caught an exception while trigger job executor ..." );
2730 : }
2731 38 : }
2732 :
2733 0 : void Desktop::ShowBackingComponent(Desktop * progress)
2734 : {
2735 0 : if (GetCommandLineArgs().IsNoDefault())
2736 : {
2737 0 : return;
2738 : }
2739 0 : Reference< XComponentContext > xContext = comphelper::getProcessComponentContext();
2740 0 : Reference< XDesktop2 > xDesktop = css::frame::Desktop::create(xContext);
2741 0 : if (progress != 0)
2742 : {
2743 0 : progress->SetSplashScreenProgress(60);
2744 : }
2745 0 : Reference< XFrame > xBackingFrame = xDesktop->findFrame(OUString( "_blank" ), 0);
2746 0 : Reference< ::com::sun::star::awt::XWindow > xContainerWindow;
2747 :
2748 0 : if (xBackingFrame.is())
2749 0 : xContainerWindow = xBackingFrame->getContainerWindow();
2750 0 : if (xContainerWindow.is())
2751 : {
2752 : // set the WB_EXT_DOCUMENT style. Normally, this is done by the TaskCreator service when a "_blank"
2753 : // frame/window is created. Since we do not use the TaskCreator here, we need to mimic its behavior,
2754 : // otherwise documents loaded into this frame will later on miss functionality depending on the style.
2755 0 : vcl::Window* pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
2756 : SAL_WARN_IF( !pContainerWindow, "desktop.app", "Desktop::Main: no implementation access to the frame's container window!" );
2757 0 : pContainerWindow->SetExtendedStyle( pContainerWindow->GetExtendedStyle() | WB_EXT_DOCUMENT );
2758 0 : if (progress != 0)
2759 : {
2760 0 : progress->SetSplashScreenProgress(75);
2761 : }
2762 :
2763 0 : Reference< XController > xStartModule = StartModule::createWithParentWindow( xContext, xContainerWindow);
2764 : // Attention: You MUST(!) call setComponent() before you call attachFrame().
2765 : // Because the backing component set the property "IsBackingMode" of the frame
2766 : // to true inside attachFrame(). But setComponent() reset this state everytimes ...
2767 0 : xBackingFrame->setComponent(Reference< XWindow >(xStartModule, UNO_QUERY), xStartModule);
2768 0 : if (progress != 0)
2769 : {
2770 0 : progress->SetSplashScreenProgress(100);
2771 : }
2772 0 : xStartModule->attachFrame(xBackingFrame);
2773 0 : if (progress != 0)
2774 : {
2775 0 : progress->CloseSplashScreen();
2776 : }
2777 0 : xContainerWindow->setVisible(sal_True);
2778 0 : }
2779 : }
2780 :
2781 :
2782 64 : void Desktop::CheckFirstRun( )
2783 : {
2784 64 : if (officecfg::Office::Common::Misc::FirstRun::get())
2785 : {
2786 : // use VCL timer, which won't trigger during shutdown if the
2787 : // application exits before timeout
2788 47 : m_firstRunTimer.SetTimeout(3000); // 3 sec.
2789 47 : m_firstRunTimer.SetTimeoutHdl(LINK(this, Desktop, AsyncInitFirstRun));
2790 47 : m_firstRunTimer.Start();
2791 :
2792 : #ifdef WNT
2793 : // Check if Quckstarter should be started (on Windows only)
2794 : TCHAR szValue[8192];
2795 : DWORD nValueSize = sizeof(szValue);
2796 : HKEY hKey;
2797 : if ( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE, "Software\\LibreOffice", &hKey ) )
2798 : {
2799 : if ( ERROR_SUCCESS == RegQueryValueEx( hKey, TEXT("RunQuickstartAtFirstStart"), NULL, NULL, (LPBYTE)szValue, &nValueSize ) )
2800 : {
2801 : css::uno::Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
2802 : css::office::Quickstart::createAutoStart(xContext, true/*Quickstart*/, true/*bAutostart*/);
2803 : RegCloseKey( hKey );
2804 : }
2805 : }
2806 : #endif
2807 :
2808 : std::shared_ptr< comphelper::ConfigurationChanges > batch(
2809 47 : comphelper::ConfigurationChanges::create());
2810 47 : officecfg::Office::Common::Misc::FirstRun::set(false, batch);
2811 47 : batch->commit();
2812 : }
2813 64 : }
2814 :
2815 348 : }
2816 :
2817 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|