GPU-Calc: remove Alloc_Host_Ptr for clmem of NAN vector
[LibreOffice.git] / desktop / source / app / app.cxx
blobee3b4d5048f722af7e982a91c15f6481396ecfa2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
21 #include <config_folders.h>
23 #include "sal/config.h"
25 #include <iostream>
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"
39 #include <svl/languageoptions.hxx>
40 #include <svtools/javacontext.hxx>
41 #include <com/sun/star/beans/XPropertySet.hpp>
42 #include <com/sun/star/frame/AutoRecovery.hpp>
43 #include <com/sun/star/frame/GlobalEventBroadcaster.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/JobExecutor.hpp>
68 #include <com/sun/star/task/OfficeRestartManager.hpp>
69 #include <com/sun/star/task/XRestartManager.hpp>
70 #include <com/sun/star/document/XEventListener.hpp>
71 #include <com/sun/star/frame/UICommandDescription.hpp>
72 #include <com/sun/star/ui/UIElementFactoryManager.hpp>
73 #include <com/sun/star/ui/WindowStateConfiguration.hpp>
74 #include <com/sun/star/frame/XUIControllerRegistration.hpp>
75 #include <com/sun/star/frame/ToolbarControllerFactory.hpp>
76 #include <com/sun/star/frame/PopupMenuControllerFactory.hpp>
77 #include <com/sun/star/office/Quickstart.hpp>
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 <officecfg/Office/Common.hxx>
86 #include <officecfg/Office/Recovery.hxx>
87 #include <officecfg/Setup.hxx>
88 #include <osl/file.hxx>
89 #include <osl/process.h>
90 #include <rtl/uri.hxx>
91 #include <unotools/pathoptions.hxx>
92 #include <svtools/miscopt.hxx>
93 #include <svtools/menuoptions.hxx>
94 #include <rtl/bootstrap.hxx>
95 #include <vcl/help.hxx>
96 #include <vcl/msgbox.hxx>
97 #include <sfx2/sfx.hrc>
98 #include <sfx2/app.hxx>
99 #include <svl/itemset.hxx>
100 #include <svl/eitem.hxx>
102 #include <svtools/fontsubstconfig.hxx>
103 #include <svtools/accessibilityoptions.hxx>
104 #include <svtools/apearcfg.hxx>
105 #include <vcl/graphicfilter.hxx>
107 #include "langselect.hxx"
109 #include <config_telepathy.h>
111 #if ENABLE_TELEPATHY
112 #include <tubes/manager.hxx>
113 #endif
115 #if defined MACOSX
116 #include <errno.h>
117 #include <sys/wait.h>
118 #endif
120 #ifdef WNT
121 #ifdef _MSC_VER
122 #pragma warning(push, 1) /* disable warnings within system headers */
123 #pragma warning (disable: 4005)
124 #endif
125 #define WIN32_LEAN_AND_MEAN
126 #include <windows.h>
127 #ifdef _MSC_VER
128 #pragma warning(pop)
129 #endif
130 #endif //WNT
132 #if defined WNT
133 #include <process.h>
134 #define GETPID _getpid
135 #else
136 #include <unistd.h>
137 #define GETPID getpid
138 #endif
140 using namespace ::com::sun::star::awt;
141 using namespace ::com::sun::star::uno;
142 using namespace ::com::sun::star::util;
143 using namespace ::com::sun::star::lang;
144 using namespace ::com::sun::star::beans;
145 using namespace ::com::sun::star::frame;
146 using namespace ::com::sun::star::document;
147 using namespace ::com::sun::star::view;
148 using namespace ::com::sun::star::task;
149 using namespace ::com::sun::star::system;
150 using namespace ::com::sun::star::ui;
151 using namespace ::com::sun::star::ui::dialogs;
152 using namespace ::com::sun::star::container;
154 ResMgr* desktop::Desktop::pResMgr = 0;
156 namespace desktop
159 static oslSignalHandler pSignalHandler = 0;
160 static sal_Bool _bCrashReporterEnabled = sal_True;
162 namespace {
164 void removeTree(OUString const & url) {
165 osl::Directory dir(url);
166 osl::FileBase::RC rc = dir.open();
167 switch (rc) {
168 case osl::FileBase::E_None:
169 break;
170 case osl::FileBase::E_NOENT:
171 return; //TODO: SAL_WARN if recursive
172 default:
173 SAL_WARN("desktop.app", "cannot open directory " << dir.getURL() << ": " << +rc);
174 return;
176 for (;;) {
177 osl::DirectoryItem i;
178 rc = dir.getNextItem(i, SAL_MAX_UINT32);
179 if (rc == osl::FileBase::E_NOENT) {
180 break;
182 if (rc != osl::FileBase::E_None) {
183 SAL_WARN( "desktop.app", "cannot iterate directory " << dir.getURL() << ": " << +rc);
184 break;
186 osl::FileStatus stat(
187 osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName |
188 osl_FileStatus_Mask_FileURL);
189 rc = i.getFileStatus(stat);
190 if (rc != osl::FileBase::E_None) {
191 SAL_WARN( "desktop.app", "cannot stat in directory " << dir.getURL() << ": " << +rc);
192 continue;
194 if (stat.getFileType() == osl::FileStatus::Directory) { //TODO: symlinks
195 removeTree(stat.getFileURL());
196 } else {
197 rc = osl::File::remove(stat.getFileURL());
198 SAL_WARN_IF(
199 rc != osl::FileBase::E_None, "desktop.app",
200 "cannot remove file " << stat.getFileURL() << ": " << +rc);
203 if (dir.isOpen()) {
204 rc = dir.close();
205 SAL_WARN_IF(
206 rc != osl::FileBase::E_None, "desktop.app",
207 "cannot close directory " << dir.getURL() << ": " << +rc);
209 rc = osl::Directory::remove(url);
210 SAL_WARN_IF(
211 rc != osl::FileBase::E_None, "desktop.app",
212 "cannot remove directory " << url << ": " << +rc);
215 // Remove any existing UserInstallation's extensions cache data remaining from
216 // old installations. This addresses at least two problems:
218 // For one, apparently due to the old share/prereg/bundled mechanism (disabled
219 // since 5c47e5f63a79a9e72ec4a100786b1bbf65137ed4 "fdo#51252 Disable copying
220 // share/prereg/bundled to avoid startup crashes"), the user/extensions/bundled
221 // cache could contain corrupted information (like a UNO component registered
222 // twice, which got changed from active to passive registration in one LO
223 // version, but the version of the corresponding bundled extension only
224 // incremented in a later LO version).
226 // For another, UserInstallations have been seen in the wild where no extensions
227 // were installed per-user (any longer), but user/uno_packages/cache/registry/
228 // com.sun.star.comp.deployment.component.PackageRegistryBackend/*.rdb files
229 // contained data nevertheless.
231 // When a LO upgrade is detected (i.e., no user/extensions/buildid or one
232 // containing an old build ID), then user/extensions and
233 // user/uno_packages/cache/registry/
234 // com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc are
235 // removed. That should prevent any problems starting the service manager due
236 // to old junk. Later on in Desktop::SynchronizeExtensionRepositories, the
237 // removed cache data is recreated.
239 // Multiple instances of soffice.bin can execute this code in parallel for a
240 // single UserInstallation, as it is called before OfficeIPCThread is set up.
241 // Therefore, any errors here only lead to SAL_WARNs.
243 // At least in theory, this function could be removed again once no
244 // UserInstallation can be poisoned by old junk any more.
245 bool cleanExtensionCache() {
246 OUString buildId(
247 "${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("version") ":buildid}");
248 rtl::Bootstrap::expandMacros(buildId); //TODO: detect failure
249 OUString extDir(
250 "${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap")
251 ":UserInstallation}/user/extensions");
252 rtl::Bootstrap::expandMacros(extDir); //TODO: detect failure
253 OUString buildIdFile(extDir + "/buildid");
254 osl::File fr(buildIdFile);
255 osl::FileBase::RC rc = fr.open(osl_File_OpenFlag_Read);
256 switch (rc) {
257 case osl::FileBase::E_None:
259 rtl::ByteSequence s1;
260 rc = fr.readLine(s1);
261 osl::FileBase::RC rc2 = fr.close();
262 SAL_WARN_IF(
263 rc2 != osl::FileBase::E_None, "desktop.app",
264 "cannot close " << fr.getURL() << " after reading: " << +rc2);
265 if (rc != osl::FileBase::E_None) {
266 SAL_WARN( "desktop.app", "cannot read from " << fr.getURL() << ": " << +rc);
267 break;
269 OUString s2(
270 reinterpret_cast< char const * >(s1.getConstArray()),
271 s1.getLength(), RTL_TEXTENCODING_ISO_8859_1);
272 // using ISO 8859-1 avoids any and all conversion errors; the
273 // content should only be a subset of ASCII, anyway
274 if (s2 == buildId) {
275 return false;
277 break;
279 case osl::FileBase::E_NOENT:
280 break;
281 default:
282 SAL_WARN( "desktop.app", "cannot open " << fr.getURL() << " for reading: " << +rc);
283 break;
285 removeTree(extDir);
286 OUString userRcFile(
287 "$UNO_USER_PACKAGES_CACHE/registry/"
288 "com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc");
289 rtl::Bootstrap::expandMacros(userRcFile); //TODO: detect failure
290 rc = osl::File::remove(userRcFile);
291 SAL_WARN_IF(
292 rc != osl::FileBase::E_None && rc != osl::FileBase::E_NOENT, "desktop.app",
293 "cannot remove file " << userRcFile << ": " << +rc);
294 rc = osl::Directory::createPath(extDir);
295 SAL_WARN_IF(
296 rc != osl::FileBase::E_None && rc != osl::FileBase::E_EXIST, "desktop.app",
297 "cannot create path " << extDir << ": " << +rc);
298 osl::File fw(buildIdFile);
299 rc = fw.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Create);
300 if (rc != osl::FileBase::E_None) {
301 SAL_WARN( "desktop.app", "cannot open " << fw.getURL() << " for writing: " << +rc);
302 return true;
304 OString buf(OUStringToOString(buildId, RTL_TEXTENCODING_UTF8));
305 // using UTF-8 avoids almost all conversion errors (and buildid
306 // containing single surrogate halves should never happen, anyway); the
307 // content should only be a subset of ASCII, anyway
308 sal_uInt64 n = 0;
309 rc = fw.write(buf.getStr(), buf.getLength(), n);
310 SAL_WARN_IF(
311 (rc != osl::FileBase::E_None
312 || n != static_cast< sal_uInt32 >(buf.getLength())),
313 "desktop.app",
314 "cannot write to " << fw.getURL() << ": " << +rc << ", " << n);
315 rc = fw.close();
316 SAL_WARN_IF(
317 rc != osl::FileBase::E_None, "desktop.app",
318 "cannot close " << fw.getURL() << " after writing: " << +rc);
319 return true;
322 bool shouldLaunchQuickstart()
324 bool bQuickstart = Desktop::GetCommandLineArgs().IsQuickstart();
325 if (!bQuickstart)
327 const SfxPoolItem* pItem=0;
328 SfxItemSet aQLSet(SFX_APP()->GetPool(), SID_ATTR_QUICKLAUNCHER, SID_ATTR_QUICKLAUNCHER);
329 SFX_APP()->GetOptions(aQLSet);
330 SfxItemState eState = aQLSet.GetItemState(SID_ATTR_QUICKLAUNCHER, sal_False, &pItem);
331 if (SFX_ITEM_SET == eState)
332 bQuickstart = ((SfxBoolItem*)pItem)->GetValue();
334 return bQuickstart;
337 void SetRestartState() {
338 try {
339 boost::shared_ptr< comphelper::ConfigurationChanges > batch(
340 comphelper::ConfigurationChanges::create());
341 officecfg::Setup::Office::OfficeRestartInProgress::set(true, batch);
342 batch->commit();
343 } catch (css::uno::Exception & e) {
344 SAL_WARN("desktop.app", "ignoring Exception \"" << e.Message << "\"");
348 void DoRestartActionsIfNecessary(bool quickstart) {
349 if (quickstart) {
350 try {
351 if (officecfg::Setup::Office::OfficeRestartInProgress::get()) {
352 boost::shared_ptr< comphelper::ConfigurationChanges > batch(
353 comphelper::ConfigurationChanges::create());
354 officecfg::Setup::Office::OfficeRestartInProgress::set(
355 false, batch);
356 batch->commit();
357 css::office::Quickstart::createStart(
358 comphelper::getProcessComponentContext(),
359 shouldLaunchQuickstart());
361 } catch (css::uno::Exception & e) {
362 SAL_WARN(
363 "desktop.app", "ignoring Exception \"" << e.Message << "\"");
370 // ----------------------------------------------------------------------------
372 ResMgr* Desktop::GetDesktopResManager()
374 if ( !Desktop::pResMgr )
376 // Create desktop resource manager and bootstrap process
377 // was successful. Use default way to get language specific message.
378 if ( Application::IsInExecute() )
379 Desktop::pResMgr = ResMgr::CreateResMgr("dkt");
381 if ( !Desktop::pResMgr )
383 // Use VCL to get the correct language specific message as we
384 // are in the bootstrap process and not able to get the installed
385 // language!!
386 OUString aUILocaleString = langselect::getEmergencyLocale();
387 LanguageTag aLanguageTag( aUILocaleString);
388 //! ResMgr may modify the Locale for fallback!
389 Desktop::pResMgr = ResMgr::SearchCreateResMgr( "dkt", aLanguageTag);
390 AllSettings as = GetSettings();
391 as.SetUILanguageTag(aLanguageTag);
392 SetSettings(as);
396 return Desktop::pResMgr;
399 namespace {
401 // ----------------------------------------------------------------------------
402 // Get a message string securely. There is a fallback string if the resource
403 // is not available.
405 OUString GetMsgString(
406 sal_uInt16 nId, const OUString& aFallbackMsg,
407 bool bAlwaysUseFallbackMsg = false )
409 if ( !bAlwaysUseFallbackMsg )
411 ResMgr* resMgr = Desktop::GetDesktopResManager();
412 if ( resMgr )
413 return ResId(nId, *resMgr).toString();
415 return aFallbackMsg;
418 OUString MakeStartupErrorMessage(
419 OUString const & aErrorMessage, bool bAlwaysUseFallbackMsg = false )
421 OUStringBuffer aDiagnosticMessage( 100 );
423 aDiagnosticMessage.append(
424 GetMsgString(
425 STR_BOOTSTRAP_ERR_CANNOT_START, "The program cannot be started.",
426 bAlwaysUseFallbackMsg ) );
428 aDiagnosticMessage.appendAscii( "\n" );
430 aDiagnosticMessage.append( aErrorMessage );
432 return aDiagnosticMessage.makeStringAndClear();
435 OUString MakeStartupConfigAccessErrorMessage( OUString const & aInternalErrMsg )
437 OUStringBuffer aDiagnosticMessage( 200 );
439 ResMgr* pResMgr = Desktop::GetDesktopResManager();
440 if ( pResMgr )
441 aDiagnosticMessage.append( ResId(STR_BOOTSTRAP_ERR_CFG_DATAACCESS, *pResMgr).toString() );
442 else
443 aDiagnosticMessage.appendAscii( "The program cannot be started." );
445 if ( !aInternalErrMsg.isEmpty() )
447 aDiagnosticMessage.appendAscii( "\n\n" );
448 if ( pResMgr )
449 aDiagnosticMessage.append( ResId(STR_INTERNAL_ERRMSG, *pResMgr).toString() );
450 else
451 aDiagnosticMessage.appendAscii( "The following internal error has occurred:\n\n" );
452 aDiagnosticMessage.append( aInternalErrMsg );
455 return aDiagnosticMessage.makeStringAndClear();
458 //=============================================================================
459 // shows a simple error box with the given message ... but exits from these process !
460 // Fatal errors cant be solved by the process ... nor any recovery can help.
461 // Mostly the installation was damaged and must be repaired manually .. or by calling
462 // setup again.
463 // On the other side we must make sure that no further actions will be possible within
464 // the current office process ! No pipe requests, no menu/toolbar/shortuct actions
465 // are allowed. Otherwise we will force a "crash inside a crash".
466 // Thats why we have to use a special native message box here which does not use yield :-)
467 //=============================================================================
468 void FatalError(const OUString& sMessage)
470 OUString sProductKey = ::utl::Bootstrap::getProductKey();
471 if ( sProductKey.isEmpty())
473 osl_getExecutableFile( &sProductKey.pData );
475 ::sal_uInt32 nLastIndex = sProductKey.lastIndexOf('/');
476 if ( nLastIndex > 0 )
477 sProductKey = sProductKey.copy( nLastIndex+1 );
480 OUStringBuffer sTitle (128);
481 sTitle.append (sProductKey );
482 sTitle.appendAscii (" - Fatal Error");
484 Application::ShowNativeErrorBox (sTitle.makeStringAndClear (), sMessage);
485 _exit(EXITHELPER_FATAL_ERROR);
488 static bool ShouldSuppressUI(const CommandLineArgs& rCmdLine)
490 return rCmdLine.IsInvisible() ||
491 rCmdLine.IsHeadless() ||
492 rCmdLine.IsQuickstart();
495 struct theCommandLineArgs : public rtl::Static< CommandLineArgs, theCommandLineArgs > {};
499 CommandLineArgs& Desktop::GetCommandLineArgs()
501 return theCommandLineArgs::get();
504 namespace
506 struct BrandName
507 : public rtl::Static< OUString, BrandName > {};
508 struct Version
509 : public rtl::Static< OUString, Version > {};
510 struct AboutBoxVersion
511 : public rtl::Static< OUString, AboutBoxVersion > {};
512 struct AboutBoxVersionSuffix
513 : public rtl::Static< OUString, AboutBoxVersionSuffix > {};
514 struct OOOVendor
515 : public rtl::Static< OUString, OOOVendor > {};
516 struct Extension
517 : public rtl::Static< OUString, Extension > {};
520 OUString ReplaceStringHookProc( const OUString& rStr )
522 OUString sRet(rStr);
524 if (sRet.indexOf("%PRODUCT") != -1 || sRet.indexOf("%ABOUTBOX") != -1)
526 OUString sBrandName = BrandName::get();
527 OUString sVersion = Version::get();
528 OUString sBuildId = utl::Bootstrap::getBuildIdData("development");
529 OUString sAboutBoxVersion = AboutBoxVersion::get();
530 OUString sAboutBoxVersionSuffix = AboutBoxVersionSuffix::get();
531 OUString sExtension = Extension::get();
533 if ( sBrandName.isEmpty() )
535 sBrandName = utl::ConfigManager::getProductName();
536 sVersion = utl::ConfigManager::getProductVersion();
537 sAboutBoxVersion = utl::ConfigManager::getAboutBoxProductVersion();
538 sAboutBoxVersionSuffix = utl::ConfigManager::getAboutBoxProductVersionSuffix();
539 if ( sExtension.isEmpty() )
541 sExtension = utl::ConfigManager::getProductExtension();
545 sRet = sRet.replaceAll( "%PRODUCTNAME", sBrandName );
546 sRet = sRet.replaceAll( "%PRODUCTVERSION", sVersion );
547 sRet = sRet.replaceAll( "%BUILDID", sBuildId );
548 sRet = sRet.replaceAll( "%ABOUTBOXPRODUCTVERSIONSUFFIX", sAboutBoxVersionSuffix );
549 sRet = sRet.replaceAll( "%ABOUTBOXPRODUCTVERSION", sAboutBoxVersion );
550 sRet = sRet.replaceAll( "%PRODUCTEXTENSION", sExtension );
553 if ( sRet.indexOf( "%OOOVENDOR" ) != -1 )
555 OUString sOOOVendor = OOOVendor::get();
557 if ( sOOOVendor.isEmpty() )
559 sOOOVendor = utl::ConfigManager::getVendor();
562 sRet = sRet.replaceAll( "%OOOVENDOR", sOOOVendor );
565 return sRet;
568 Desktop::Desktop()
569 : m_bCleanedExtensionCache( false )
570 , m_bServicesRegistered( false )
571 , m_aBootstrapError( BE_OK )
573 SAL_INFO( "desktop.app", "desktop (cd100003) ::Desktop::Desktop" );
576 Desktop::~Desktop()
578 #if ENABLE_TELEPATHY
579 TeleManager::finalize();
580 #endif
583 void Desktop::Init()
585 SAL_INFO( "desktop.app", "desktop (cd100003) ::Desktop::Init" );
586 SetBootstrapStatus(BS_OK);
588 m_bCleanedExtensionCache = cleanExtensionCache();
590 // We need to have service factory before going further, but see fdo#37195.
591 // Doing this will mmap common.rdb, making it not overwritable on windows,
592 // so this can't happen before the synchronization above. Lets rework this
593 // so that the above is called *from* CreateApplicationServiceManager or
594 // something to enforce this gotcha
597 InitApplicationServiceManager();
599 catch (css::uno::Exception & e)
601 SetBootstrapError( BE_UNO_SERVICEMANAGER, e.Message );
604 if ( m_aBootstrapError == BE_OK )
608 if (!langselect::prepareLocale())
610 SetBootstrapError( BE_LANGUAGE_MISSING, OUString() );
613 catch (css::uno::Exception & e)
615 SetBootstrapError( BE_OFFICECONFIG_BROKEN, e.Message );
619 if ( 1 )
621 const CommandLineArgs& rCmdLineArgs = GetCommandLineArgs();
623 // start ipc thread only for non-remote offices
624 SAL_INFO( "desktop.app", "desktop (cd100003) ::OfficeIPCThread::EnableOfficeIPCThread" );
625 OfficeIPCThread::Status aStatus = OfficeIPCThread::EnableOfficeIPCThread();
626 if ( aStatus == OfficeIPCThread::IPC_STATUS_PIPE_ERROR )
628 #if HAVE_FEATURE_MACOSX_SANDBOX
629 // In a sandboxed LO, on 10.8.2 at least, creating the
630 // Unix domain socket fails. Ignore that as hopefully
631 // people running a sandboxed LO won't attempt starting it
632 // from the command-line or otherwise in tricky ways, so
633 // the normal OS X mechanism that prevents multiple
634 // instances of an app from being started should work
635 // fine. I hope.
636 #elif defined ANDROID
637 // Ignore crack pipe errors on Android, too
638 #else
639 // Keep using this oddly named BE_PATHINFO_MISSING value
640 // for pipe-related errors on other platforms. Of course
641 // this crack with two (if not more) levels of our own
642 // error codes hiding the actual system error code is
643 // broken, but that is done all over the code, let's leave
644 // re-enginering that to another year.
645 SetBootstrapError( BE_PATHINFO_MISSING, OUString() );
646 #endif
648 else if ( aStatus == OfficeIPCThread::IPC_STATUS_BOOTSTRAP_ERROR )
650 SetBootstrapError( BE_PATHINFO_MISSING, OUString() );
652 else if ( aStatus == OfficeIPCThread::IPC_STATUS_2ND_OFFICE )
654 // 2nd office startup should terminate after sending cmdlineargs through pipe
655 SetBootstrapStatus(BS_TERMINATE);
657 else if ( !rCmdLineArgs.GetUnknown().isEmpty()
658 || rCmdLineArgs.IsHelp() || rCmdLineArgs.IsVersion() )
660 // disable IPC thread in an instance that is just showing a help message
661 OfficeIPCThread::DisableOfficeIPCThread();
663 pSignalHandler = osl_addSignalHandler(SalMainPipeExchangeSignal_impl, NULL);
667 void Desktop::InitFinished()
669 SAL_INFO( "desktop.app", "desktop (cd100003) ::Desktop::InitFinished" );
671 CloseSplashScreen();
674 void Desktop::DeInit()
676 SAL_INFO( "desktop.app", "desktop (cd100003) ::Desktop::DeInit" );
678 try {
679 // instead of removing of the configManager just let it commit all the changes
680 SAL_INFO( "desktop.app", "<- store config items" );
681 utl::ConfigManager::storeConfigItems();
682 FlushConfiguration();
683 SAL_INFO( "desktop.app", "<- store config items" );
685 // close splashscreen if it's still open
686 CloseSplashScreen();
687 Reference< XComponent >(
688 comphelper::getProcessComponentContext(), UNO_QUERY_THROW )->
689 dispose();
690 // nobody should get a destroyed service factory...
691 ::comphelper::setProcessServiceFactory( NULL );
693 // clear lockfile
694 m_xLockfile.reset();
696 OfficeIPCThread::DisableOfficeIPCThread();
697 if( pSignalHandler )
698 osl_removeSignalHandler( pSignalHandler );
699 } catch (const RuntimeException&) {
700 // someone threw an exception during shutdown
701 // this will leave some garbage behind..
704 SAL_INFO( "desktop.app", "FINISHED WITH Destop::DeInit" );
707 sal_Bool Desktop::QueryExit()
711 SAL_INFO( "desktop.app", "<- store config items" );
712 utl::ConfigManager::storeConfigItems();
713 SAL_INFO( "desktop.app", "<- store config items" );
715 catch ( const RuntimeException& )
719 const sal_Char SUSPEND_QUICKSTARTVETO[] = "SuspendQuickstartVeto";
721 Reference< XDesktop2 > xDesktop = css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
722 Reference< XPropertySet > xPropertySet(xDesktop, UNO_QUERY_THROW);
723 xPropertySet->setPropertyValue( OUString(SUSPEND_QUICKSTARTVETO ), Any((sal_Bool)sal_True) );
725 sal_Bool bExit = xDesktop->terminate();
727 if ( !bExit )
729 xPropertySet->setPropertyValue( OUString(SUSPEND_QUICKSTARTVETO ), Any((sal_Bool)sal_False) );
731 else
733 FlushConfiguration();
736 // it is no problem to call DisableOfficeIPCThread() more than once
737 // it also looks to be threadsafe
738 OfficeIPCThread::DisableOfficeIPCThread();
740 catch ( const RuntimeException& )
744 m_xLockfile.reset();
748 return bExit;
751 void Desktop::HandleBootstrapPathErrors( ::utl::Bootstrap::Status aBootstrapStatus, const OUString& aDiagnosticMessage )
753 if ( aBootstrapStatus != ::utl::Bootstrap::DATA_OK )
755 OUString aProductKey;
756 OUString aTemp;
758 osl_getExecutableFile( &aProductKey.pData );
759 sal_uInt32 lastIndex = aProductKey.lastIndexOf('/');
760 if ( lastIndex > 0 )
761 aProductKey = aProductKey.copy( lastIndex+1 );
763 aTemp = ::utl::Bootstrap::getProductKey( aProductKey );
764 if ( !aTemp.isEmpty() )
765 aProductKey = aTemp;
767 OUString const aMessage(aDiagnosticMessage + "\n");
769 ErrorBox aBootstrapFailedBox( NULL, WB_OK, aMessage );
770 aBootstrapFailedBox.SetText( aProductKey );
771 aBootstrapFailedBox.Execute();
775 // Create a error message depending on bootstrap failure code and an optional file url
776 OUString Desktop::CreateErrorMsgString(
777 utl::Bootstrap::FailureCode nFailureCode,
778 const OUString& aFileURL )
780 OUString aMsg;
781 OUString aFilePath;
782 sal_Bool bFileInfo = sal_True;
784 switch ( nFailureCode )
786 /// the shared installation directory could not be located
787 case ::utl::Bootstrap::MISSING_INSTALL_DIRECTORY:
789 aMsg = GetMsgString( STR_BOOTSTRAP_ERR_PATH_INVALID,
790 OUString( "The installation path is not available." ) );
791 bFileInfo = sal_False;
793 break;
795 /// the bootstrap INI file could not be found or read
796 case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE:
798 aMsg = GetMsgString( STR_BOOTSTRAP_ERR_FILE_MISSING,
799 OUString( "The configuration file \"$1\" is missing." ) );
801 break;
803 /// the bootstrap INI is missing a required entry
804 /// the bootstrap INI contains invalid data
805 case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE_ENTRY:
806 case ::utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY:
808 aMsg = GetMsgString( STR_BOOTSTRAP_ERR_FILE_CORRUPT,
809 OUString( "The configuration file \"$1\" is corrupt." ) );
811 break;
813 /// the version locator INI file could not be found or read
814 case ::utl::Bootstrap::MISSING_VERSION_FILE:
816 aMsg = GetMsgString( STR_BOOTSTRAP_ERR_FILE_MISSING,
817 OUString( "The configuration file \"$1\" is missing." ) );
819 break;
821 /// the version locator INI has no entry for this version
822 case ::utl::Bootstrap::MISSING_VERSION_FILE_ENTRY:
824 aMsg = GetMsgString( STR_BOOTSTRAP_ERR_NO_SUPPORT,
825 OUString( "The main configuration file \"$1\" does not support the current version." ) );
827 break;
829 /// the user installation directory does not exist
830 case ::utl::Bootstrap::MISSING_USER_DIRECTORY:
832 aMsg = GetMsgString( STR_BOOTSTRAP_ERR_DIR_MISSING,
833 OUString( "The configuration directory \"$1\" is missing." ) );
835 break;
837 /// some bootstrap data was invalid in unexpected ways
838 case ::utl::Bootstrap::INVALID_BOOTSTRAP_DATA:
840 aMsg = GetMsgString( STR_BOOTSTRAP_ERR_INTERNAL,
841 OUString( "An internal failure occurred." ) );
842 bFileInfo = sal_False;
844 break;
846 case ::utl::Bootstrap::INVALID_VERSION_FILE_ENTRY:
848 // This needs to be improved, see #i67575#:
849 aMsg = "Invalid version file entry";
850 bFileInfo = sal_False;
852 break;
854 case ::utl::Bootstrap::NO_FAILURE:
856 OSL_ASSERT(false);
858 break;
861 if ( bFileInfo )
863 OUString aMsgString( aMsg );
865 osl::File::getSystemPathFromFileURL( aFileURL, aFilePath );
867 aMsgString = aMsgString.replaceFirst( "$1", aFilePath );
868 aMsg = aMsgString;
871 return MakeStartupErrorMessage( aMsg );
874 void Desktop::HandleBootstrapErrors(
875 BootstrapError aBootstrapError, OUString const & aErrorMessage )
877 if ( aBootstrapError == BE_PATHINFO_MISSING )
879 OUString aErrorMsg;
880 OUString aBuffer;
881 utl::Bootstrap::Status aBootstrapStatus;
882 utl::Bootstrap::FailureCode nFailureCode;
884 aBootstrapStatus = ::utl::Bootstrap::checkBootstrapStatus( aBuffer, nFailureCode );
885 if ( aBootstrapStatus != ::utl::Bootstrap::DATA_OK )
887 switch ( nFailureCode )
889 case ::utl::Bootstrap::MISSING_INSTALL_DIRECTORY:
890 case ::utl::Bootstrap::INVALID_BOOTSTRAP_DATA:
892 aErrorMsg = CreateErrorMsgString( nFailureCode, OUString() );
894 break;
896 /// the bootstrap INI file could not be found or read
897 /// the bootstrap INI is missing a required entry
898 /// the bootstrap INI contains invalid data
899 case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE_ENTRY:
900 case ::utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY:
901 case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE:
903 OUString aBootstrapFileURL;
905 utl::Bootstrap::locateBootstrapFile( aBootstrapFileURL );
906 aErrorMsg = CreateErrorMsgString( nFailureCode, aBootstrapFileURL );
908 break;
910 /// the version locator INI file could not be found or read
911 /// the version locator INI has no entry for this version
912 /// the version locator INI entry is not a valid directory URL
913 case ::utl::Bootstrap::INVALID_VERSION_FILE_ENTRY:
914 case ::utl::Bootstrap::MISSING_VERSION_FILE_ENTRY:
915 case ::utl::Bootstrap::MISSING_VERSION_FILE:
917 OUString aVersionFileURL;
919 utl::Bootstrap::locateVersionFile( aVersionFileURL );
920 aErrorMsg = CreateErrorMsgString( nFailureCode, aVersionFileURL );
922 break;
924 /// the user installation directory does not exist
925 case ::utl::Bootstrap::MISSING_USER_DIRECTORY:
927 OUString aUserInstallationURL;
929 utl::Bootstrap::locateUserInstallation( aUserInstallationURL );
930 aErrorMsg = CreateErrorMsgString( nFailureCode, aUserInstallationURL );
932 break;
934 case ::utl::Bootstrap::NO_FAILURE:
936 OSL_ASSERT(false);
938 break;
941 HandleBootstrapPathErrors( aBootstrapStatus, aErrorMsg );
944 else if ( aBootstrapError == BE_UNO_SERVICEMANAGER || aBootstrapError == BE_UNO_SERVICE_CONFIG_MISSING )
946 // Uno service manager is not available. VCL needs a uno service manager to display a message box!!!
947 // Currently we are not able to display a message box with a service manager due to this limitations inside VCL.
949 // When UNO is not properly initialized, all kinds of things can fail
950 // and cause the process to crash (e.g., a call to GetMsgString may
951 // crash when somewhere deep within that call Any::operator <= is used
952 // with a PropertyValue, and no binary UNO type description for
953 // PropertyValue is available). To give the user a hint even if
954 // generating and displaying a message box below crashes, print a
955 // hard-coded message on stderr first:
956 std::cerr
957 << "The application cannot be started.\n"
958 // STR_BOOTSTRAP_ERR_CANNOT_START
959 << (aBootstrapError == BE_UNO_SERVICEMANAGER
960 ? "The component manager is not available.\n"
961 // STR_BOOTSTRAP_ERR_NO_SERVICE
962 : "The configuration service is not available.\n");
963 // STR_BOOTSTRAP_ERR_NO_CFG_SERVICE
964 if ( !aErrorMessage.isEmpty() )
966 std::cerr << "(\"" << aErrorMessage << "\")\n";
969 // First sentence. We cannot bootstrap office further!
970 OUString aMessage;
971 OUStringBuffer aDiagnosticMessage( 100 );
973 OUString aErrorMsg;
975 if ( aBootstrapError == BE_UNO_SERVICEMANAGER )
976 aErrorMsg = "The service manager is not available.";
977 else
978 aErrorMsg = GetMsgString( STR_BOOTSTRAP_ERR_NO_CFG_SERVICE,
979 OUString( "The configuration service is not available." ) );
981 aDiagnosticMessage.append( aErrorMsg );
982 aDiagnosticMessage.appendAscii( "\n" );
983 if ( !aErrorMessage.isEmpty() )
985 aDiagnosticMessage.appendAscii( "(\"" );
986 aDiagnosticMessage.append( aErrorMessage );
987 aDiagnosticMessage.appendAscii( "\")\n" );
990 // Due to the fact the we haven't a backup applicat.rdb file anymore it is not possible to
991 // repair the installation with the setup executable besides the office executable. Now
992 // we have to ask the user to start the setup on CD/installation directory manually!!
993 OUString aStartSetupManually( GetMsgString(
994 STR_ASK_START_SETUP_MANUALLY,
995 OUString( "Start setup application to repair the installation from CD, or the folder containing the installation packages." ),
996 aBootstrapError == BE_UNO_SERVICEMANAGER ) );
998 aDiagnosticMessage.append( aStartSetupManually );
999 aMessage = MakeStartupErrorMessage(
1000 aDiagnosticMessage.makeStringAndClear(),
1001 aBootstrapError == BE_UNO_SERVICEMANAGER );
1003 FatalError( aMessage);
1005 else if ( aBootstrapError == BE_OFFICECONFIG_BROKEN )
1007 OUString msg(
1008 GetMsgString(
1009 STR_CONFIG_ERR_ACCESS_GENERAL,
1010 ("A general error occurred while accessing your central"
1011 " configuration.")));
1012 if (!aErrorMessage.isEmpty()) {
1013 msg += "\n(\"" + aErrorMessage + "\")";
1015 FatalError(MakeStartupErrorMessage(msg));
1017 else if ( aBootstrapError == BE_USERINSTALL_FAILED )
1019 OUString aMessage;
1020 OUStringBuffer aDiagnosticMessage( 100 );
1021 OUString aErrorMsg;
1022 aErrorMsg = GetMsgString( STR_BOOTSTRAP_ERR_USERINSTALL_FAILED,
1023 OUString( "User installation could not be completed" ) );
1024 aDiagnosticMessage.append( aErrorMsg );
1025 aMessage = MakeStartupErrorMessage( aDiagnosticMessage.makeStringAndClear() );
1026 FatalError(aMessage);
1028 else if ( aBootstrapError == BE_LANGUAGE_MISSING )
1030 OUString aMessage;
1031 OUStringBuffer aDiagnosticMessage( 100 );
1032 OUString aErrorMsg;
1033 aErrorMsg = GetMsgString(
1034 //@@@ FIXME: should use an own resource string => #i36213#
1035 STR_BOOTSTRAP_ERR_LANGUAGE_MISSING,
1036 OUString( "Language could not be determined." ) );
1037 aDiagnosticMessage.append( aErrorMsg );
1038 aMessage = MakeStartupErrorMessage(
1039 aDiagnosticMessage.makeStringAndClear() );
1040 FatalError(aMessage);
1042 else if (( aBootstrapError == BE_USERINSTALL_NOTENOUGHDISKSPACE ) ||
1043 ( aBootstrapError == BE_USERINSTALL_NOWRITEACCESS ))
1045 OUString aUserInstallationURL;
1046 OUString aUserInstallationPath;
1047 OUString aMessage;
1048 OUString aErrorMsg;
1049 OUStringBuffer aDiagnosticMessage( 100 );
1051 utl::Bootstrap::locateUserInstallation( aUserInstallationURL );
1053 if ( aBootstrapError == BE_USERINSTALL_NOTENOUGHDISKSPACE )
1054 aErrorMsg = GetMsgString(
1055 STR_BOOSTRAP_ERR_NOTENOUGHDISKSPACE,
1056 OUString( "User installation could not be completed due to insufficient free disk space." ) );
1057 else
1058 aErrorMsg = GetMsgString(
1059 STR_BOOSTRAP_ERR_NOACCESSRIGHTS,
1060 OUString( "User installation could not be processed due to missing access rights." ) );
1062 osl::File::getSystemPathFromFileURL( aUserInstallationURL, aUserInstallationPath );
1064 aDiagnosticMessage.append( aErrorMsg );
1065 aDiagnosticMessage.append( aUserInstallationPath );
1066 aMessage = MakeStartupErrorMessage(
1067 aDiagnosticMessage.makeStringAndClear() );
1068 FatalError(aMessage);
1071 return;
1075 void Desktop::retrieveCrashReporterState()
1077 _bCrashReporterEnabled
1078 = officecfg::Office::Recovery::CrashReporter::Enabled::get();
1081 sal_Bool Desktop::isUIOnSessionShutdownAllowed()
1083 return officecfg::Office::Recovery::SessionShutdown::DocumentStoreUIEnabled
1084 ::get();
1087 //-----------------------------------------------
1088 /** @short check if crash reporter feature is enabled or
1089 disabled.
1091 sal_Bool Desktop::isCrashReporterEnabled()
1093 return _bCrashReporterEnabled;
1096 //-----------------------------------------------
1097 /** @short check if recovery must be started or not.
1099 @param bCrashed [boolean ... out!]
1100 the office crashed last times.
1101 But may be there are no recovery data.
1102 Useful to trigger the error report tool without
1103 showing the recovery UI.
1105 @param bRecoveryDataExists [boolean ... out!]
1106 there exists some recovery data.
1108 @param bSessionDataExists [boolean ... out!]
1109 there exists some session data.
1110 Because the user may be logged out last time from it's
1111 unix session...
1113 void impl_checkRecoveryState(sal_Bool& bCrashed ,
1114 sal_Bool& bRecoveryDataExists,
1115 sal_Bool& bSessionDataExists )
1117 bCrashed = officecfg::Office::Recovery::RecoveryInfo::Crashed::get();
1118 bool elements = officecfg::Office::Recovery::RecoveryList::get()->
1119 hasElements();
1120 bool session
1121 = officecfg::Office::Recovery::RecoveryInfo::SessionData::get();
1122 bRecoveryDataExists = elements && !session;
1123 bSessionDataExists = elements && session;
1126 //-----------------------------------------------
1127 /* @short start the recovery wizard.
1129 @param bEmergencySave
1130 differs between EMERGENCY_SAVE and RECOVERY
1132 sal_Bool impl_callRecoveryUI(sal_Bool bEmergencySave ,
1133 sal_Bool bCrashed ,
1134 sal_Bool bExistsRecoveryData)
1136 static OUString SERVICENAME_RECOVERYUI("com.sun.star.comp.svx.RecoveryUI");
1137 static OUString COMMAND_EMERGENCYSAVE("vnd.sun.star.autorecovery:/doEmergencySave");
1138 static OUString COMMAND_RECOVERY("vnd.sun.star.autorecovery:/doAutoRecovery");
1139 static OUString COMMAND_CRASHREPORT("vnd.sun.star.autorecovery:/doCrashReport");
1141 css::uno::Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
1143 Reference< css::frame::XSynchronousDispatch > xRecoveryUI(
1144 xContext->getServiceManager()->createInstanceWithContext(SERVICENAME_RECOVERYUI, xContext),
1145 css::uno::UNO_QUERY_THROW);
1147 Reference< css::util::XURLTransformer > xURLParser =
1148 css::util::URLTransformer::create(::comphelper::getProcessComponentContext());
1150 css::util::URL aURL;
1151 if (bEmergencySave)
1152 aURL.Complete = COMMAND_EMERGENCYSAVE;
1153 else if (bExistsRecoveryData)
1154 aURL.Complete = COMMAND_RECOVERY;
1155 else if (bCrashed && Desktop::isCrashReporterEnabled() )
1156 aURL.Complete = COMMAND_CRASHREPORT;
1157 else
1158 return false;
1160 xURLParser->parseStrict(aURL);
1162 css::uno::Any aRet = xRecoveryUI->dispatchWithReturnValue(aURL, css::uno::Sequence< css::beans::PropertyValue >());
1163 sal_Bool bRet = sal_False;
1164 aRet >>= bRet;
1165 return !bEmergencySave || bRet;
1169 * Save all open documents so they will be reopened
1170 * the next time the application is started
1172 * returns sal_True if at least one document could be saved...
1176 sal_Bool Desktop::SaveTasks()
1178 return impl_callRecoveryUI(
1179 sal_True , // sal_True => force emergency save
1180 sal_False, // 2. and 3. param not used if 1. = true!
1181 sal_False);
1184 namespace {
1186 void restartOnMac(bool passArguments) {
1187 #if defined MACOSX
1188 OfficeIPCThread::DisableOfficeIPCThread();
1189 #if HAVE_FEATURE_MACOSX_SANDBOX
1190 (void) passArguments; // avoid warnings
1191 ResMgr *resMgr = Desktop::GetDesktopResManager();
1192 OUString aMessage = ResId(STR_LO_MUST_BE_RESTARTED, *resMgr).toString();
1194 ErrorBox aRestartBox( NULL, WB_OK, aMessage );
1195 aRestartBox.Execute();
1196 #else
1197 OUString execUrl;
1198 OSL_VERIFY(osl_getExecutableFile(&execUrl.pData) == osl_Process_E_None);
1199 OUString execPath;
1200 OString execPath8;
1201 if ((osl::FileBase::getSystemPathFromFileURL(execUrl, execPath)
1202 != osl::FileBase::E_None) ||
1203 !execPath.convertToString(
1204 &execPath8, osl_getThreadTextEncoding(),
1205 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
1206 RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
1208 std::abort();
1210 std::vector< OString > args;
1211 args.push_back(execPath8);
1212 bool wait = false;
1213 if (passArguments) {
1214 sal_uInt32 n = osl_getCommandArgCount();
1215 for (sal_uInt32 i = 0; i < n; ++i) {
1216 OUString arg;
1217 OSL_VERIFY(osl_getCommandArg(i, &arg.pData) == osl_Process_E_None);
1218 if (arg.match("--accept=")) {
1219 wait = true;
1221 OString arg8;
1222 if (!arg.convertToString(
1223 &arg8, osl_getThreadTextEncoding(),
1224 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
1225 RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
1227 std::abort();
1229 args.push_back(arg8);
1232 std::vector< char const * > argPtrs;
1233 for (std::vector< OString >::iterator i(args.begin()); i != args.end();
1234 ++i)
1236 argPtrs.push_back(i->getStr());
1238 argPtrs.push_back(0);
1239 execv(execPath8.getStr(), const_cast< char ** >(&argPtrs[0]));
1240 if (errno == ENOTSUP) { // happens when multithreaded on OS X < 10.6
1241 pid_t pid = fork();
1242 if (pid == 0) {
1243 execv(execPath8.getStr(), const_cast< char ** >(&argPtrs[0]));
1244 } else if (pid > 0) {
1245 // Two simultaneously running soffice processes lead to two dock
1246 // icons, so avoid waiting here unless it must be assumed that the
1247 // process invoking soffice itself wants to wait for soffice to
1248 // finish:
1249 if (!wait) {
1250 return;
1252 int stat;
1253 if (waitpid(pid, &stat, 0) == pid && WIFEXITED(stat)) {
1254 _exit(WEXITSTATUS(stat));
1258 std::abort();
1259 #endif
1260 #else
1261 (void) passArguments; // avoid warnings
1262 #endif
1267 sal_uInt16 Desktop::Exception(sal_uInt16 nError)
1269 // protect against recursive calls
1270 static sal_Bool bInException = sal_False;
1272 sal_uInt16 nOldMode = Application::GetSystemWindowMode();
1273 Application::SetSystemWindowMode( nOldMode & ~SYSTEMWINDOW_MODE_NOAUTOMODE );
1274 Application::SetDefDialogParent( NULL );
1276 if ( bInException )
1278 OUString aDoubleExceptionString;
1279 Application::Abort( aDoubleExceptionString );
1282 bInException = sal_True;
1283 const CommandLineArgs& rArgs = GetCommandLineArgs();
1285 // save all modified documents ... if it's allowed doing so.
1286 sal_Bool bRestart = sal_False;
1287 sal_Bool bAllowRecoveryAndSessionManagement = (
1288 ( !rArgs.IsNoRestore() ) && // some use cases of office must work without recovery
1289 ( !rArgs.IsHeadless() ) &&
1290 (( nError & EXC_MAJORTYPE ) != EXC_DISPLAY ) && // recovery cant work without UI ... but UI layer seams to be the reason for this crash
1291 ( Application::IsInExecute() ) // crashes during startup and shutdown should be ignored (they indicates a corrupt installation ...)
1293 if ( bAllowRecoveryAndSessionManagement )
1294 bRestart = SaveTasks();
1296 FlushConfiguration();
1298 switch( nError & EXC_MAJORTYPE )
1300 case EXC_RSCNOTLOADED:
1302 OUString aResExceptionString;
1303 Application::Abort( aResExceptionString );
1304 break;
1307 case EXC_SYSOBJNOTCREATED:
1309 OUString aSysResExceptionString;
1310 Application::Abort( aSysResExceptionString );
1311 break;
1314 default:
1316 m_xLockfile.reset();
1318 if( bRestart )
1320 OfficeIPCThread::DisableOfficeIPCThread();
1321 if( pSignalHandler )
1322 osl_removeSignalHandler( pSignalHandler );
1324 restartOnMac(false);
1325 if ( m_rSplashScreen.is() )
1326 m_rSplashScreen->reset();
1328 _exit( EXITHELPER_CRASH_WITH_RESTART );
1330 else
1332 Application::Abort( OUString() );
1335 break;
1339 OSL_ASSERT(false); // unreachable
1340 return 0;
1343 void Desktop::AppEvent( const ApplicationEvent& rAppEvent )
1345 HandleAppEvent( rAppEvent );
1349 struct ExecuteGlobals
1351 Reference < css::document::XEventListener > xGlobalBroadcaster;
1352 sal_Bool bRestartRequested;
1353 sal_Bool bUseSystemFileDialog;
1354 std::auto_ptr<SvtLanguageOptions> pLanguageOptions;
1355 std::auto_ptr<SvtPathOptions> pPathOptions;
1357 ExecuteGlobals()
1358 : bRestartRequested( sal_False )
1359 , bUseSystemFileDialog( sal_True )
1363 static ExecuteGlobals* pExecGlobals = NULL;
1365 int Desktop::Main()
1367 pExecGlobals = new ExecuteGlobals();
1369 SAL_INFO( "desktop.app", "desktop (cd100003) ::Desktop::Main" );
1371 // Remember current context object
1372 com::sun::star::uno::ContextLayer layer(
1373 com::sun::star::uno::getCurrentContext() );
1375 if ( m_aBootstrapError != BE_OK )
1377 HandleBootstrapErrors( m_aBootstrapError, m_aBootstrapErrorMessage );
1378 return EXIT_FAILURE;
1381 BootstrapStatus eStatus = GetBootstrapStatus();
1382 if (eStatus == BS_TERMINATE) {
1383 return EXIT_SUCCESS;
1386 // Detect desktop environment - need to do this as early as possible
1387 com::sun::star::uno::setCurrentContext(
1388 new DesktopContext( com::sun::star::uno::getCurrentContext() ) );
1390 CommandLineArgs& rCmdLineArgs = GetCommandLineArgs();
1392 #if HAVE_FEATURE_DESKTOP
1393 OUString aUnknown( rCmdLineArgs.GetUnknown() );
1394 if ( !aUnknown.isEmpty() )
1396 displayCmdlineHelp( aUnknown );
1397 return EXIT_FAILURE;
1399 if ( rCmdLineArgs.IsHelp() )
1401 displayCmdlineHelp( OUString() );
1402 return EXIT_SUCCESS;
1404 if ( rCmdLineArgs.IsVersion() )
1406 displayVersion();
1407 return EXIT_SUCCESS;
1409 #endif
1410 // setup configuration error handling
1411 ConfigurationErrorHandler aConfigErrHandler;
1412 if (!ShouldSuppressUI(rCmdLineArgs))
1413 aConfigErrHandler.activate();
1415 ResMgr::SetReadStringHook( ReplaceStringHookProc );
1417 // Startup screen
1418 SAL_INFO( "desktop.app", "desktop (lo119109) Desktop::Main { OpenSplashScreen" );
1419 OpenSplashScreen();
1420 SAL_INFO( "desktop.app", "desktop (lo119109) Desktop::Main } OpenSplashScreen" );
1422 SetSplashScreenProgress(10);
1424 userinstall::Status inst_fin = userinstall::finalize();
1425 if (inst_fin != userinstall::EXISTED && inst_fin != userinstall::CREATED)
1427 SAL_WARN( "desktop.app", "userinstall failed");
1428 if ( inst_fin == userinstall::ERROR_NO_SPACE )
1429 HandleBootstrapErrors(
1430 BE_USERINSTALL_NOTENOUGHDISKSPACE, OUString() );
1431 else if ( inst_fin == userinstall::ERROR_CANT_WRITE )
1432 HandleBootstrapErrors( BE_USERINSTALL_NOWRITEACCESS, OUString() );
1433 else
1434 HandleBootstrapErrors( BE_USERINSTALL_FAILED, OUString() );
1435 return EXIT_FAILURE;
1437 // refresh path information
1438 utl::Bootstrap::reloadData();
1439 SetSplashScreenProgress(20);
1441 Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
1443 Reference< XRestartManager > xRestartManager( OfficeRestartManager::get(xContext) );
1445 Reference< XDesktop2 > xDesktop;
1448 RegisterServices(xContext);
1450 SetSplashScreenProgress(25);
1452 // check user installation directory for lockfile so we can be sure
1453 // there is no other instance using our data files from a remote host
1454 SAL_INFO( "desktop.app", "desktop (lo119109) Desktop::Main -> Lockfile" );
1455 m_xLockfile.reset(new Lockfile);
1457 #if HAVE_FEATURE_DESKTOP
1458 if ( !rCmdLineArgs.IsHeadless() && !rCmdLineArgs.IsInvisible() &&
1459 !rCmdLineArgs.IsNoLockcheck() && !m_xLockfile->check( Lockfile_execWarning ))
1461 // Lockfile exists, and user clicked 'no'
1462 return EXIT_FAILURE;
1464 SAL_INFO( "desktop.app", "desktop (lo119109) Desktop::Main <- Lockfile" );
1466 // check if accessibility is enabled but not working and allow to quit
1467 SAL_INFO( "desktop.app", "{ GetEnableATToolSupport" );
1468 if( Application::GetSettings().GetMiscSettings().GetEnableATToolSupport() )
1470 bool bQuitApp;
1472 if( !InitAccessBridge( true, bQuitApp ) )
1473 if( bQuitApp )
1474 return EXIT_FAILURE;
1476 SAL_INFO( "desktop.app", "} GetEnableATToolSupport" );
1477 #endif
1479 // terminate if requested...
1480 if( rCmdLineArgs.IsTerminateAfterInit() )
1481 return EXIT_SUCCESS;
1483 // Read the common configuration items for optimization purpose
1484 if ( !InitializeConfiguration() )
1485 return EXIT_FAILURE;
1487 SetSplashScreenProgress(30);
1489 // set static variable to enabled/disable crash reporter
1490 retrieveCrashReporterState();
1491 if ( !isCrashReporterEnabled() )
1493 osl_setErrorReporting( sal_False );
1494 // disable stack trace feature
1497 // create title string
1498 LanguageTag aLocale( LANGUAGE_SYSTEM);
1499 ResMgr* pLabelResMgr = ResMgr::SearchCreateResMgr( "ofa", aLocale );
1500 OUString aTitle = pLabelResMgr ? ResId(RID_APPTITLE, *pLabelResMgr).toString() : OUString();
1501 delete pLabelResMgr;
1503 #ifdef DBG_UTIL
1504 //include buildid in non product builds
1505 OUString aDefault("development");
1506 aTitle += " [";
1507 aTitle += utl::Bootstrap::getBuildIdData(aDefault);
1508 aTitle += "]";
1509 #endif
1511 SetDisplayName( aTitle );
1512 SetSplashScreenProgress(35);
1513 SAL_INFO( "desktop.app", "{ create SvtPathOptions and SvtLanguageOptions" );
1514 pExecGlobals->pPathOptions.reset( new SvtPathOptions);
1515 SetSplashScreenProgress(40);
1516 SAL_INFO( "desktop.app", "} create SvtPathOptions and SvtLanguageOptions" );
1518 xDesktop = css::frame::Desktop::create( xContext );
1520 // create service for loadin SFX (still needed in startup)
1521 pExecGlobals->xGlobalBroadcaster = Reference < css::document::XEventListener >
1522 ( css::frame::GlobalEventBroadcaster::create(xContext), UNO_QUERY_THROW );
1524 /* ensure existance of a default window that messages can be dispatched to
1525 This is for the benefit of testtool which uses PostUserEvent extensively
1526 and else can deadlock while creating this window from another tread while
1527 the main thread is not yet in the event loop.
1529 Application::GetDefaultDevice();
1531 #if HAVE_FEATURE_EXTENSIONS
1532 // Check if bundled or shared extensions were added /removed
1533 // and process those extensions (has to be done before checking
1534 // the extension dependencies!
1535 SynchronizeExtensionRepositories();
1536 bool bAbort = CheckExtensionDependencies();
1537 if ( bAbort )
1538 return EXIT_FAILURE;
1540 if (inst_fin == userinstall::CREATED)
1542 Migration::migrateSettingsIfNecessary();
1544 #endif
1546 // keep a language options instance...
1547 pExecGlobals->pLanguageOptions.reset( new SvtLanguageOptions(sal_True));
1549 css::document::EventObject aEvent;
1550 aEvent.EventName = "OnStartApp";
1551 pExecGlobals->xGlobalBroadcaster->notifyEvent(aEvent);
1553 SetSplashScreenProgress(50);
1555 // Backing Component
1556 sal_Bool bCrashed = sal_False;
1557 sal_Bool bExistsRecoveryData = sal_False;
1558 sal_Bool bExistsSessionData = sal_False;
1560 SAL_INFO( "desktop.app", "{ impl_checkRecoveryState" );
1561 impl_checkRecoveryState(bCrashed, bExistsRecoveryData, bExistsSessionData);
1562 SAL_INFO( "desktop.app", "} impl_checkRecoveryState" );
1564 OUString pidfileName = rCmdLineArgs.GetPidfileName();
1565 if ( !pidfileName.isEmpty() )
1567 OUString pidfileURL;
1569 if ( osl_getFileURLFromSystemPath(pidfileName.pData, &pidfileURL.pData) == osl_File_E_None )
1571 osl::File pidfile( pidfileURL );
1572 osl::FileBase::RC rc;
1574 osl::File::remove( pidfileURL );
1575 if ( (rc = pidfile.open( osl_File_OpenFlag_Write | osl_File_OpenFlag_Create ) ) == osl::File::E_None )
1577 OString pid( OString::number( GETPID() ) );
1578 sal_uInt64 written = 0;
1579 if ( pidfile.write(pid.getStr(), pid.getLength(), written) != osl::File::E_None )
1581 SAL_WARN("desktop.app", "cannot write pidfile " << pidfile.getURL());
1583 pidfile.close();
1585 else
1587 SAL_WARN("desktop.app", "cannot open pidfile " << pidfile.getURL() << osl::FileBase::RC(rc));
1590 else
1592 SAL_WARN("desktop.app", "cannot get pidfile URL from path" << pidfileName);
1596 if ( rCmdLineArgs.IsHeadless() )
1598 // Ensure that we use not the system file dialogs as
1599 // headless mode relies on Application::EnableHeadlessMode()
1600 // which does only work for VCL dialogs!!
1601 SvtMiscOptions aMiscOptions;
1602 pExecGlobals->bUseSystemFileDialog = aMiscOptions.UseSystemFileDialog();
1603 aMiscOptions.SetUseSystemFileDialog( sal_False );
1606 pExecGlobals->bRestartRequested = xRestartManager->isRestartRequested(
1607 true);
1608 if ( !pExecGlobals->bRestartRequested )
1610 if ((!rCmdLineArgs.WantsToLoadDocument() && !rCmdLineArgs.IsInvisible() && !rCmdLineArgs.IsHeadless() && !rCmdLineArgs.IsQuickstart()) &&
1611 (SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::E_SSTARTMODULE)) &&
1612 (!bExistsRecoveryData ) &&
1613 (!bExistsSessionData ) &&
1614 (!Application::AnyInput( VCL_INPUT_APPEVENT ) ))
1616 SAL_INFO( "desktop.app", "{ create BackingComponent" );
1617 ShowBackingComponent(this);
1618 SAL_INFO( "desktop.app", "} create BackingComponent" );
1622 catch ( const com::sun::star::lang::WrappedTargetException& wte )
1624 com::sun::star::uno::Exception te;
1625 wte.TargetException >>= te;
1626 FatalError( MakeStartupConfigAccessErrorMessage(wte.Message + te.Message) );
1628 catch ( const com::sun::star::uno::Exception& e )
1630 FatalError( MakeStartupErrorMessage(e.Message) );
1632 SetSplashScreenProgress(55);
1634 SvtFontSubstConfig().Apply();
1636 SvtTabAppearanceCfg aAppearanceCfg;
1637 aAppearanceCfg.SetInitialized();
1638 aAppearanceCfg.SetApplicationDefaults( this );
1639 SvtAccessibilityOptions aOptions;
1640 aOptions.SetVCLSettings();
1641 SetSplashScreenProgress(60);
1643 #if ENABLE_TELEPATHY
1644 bool bListen = rCmdLineArgs.IsInvisible();
1645 TeleManager::init( bListen );
1646 #endif
1648 if ( !pExecGlobals->bRestartRequested )
1650 Application::SetFilterHdl( LINK( this, Desktop, ImplInitFilterHdl ) );
1651 sal_Bool bTerminateRequested = sal_False;
1653 // Preload function depends on an initialized sfx application!
1654 SetSplashScreenProgress(75);
1656 // use system window dialogs
1657 Application::SetSystemWindowMode( SYSTEMWINDOW_MODE_DIALOG );
1659 SetSplashScreenProgress(80);
1661 if ( !bTerminateRequested && !rCmdLineArgs.IsInvisible() &&
1662 !rCmdLineArgs.IsNoQuickstart() )
1663 InitializeQuickstartMode( xContext );
1665 SAL_INFO( "desktop.app", "desktop (cd100003) createInstance com.sun.star.frame.Desktop" );
1668 if ( xDesktop.is() )
1669 xDesktop->addTerminateListener( new OfficeIPCThreadController );
1670 SetSplashScreenProgress(100);
1672 catch ( const com::sun::star::uno::Exception& e )
1674 FatalError( MakeStartupErrorMessage(e.Message) );
1677 // Release solar mutex just before we wait for our client to connect
1678 int nAcquireCount = Application::ReleaseSolarMutex();
1680 // Post user event to startup first application component window
1681 // We have to send this OpenClients message short before execute() to
1682 // minimize the risk that this message overtakes type detection contruction!!
1683 Application::PostUserEvent( LINK( this, Desktop, OpenClients_Impl ) );
1685 // Post event to enable acceptors
1686 Application::PostUserEvent( LINK( this, Desktop, EnableAcceptors_Impl) );
1688 // The configuration error handler currently is only for startup
1689 aConfigErrHandler.deactivate();
1691 // Acquire solar mutex just before we enter our message loop
1692 if ( nAcquireCount )
1693 Application::AcquireSolarMutex( nAcquireCount );
1695 // call Application::Execute to process messages in vcl message loop
1696 SAL_INFO( "desktop.app", "PERFORMANCE - enter Application::Execute()" );
1700 #if HAVE_FEATURE_JAVA
1701 // The JavaContext contains an interaction handler which is used when
1702 // the creation of a Java Virtual Machine fails
1703 com::sun::star::uno::ContextLayer layer2(
1704 new svt::JavaContext( com::sun::star::uno::getCurrentContext() ) );
1705 #endif
1706 // check whether the shutdown is caused by restart just before entering the Execute
1707 pExecGlobals->bRestartRequested = pExecGlobals->bRestartRequested ||
1708 xRestartManager->isRestartRequested(true);
1710 if ( !pExecGlobals->bRestartRequested )
1712 // if this run of the office is triggered by restart, some additional actions should be done
1713 DoRestartActionsIfNecessary( !rCmdLineArgs.IsInvisible() && !rCmdLineArgs.IsNoQuickstart() );
1715 Execute();
1718 catch(const com::sun::star::document::CorruptedFilterConfigurationException& exFilterCfg)
1720 OfficeIPCThread::SetDowning();
1721 FatalError( MakeStartupErrorMessage(exFilterCfg.Message) );
1723 catch(const com::sun::star::configuration::CorruptedConfigurationException& exAnyCfg)
1725 OfficeIPCThread::SetDowning();
1726 FatalError( MakeStartupErrorMessage(exAnyCfg.Message) );
1728 catch( const ::com::sun::star::uno::Exception& exUNO)
1730 OfficeIPCThread::SetDowning();
1731 FatalError( exUNO.Message);
1733 catch( const std::exception& exSTD)
1735 OfficeIPCThread::SetDowning();
1736 FatalError( OUString::createFromAscii( exSTD.what()));
1738 catch( ...)
1740 OfficeIPCThread::SetDowning();
1741 FatalError( OUString( "Caught Unknown Exception: Aborting!"));
1744 else
1746 if (xDesktop.is())
1747 xDesktop->terminate();
1749 // CAUTION: you do not necessarily get here e.g. on the Mac.
1750 // please put all deinitialization code into doShutdown
1751 return doShutdown();
1754 int Desktop::doShutdown()
1756 if( ! pExecGlobals )
1757 return EXIT_SUCCESS;
1759 pExecGlobals->bRestartRequested = pExecGlobals->bRestartRequested ||
1760 OfficeRestartManager::get(comphelper::getProcessComponentContext())->
1761 isRestartRequested(true);
1762 if ( pExecGlobals->bRestartRequested )
1763 SetRestartState();
1765 if (pExecGlobals->xGlobalBroadcaster.is())
1767 css::document::EventObject aEvent;
1768 aEvent.EventName = "OnCloseApp";
1769 pExecGlobals->xGlobalBroadcaster->notifyEvent(aEvent);
1772 delete pResMgr, pResMgr = NULL;
1773 // Restore old value
1774 const CommandLineArgs& rCmdLineArgs = GetCommandLineArgs();
1775 if ( rCmdLineArgs.IsHeadless() )
1776 SvtMiscOptions().SetUseSystemFileDialog( pExecGlobals->bUseSystemFileDialog );
1778 OUString pidfileName = rCmdLineArgs.GetPidfileName();
1779 if ( !pidfileName.isEmpty() )
1781 OUString pidfileURL;
1783 if ( osl_getFileURLFromSystemPath(pidfileName.pData, &pidfileURL.pData) == osl_File_E_None )
1785 if ( osl::File::remove( pidfileURL ) != osl::FileBase::E_None )
1787 SAL_WARN("desktop.app", "shutdown: cannot remove pidfile " << pidfileURL);
1790 else
1792 SAL_WARN("desktop.app", "shutdown: cannot get pidfile URL from path" << pidfileName);
1796 // remove temp directory
1797 RemoveTemporaryDirectory();
1798 FlushConfiguration();
1799 // The acceptors in the AcceptorMap must be released (in DeregisterServices)
1800 // with the solar mutex unlocked, to avoid deadlock:
1801 sal_uLong nAcquireCount = Application::ReleaseSolarMutex();
1802 DeregisterServices();
1803 Application::AcquireSolarMutex(nAcquireCount);
1804 // be sure that path/language options gets destroyed before
1805 // UCB is deinitialized
1806 SAL_INFO( "desktop.app", "-> dispose path/language options" );
1807 pExecGlobals->pLanguageOptions.reset( 0 );
1808 pExecGlobals->pPathOptions.reset( 0 );
1809 SAL_INFO( "desktop.app", "<- dispose path/language options" );
1811 sal_Bool bRR = pExecGlobals->bRestartRequested;
1812 delete pExecGlobals, pExecGlobals = NULL;
1814 SAL_INFO( "desktop.app", "FINISHED WITH Destop::Main" );
1815 if ( bRR )
1817 restartOnMac(true);
1818 if ( m_rSplashScreen.is() )
1819 m_rSplashScreen->reset();
1821 return EXITHELPER_NORMAL_RESTART;
1823 return EXIT_SUCCESS;
1826 IMPL_LINK( Desktop, ImplInitFilterHdl, ConvertData*, pData )
1828 return GraphicFilter::GetGraphicFilter().GetFilterCallback().Call( pData );
1831 bool Desktop::InitializeConfiguration()
1833 SAL_INFO( "desktop.app", "desktop (jb99855) ::InitConfiguration" );
1836 css::configuration::theDefaultProvider::get(
1837 comphelper::getProcessComponentContext() );
1838 return true;
1840 catch( ::com::sun::star::lang::ServiceNotRegisteredException & e )
1842 this->HandleBootstrapErrors(
1843 Desktop::BE_UNO_SERVICE_CONFIG_MISSING, e.Message );
1845 catch( const ::com::sun::star::configuration::MissingBootstrapFileException& e )
1847 OUString aMsg( CreateErrorMsgString( utl::Bootstrap::MISSING_BOOTSTRAP_FILE,
1848 e.BootstrapFileURL ));
1849 HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_USER_INSTALL, aMsg );
1851 catch( const ::com::sun::star::configuration::InvalidBootstrapFileException& e )
1853 OUString aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY,
1854 e.BootstrapFileURL ));
1855 HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL, aMsg );
1857 catch( const ::com::sun::star::configuration::InstallationIncompleteException& )
1859 OUString aVersionFileURL;
1860 OUString aMsg;
1861 utl::Bootstrap::PathStatus aPathStatus = utl::Bootstrap::locateVersionFile( aVersionFileURL );
1862 if ( aPathStatus == utl::Bootstrap::PATH_EXISTS )
1863 aMsg = CreateErrorMsgString( utl::Bootstrap::MISSING_VERSION_FILE_ENTRY, aVersionFileURL );
1864 else
1865 aMsg = CreateErrorMsgString( utl::Bootstrap::MISSING_VERSION_FILE, aVersionFileURL );
1867 HandleBootstrapPathErrors( ::utl::Bootstrap::MISSING_USER_INSTALL, aMsg );
1869 catch ( const com::sun::star::configuration::backend::BackendAccessException& exception)
1871 // [cm122549] It is assumed in this case that the message
1872 // coming from InitConfiguration (in fact CreateApplicationConf...)
1873 // is suitable for display directly.
1874 FatalError( MakeStartupErrorMessage( exception.Message ) );
1876 catch ( const com::sun::star::configuration::backend::BackendSetupException& exception)
1878 // [cm122549] It is assumed in this case that the message
1879 // coming from InitConfiguration (in fact CreateApplicationConf...)
1880 // is suitable for display directly.
1881 FatalError( MakeStartupErrorMessage( exception.Message ) );
1883 catch ( const ::com::sun::star::configuration::CannotLoadConfigurationException& )
1885 OUString aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_DATA,
1886 OUString() ));
1887 HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL, aMsg );
1889 catch( const ::com::sun::star::uno::Exception& )
1891 OUString aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_DATA,
1892 OUString() ));
1893 HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL, aMsg );
1895 return false;
1898 void Desktop::FlushConfiguration()
1900 css::uno::Reference< css::util::XFlushable >(
1901 css::configuration::theDefaultProvider::get(
1902 comphelper::getProcessComponentContext()),
1903 css::uno::UNO_QUERY_THROW)->flush();
1906 sal_Bool Desktop::InitializeQuickstartMode( const Reference< XComponentContext >& rxContext )
1910 // the shutdown icon sits in the systray and allows the user to keep
1911 // the office instance running for quicker restart
1912 // this will only be activated if --quickstart was specified on cmdline
1913 SAL_INFO( "desktop.app", "desktop (cd100003) createInstance com.sun.star.office.Quickstart" );
1915 sal_Bool bQuickstart = shouldLaunchQuickstart();
1917 // Try to instantiate quickstart service. This service is not mandatory, so
1918 // do nothing if service is not available
1920 // #i105753# the following if was invented for performance
1921 // unfortunately this broke the Mac behavior which is to always run
1922 // in quickstart mode since Mac applications do not usually quit
1923 // when the last document closes.
1924 // Note that this claim that on OS X we "always run in quickstart mode"
1925 // has nothing to do with (quick) *starting* (i.e. starting automatically
1926 // when the user logs in), though, but with not quitting when no documents
1927 // are open.
1928 #ifndef MACOSX
1929 if ( bQuickstart )
1930 #endif
1932 css::office::Quickstart::createStart(rxContext, bQuickstart);
1934 return sal_True;
1936 catch( const ::com::sun::star::uno::Exception& )
1938 return sal_False;
1942 void Desktop::SystemSettingsChanging( AllSettings& rSettings, Window* )
1944 if ( !SvtTabAppearanceCfg::IsInitialized () )
1945 return;
1947 # define DRAGFULL_OPTION_ALL \
1948 ( DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE \
1949 | DRAGFULL_OPTION_OBJECTMOVE | DRAGFULL_OPTION_OBJECTSIZE \
1950 | DRAGFULL_OPTION_DOCKING | DRAGFULL_OPTION_SPLIT \
1951 | DRAGFULL_OPTION_SCROLL )
1952 # define DRAGFULL_OPTION_NONE ((sal_uInt32)~DRAGFULL_OPTION_ALL)
1954 StyleSettings hStyleSettings = rSettings.GetStyleSettings();
1955 MouseSettings hMouseSettings = rSettings.GetMouseSettings();
1957 sal_uInt32 nDragFullOptions = hStyleSettings.GetDragFullOptions();
1959 SvtTabAppearanceCfg aAppearanceCfg;
1960 sal_uInt16 nGet = aAppearanceCfg.GetDragMode();
1961 switch ( nGet )
1963 case DragFullWindow:
1964 nDragFullOptions |= DRAGFULL_OPTION_ALL;
1965 break;
1966 case DragFrame:
1967 nDragFullOptions &= DRAGFULL_OPTION_NONE;
1968 break;
1969 case DragSystemDep:
1970 default:
1971 break;
1974 sal_uInt32 nFollow = hMouseSettings.GetFollow();
1975 hMouseSettings.SetFollow( aAppearanceCfg.IsMenuMouseFollow() ? (nFollow|MOUSE_FOLLOW_MENU) : (nFollow&~MOUSE_FOLLOW_MENU));
1976 rSettings.SetMouseSettings(hMouseSettings);
1978 SvtMenuOptions aMenuOpt;
1979 hStyleSettings.SetUseImagesInMenus(aMenuOpt.GetMenuIconsState());
1980 hStyleSettings.SetDragFullOptions( nDragFullOptions );
1981 rSettings.SetStyleSettings ( hStyleSettings );
1984 // ========================================================================
1985 IMPL_LINK_NOARG(Desktop, AsyncInitFirstRun)
1987 DoFirstRunInitializations();
1988 return 0L;
1991 // ========================================================================
1993 class ExitTimer : public Timer
1995 public:
1996 ExitTimer()
1998 SetTimeout(500);
1999 Start();
2001 virtual void Timeout()
2003 exit(42);
2007 IMPL_LINK_NOARG(Desktop, OpenClients_Impl)
2009 SAL_INFO( "desktop.app", "PERFORMANCE - DesktopOpenClients_Impl()" );
2011 try {
2012 OpenClients();
2014 OfficeIPCThread::SetReady();
2016 CloseSplashScreen();
2017 CheckFirstRun( );
2018 EnableOleAutomation();
2020 if (getenv ("OOO_EXIT_POST_STARTUP"))
2021 new ExitTimer();
2022 } catch (const ::com::sun::star::uno::Exception &e) {
2023 OUString a( "UNO exception during client open:\n" );
2024 Application::Abort( a + e.Message );
2026 return 0;
2029 // enable acceptos
2030 IMPL_LINK_NOARG(Desktop, EnableAcceptors_Impl)
2032 enableAcceptors();
2033 return 0;
2037 // Registers a COM class factory of the service manager with the windows operating system.
2038 void Desktop::EnableOleAutomation()
2040 SAL_INFO( "desktop.app", "desktop (jl97489) ::Desktop::EnableOleAutomation" );
2041 #ifdef WNT
2042 Reference< XMultiServiceFactory > xSMgr= comphelper::getProcessServiceFactory();
2043 xSMgr->createInstance("com.sun.star.bridge.OleApplicationRegistration");
2044 xSMgr->createInstance("com.sun.star.comp.ole.EmbedServer");
2045 #endif
2048 void Desktop::PreloadModuleData( const CommandLineArgs& rArgs )
2050 Sequence < com::sun::star::beans::PropertyValue > args(1);
2051 args[0].Name = "Hidden";
2052 args[0].Value <<= sal_True;
2053 Reference < XDesktop2 > xDesktop = css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
2055 if ( rArgs.IsWriter() )
2059 Reference < ::com::sun::star::util::XCloseable > xDoc( xDesktop->loadComponentFromURL( OUString("private:factory/swriter"),
2060 OUString("_blank"), 0, args ), UNO_QUERY_THROW );
2061 xDoc->close( sal_False );
2063 catch ( const com::sun::star::uno::Exception& )
2067 if ( rArgs.IsCalc() )
2071 Reference < ::com::sun::star::util::XCloseable > xDoc( xDesktop->loadComponentFromURL( OUString("private:factory/scalc"),
2072 OUString("_blank"), 0, args ), UNO_QUERY_THROW );
2073 xDoc->close( sal_False );
2075 catch ( const com::sun::star::uno::Exception& )
2079 if ( rArgs.IsDraw() )
2083 Reference < ::com::sun::star::util::XCloseable > xDoc( xDesktop->loadComponentFromURL( OUString("private:factory/sdraw"),
2084 OUString("_blank"), 0, args ), UNO_QUERY_THROW );
2085 xDoc->close( sal_False );
2087 catch ( const com::sun::star::uno::Exception& )
2091 if ( rArgs.IsImpress() )
2095 Reference < ::com::sun::star::util::XCloseable > xDoc( xDesktop->loadComponentFromURL( OUString("private:factory/simpress"),
2096 OUString("_blank"), 0, args ), UNO_QUERY_THROW );
2097 xDoc->close( sal_False );
2099 catch ( const com::sun::star::uno::Exception& )
2105 void Desktop::PreloadConfigurationData()
2107 Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
2108 Reference< XNameAccess > xNameAccess = css::frame::UICommandDescription::create(xContext);
2110 OUString aWriterDoc( "com.sun.star.text.TextDocument" );
2111 OUString aCalcDoc( "com.sun.star.sheet.SpreadsheetDocument" );
2112 OUString aDrawDoc( "com.sun.star.drawing.DrawingDocument" );
2113 OUString aImpressDoc( "com.sun.star.presentation.PresentationDocument" );
2115 // preload commands configuration
2116 Any a;
2117 Reference< XNameAccess > xCmdAccess;
2121 a = xNameAccess->getByName( aWriterDoc );
2122 a >>= xCmdAccess;
2123 if ( xCmdAccess.is() )
2125 xCmdAccess->getByName(".uno:BasicShapes");
2126 xCmdAccess->getByName(".uno:EditGlossary");
2129 catch ( const ::com::sun::star::uno::Exception& )
2135 a = xNameAccess->getByName( aCalcDoc );
2136 a >>= xCmdAccess;
2137 if ( xCmdAccess.is() )
2138 xCmdAccess->getByName(".uno:InsertObjectStarMath");
2140 catch ( const ::com::sun::star::uno::Exception& )
2146 // draw and impress share the same configuration file (DrawImpressCommands.xcu)
2147 a = xNameAccess->getByName( aDrawDoc );
2148 a >>= xCmdAccess;
2149 if ( xCmdAccess.is() )
2150 xCmdAccess->getByName(".uno:Polygon");
2152 catch ( const ::com::sun::star::uno::Exception& )
2156 // preload window state configuration
2157 xNameAccess = WindowStateConfiguration::create( xContext );
2158 Reference< XNameAccess > xWindowAccess;
2161 a = xNameAccess->getByName( aWriterDoc );
2162 a >>= xWindowAccess;
2163 if ( xWindowAccess.is() )
2164 xWindowAccess->getByName("private:resource/toolbar/standardbar");
2166 catch ( const ::com::sun::star::uno::Exception& )
2171 a = xNameAccess->getByName( aCalcDoc );
2172 a >>= xWindowAccess;
2173 if ( xWindowAccess.is() )
2174 xWindowAccess->getByName("private:resource/toolbar/standardbar");
2176 catch ( const ::com::sun::star::uno::Exception& )
2181 a = xNameAccess->getByName( aDrawDoc );
2182 a >>= xWindowAccess;
2183 if ( xWindowAccess.is() )
2184 xWindowAccess->getByName("private:resource/toolbar/standardbar");
2186 catch ( const ::com::sun::star::uno::Exception& )
2191 a = xNameAccess->getByName( aImpressDoc );
2192 a >>= xWindowAccess;
2193 if ( xWindowAccess.is() )
2194 xWindowAccess->getByName("private:resource/toolbar/standardbar");
2196 catch ( const ::com::sun::star::uno::Exception& )
2200 // preload user interface element factories
2201 Sequence< Sequence< css::beans::PropertyValue > > aSeqSeqPropValue;
2202 Reference< XUIElementFactoryManager > xUIElementFactory = UIElementFactoryManager::create( xContext );
2205 aSeqSeqPropValue = xUIElementFactory->getRegisteredFactories();
2207 catch ( const ::com::sun::star::uno::Exception& )
2211 // preload popup menu controller factories. As all controllers are in the same
2212 // configuration file they also get preloaded!
2214 Reference< css::frame::XUIControllerRegistration > xPopupMenuControllerFactory =
2215 css::frame::PopupMenuControllerFactory::create( xContext );
2218 xPopupMenuControllerFactory->hasController(
2219 OUString( ".uno:CharFontName" ),
2220 OUString() );
2222 catch ( const ::com::sun::star::uno::Exception& )
2226 // preload filter configuration
2227 Sequence< OUString > aSeq;
2228 xNameAccess = Reference< XNameAccess >(
2229 xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.FilterFactory", xContext),
2230 UNO_QUERY );
2231 if ( xNameAccess.is() )
2235 aSeq = xNameAccess->getElementNames();
2237 catch ( const ::com::sun::star::uno::Exception& )
2242 // preload type detection configuration
2243 xNameAccess = Reference< XNameAccess >(
2244 xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", xContext),
2245 UNO_QUERY );
2246 if ( xNameAccess.is() )
2250 aSeq = xNameAccess->getElementNames();
2252 catch ( const ::com::sun::star::uno::Exception& )
2258 void Desktop::OpenClients()
2261 // check if a document has been recovered - if there is one of if a document was loaded by cmdline, no default document
2262 // should be created
2263 Reference < XComponent > xFirst;
2264 bool bRecovery = false;
2266 const CommandLineArgs& rArgs = GetCommandLineArgs();
2268 if (!rArgs.IsQuickstart())
2270 sal_Bool bShowHelp = sal_False;
2271 OUStringBuffer aHelpURLBuffer;
2272 if (rArgs.IsHelpWriter()) {
2273 bShowHelp = sal_True;
2274 aHelpURLBuffer.appendAscii("vnd.sun.star.help://swriter/start");
2275 } else if (rArgs.IsHelpCalc()) {
2276 bShowHelp = sal_True;
2277 aHelpURLBuffer.appendAscii("vnd.sun.star.help://scalc/start");
2278 } else if (rArgs.IsHelpDraw()) {
2279 bShowHelp = sal_True;
2280 aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdraw/start");
2281 } else if (rArgs.IsHelpImpress()) {
2282 bShowHelp = sal_True;
2283 aHelpURLBuffer.appendAscii("vnd.sun.star.help://simpress/start");
2284 } else if (rArgs.IsHelpBase()) {
2285 bShowHelp = sal_True;
2286 aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdatabase/start");
2287 } else if (rArgs.IsHelpBasic()) {
2288 bShowHelp = sal_True;
2289 aHelpURLBuffer.appendAscii("vnd.sun.star.help://sbasic/start");
2290 } else if (rArgs.IsHelpMath()) {
2291 bShowHelp = sal_True;
2292 aHelpURLBuffer.appendAscii("vnd.sun.star.help://smath/start");
2294 if (bShowHelp) {
2295 aHelpURLBuffer.appendAscii("?Language=");
2296 aHelpURLBuffer.append(utl::ConfigManager::getLocale());
2297 #if defined UNX
2298 aHelpURLBuffer.appendAscii("&System=UNX");
2299 #elif defined WNT
2300 aHelpURLBuffer.appendAscii("&System=WIN");
2301 #endif
2302 Application::GetHelp()->Start(
2303 aHelpURLBuffer.makeStringAndClear(), NULL);
2304 return;
2307 else
2309 OUString aIniName;
2311 osl_getExecutableFile( &aIniName.pData );
2312 sal_uInt32 lastIndex = aIniName.lastIndexOf('/');
2313 if ( lastIndex > 0 )
2315 aIniName = aIniName.copy( 0, lastIndex+1 );
2316 aIniName += "perftune";
2317 #if defined(WNT)
2318 aIniName += ".ini";
2319 #else
2320 aIniName += "rc";
2321 #endif
2324 rtl::Bootstrap aPerfTuneIniFile( aIniName );
2326 OUString aDefault( "0" );
2327 OUString aPreloadData;
2329 aPerfTuneIniFile.getFrom( OUString( "QuickstartPreloadConfiguration" ), aPreloadData, aDefault );
2330 if ( aPreloadData == "1" )
2332 if ( rArgs.IsWriter() ||
2333 rArgs.IsCalc() ||
2334 rArgs.IsDraw() ||
2335 rArgs.IsImpress() )
2337 PreloadModuleData( rArgs );
2340 PreloadConfigurationData();
2344 // Disable AutoSave feature in case "--norestore" or a similar command line switch is set on the command line.
2345 // The reason behind: AutoSave/EmergencySave/AutoRecovery share the same data.
2346 // But the require that all documents, which are saved as backup should exists inside
2347 // memory. May be this mechanism will be inconsistent if the configuration exists ...
2348 // but no document inside memory corrspond to this data.
2349 // Furter it's not acceptable to recover such documents without any UI. It can
2350 // need some time, where the user wont see any results and wait for finishing the office startup ...
2351 sal_Bool bAllowRecoveryAndSessionManagement = (
2352 ( !rArgs.IsNoRestore() ) &&
2353 ( !rArgs.IsHeadless() )
2356 if ( ! bAllowRecoveryAndSessionManagement )
2360 Reference< XDispatch > xRecovery = css::frame::AutoRecovery::create( ::comphelper::getProcessComponentContext() );
2361 Reference< css::util::XURLTransformer > xParser = css::util::URLTransformer::create( ::comphelper::getProcessComponentContext() );
2363 css::util::URL aCmd;
2364 aCmd.Complete = "vnd.sun.star.autorecovery:/disableRecovery";
2365 xParser->parseStrict(aCmd);
2367 xRecovery->dispatch(aCmd, css::uno::Sequence< css::beans::PropertyValue >());
2369 catch(const css::uno::Exception& e)
2371 SAL_WARN( "desktop.app", "Could not disable AutoRecovery." << e.Message);
2374 else
2376 sal_Bool bCrashed = sal_False;
2377 sal_Bool bExistsRecoveryData = sal_False;
2378 sal_Bool bExistsSessionData = sal_False;
2380 impl_checkRecoveryState(bCrashed, bExistsRecoveryData, bExistsSessionData);
2382 if ( !getenv ("OOO_DISABLE_RECOVERY") &&
2384 ( bExistsRecoveryData ) || // => crash with files => recovery
2385 ( bCrashed ) // => crash without files => error report
2391 bRecovery = impl_callRecoveryUI(
2392 sal_False , // false => force recovery instead of emergency save
2393 bCrashed ,
2394 bExistsRecoveryData);
2396 catch(const css::uno::Exception& e)
2398 SAL_WARN( "desktop.app", "Error during recovery" << e.Message);
2402 Reference< XSessionManagerListener2 > xSessionListener;
2405 // specifies whether the UI-interaction on Session shutdown is allowed
2406 sal_Bool bAllowUI = isUIOnSessionShutdownAllowed();
2408 xSessionListener = SessionListener::createWithOnQuitFlag(::comphelper::getProcessComponentContext(), bAllowUI);
2410 // css::beans::NamedValue aProperty( OUString( "AllowUserInteractionOnQuit" ),
2411 // css::uno::makeAny( bAllowUI ) );
2412 // css::uno::Sequence< css::uno::Any > aArgs( 1 );
2413 // aArgs[0] <<= aProperty;
2415 // xSessionListener->initialize( aArgs );
2417 catch(const com::sun::star::uno::Exception& e)
2419 SAL_WARN( "desktop.app", "Registration of session listener failed" << e.Message);
2422 if ( !bExistsRecoveryData )
2424 // session management
2427 xSessionListener->doRestore();
2429 catch(const com::sun::star::uno::Exception& e)
2431 SAL_WARN( "desktop.app", "Error in session management" << e.Message);
2436 OfficeIPCThread::EnableRequests();
2438 ProcessDocumentsRequest aRequest(rArgs.getCwdUrl());
2439 aRequest.pcProcessed = NULL;
2441 aRequest.aOpenList = rArgs.GetOpenList();
2442 aRequest.aViewList = rArgs.GetViewList();
2443 aRequest.aStartList = rArgs.GetStartList();
2444 aRequest.aPrintList = rArgs.GetPrintList();
2445 aRequest.aPrintToList = rArgs.GetPrintToList();
2446 aRequest.aPrinterName = rArgs.GetPrinterName();
2447 aRequest.aForceOpenList = rArgs.GetForceOpenList();
2448 aRequest.aForceNewList = rArgs.GetForceNewList();
2449 aRequest.aConversionList = rArgs.GetConversionList();
2450 aRequest.aConversionParams = rArgs.GetConversionParams();
2451 aRequest.aConversionOut = rArgs.GetConversionOut();
2452 aRequest.aInFilter = rArgs.GetInFilter();
2454 if ( !aRequest.aOpenList.empty() ||
2455 !aRequest.aViewList.empty() ||
2456 !aRequest.aStartList.empty() ||
2457 !aRequest.aPrintList.empty() ||
2458 !aRequest.aForceOpenList.empty() ||
2459 !aRequest.aForceNewList.empty() ||
2460 ( !aRequest.aPrintToList.empty() && !aRequest.aPrinterName.isEmpty() ) ||
2461 !aRequest.aConversionList.empty() )
2463 if ( rArgs.HasModuleParam() )
2465 SvtModuleOptions aOpt;
2467 // Support command line parameters to start a module (as preselection)
2468 if ( rArgs.IsWriter() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
2469 aRequest.aModule = aOpt.GetFactoryName( SvtModuleOptions::E_WRITER );
2470 else if ( rArgs.IsCalc() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) )
2471 aRequest.aModule = aOpt.GetFactoryName( SvtModuleOptions::E_CALC );
2472 else if ( rArgs.IsImpress() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) )
2473 aRequest.aModule= aOpt.GetFactoryName( SvtModuleOptions::E_IMPRESS );
2474 else if ( rArgs.IsDraw() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) )
2475 aRequest.aModule= aOpt.GetFactoryName( SvtModuleOptions::E_DRAW );
2478 // check for printing disabled
2479 if( ( !(aRequest.aPrintList.empty() && aRequest.aPrintToList.empty()) )
2480 && Application::GetSettings().GetMiscSettings().GetDisablePrinting() )
2482 aRequest.aPrintList.clear();
2483 aRequest.aPrintToList.clear();
2484 ResMgr* pDtResMgr = GetDesktopResManager();
2485 if( pDtResMgr )
2487 ErrorBox aBox( NULL, ResId( EBX_ERR_PRINTDISABLED, *pDtResMgr ) );
2488 aBox.Execute();
2492 // Process request
2493 if ( OfficeIPCThread::ExecuteCmdLineRequests( aRequest ) )
2495 // Don't do anything if we have successfully called terminate at desktop:
2496 return;
2500 // no default document if a document was loaded by recovery or by command line or if soffice is used as server
2501 Reference< XDesktop2 > xDesktop = css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
2502 Reference< XElementAccess > xList( xDesktop->getFrames(), UNO_QUERY_THROW );
2503 if ( xList->hasElements() )
2504 return;
2506 if ( rArgs.IsQuickstart() || rArgs.IsInvisible() || Application::AnyInput( VCL_INPUT_APPEVENT ) )
2507 // soffice was started as tray icon ...
2508 return;
2510 if ( bRecovery )
2512 ShowBackingComponent(0);
2514 else
2516 OpenDefault();
2520 void Desktop::OpenDefault()
2523 SAL_INFO( "desktop.app", "desktop (cd100003) ::Desktop::OpenDefault" );
2525 OUString aName;
2526 SvtModuleOptions aOpt;
2528 const CommandLineArgs& rArgs = GetCommandLineArgs();
2529 if ( rArgs.IsNoDefault() ) return;
2530 if ( rArgs.HasModuleParam() )
2532 // Support new command line parameters to start a module
2533 if ( rArgs.IsWriter() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
2534 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITER );
2535 else if ( rArgs.IsCalc() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) )
2536 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_CALC );
2537 else if ( rArgs.IsImpress() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) )
2538 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_IMPRESS );
2539 else if ( rArgs.IsBase() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SDATABASE ) )
2540 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DATABASE );
2541 else if ( rArgs.IsDraw() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) )
2542 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DRAW );
2543 else if ( rArgs.IsMath() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SMATH ) )
2544 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_MATH );
2545 else if ( rArgs.IsGlobal() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
2546 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITERGLOBAL );
2547 else if ( rArgs.IsWeb() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
2548 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITERWEB );
2551 if ( aName.isEmpty() )
2553 // Old way to create a default document
2554 if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
2555 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITER );
2556 else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) )
2557 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_CALC );
2558 else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) )
2559 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_IMPRESS );
2560 else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SDATABASE ) )
2561 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DATABASE );
2562 else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) )
2563 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DRAW );
2564 else
2565 return;
2568 ProcessDocumentsRequest aRequest(rArgs.getCwdUrl());
2569 aRequest.pcProcessed = NULL;
2570 aRequest.aOpenList.push_back(aName);
2571 OfficeIPCThread::ExecuteCmdLineRequests( aRequest );
2575 OUString GetURL_Impl(
2576 const OUString& rName, boost::optional< OUString > const & cwdUrl )
2578 // if rName is a vnd.sun.star.script URL do not attempt to parse it
2579 // as INetURLObj does not handle handle there URLs
2580 if (rName.startsWith("vnd.sun.star.script"))
2582 return rName;
2585 // dont touch file urls, those should already be in internal form
2586 // they won't get better here (#112849#)
2587 if (rName.startsWith("file:"))
2589 return rName;
2592 if ( rName.startsWith("service:"))
2594 return rName;
2597 // Add path separator to these directory and make given URL (rName) absolute by using of current working directory
2598 // Attention: "setFinalSlash()" is necessary for calling "smartRel2Abs()"!!!
2599 // Otherwhise last part will be ignored and wrong result will be returned!!!
2600 // "smartRel2Abs()" interpret given URL as file not as path. So he truncate last element to get the base path ...
2601 // But if we add a separator - he doesn't do it anymore.
2602 INetURLObject aObj;
2603 if (cwdUrl) {
2604 aObj.SetURL(*cwdUrl);
2605 aObj.setFinalSlash();
2608 // Use the provided parameters for smartRel2Abs to support the usage of '%' in system paths.
2609 // Otherwise this char won't get encoded and we are not able to load such files later,
2610 bool bWasAbsolute;
2611 INetURLObject aURL = aObj.smartRel2Abs( rName, bWasAbsolute, false, INetURLObject::WAS_ENCODED,
2612 RTL_TEXTENCODING_UTF8, true );
2613 OUString aFileURL = aURL.GetMainURL(INetURLObject::NO_DECODE);
2615 ::osl::FileStatus aStatus( osl_FileStatus_Mask_FileURL );
2616 ::osl::DirectoryItem aItem;
2617 if( ::osl::FileBase::E_None == ::osl::DirectoryItem::get( aFileURL, aItem ) &&
2618 ::osl::FileBase::E_None == aItem.getFileStatus( aStatus ) )
2619 aFileURL = aStatus.getFileURL();
2621 return aFileURL;
2624 void Desktop::HandleAppEvent( const ApplicationEvent& rAppEvent )
2626 switch ( rAppEvent.GetEvent() )
2628 case ApplicationEvent::TYPE_ACCEPT:
2629 // every time an accept parameter is used we create an acceptor
2630 // with the corresponding accept-string
2631 createAcceptor(rAppEvent.GetStringData());
2632 break;
2633 case ApplicationEvent::TYPE_APPEAR:
2634 if ( !GetCommandLineArgs().IsInvisible() )
2636 Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
2638 // find active task - the active task is always a visible task
2639 Reference< css::frame::XDesktop2 > xDesktop = css::frame::Desktop::create( xContext );
2640 Reference< css::frame::XFrame > xTask = xDesktop->getActiveFrame();
2641 if ( !xTask.is() )
2643 // get any task if there is no active one
2644 Reference< css::container::XIndexAccess > xList( xDesktop->getFrames(), ::com::sun::star::uno::UNO_QUERY );
2645 if ( xList->getCount() > 0 )
2646 xList->getByIndex(0) >>= xTask;
2649 if ( xTask.is() )
2651 Reference< com::sun::star::awt::XTopWindow > xTop( xTask->getContainerWindow(), UNO_QUERY );
2652 xTop->toFront();
2654 else
2656 // no visible task that could be activated found
2657 Reference< ::com::sun::star::awt::XWindow > xContainerWindow;
2658 Reference< XFrame > xBackingFrame = xDesktop->findFrame(OUString( "_blank" ), 0);
2659 if (xBackingFrame.is())
2660 xContainerWindow = xBackingFrame->getContainerWindow();
2661 if (xContainerWindow.is())
2663 Reference< XController > xStartModule = StartModule::createWithParentWindow(xContext, xContainerWindow);
2664 Reference< ::com::sun::star::awt::XWindow > xBackingWin(xStartModule, UNO_QUERY);
2665 // Attention: You MUST(!) call setComponent() before you call attachFrame().
2666 // Because the backing component set the property "IsBackingMode" of the frame
2667 // to true inside attachFrame(). But setComponent() reset this state every time ...
2668 xBackingFrame->setComponent(xBackingWin, xStartModule);
2669 xStartModule->attachFrame(xBackingFrame);
2670 xContainerWindow->setVisible(sal_True);
2672 Window* pCompWindow = VCLUnoHelper::GetWindow(xBackingFrame->getComponentWindow());
2673 if (pCompWindow)
2674 pCompWindow->Update();
2678 break;
2679 case ApplicationEvent::TYPE_HELP:
2680 displayCmdlineHelp(rAppEvent.GetStringData());
2681 break;
2682 case ApplicationEvent::TYPE_VERSION:
2683 displayVersion();
2684 break;
2685 case ApplicationEvent::TYPE_OPEN:
2687 const CommandLineArgs& rCmdLine = GetCommandLineArgs();
2688 if ( !rCmdLine.IsInvisible() && !rCmdLine.IsTerminateAfterInit() )
2690 ProcessDocumentsRequest* pDocsRequest = new ProcessDocumentsRequest(
2691 rCmdLine.getCwdUrl());
2692 std::vector<OUString> const & data(rAppEvent.GetStringsData());
2693 pDocsRequest->aOpenList.insert(
2694 pDocsRequest->aOpenList.end(), data.begin(), data.end());
2695 pDocsRequest->pcProcessed = NULL;
2697 OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest );
2698 delete pDocsRequest;
2701 break;
2702 case ApplicationEvent::TYPE_OPENHELPURL:
2703 // start help for a specific URL
2704 Application::GetHelp()->Start(rAppEvent.GetStringData(), NULL);
2705 break;
2706 case ApplicationEvent::TYPE_PRINT:
2708 const CommandLineArgs& rCmdLine = GetCommandLineArgs();
2709 if ( !rCmdLine.IsInvisible() && !rCmdLine.IsTerminateAfterInit() )
2711 ProcessDocumentsRequest* pDocsRequest = new ProcessDocumentsRequest(
2712 rCmdLine.getCwdUrl());
2713 std::vector<OUString> const & data(rAppEvent.GetStringsData());
2714 pDocsRequest->aPrintList.insert(
2715 pDocsRequest->aPrintList.end(), data.begin(), data.end());
2716 pDocsRequest->pcProcessed = NULL;
2718 OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest );
2719 delete pDocsRequest;
2722 break;
2723 case ApplicationEvent::TYPE_PRIVATE_DOSHUTDOWN:
2725 Desktop* pD = dynamic_cast<Desktop*>(GetpApp());
2726 OSL_ENSURE( pD, "no desktop ?!?" );
2727 if( pD )
2728 pD->doShutdown();
2730 break;
2731 case ApplicationEvent::TYPE_QUICKSTART:
2732 if ( !GetCommandLineArgs().IsInvisible() )
2734 // If the office has been started the second time its command line arguments are sent through a pipe
2735 // connection to the first office. We want to reuse the quickstart option for the first office.
2736 // NOTICE: The quickstart service must be initialized inside the "main thread", so we use the
2737 // application events to do this (they are executed inside main thread)!!!
2738 // Don't start quickstart service if the user specified "--invisible" on the command line!
2739 Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
2740 css::office::Quickstart::createStart(xContext, true/*Quickstart*/);
2742 break;
2743 case ApplicationEvent::TYPE_SHOWDIALOG:
2744 // ignore all errors here. It's clicking a menu entry only ...
2745 // The user will try it again, in case nothing happens .-)
2748 Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
2750 Reference< css::frame::XDesktop2 > xDesktop = css::frame::Desktop::create( xContext );
2752 Reference< css::util::XURLTransformer > xParser = css::util::URLTransformer::create(xContext);
2753 css::util::URL aCommand;
2754 if( rAppEvent.GetStringData() == "PREFERENCES" )
2755 aCommand.Complete = ".uno:OptionsTreeDialog";
2756 else if( rAppEvent.GetStringData() == "ABOUT" )
2757 aCommand.Complete = ".uno:About";
2758 if( !aCommand.Complete.isEmpty() )
2760 xParser->parseStrict(aCommand);
2762 css::uno::Reference< css::frame::XDispatch > xDispatch = xDesktop->queryDispatch(aCommand, OUString(), 0);
2763 if (xDispatch.is())
2764 xDispatch->dispatch(aCommand, css::uno::Sequence< css::beans::PropertyValue >());
2767 catch(const css::uno::Exception&)
2769 break;
2770 case ApplicationEvent::TYPE_UNACCEPT:
2771 // try to remove corresponding acceptor
2772 destroyAcceptor(rAppEvent.GetStringData());
2773 break;
2774 default:
2775 SAL_WARN( "desktop.app", "this cannot happen");
2776 break;
2780 void Desktop::OpenSplashScreen()
2782 const CommandLineArgs &rCmdLine = GetCommandLineArgs();
2783 sal_Bool bVisible = sal_False;
2784 // Show intro only if this is normal start (e.g. no server, no quickstart, no printing )
2785 if ( !rCmdLine.IsInvisible() &&
2786 !rCmdLine.IsHeadless() &&
2787 !rCmdLine.IsQuickstart() &&
2788 !rCmdLine.IsMinimized() &&
2789 !rCmdLine.IsNoLogo() &&
2790 !rCmdLine.IsTerminateAfterInit() &&
2791 rCmdLine.GetPrintList().empty() &&
2792 rCmdLine.GetPrintToList().empty() &&
2793 rCmdLine.GetConversionList().empty() )
2795 // Determine application name from command line parameters
2796 OUString aAppName;
2797 if ( rCmdLine.IsWriter() )
2798 aAppName = "writer";
2799 else if ( rCmdLine.IsCalc() )
2800 aAppName = "calc";
2801 else if ( rCmdLine.IsDraw() )
2802 aAppName = "draw";
2803 else if ( rCmdLine.IsImpress() )
2804 aAppName = "impress";
2805 else if ( rCmdLine.IsBase() )
2806 aAppName = "base";
2807 else if ( rCmdLine.IsGlobal() )
2808 aAppName = "global";
2809 else if ( rCmdLine.IsMath() )
2810 aAppName = "math";
2811 else if ( rCmdLine.IsWeb() )
2812 aAppName = "web";
2814 // Which splash to use
2815 OUString aSplashService( "com.sun.star.office.SplashScreen" );
2816 if ( rCmdLine.HasSplashPipe() )
2817 aSplashService = "com.sun.star.office.PipeSplashScreen";
2819 bVisible = sal_True;
2820 Sequence< Any > aSeq( 2 );
2821 aSeq[0] <<= bVisible;
2822 aSeq[1] <<= aAppName;
2823 css::uno::Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
2824 m_rSplashScreen = Reference<XStatusIndicator>(
2825 xContext->getServiceManager()->createInstanceWithArgumentsAndContext(aSplashService, aSeq, xContext),
2826 UNO_QUERY);
2828 if(m_rSplashScreen.is())
2829 m_rSplashScreen->start(OUString("SplashScreen"), 100);
2834 void Desktop::SetSplashScreenProgress(sal_Int32 iProgress)
2836 if(m_rSplashScreen.is())
2838 m_rSplashScreen->setValue(iProgress);
2842 void Desktop::SetSplashScreenText( const OUString& rText )
2844 if( m_rSplashScreen.is() )
2846 m_rSplashScreen->setText( rText );
2850 void Desktop::CloseSplashScreen()
2852 if(m_rSplashScreen.is())
2854 m_rSplashScreen->end();
2855 m_rSplashScreen = NULL;
2859 // ========================================================================
2860 void Desktop::DoFirstRunInitializations()
2864 Reference< XJobExecutor > xExecutor = JobExecutor::create( ::comphelper::getProcessComponentContext() );
2865 xExecutor->trigger( OUString("onFirstRunInitialization") );
2867 catch(const ::com::sun::star::uno::Exception&)
2869 SAL_WARN( "desktop.app", "Desktop::DoFirstRunInitializations: caught an exception while trigger job executor ..." );
2873 void Desktop::ShowBackingComponent(Desktop * progress)
2875 if (GetCommandLineArgs().IsNoDefault())
2877 return;
2879 Reference< XComponentContext > xContext = comphelper::getProcessComponentContext();
2880 Reference< XDesktop2 > xDesktop = css::frame::Desktop::create(xContext);
2881 if (progress != 0)
2883 progress->SetSplashScreenProgress(60);
2885 Reference< XFrame > xBackingFrame = xDesktop->findFrame(OUString( "_blank" ), 0);
2886 Reference< ::com::sun::star::awt::XWindow > xContainerWindow;
2888 if (xBackingFrame.is())
2889 xContainerWindow = xBackingFrame->getContainerWindow();
2890 if (xContainerWindow.is())
2892 // set the WB_EXT_DOCUMENT style. Normally, this is done by the TaskCreator service when a "_blank"
2893 // frame/window is created. Since we do not use the TaskCreator here, we need to mimic its behavior,
2894 // otherwise documents loaded into this frame will later on miss functionality depending on the style.
2895 Window* pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
2896 SAL_WARN_IF( !pContainerWindow, "desktop.app", "Desktop::Main: no implementation access to the frame's container window!" );
2897 pContainerWindow->SetExtendedStyle( pContainerWindow->GetExtendedStyle() | WB_EXT_DOCUMENT );
2898 if (progress != 0)
2900 progress->SetSplashScreenProgress(75);
2903 Reference< XController > xStartModule = StartModule::createWithParentWindow( xContext, xContainerWindow);
2904 // Attention: You MUST(!) call setComponent() before you call attachFrame().
2905 // Because the backing component set the property "IsBackingMode" of the frame
2906 // to true inside attachFrame(). But setComponent() reset this state everytimes ...
2907 xBackingFrame->setComponent(Reference< XWindow >(xStartModule, UNO_QUERY), xStartModule);
2908 if (progress != 0)
2910 progress->SetSplashScreenProgress(100);
2912 xStartModule->attachFrame(xBackingFrame);
2913 if (progress != 0)
2915 progress->CloseSplashScreen();
2917 xContainerWindow->setVisible(sal_True);
2921 // ========================================================================
2922 void Desktop::CheckFirstRun( )
2924 if (officecfg::Office::Common::Misc::FirstRun::get())
2926 // this has once been done using a vos timer. this could lead to problems when
2927 // the timer would trigger when the app is already going down again, since VCL would
2928 // no longer be available. Since the old handler would do a postUserEvent to the main
2929 // thread anyway, we can use a vcl timer here to prevent the race contition (#107197#)
2930 m_firstRunTimer.SetTimeout(3000); // 3 sec.
2931 m_firstRunTimer.SetTimeoutHdl(LINK(this, Desktop, AsyncInitFirstRun));
2932 m_firstRunTimer.Start();
2934 #ifdef WNT
2935 // Check if Quckstarter should be started (on Windows only)
2936 TCHAR szValue[8192];
2937 DWORD nValueSize = sizeof(szValue);
2938 HKEY hKey;
2939 if ( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE, "Software\\LibreOffice", &hKey ) )
2941 if ( ERROR_SUCCESS == RegQueryValueEx( hKey, TEXT("RunQuickstartAtFirstStart"), NULL, NULL, (LPBYTE)szValue, &nValueSize ) )
2943 css::uno::Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
2944 css::office::Quickstart::createAutoStart(xContext, true/*Quickstart*/, true/*bAutostart*/);
2945 RegCloseKey( hKey );
2948 #endif
2950 boost::shared_ptr< comphelper::ConfigurationChanges > batch(
2951 comphelper::ConfigurationChanges::create());
2952 officecfg::Office::Common::Misc::FirstRun::set(false, batch);
2953 batch->commit();
2959 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */