1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_desktop.hxx"
26
27 #include <cstdlib>
28 #include <vector>
29
30 #include <memory>
31 #include <unistd.h>
32 #include "app.hxx"
33 #include "desktop.hrc"
34 #include "appinit.hxx"
35 #include "officeipcthread.hxx"
36 #include "cmdlineargs.hxx"
37 #include "desktopresid.hxx"
38 #include "dispatchwatcher.hxx"
39 #include "configinit.hxx"
40 #include "lockfile.hxx"
41 #include "checkinstall.hxx"
42 #include "cmdlinehelp.hxx"
43 #include "userinstall.hxx"
44 #include "desktopcontext.hxx"
45 #include "exithelper.hxx"
46 #include "../migration/pages.hxx"
47
48 #include <svtools/javacontext.hxx>
49 #include <com/sun/star/frame/XSessionManagerListener.hpp>
50 #include <com/sun/star/frame/XSynchronousDispatch.hpp>
51 #include <com/sun/star/document/CorruptedFilterConfigurationException.hpp>
52 #include <com/sun/star/configuration/CorruptedConfigurationException.hpp>
53 #include <com/sun/star/frame/XStorable.hpp>
54 #include <com/sun/star/util/XModifiable.hpp>
55 #include <com/sun/star/util/XFlushable.hpp>
56 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
57 #include <com/sun/star/beans/XPropertySet.hpp>
58 #include <com/sun/star/lang/XComponent.hpp>
59 #include <com/sun/star/uno/RuntimeException.hpp>
60 #include <com/sun/star/io/IOException.hpp>
61 #include <com/sun/star/lang/IllegalArgumentException.hpp>
62 #include <com/sun/star/lang/WrappedTargetException.hpp>
63 #include <com/sun/star/frame/XDesktop.hpp>
64 #include <com/sun/star/frame/XComponentLoader.hpp>
65 #include <com/sun/star/view/XPrintable.hpp>
66 #include <com/sun/star/lang/XInitialization.hpp>
67 #include <com/sun/star/frame/XFramesSupplier.hpp>
68 #include <com/sun/star/awt/XTopWindow.hpp>
69 #include <com/sun/star/util/XURLTransformer.hpp>
70 #include <com/sun/star/util/URL.hpp>
71 #include <com/sun/star/util/XCloseable.hpp>
72 #include <com/sun/star/frame/XDispatch.hpp>
73 #include <com/sun/star/frame/XDispatchProvider.hpp>
74 #include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
75 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
76 #include <com/sun/star/configuration/MissingBootstrapFileException.hpp>
77 #include <com/sun/star/configuration/InvalidBootstrapFileException.hpp>
78 #include <com/sun/star/configuration/InstallationIncompleteException.hpp>
79 #include <com/sun/star/configuration/backend/BackendSetupException.hpp>
80 #include <com/sun/star/configuration/backend/BackendAccessException.hpp>
81 #include <com/sun/star/container/XEnumeration.hpp>
82 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
83 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
84 #include <com/sun/star/task/XJobExecutor.hpp>
85 #include <com/sun/star/task/XRestartManager.hpp>
86 #ifndef _COM_SUN_STAR_TASK_XJOBEXECUTOR_HPP_
87 #include <com/sun/star/task/XJob.hpp>
88 #endif
89 #include <com/sun/star/beans/XPropertySet.hpp>
90 #include <com/sun/star/beans/NamedValue.hpp>
91 #include <com/sun/star/task/XJob.hpp>
92 #include <com/sun/star/document/XEventListener.hpp>
93 #include <com/sun/star/ui/XUIElementFactoryRegistration.hpp>
94 #include <com/sun/star/frame/XUIControllerRegistration.hpp>
95
96 #include <com/sun/star/java/XJavaVM.hpp>
97 #include <tools/testtoolloader.hxx>
98 #include <tools/solar.h>
99 #ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_
100 #include <toolkit/helper/vclunohelper.hxx>
101 #endif
102 #include <vos/security.hxx>
103 #include <vos/ref.hxx>
104 #include <comphelper/processfactory.hxx>
105 #include <comphelper/componentcontext.hxx>
106 #include <comphelper/configurationhelper.hxx>
107 #ifndef _UTL__HXX_
108 #include <unotools/configmgr.hxx>
109 #endif
110 #include <unotools/configitem.hxx>
111 #include <unotools/confignode.hxx>
112 #include <unotools/ucbhelper.hxx>
113 #include <tools/tempfile.hxx>
114 #include <tools/urlobj.hxx>
115 #include <unotools/moduleoptions.hxx>
116 #include <osl/module.h>
117 #include <osl/file.hxx>
118 #include <osl/signal.h>
119 #include <osl/thread.hxx>
120 #include <rtl/uuid.h>
121 #include <rtl/uri.hxx>
122 #include <unotools/pathoptions.hxx>
123 #include <svl/languageoptions.hxx>
124 #include <unotools/internaloptions.hxx>
125 #include <svtools/miscopt.hxx>
126 #include <svtools/menuoptions.hxx>
127 #include <unotools/syslocaleoptions.hxx>
128 #include <unotools/syslocale.hxx>
129 #include <svl/folderrestriction.hxx>
130 #include <svl/eitem.hxx>
131 #include <svl/itemset.hxx>
132 #include <unotools/tempfile.hxx>
133 #include <rtl/logfile.hxx>
134 #include <rtl/ustrbuf.hxx>
135 #include <rtl/strbuf.hxx>
136 #include <rtl/bootstrap.hxx>
137 #include <rtl/instance.hxx>
138 #include <unotools/configmgr.hxx>
139 #include <vcl/help.hxx>
140 #include <vcl/msgbox.hxx>
141 #include <vcl/bitmap.hxx>
142 #include <vcl/stdtext.hxx>
143 #include <vcl/msgbox.hxx>
144 #include <sfx2/sfx.hrc>
145 #include <sfx2/app.hxx>
146 #include <ucbhelper/contentbroker.hxx>
147 #include <unotools/bootstrap.hxx>
148 #include <cppuhelper/bootstrap.hxx>
149
150 #include "vos/process.hxx"
151
152 #include <svtools/fontsubstconfig.hxx>
153 #include <svtools/accessibilityoptions.hxx>
154 #include <svtools/apearcfg.hxx>
155 #include <unotools/misccfg.hxx>
156 #include <svtools/filter.hxx>
157
158 #include "langselect.hxx"
159
160 #include "com/sun/star/deployment/ExtensionManager.hpp"
161 #include "com/sun/star/deployment/XExtensionManager.hpp"
162 #include "com/sun/star/task/XInteractionApprove.hpp"
163 #include "com/sun/star/task/XInteractionAbort.hpp"
164 #include "cppuhelper/compbase3.hxx"
165 #include <hash_set>
166
167 #include "com/sun/star/deployment/VersionException.hpp"
168 #include <dp_gui_handleversionexception.hxx>
169
170 #if defined MACOSX
171 #include <errno.h>
172 #include <sys/wait.h>
173 #endif
174
175 #define DEFINE_CONST_UNICODE(CONSTASCII) UniString(RTL_CONSTASCII_USTRINGPARAM(CONSTASCII))
176 #define OUSTR(x) ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(x))
177 #define U2S(STRING) ::rtl::OUStringToOString(STRING, RTL_TEXTENCODING_UTF8)
178
179 using namespace vos;
180 using namespace rtl;
181
182 using namespace ::com::sun::star::uno;
183 using namespace ::com::sun::star::util;
184 using namespace ::com::sun::star::lang;
185 using namespace ::com::sun::star::beans;
186 using namespace ::com::sun::star::frame;
187 using namespace ::com::sun::star::document;
188 using namespace ::com::sun::star::view;
189 using namespace ::com::sun::star::task;
190 using namespace ::com::sun::star::system;
191 using namespace ::com::sun::star::ui::dialogs;
192 using namespace ::com::sun::star::container;
193
194 namespace css = ::com::sun::star;
195
196 ResMgr* desktop::Desktop::pResMgr = 0;
197
198 namespace {
199
200 /** Write a marker file that is basically empty (just a single
201 character to prevent it from being deleted.) Its time of last
202 modification is its only important feature.
203
204 This is a simplified version of the function in
205 dp_extensionmanager.cxx. It uses direct file access instead of
206 the UCB. May prove to be too simple, but then again, it may not.
207 */
writeLastModified(::rtl::OUString & rsURL)208 bool writeLastModified (::rtl::OUString& rsURL)
209 {
210 try
211 {
212 // Remove the file if it already exists.
213 ::osl::File::remove(rsURL);
214
215 ::osl::File aFile (rsURL);
216 if (aFile.open(OpenFlag_Create | OpenFlag_Write) != ::osl::File::E_None)
217 return false;
218
219 const char aBuffer[] = "1";
220 sal_uInt64 nBytesWritten (0);
221 if (aFile.write(aBuffer, strlen(aBuffer), nBytesWritten) != ::osl::File::E_None)
222 return false;
223
224 if (aFile.close() != ::osl::File::E_None)
225 return false;
226
227 return true;
228 }
229 catch(...)
230 {
231 }
232 return false;
233 }
234
235 } // end of anonymous namespace
236
237
238
239 namespace desktop
240 {
241
242 static SalMainPipeExchangeSignalHandler* pSignalHandler = 0;
243 static sal_Bool _bCrashReporterEnabled = sal_True;
244
245 static const ::rtl::OUString CFG_PACKAGE_COMMON_HELP ( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.Office.Common/Help"));
246
247 static ::rtl::OUString getBrandSharePreregBundledPathURL();
248 // #i119950# Add a option that not to display the "Fatal Error" on dialog title
249 void FatalError(const ::rtl::OUString& sMessage, const sal_Bool isDisplayErrorString = sal_True);
250 // ----------------------------------------------------------------------------
251
GetDesktopResManager()252 ResMgr* Desktop::GetDesktopResManager()
253 {
254 if ( !Desktop::pResMgr )
255 {
256 const char* pMgrName = "dkt";
257
258 // Create desktop resource manager and bootstrap process
259 // was successful. Use default way to get language specific message.
260 if ( Application::IsInExecute() )
261 Desktop::pResMgr = ResMgr::CreateResMgr( pMgrName);
262
263 if ( !Desktop::pResMgr )
264 {
265 // Use VCL to get the correct language specific message as we
266 // are in the bootstrap process and not able to get the installed
267 // language!!
268 /*
269 LanguageType aLanguageType = LANGUAGE_DONTKNOW;
270
271 Desktop::pResMgr = ResMgr::SearchCreateResMgr( pMgrName, aLanguageType );
272 AllSettings as = GetSettings();
273 as.SetUILanguage(aLanguageType);
274 SetSettings(as);
275 */
276 // LanguageSelection langselect;
277 OUString aUILocaleString = LanguageSelection::getLanguageString();
278 sal_Int32 nIndex = 0;
279 OUString aLanguage = aUILocaleString.getToken( 0, '-', nIndex);
280 OUString aCountry = aUILocaleString.getToken( 0, '-', nIndex);
281 OUString aVariant = aUILocaleString.getToken( 0, '-', nIndex);
282
283 ::com::sun::star::lang::Locale aLocale( aLanguage, aCountry, aVariant );
284
285 Desktop::pResMgr = ResMgr::SearchCreateResMgr( pMgrName, aLocale);
286 AllSettings as = GetSettings();
287 as.SetUILocale(aLocale);
288 SetSettings(as);
289 }
290 }
291
292 return Desktop::pResMgr;
293 }
294
295 // ----------------------------------------------------------------------------
296 // Get a message string securely. There is a fallback string if the resource
297 // is not available.
298
GetMsgString(sal_uInt16 nId,const OUString & aFaultBackMsg)299 OUString Desktop::GetMsgString( sal_uInt16 nId, const OUString& aFaultBackMsg )
300 {
301 ResMgr* resMgr = GetDesktopResManager();
302 if ( !resMgr )
303 return aFaultBackMsg;
304 else
305 return OUString( String( ResId( nId, *resMgr )));
306 }
307
MakeStartupErrorMessage(OUString const & aErrorMessage)308 OUString MakeStartupErrorMessage(OUString const & aErrorMessage)
309 {
310 OUStringBuffer aDiagnosticMessage( 100 );
311
312 ResMgr* pResMgr = Desktop::GetDesktopResManager();
313 if ( pResMgr )
314 aDiagnosticMessage.append( OUString(String(ResId(STR_BOOTSTRAP_ERR_CANNOT_START, *pResMgr))) );
315 else
316 aDiagnosticMessage.appendAscii( "The program cannot be started." );
317
318 aDiagnosticMessage.appendAscii( "\n" );
319
320 aDiagnosticMessage.append( aErrorMessage );
321
322 return aDiagnosticMessage.makeStringAndClear();
323 }
324
MakeStartupConfigAccessErrorMessage(OUString const & aInternalErrMsg)325 OUString MakeStartupConfigAccessErrorMessage( OUString const & aInternalErrMsg )
326 {
327 OUStringBuffer aDiagnosticMessage( 200 );
328
329 ResMgr* pResMgr = Desktop::GetDesktopResManager();
330 if ( pResMgr )
331 aDiagnosticMessage.append( OUString(String(ResId(STR_BOOTSTRAP_ERR_CFG_DATAACCESS, *pResMgr ))) );
332 else
333 aDiagnosticMessage.appendAscii( "The program cannot be started." );
334
335 if ( aInternalErrMsg.getLength() > 0 )
336 {
337 aDiagnosticMessage.appendAscii( "\n\n" );
338 if ( pResMgr )
339 aDiagnosticMessage.append( OUString(String(ResId(STR_INTERNAL_ERRMSG, *pResMgr ))) );
340 else
341 aDiagnosticMessage.appendAscii( "The following internal error has occurred:\n\n" );
342 aDiagnosticMessage.append( aInternalErrMsg );
343 }
344
345 return aDiagnosticMessage.makeStringAndClear();
346 }
347
348 //=============================================================================
349 // shows a simple error box with the given message ... but exits from these process !
350 //
351 // Fatal errors can't be solved by the process ... nor any recovery can help.
352 // Mostly the installation was damaged and must be repaired manually .. or by calling
353 // setup again.
354 //
355 // On the other side we must make sure that no further actions will be possible within
356 // the current office process ! No pipe requests, no menu/toolbar/shortcut actions
357 // are allowed. Otherwise we will force a "crash inside a crash".
358 //
359 // That's why we have to use a special native message box here which does not use yield :-)
360 //=============================================================================
FatalError(const::rtl::OUString & sMessage,const sal_Bool isDisplayErrorString)361 void FatalError(const ::rtl::OUString& sMessage, const sal_Bool isDisplayErrorString)
362 {
363 ::rtl::OUString sProductKey = ::utl::Bootstrap::getProductKey();
364 if ( ! sProductKey.getLength())
365 {
366 ::vos::OStartupInfo aInfo;
367 aInfo.getExecutableFile( sProductKey );
368
369 ::sal_uInt32 nLastIndex = sProductKey.lastIndexOf('/');
370 if ( nLastIndex > 0 )
371 sProductKey = sProductKey.copy( nLastIndex+1 );
372 }
373
374 ::rtl::OUStringBuffer sTitle (128);
375 sTitle.append (sProductKey );
376 if (isDisplayErrorString) {
377 sTitle.appendAscii (" - Fatal Error");
378 }
379 Application::ShowNativeErrorBox (sTitle.makeStringAndClear (), sMessage);
380 _exit(ExitHelper::E_FATAL_ERROR);
381 }
382
ShouldSuppressUI(CommandLineArgs * pCmdLine)383 static bool ShouldSuppressUI(CommandLineArgs* pCmdLine)
384 {
385 return pCmdLine->IsInvisible() ||
386 pCmdLine->IsHeadless() ||
387 pCmdLine->IsQuickstart();
388 }
389
GetCommandLineArgs()390 CommandLineArgs* Desktop::GetCommandLineArgs()
391 {
392 static CommandLineArgs* pArgs = 0;
393 if ( !pArgs )
394 {
395 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
396 if ( !pArgs )
397 pArgs = new CommandLineArgs;
398 }
399
400 return pArgs;
401 }
402
InitConfiguration()403 sal_Bool InitConfiguration()
404 {
405 RTL_LOGFILE_CONTEXT( aLog, "desktop (jb99855) ::InitConfiguration" );
406
407 Reference< XMultiServiceFactory > xProvider( CreateApplicationConfigurationProvider( ) );
408 return xProvider.is();
409 }
410
411 namespace
412 {
413 struct BrandName
414 : public rtl::Static< String, BrandName > {};
415 struct FullProductname
416 : public rtl::Static< String, FullProductname > {};
417 struct Version
418 : public rtl::Static< String, Version > {};
419 struct AboutBoxVersion
420 : public rtl::Static< String, AboutBoxVersion > {};
421 struct OOOVendor
422 : public rtl::Static< String, OOOVendor > {};
423 struct Extension
424 : public rtl::Static< String, Extension > {};
425 struct XMLFileFormatName
426 : public rtl::Static< String, XMLFileFormatName > {};
427 struct XMLFileFormatVersion
428 : public rtl::Static< String, XMLFileFormatVersion > {};
429 struct WriterCompatibilityVersionOOo11
430 : public rtl::Static< String, WriterCompatibilityVersionOOo11 > {};
431 }
432
ReplaceStringHookProc(UniString & rStr)433 void ReplaceStringHookProc( UniString& rStr )
434 {
435 static int nAll = 0, nPro = 0;
436
437 nAll++;
438 if ( ( rStr.SearchAscii( "%PRODUCT" ) != STRING_NOTFOUND ) ||
439 ( rStr.SearchAscii( "%FULLPRODUCT" ) != STRING_NOTFOUND ) )
440 {
441 String &rBrandName = BrandName::get();
442 String& rFullProductname = FullProductname::get();
443 String &rVersion = Version::get();
444 String &rAboutBoxVersion = AboutBoxVersion::get();
445 String &rExtension = Extension::get();
446 String &rXMLFileFormatName = XMLFileFormatName::get();
447 String &rXMLFileFormatVersion = XMLFileFormatVersion::get();
448
449 if ( !rBrandName.Len() )
450 {
451 rtl::OUString aTmp;
452 Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTNAME );
453 aRet >>= aTmp;
454 rBrandName = aTmp;
455
456 aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::FULLPRODUCTNAME );
457 aRet >>= aTmp;
458 rFullProductname = aTmp;
459
460 aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTXMLFILEFORMATNAME );
461 aRet >>= aTmp;
462 rXMLFileFormatName = aTmp;
463
464 aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTXMLFILEFORMATVERSION );
465 aRet >>= aTmp;
466 rXMLFileFormatVersion = aTmp;
467
468 aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTVERSION );
469 aRet >>= aTmp;
470 rVersion = aTmp;
471
472 aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::ABOUTBOXPRODUCTVERSION );
473 aRet >>= aTmp;
474 rAboutBoxVersion = aTmp;
475
476 if ( !rExtension.Len() )
477 {
478 aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTEXTENSION );
479 aRet >>= aTmp;
480 rExtension = aTmp;
481 }
482 }
483
484 nPro++;
485 rStr.SearchAndReplaceAllAscii( "%PRODUCTNAME", rBrandName );
486 rStr.SearchAndReplaceAllAscii( "%FULLPRODUCTNAME", rFullProductname );
487 rStr.SearchAndReplaceAllAscii( "%PRODUCTVERSION", rVersion );
488 rStr.SearchAndReplaceAllAscii( "%ABOUTBOXPRODUCTVERSION", rAboutBoxVersion );
489 rStr.SearchAndReplaceAllAscii( "%PRODUCTEXTENSION", rExtension );
490 rStr.SearchAndReplaceAllAscii( "%PRODUCTXMLFILEFORMATNAME", rXMLFileFormatName );
491 rStr.SearchAndReplaceAllAscii( "%PRODUCTXMLFILEFORMATVERSION", rXMLFileFormatVersion );
492 }
493 if ( rStr.SearchAscii( "%OOOVENDOR" ) != STRING_NOTFOUND )
494 {
495 String &rOOOVendor = OOOVendor::get();
496
497 if ( !rOOOVendor.Len() )
498 {
499 rtl::OUString aTmp;
500 Any aRet = ::utl::ConfigManager::GetDirectConfigProperty(
501 ::utl::ConfigManager::OOOVENDOR );
502 aRet >>= aTmp;
503 rOOOVendor = aTmp;
504
505 }
506 rStr.SearchAndReplaceAllAscii( "%OOOVENDOR" ,rOOOVendor );
507 }
508
509 if ( rStr.SearchAscii( "%WRITERCOMPATIBILITYVERSIONOOO11" ) != STRING_NOTFOUND )
510 {
511 String &rWriterCompatibilityVersionOOo11 = WriterCompatibilityVersionOOo11::get();
512 if ( !rWriterCompatibilityVersionOOo11.Len() )
513 {
514 rtl::OUString aTmp;
515 Any aRet = ::utl::ConfigManager::GetDirectConfigProperty(
516 ::utl::ConfigManager::WRITERCOMPATIBILITYVERSIONOOO11 );
517 aRet >>= aTmp;
518 rWriterCompatibilityVersionOOo11 = aTmp;
519 }
520
521 rStr.SearchAndReplaceAllAscii( "%WRITERCOMPATIBILITYVERSIONOOO11",
522 rWriterCompatibilityVersionOOo11 );
523 }
524 }
525
526 static const char pLastSyncFileName[] = "lastsynchronized";
527 static const sal_Int32 nStrLenLastSync = 16;
528
needsSynchronization(::rtl::OUString const & baseSynchronizedURL,::rtl::OUString const & userSynchronizedURL)529 static bool needsSynchronization(
530 ::rtl::OUString const & baseSynchronizedURL, ::rtl::OUString const & userSynchronizedURL )
531 {
532 bool bNeedsSync( false );
533
534 ::osl::DirectoryItem itemUserFile;
535 ::osl::File::RC err1 =
536 ::osl::DirectoryItem::get(userSynchronizedURL, itemUserFile);
537
538 //If it does not exist, then there is nothing to be done
539 if (err1 == ::osl::File::E_NOENT)
540 {
541 return true;
542 }
543 else if (err1 != ::osl::File::E_None)
544 {
545 OSL_ENSURE(0, "Cannot access lastsynchronized in user layer");
546 return true; //sync just in case
547 }
548
549 //If last synchronized does not exist in base layer, then do nothing
550 ::osl::DirectoryItem itemBaseFile;
551 ::osl::File::RC err2 = ::osl::DirectoryItem::get(baseSynchronizedURL, itemBaseFile);
552 if (err2 == ::osl::File::E_NOENT)
553 {
554 return true;
555
556 }
557 else if (err2 != ::osl::File::E_None)
558 {
559 OSL_ENSURE(0, "Cannot access file lastsynchronized in base layer");
560 return true; //sync just in case
561 }
562
563 //compare the modification time of the extension folder and the last
564 //modified file
565 ::osl::FileStatus statUser(FileStatusMask_ModifyTime);
566 ::osl::FileStatus statBase(FileStatusMask_ModifyTime);
567 if (itemUserFile.getFileStatus(statUser) == ::osl::File::E_None)
568 {
569 if (itemBaseFile.getFileStatus(statBase) == ::osl::File::E_None)
570 {
571 TimeValue timeUser = statUser.getModifyTime();
572 TimeValue timeBase = statBase.getModifyTime();
573
574 if (timeUser.Seconds < timeBase.Seconds)
575 bNeedsSync = true;
576 }
577 else
578 {
579 OSL_ASSERT(0);
580 bNeedsSync = true;
581 }
582 }
583 else
584 {
585 OSL_ASSERT(0);
586 bNeedsSync = true;
587 }
588
589 return bNeedsSync;
590 }
591
getBrandSharePreregBundledPathURL()592 static ::rtl::OUString getBrandSharePreregBundledPathURL()
593 {
594 ::rtl::OUString url(
595 RTL_CONSTASCII_USTRINGPARAM("$OOO_BASE_DIR/share/prereg/bundled"));
596
597 ::rtl::Bootstrap::expandMacros(url);
598 return url;
599 }
600
getUserBundledExtPathURL()601 static ::rtl::OUString getUserBundledExtPathURL()
602 {
603 ::rtl::OUString folder( RTL_CONSTASCII_USTRINGPARAM( "$BUNDLED_EXTENSIONS_USER" ));
604 ::rtl::Bootstrap::expandMacros(folder);
605
606 return folder;
607 }
608
getLastSyncFileURLFromBrandInstallation()609 static ::rtl::OUString getLastSyncFileURLFromBrandInstallation()
610 {
611 ::rtl::OUString aURL = getBrandSharePreregBundledPathURL();
612 ::sal_Int32 nLastIndex = aURL.lastIndexOf('/');
613
614 ::rtl::OUStringBuffer aTmp( aURL );
615
616 if ( nLastIndex != aURL.getLength()-1 )
617 aTmp.appendAscii( "/" );
618 aTmp.appendAscii( pLastSyncFileName );
619
620 return aTmp.makeStringAndClear();
621 }
622
getLastSyncFileURLFromUserInstallation()623 static ::rtl::OUString getLastSyncFileURLFromUserInstallation()
624 {
625 ::rtl::OUString aUserBundledPathURL = getUserBundledExtPathURL();
626 ::sal_Int32 nLastIndex = aUserBundledPathURL.lastIndexOf('/');
627
628 ::rtl::OUStringBuffer aTmp( aUserBundledPathURL );
629
630 if ( nLastIndex != aUserBundledPathURL.getLength()-1 )
631 aTmp.appendAscii( "/" );
632 aTmp.appendAscii( pLastSyncFileName );
633
634 return aTmp.makeStringAndClear();
635 }
636 //Checks if the argument src is the folder of the help or configuration
637 //backend in the prereg folder
excludeTmpFilesAndFolders(const rtl::OUString & src)638 static bool excludeTmpFilesAndFolders(const rtl::OUString & src)
639 {
640 const char helpBackend[] = "com.sun.star.comp.deployment.help.PackageRegistryBackend";
641 const char configBackend[] = "com.sun.star.comp.deployment.configuration.PackageRegistryBackend";
642 if (src.endsWithAsciiL(helpBackend, sizeof(helpBackend) - 1 )
643 || src.endsWithAsciiL(configBackend, sizeof(configBackend) - 1))
644 {
645 return true;
646 }
647 return false;
648 }
649
650 //If we are about to copy the contents of some special folder as determined
651 //by excludeTmpFilesAndFolders, then we omit those files or folders with a name
652 //derived from temporary folders.
isExcludedFileOrFolder(const rtl::OUString & name)653 static bool isExcludedFileOrFolder( const rtl::OUString & name)
654 {
655 char const * allowed[] = {
656 "backenddb.xml",
657 "configmgr.ini",
658 "registered_packages.db"
659 };
660
661 const unsigned int size = sizeof(allowed) / sizeof (char const *);
662 bool bExclude = true;
663 for (unsigned int i= 0; i < size; i ++)
664 {
665 ::rtl::OUString allowedName = ::rtl::OUString::createFromAscii(allowed[i]);
666 if (allowedName.equals(name))
667 {
668 bExclude = false;
669 break;
670 }
671 }
672 return bExclude;
673 }
674
copy_prereg_bundled_recursive(const rtl::OUString & srcUnqPath,const rtl::OUString & dstUnqPath,sal_Int32 TypeToCopy)675 static osl::FileBase::RC copy_prereg_bundled_recursive(
676 const rtl::OUString& srcUnqPath,
677 const rtl::OUString& dstUnqPath,
678 sal_Int32 TypeToCopy )
679 throw()
680 {
681 osl::FileBase::RC err = osl::FileBase::E_None;
682
683 if( TypeToCopy == -1 ) // Document
684 {
685 err = osl::File::copy( srcUnqPath,dstUnqPath );
686 }
687 else if( TypeToCopy == +1 ) // Folder
688 {
689 osl::Directory aDir( srcUnqPath );
690 err = aDir.open();
691 if ( err != osl::FileBase::E_None )
692 return err;
693
694 err = osl::Directory::create( dstUnqPath );
695 osl::FileBase::RC next = err;
696 if( err == osl::FileBase::E_None ||
697 err == osl::FileBase::E_EXIST )
698 {
699 err = osl::FileBase::E_None;
700 sal_Int32 n_Mask = FileStatusMask_FileURL | FileStatusMask_FileName | FileStatusMask_Type;
701
702 osl::DirectoryItem aDirItem;
703 bool bExcludeFiles = excludeTmpFilesAndFolders(srcUnqPath);
704
705 while( err == osl::FileBase::E_None && ( next = aDir.getNextItem( aDirItem ) ) == osl::FileBase::E_None )
706 {
707 sal_Bool IsDoc = false;
708 sal_Bool bFilter = false;
709 osl::FileStatus aFileStatus( n_Mask );
710 aDirItem.getFileStatus( aFileStatus );
711 if( aFileStatus.isValid( FileStatusMask_Type ) )
712 IsDoc = aFileStatus.getFileType() == osl::FileStatus::Regular;
713
714 // Getting the information for the next recursive copy
715 sal_Int32 newTypeToCopy = IsDoc ? -1 : +1;
716
717 rtl::OUString newSrcUnqPath;
718 if( aFileStatus.isValid( FileStatusMask_FileURL ) )
719 newSrcUnqPath = aFileStatus.getFileURL();
720
721 rtl::OUString newDstUnqPath = dstUnqPath;
722 rtl::OUString tit;
723 if( aFileStatus.isValid( FileStatusMask_FileName ) )
724 {
725 ::rtl::OUString aFileName = aFileStatus.getFileName();
726 tit = rtl::Uri::encode( aFileName,
727 rtl_UriCharClassPchar,
728 rtl_UriEncodeIgnoreEscapes,
729 RTL_TEXTENCODING_UTF8 );
730
731 // Special treatment for "lastsychronized" file. Must not be
732 // copied from the bundled folder!
733 //Also do not copy *.tmp files and *.tmp_ folders. This affects the files/folders
734 //from the help and configuration backend
735 if ( IsDoc && (aFileName.equalsAscii( pLastSyncFileName )
736 || bExcludeFiles && isExcludedFileOrFolder(aFileName)))
737 bFilter = true;
738 else if (!IsDoc && bExcludeFiles && isExcludedFileOrFolder(aFileName))
739 bFilter = true;
740 }
741
742 if( newDstUnqPath.lastIndexOf( sal_Unicode('/') ) != newDstUnqPath.getLength()-1 )
743 newDstUnqPath += rtl::OUString::createFromAscii( "/" );
744
745 newDstUnqPath += tit;
746
747 if (( newSrcUnqPath != dstUnqPath ) && !bFilter )
748 err = copy_prereg_bundled_recursive( newSrcUnqPath,newDstUnqPath, newTypeToCopy );
749 }
750
751 if( err == osl::FileBase::E_None && next != osl::FileBase::E_NOENT )
752 err = next;
753 }
754 aDir.close();
755 }
756
757 return err;
758 }
759
760
761 //====================================================================================
762
763 // MinimalCommandEnv: a tribute owed to ExtensionManager being an UNO stronghold
764 class MinimalCommandEnv
765 : public ::cppu::WeakImplHelper3< css::ucb::XCommandEnvironment,
766 css::task::XInteractionHandler,
767 css::ucb::XProgressHandler >
768 {
769 public:
770 // XCommandEnvironment
getInteractionHandler()771 virtual css::uno::Reference< css::task::XInteractionHandler> SAL_CALL getInteractionHandler()
772 { return this;}
getProgressHandler()773 virtual css::uno::Reference< css::ucb::XProgressHandler> SAL_CALL getProgressHandler()
774 { return this;}
775
776 // XInteractionHandler
777 virtual void SAL_CALL handle( const css::uno::Reference< css::task::XInteractionRequest>&);
778
779 // XProgressHandler
push(const css::uno::Any &)780 virtual void SAL_CALL push( const css::uno::Any& /*Status*/)
781 {}
update(const css::uno::Any &)782 virtual void SAL_CALL update( const css::uno::Any& /*Status*/)
783 {}
pop()784 virtual void SAL_CALL pop()
785 {}
786 };
787
788 // MinimalCommandEnv's XInteractionHandler simply approves
handle(css::uno::Reference<css::task::XInteractionRequest> const & xRequest)789 void MinimalCommandEnv::handle(
790 css::uno::Reference< css::task::XInteractionRequest> const& xRequest)
791 {
792 bool bApprove = true;
793
794 css::deployment::VersionException verExc;
795 if ( xRequest->getRequest() >>= verExc )
796 {
797 // choose newest version, if an extension is already been installed.
798 const bool bChooseNewestVersion = true;
799 bApprove = handleVersionException( verExc, 0, bChooseNewestVersion );
800 }
801
802 const css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > conts( xRequest->getContinuations());
803 const css::uno::Reference< css::task::XInteractionContinuation>* pConts = conts.getConstArray();
804 const sal_Int32 len = conts.getLength();
805 for( sal_Int32 pos = 0; pos < len; ++pos )
806 {
807 if ( bApprove )
808 {
809 css::uno::Reference< css::task::XInteractionApprove> xInteractionApprove( pConts[ pos ], css::uno::UNO_QUERY);
810 if( xInteractionApprove.is())
811 {
812 xInteractionApprove->select();
813 // don't query again for ongoing continuations:
814 break;
815 }
816 }
817 else
818 {
819 css::uno::Reference< css::task::XInteractionAbort > xInteractionAbort( pConts[ pos ], css::uno::UNO_QUERY );
820 if (xInteractionAbort.is())
821 {
822 xInteractionAbort->select();
823 // don't query again for ongoing continuations:
824 break;
825 }
826 }
827 }
828 }
829
830
831 /** Check if installBundledExtensionBlobs() has to be run.
832 It uses the time stamps of a marker file (rsMarkerURL) on the one
833 hand and of the files in the given directory on the other.
834 Returns </TRUE> when either the marker does not yet exist or any
835 file in the given directory is newer than the marker.
836 */
needsInstallBundledExtensionBlobs(const::rtl::OUString & rsMarkerURL,const::rtl::OUString & rsDirectoryURL)837 static bool needsInstallBundledExtensionBlobs (
838 const ::rtl::OUString& rsMarkerURL,
839 const ::rtl::OUString& rsDirectoryURL)
840 {
841 ::osl::DirectoryItem aMarkerItem;
842 if (::osl::DirectoryItem::get(rsMarkerURL, aMarkerItem) == ::osl::File::E_NOENT)
843 {
844 // Marker does not exist. Extensions where never installed.
845 return true;
846 }
847
848 ::osl::FileStatus aMarkerStat (FileStatusMask_ModifyTime);
849 if (aMarkerItem.getFileStatus(aMarkerStat) != ::osl::File::E_None)
850 {
851 // Can not get marker state. Reason?
852 return true;
853 }
854
855 const TimeValue aMarkerModifyTime (aMarkerStat.getModifyTime());
856
857 ::osl::Directory aDirectory (rsDirectoryURL);
858 if (aDirectory.open() != osl::File::E_None)
859 {
860 // No extension directory. Nothing to be done.
861 return false;
862 }
863
864 // Check the date of each extension in the given directory. If
865 // any of them is newer than the marker file then an installation
866 // is necessary.
867 ::osl::DirectoryItem aDirectoryItem;
868 while (aDirectory.getNextItem(aDirectoryItem) == osl::File::E_None)
869 {
870 ::osl::FileStatus aFileStat (FileStatusMask_ModifyTime);
871 if (aDirectoryItem.getFileStatus(aFileStat) != ::osl::File::E_None)
872 continue;
873 if (aFileStat.getFileType() != ::osl::FileStatus::Regular)
874 continue;
875 if (aFileStat.getModifyTime().Seconds > aMarkerModifyTime.Seconds)
876 {
877 aDirectory.close();
878 return true;
879 }
880 }
881 aDirectory.close();
882
883 // Also check the last modification time of the containing
884 // directory. This ensures installation after an update of
885 // OpenOffice. Without it the extensions have the date on which
886 // they where built, not the date on which they where installed.
887 if (::osl::DirectoryItem::get(rsDirectoryURL, aDirectoryItem) == osl::File::E_None)
888 {
889 ::osl::FileStatus aDirectoryStat (FileStatusMask_ModifyTime);
890 const ::osl::FileBase::RC eResult (aDirectoryItem.getFileStatus(aDirectoryStat));
891 if (eResult == ::osl::File::E_None)
892 {
893 if (aDirectoryStat.getModifyTime().Seconds > aMarkerModifyTime.Seconds)
894 return true;
895 }
896 }
897
898 // No file in the directory is newer than the marker.
899 return false;
900 }
901
902
903 // install bundled but non-pre-registered extension blobs
installBundledExtensionBlobs()904 static void installBundledExtensionBlobs()
905 {
906 rtl::OUString aDirUrl( OUSTR("$OOO_BASE_DIR/share/extensions/install"));
907 ::rtl::Bootstrap::expandMacros( aDirUrl);
908
909 // Find out if we can exit early: only when there is an extension file newer
910 // than the marker we have to install any extension.
911 ::rtl::OUString sMarkerURL (RTL_CONSTASCII_USTRINGPARAM("$BUNDLED_EXTENSIONS_USER/lastsynchronized.bundled"));
912 ::rtl::Bootstrap::expandMacros(sMarkerURL);
913 if ( ! needsInstallBundledExtensionBlobs(sMarkerURL, aDirUrl))
914 return;
915 writeLastModified(sMarkerURL);
916
917 // get the ExtensionManager
918 ::css::uno::Reference< ::css::uno::XComponentContext> xContext = comphelper::getProcessComponentContext();
919 ::css::uno::Reference< ::css::deployment::XExtensionManager> xEM = ::css::deployment::ExtensionManager::get( xContext);
920 // provide the minimal set of requirements to call ExtensionManager's methods
921 MinimalCommandEnv* pMiniCmdEnv = new MinimalCommandEnv;
922 ::css::uno::Reference< css::ucb::XCommandEnvironment> xCmdEnv( static_cast< cppu::OWeakObject*>(pMiniCmdEnv), css::uno::UNO_QUERY);
923 ::css::uno::Reference< ::css::task::XAbortChannel> xAbortChannel;
924
925 const ::css::beans::NamedValue aNamedProps( OUSTR("SUPPRESS_LICENSE"), ::css::uno::makeAny( OUSTR("1")));
926 const ::css::uno::Sequence< ::css::beans::NamedValue> xProperties( &aNamedProps, 1);
927
928 // iterate over the bundled extension blobs
929 ::osl::Directory aDir( aDirUrl);
930 ::osl::File::RC rc = aDir.open();
931 while( rc == osl::File::E_None)
932 {
933 ::osl::DirectoryItem aDI;
934 if( aDir.getNextItem( aDI) != osl::File::E_None)
935 break;
936 ::osl::FileStatus aFileStat( FileStatusMask_Type | FileStatusMask_FileURL);
937 if( aDI.getFileStatus( aFileStat) != ::osl::File::E_None)
938 continue;
939 if( aFileStat.getFileType() != ::osl::FileStatus::Regular)
940 continue;
941 try
942 {
943 // request to install the extension blob
944 xEM->addExtension( aFileStat.getFileURL(), xProperties, OUSTR("user"), xAbortChannel, xCmdEnv);
945 }
946 // ExtensionManager problems are not worth to die for here
947 catch( css::uno::RuntimeException&)
948 {}
949 catch( css::deployment::DeploymentException&)
950 {}
951 catch ( css::ucb::CommandFailedException& )
952 {
953 }
954 catch ( css::ucb::CommandAbortedException& )
955 {
956 }
957 catch ( css::lang::IllegalArgumentException& )
958 {
959 }
960 }
961 }
962
963 //=============================================================================
964
Desktop()965 Desktop::Desktop()
966 : m_bServicesRegistered( false )
967 , m_aBootstrapError( BE_OK )
968 , m_pLockfile( NULL )
969 {
970 RTL_LOGFILE_TRACE( "desktop (cd100003) ::Desktop::Desktop" );
971 }
972
~Desktop()973 Desktop::~Desktop()
974 {
975 }
976
Init()977 void Desktop::Init()
978 {
979 RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::Init" );
980 SetBootstrapStatus(BS_OK);
981
982 // Check for lastsynchronized file for pre-registered bundled extensions in the user directory
983 // and test if synchronization is necessary!
984 {
985 ::rtl::OUString aUserLastSyncFilePathURL = getLastSyncFileURLFromUserInstallation();
986 ::rtl::OUString aPreregSyncFilePathURL = getLastSyncFileURLFromBrandInstallation();
987
988 if ( needsSynchronization( aPreregSyncFilePathURL, aUserLastSyncFilePathURL ))
989 {
990 rtl::OUString aUserPath = getUserBundledExtPathURL();
991 rtl::OUString aPreregBundledPath = getBrandSharePreregBundledPathURL();
992
993 // copy bundled folder to the user directory
994 osl::FileBase::RC rc = osl::Directory::createPath(aUserPath);
995 (void) rc;
996 copy_prereg_bundled_recursive( aPreregBundledPath, aUserPath, +1 );
997 }
998 }
999
1000 // create service factory...
1001 Reference < XMultiServiceFactory > rSMgr = CreateApplicationServiceManager();
1002 if( rSMgr.is() )
1003 {
1004 ::comphelper::setProcessServiceFactory( rSMgr );
1005 }
1006 else
1007 {
1008 SetBootstrapError( BE_UNO_SERVICEMANAGER );
1009 }
1010
1011 if ( GetBootstrapError() == BE_OK )
1012 {
1013 // prepare language
1014 if ( !LanguageSelection::prepareLanguage() )
1015 {
1016 if ( LanguageSelection::getStatus() == LanguageSelection::LS_STATUS_CANNOT_DETERMINE_LANGUAGE )
1017 SetBootstrapError( BE_LANGUAGE_MISSING );
1018 else
1019 SetBootstrapError( BE_OFFICECONFIG_BROKEN );
1020 }
1021 }
1022
1023 if ( GetBootstrapError() == BE_OK )
1024 {
1025 CommandLineArgs* pCmdLineArgs = GetCommandLineArgs();
1026 #ifdef UNX
1027 // check whether we need to print cmdline help
1028 if ( pCmdLineArgs->IsHelp() ) {
1029 displayCmdlineHelp();
1030 SetBootstrapStatus(BS_TERMINATE);
1031 }
1032 #endif
1033 // start ipc thread only for non-remote offices
1034 RTL_LOGFILE_CONTEXT( aLog2, "desktop (cd100003) ::OfficeIPCThread::EnableOfficeIPCThread" );
1035 OfficeIPCThread::Status aStatus = OfficeIPCThread::EnableOfficeIPCThread();
1036 if ( aStatus == OfficeIPCThread::IPC_STATUS_BOOTSTRAP_ERROR )
1037 {
1038 SetBootstrapError( BE_PATHINFO_MISSING );
1039
1040 }
1041 else if ( aStatus == OfficeIPCThread::IPC_STATUS_MULTI_TS_ERROR )
1042 {
1043 SetBootstrapError( BE_MUTLISESSION_NOT_SUPPROTED );
1044 }
1045 else if ( aStatus == OfficeIPCThread::IPC_STATUS_2ND_OFFICE )
1046 {
1047 // 2nd office startup should terminate after sending cmdlineargs through pipe
1048 SetBootstrapStatus(BS_TERMINATE);
1049 }
1050 else if ( pCmdLineArgs->IsHelp() )
1051 {
1052 // disable IPC thread in an instance that is just showing a help message
1053 OfficeIPCThread::DisableOfficeIPCThread();
1054 }
1055 pSignalHandler = new SalMainPipeExchangeSignalHandler;
1056 }
1057 }
1058
DeInit()1059 void Desktop::DeInit()
1060 {
1061 RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::DeInit" );
1062
1063 try {
1064 // instead of removing of the configManager just let it commit all the changes
1065 RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" );
1066 utl::ConfigManager::GetConfigManager()->StoreConfigItems();
1067 FlushConfiguration();
1068 RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" );
1069
1070 // close splashscreen if it's still open
1071 CloseSplashScreen();
1072 Reference<XMultiServiceFactory> xXMultiServiceFactory(::comphelper::getProcessServiceFactory());
1073 DestroyApplicationServiceManager( xXMultiServiceFactory );
1074 // nobody should get a destroyd service factory...
1075 ::comphelper::setProcessServiceFactory( NULL );
1076
1077 // clear lockfile
1078 if (m_pLockfile != NULL)
1079 m_pLockfile->clean();
1080
1081 OfficeIPCThread::DisableOfficeIPCThread();
1082 if( pSignalHandler )
1083 DELETEZ( pSignalHandler );
1084 } catch (RuntimeException&) {
1085 // someone threw an exception during shutdown
1086 // this will leave some garbage behind..
1087 }
1088
1089 RTL_LOGFILE_CONTEXT_TRACE( aLog, "FINISHED WITH Destop::DeInit" );
1090 }
1091
QueryExit()1092 sal_Bool Desktop::QueryExit()
1093 {
1094 try
1095 {
1096 RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" );
1097 utl::ConfigManager::GetConfigManager()->StoreConfigItems();
1098 RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" );
1099 }
1100 catch ( RuntimeException& )
1101 {
1102 }
1103
1104 const sal_Char SUSPEND_QUICKSTARTVETO[] = "SuspendQuickstartVeto";
1105
1106 Reference< ::com::sun::star::frame::XDesktop >
1107 xDesktop( ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ),
1108 UNO_QUERY );
1109
1110 Reference < ::com::sun::star::beans::XPropertySet > xPropertySet( xDesktop, UNO_QUERY );
1111 if ( xPropertySet.is() )
1112 {
1113 Any a;
1114 a <<= (sal_Bool)sal_True;
1115 xPropertySet->setPropertyValue( OUSTRING(RTL_CONSTASCII_USTRINGPARAM( SUSPEND_QUICKSTARTVETO )), a );
1116 }
1117
1118 sal_Bool bExit = ( !xDesktop.is() || xDesktop->terminate() );
1119
1120
1121 if ( !bExit && xPropertySet.is() )
1122 {
1123 Any a;
1124 a <<= (sal_Bool)sal_False;
1125 xPropertySet->setPropertyValue( OUSTRING(RTL_CONSTASCII_USTRINGPARAM( SUSPEND_QUICKSTARTVETO )), a );
1126 }
1127 else
1128 {
1129 FlushConfiguration();
1130 try
1131 {
1132 // it is no problem to call DisableOfficeIPCThread() more than once
1133 // it also looks to be threadsafe
1134 OfficeIPCThread::DisableOfficeIPCThread();
1135 }
1136 catch ( RuntimeException& )
1137 {
1138 }
1139
1140 if (m_pLockfile != NULL) m_pLockfile->clean();
1141 }
1142
1143 return bExit;
1144 }
1145
HandleBootstrapPathErrors(::utl::Bootstrap::Status aBootstrapStatus,const OUString & aDiagnosticMessage)1146 void Desktop::HandleBootstrapPathErrors( ::utl::Bootstrap::Status aBootstrapStatus, const OUString& aDiagnosticMessage )
1147 {
1148 if ( aBootstrapStatus != ::utl::Bootstrap::DATA_OK )
1149 {
1150 sal_Bool bWorkstationInstallation = sal_False;
1151 ::rtl::OUString aBaseInstallURL;
1152 ::rtl::OUString aUserInstallURL;
1153 ::rtl::OUString aProductKey;
1154 ::rtl::OUString aTemp;
1155 ::vos::OStartupInfo aInfo;
1156
1157 aInfo.getExecutableFile( aProductKey );
1158 sal_uInt32 lastIndex = aProductKey.lastIndexOf('/');
1159 if ( lastIndex > 0 )
1160 aProductKey = aProductKey.copy( lastIndex+1 );
1161
1162 aTemp = ::utl::Bootstrap::getProductKey( aProductKey );
1163 if ( aTemp.getLength() > 0 )
1164 aProductKey = aTemp;
1165
1166 ::utl::Bootstrap::PathStatus aBaseInstallStatus = ::utl::Bootstrap::locateBaseInstallation( aBaseInstallURL );
1167 ::utl::Bootstrap::PathStatus aUserInstallStatus = ::utl::Bootstrap::locateUserInstallation( aUserInstallURL );
1168
1169 if (( aBaseInstallStatus == ::utl::Bootstrap::PATH_EXISTS &&
1170 aUserInstallStatus == ::utl::Bootstrap::PATH_EXISTS ))
1171 {
1172 if ( aBaseInstallURL != aUserInstallURL )
1173 bWorkstationInstallation = sal_True;
1174 }
1175
1176 OUString aMessage;
1177 OUStringBuffer aBuffer( 100 );
1178 aBuffer.append( aDiagnosticMessage );
1179
1180 aBuffer.appendAscii( "\n" );
1181
1182 ErrorBox aBootstrapFailedBox( NULL, WB_OK, aMessage );
1183 aBootstrapFailedBox.SetText( aProductKey );
1184 aBootstrapFailedBox.Execute();
1185 }
1186 }
1187
1188 // Create a error message depending on bootstrap failure code and an optional file url
CreateErrorMsgString(utl::Bootstrap::FailureCode nFailureCode,const::rtl::OUString & aFileURL)1189 ::rtl::OUString Desktop::CreateErrorMsgString(
1190 utl::Bootstrap::FailureCode nFailureCode,
1191 const ::rtl::OUString& aFileURL )
1192 {
1193 OUString aMsg;
1194 OUString aFilePath;
1195 sal_Bool bFileInfo = sal_True;
1196
1197 switch ( nFailureCode )
1198 {
1199 /// the shared installation directory could not be located
1200 case ::utl::Bootstrap::MISSING_INSTALL_DIRECTORY:
1201 {
1202 aMsg = GetMsgString( STR_BOOTSTRAP_ERR_PATH_INVALID,
1203 OUString( RTL_CONSTASCII_USTRINGPARAM( "The installation path is not available." )) );
1204 bFileInfo = sal_False;
1205 }
1206 break;
1207
1208 /// the bootstrap INI file could not be found or read
1209 case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE:
1210 {
1211 aMsg = GetMsgString( STR_BOOTSTRAP_ERR_FILE_MISSING,
1212 OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration file \"$1\" is missing." )) );
1213 }
1214 break;
1215
1216 /// the bootstrap INI is missing a required entry
1217 /// the bootstrap INI contains invalid data
1218 case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE_ENTRY:
1219 case ::utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY:
1220 {
1221 aMsg = GetMsgString( STR_BOOTSTRAP_ERR_FILE_CORRUPT,
1222 OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration file \"$1\" is corrupt." )) );
1223 }
1224 break;
1225
1226 /// the version locator INI file could not be found or read
1227 case ::utl::Bootstrap::MISSING_VERSION_FILE:
1228 {
1229 aMsg = GetMsgString( STR_BOOTSTRAP_ERR_FILE_MISSING,
1230 OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration file \"$1\" is missing." )) );
1231 }
1232 break;
1233
1234 /// the version locator INI has no entry for this version
1235 case ::utl::Bootstrap::MISSING_VERSION_FILE_ENTRY:
1236 {
1237 aMsg = GetMsgString( STR_BOOTSTRAP_ERR_NO_SUPPORT,
1238 OUString( RTL_CONSTASCII_USTRINGPARAM( "The main configuration file \"$1\" does not support the current version." )) );
1239 }
1240 break;
1241
1242 /// the user installation directory does not exist
1243 case ::utl::Bootstrap::MISSING_USER_DIRECTORY:
1244 {
1245 aMsg = GetMsgString( STR_BOOTSTRAP_ERR_DIR_MISSING,
1246 OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration directory \"$1\" is missing." )) );
1247 }
1248 break;
1249
1250 /// some bootstrap data was invalid in unexpected ways
1251 case ::utl::Bootstrap::INVALID_BOOTSTRAP_DATA:
1252 {
1253 aMsg = GetMsgString( STR_BOOTSTRAP_ERR_INTERNAL,
1254 OUString( RTL_CONSTASCII_USTRINGPARAM( "An internal failure occurred." )) );
1255 bFileInfo = sal_False;
1256 }
1257 break;
1258
1259 case ::utl::Bootstrap::INVALID_VERSION_FILE_ENTRY:
1260 {
1261 // This needs to be improved, see #i67575#:
1262 aMsg = OUString(
1263 RTL_CONSTASCII_USTRINGPARAM( "Invalid version file entry" ) );
1264 bFileInfo = sal_False;
1265 }
1266 break;
1267
1268 case ::utl::Bootstrap::NO_FAILURE:
1269 {
1270 OSL_ASSERT(false);
1271 }
1272 break;
1273 }
1274
1275 if ( bFileInfo )
1276 {
1277 String aMsgString( aMsg );
1278
1279 osl::File::getSystemPathFromFileURL( aFileURL, aFilePath );
1280
1281 aMsgString.SearchAndReplaceAscii( "$1", aFilePath );
1282 aMsg = aMsgString;
1283 }
1284
1285 return MakeStartupErrorMessage( aMsg );
1286 }
1287
HandleBootstrapErrors(BootstrapError aBootstrapError)1288 void Desktop::HandleBootstrapErrors( BootstrapError aBootstrapError )
1289 {
1290 if ( aBootstrapError == BE_MUTLISESSION_NOT_SUPPROTED ) {
1291 OUString aMessage;
1292 aMessage = GetMsgString( STR_BOOTSTRAP_ERR_MULTISESSION,
1293 OUString( RTL_CONSTASCII_USTRINGPARAM( "You have another instance running in a different terminal session. Close that instance and then try again." )) );
1294 FatalError(aMessage,sal_False);
1295
1296 } else if ( aBootstrapError == BE_PATHINFO_MISSING )
1297 {
1298 OUString aErrorMsg;
1299 OUString aBuffer;
1300 utl::Bootstrap::Status aBootstrapStatus;
1301 utl::Bootstrap::FailureCode nFailureCode;
1302
1303 aBootstrapStatus = ::utl::Bootstrap::checkBootstrapStatus( aBuffer, nFailureCode );
1304 if ( aBootstrapStatus != ::utl::Bootstrap::DATA_OK )
1305 {
1306 switch ( nFailureCode )
1307 {
1308 case ::utl::Bootstrap::MISSING_INSTALL_DIRECTORY:
1309 case ::utl::Bootstrap::INVALID_BOOTSTRAP_DATA:
1310 {
1311 aErrorMsg = CreateErrorMsgString( nFailureCode, OUString() );
1312 }
1313 break;
1314
1315 /// the bootstrap INI file could not be found or read
1316 /// the bootstrap INI is missing a required entry
1317 /// the bootstrap INI contains invalid data
1318 case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE_ENTRY:
1319 case ::utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY:
1320 case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE:
1321 {
1322 OUString aBootstrapFileURL;
1323
1324 utl::Bootstrap::locateBootstrapFile( aBootstrapFileURL );
1325 aErrorMsg = CreateErrorMsgString( nFailureCode, aBootstrapFileURL );
1326 }
1327 break;
1328
1329 /// the version locator INI file could not be found or read
1330 /// the version locator INI has no entry for this version
1331 /// the version locator INI entry is not a valid directory URL
1332 case ::utl::Bootstrap::INVALID_VERSION_FILE_ENTRY:
1333 case ::utl::Bootstrap::MISSING_VERSION_FILE_ENTRY:
1334 case ::utl::Bootstrap::MISSING_VERSION_FILE:
1335 {
1336 OUString aVersionFileURL;
1337
1338 utl::Bootstrap::locateVersionFile( aVersionFileURL );
1339 aErrorMsg = CreateErrorMsgString( nFailureCode, aVersionFileURL );
1340 }
1341 break;
1342
1343 /// the user installation directory does not exist
1344 case ::utl::Bootstrap::MISSING_USER_DIRECTORY:
1345 {
1346 OUString aUserInstallationURL;
1347
1348 utl::Bootstrap::locateUserInstallation( aUserInstallationURL );
1349 aErrorMsg = CreateErrorMsgString( nFailureCode, aUserInstallationURL );
1350 }
1351 break;
1352
1353 case ::utl::Bootstrap::NO_FAILURE:
1354 {
1355 OSL_ASSERT(false);
1356 }
1357 break;
1358 }
1359
1360 HandleBootstrapPathErrors( aBootstrapStatus, aErrorMsg );
1361 }
1362 }
1363 else if ( aBootstrapError == BE_UNO_SERVICEMANAGER || aBootstrapError == BE_UNO_SERVICE_CONFIG_MISSING )
1364 {
1365 // Uno service manager is not available. VCL needs a uno service manager to display a message box!!!
1366 // Currently we are not able to display a message box with a service manager due to this limitations inside VCL.
1367
1368 // When UNO is not properly initialized, all kinds of things can fail
1369 // and cause the process to crash (e.g., a call to GetMsgString may
1370 // crash when somewhere deep within that call Any::operator <= is used
1371 // with a PropertyValue, and no binary UNO type description for
1372 // PropertyValue is available). To give the user a hint even if
1373 // generating and displaying a message box below crashes, print a
1374 // hard-coded message on stderr first:
1375 fputs(
1376 aBootstrapError == BE_UNO_SERVICEMANAGER
1377 ? ("The application cannot be started. " "\n"
1378 "The component manager is not available." "\n")
1379 // STR_BOOTSTRAP_ERR_CANNOT_START, STR_BOOTSTRAP_ERR_NO_SERVICE
1380 : ("The application cannot be started. " "\n"
1381 "The configuration service is not available." "\n"),
1382 // STR_BOOTSTRAP_ERR_CANNOT_START,
1383 // STR_BOOTSTRAP_ERR_NO_CFG_SERVICE
1384 stderr);
1385
1386 // First sentence. We cannot bootstrap office further!
1387 OUString aMessage;
1388 OUStringBuffer aDiagnosticMessage( 100 );
1389
1390 OUString aErrorMsg;
1391
1392 if ( aBootstrapError == BE_UNO_SERVICEMANAGER )
1393 aErrorMsg = GetMsgString( STR_BOOTSTRAP_ERR_NO_SERVICE,
1394 OUString( RTL_CONSTASCII_USTRINGPARAM( "The service manager is not available." )) );
1395 else
1396 aErrorMsg = GetMsgString( STR_BOOTSTRAP_ERR_NO_CFG_SERVICE,
1397 OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration service is not available." )) );
1398
1399 aDiagnosticMessage.append( aErrorMsg );
1400 aDiagnosticMessage.appendAscii( "\n" );
1401
1402 // Due to the fact the we haven't a backup applicat.rdb file anymore it is not possible to
1403 // repair the installation with the setup executable besides the office executable. Now
1404 // we have to ask the user to start the setup on CD/installation directory manually!!
1405 OUString aStartSetupManually( GetMsgString(
1406 STR_ASK_START_SETUP_MANUALLY,
1407 OUString( RTL_CONSTASCII_USTRINGPARAM( "Start setup application to repair the installation from CD, or the folder containing the installation packages." )) ));
1408
1409 aDiagnosticMessage.append( aStartSetupManually );
1410 aMessage = MakeStartupErrorMessage( aDiagnosticMessage.makeStringAndClear() );
1411
1412 FatalError( aMessage);
1413 }
1414 else if ( aBootstrapError == BE_OFFICECONFIG_BROKEN )
1415 {
1416 OUString aMessage;
1417 OUStringBuffer aDiagnosticMessage( 100 );
1418 OUString aErrorMsg;
1419 aErrorMsg = GetMsgString( STR_CONFIG_ERR_ACCESS_GENERAL,
1420 OUString( RTL_CONSTASCII_USTRINGPARAM( "A general error occurred while accessing your central configuration." )) );
1421 aDiagnosticMessage.append( aErrorMsg );
1422 aMessage = MakeStartupErrorMessage( aDiagnosticMessage.makeStringAndClear() );
1423 FatalError(aMessage);
1424 }
1425 else if ( aBootstrapError == BE_USERINSTALL_FAILED )
1426 {
1427 OUString aMessage;
1428 OUStringBuffer aDiagnosticMessage( 100 );
1429 OUString aErrorMsg;
1430 aErrorMsg = GetMsgString( STR_BOOTSTRAP_ERR_INTERNAL,
1431 OUString( RTL_CONSTASCII_USTRINGPARAM( "User installation could not be completed" )) );
1432 aDiagnosticMessage.append( aErrorMsg );
1433 aMessage = MakeStartupErrorMessage( aDiagnosticMessage.makeStringAndClear() );
1434 FatalError(aMessage);
1435 }
1436 else if ( aBootstrapError == BE_LANGUAGE_MISSING )
1437 {
1438 OUString aMessage;
1439 OUStringBuffer aDiagnosticMessage( 100 );
1440 OUString aErrorMsg;
1441 aErrorMsg = GetMsgString(
1442 //@@@ FIXME: should use an own resource string => #i36213#
1443 STR_BOOTSTRAP_ERR_LANGUAGE_MISSING,
1444 OUString( RTL_CONSTASCII_USTRINGPARAM(
1445 "Language could not be determined." )) );
1446 aDiagnosticMessage.append( aErrorMsg );
1447 aMessage = MakeStartupErrorMessage(
1448 aDiagnosticMessage.makeStringAndClear() );
1449 FatalError(aMessage);
1450 }
1451 else if (( aBootstrapError == BE_USERINSTALL_NOTENOUGHDISKSPACE ) ||
1452 ( aBootstrapError == BE_USERINSTALL_NOWRITEACCESS ))
1453 {
1454 OUString aUserInstallationURL;
1455 OUString aUserInstallationPath;
1456 OUString aMessage;
1457 OUString aErrorMsg;
1458 OUStringBuffer aDiagnosticMessage( 100 );
1459
1460 utl::Bootstrap::locateUserInstallation( aUserInstallationURL );
1461
1462 if ( aBootstrapError == BE_USERINSTALL_NOTENOUGHDISKSPACE )
1463 aErrorMsg = GetMsgString(
1464 STR_BOOSTRAP_ERR_NOTENOUGHDISKSPACE,
1465 OUString( RTL_CONSTASCII_USTRINGPARAM(
1466 "User installation could not be completed due to insufficient free disk space." )) );
1467 else
1468 aErrorMsg = GetMsgString(
1469 STR_BOOSTRAP_ERR_NOACCESSRIGHTS,
1470 OUString( RTL_CONSTASCII_USTRINGPARAM(
1471 "User installation could not be processed due to missing access rights." )) );
1472
1473 osl::File::getSystemPathFromFileURL( aUserInstallationURL, aUserInstallationPath );
1474
1475 aDiagnosticMessage.append( aErrorMsg );
1476 aDiagnosticMessage.append( aUserInstallationPath );
1477 aMessage = MakeStartupErrorMessage(
1478 aDiagnosticMessage.makeStringAndClear() );
1479 FatalError(aMessage);
1480 }
1481
1482 return;
1483 }
1484
1485
retrieveCrashReporterState()1486 void Desktop::retrieveCrashReporterState()
1487 {
1488 static const ::rtl::OUString CFG_PACKAGE_RECOVERY = ::rtl::OUString::createFromAscii("org.openoffice.Office.Recovery/");
1489 static const ::rtl::OUString CFG_PATH_CRASHREPORTER = ::rtl::OUString::createFromAscii("CrashReporter" );
1490 static const ::rtl::OUString CFG_ENTRY_ENABLED = ::rtl::OUString::createFromAscii("Enabled" );
1491
1492 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory();
1493
1494 sal_Bool bEnabled( sal_True );
1495 if ( xSMGR.is() )
1496 {
1497 css::uno::Any aVal = ::comphelper::ConfigurationHelper::readDirectKey(
1498 xSMGR,
1499 CFG_PACKAGE_RECOVERY,
1500 CFG_PATH_CRASHREPORTER,
1501 CFG_ENTRY_ENABLED,
1502 ::comphelper::ConfigurationHelper::E_READONLY);
1503 aVal >>= bEnabled;
1504 }
1505 _bCrashReporterEnabled = bEnabled;
1506 }
1507
isUIOnSessionShutdownAllowed()1508 sal_Bool Desktop::isUIOnSessionShutdownAllowed()
1509 {
1510 static const ::rtl::OUString CFG_PACKAGE_RECOVERY = ::rtl::OUString::createFromAscii("org.openoffice.Office.Recovery/");
1511 static const ::rtl::OUString CFG_PATH_SESSION = ::rtl::OUString::createFromAscii("SessionShutdown" );
1512 static const ::rtl::OUString CFG_ENTRY_UIENABLED = ::rtl::OUString::createFromAscii("DocumentStoreUIEnabled" );
1513
1514 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory();
1515
1516 sal_Bool bResult = sal_False;
1517 if ( xSMGR.is() )
1518 {
1519 css::uno::Any aVal = ::comphelper::ConfigurationHelper::readDirectKey(
1520 xSMGR,
1521 CFG_PACKAGE_RECOVERY,
1522 CFG_PATH_SESSION,
1523 CFG_ENTRY_UIENABLED,
1524 ::comphelper::ConfigurationHelper::E_READONLY);
1525 aVal >>= bResult;
1526 }
1527
1528 return bResult;
1529 }
1530
1531 //-----------------------------------------------
1532 /** @short check if crash reporter feature is enabled or
1533 disabled.
1534 */
isCrashReporterEnabled()1535 sal_Bool Desktop::isCrashReporterEnabled()
1536 {
1537 return _bCrashReporterEnabled;
1538 }
1539
1540 //-----------------------------------------------
1541 /** @short check if recovery must be started or not.
1542
1543 @param bCrashed [boolean ... out!]
1544 the office crashed last times.
1545 But may be there are no recovery data.
1546 Useful to trigger the error report tool without
1547 showing the recovery UI.
1548
1549 @param bRecoveryDataExists [boolean ... out!]
1550 there exists some recovery data.
1551
1552 @param bSessionDataExists [boolean ... out!]
1553 there exists some session data.
1554 Because the user may be logged out last time from it's
1555 unix session...
1556 */
impl_checkRecoveryState(sal_Bool & bCrashed,sal_Bool & bRecoveryDataExists,sal_Bool & bSessionDataExists)1557 void impl_checkRecoveryState(sal_Bool& bCrashed ,
1558 sal_Bool& bRecoveryDataExists,
1559 sal_Bool& bSessionDataExists )
1560 {
1561 static const ::rtl::OUString SERVICENAME_RECOVERYCORE = ::rtl::OUString::createFromAscii("com.sun.star.frame.AutoRecovery");
1562 static const ::rtl::OUString PROP_CRASHED = ::rtl::OUString::createFromAscii("Crashed" );
1563 static const ::rtl::OUString PROP_EXISTSRECOVERY = ::rtl::OUString::createFromAscii("ExistsRecoveryData" );
1564 static const ::rtl::OUString PROP_EXISTSSESSION = ::rtl::OUString::createFromAscii("ExistsSessionData" );
1565 static const ::rtl::OUString CFG_PACKAGE_RECOVERY = ::rtl::OUString::createFromAscii("org.openoffice.Office.Recovery/");
1566 static const ::rtl::OUString CFG_PATH_RECOVERYINFO = ::rtl::OUString::createFromAscii("RecoveryInfo" );
1567
1568 bCrashed = sal_False;
1569 bRecoveryDataExists = sal_False;
1570 bSessionDataExists = sal_False;
1571
1572 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory();
1573 try
1574 {
1575 css::uno::Reference< css::beans::XPropertySet > xRecovery(
1576 xSMGR->createInstance(SERVICENAME_RECOVERYCORE),
1577 css::uno::UNO_QUERY_THROW);
1578
1579 xRecovery->getPropertyValue(PROP_CRASHED ) >>= bCrashed ;
1580 xRecovery->getPropertyValue(PROP_EXISTSRECOVERY) >>= bRecoveryDataExists;
1581 xRecovery->getPropertyValue(PROP_EXISTSSESSION ) >>= bSessionDataExists ;
1582 }
1583 catch(const css::uno::Exception&) {}
1584 }
1585
1586 //-----------------------------------------------
1587 /* @short start the recovery wizard.
1588
1589 @param bEmergencySave
1590 differs between EMERGENCY_SAVE and RECOVERY
1591 */
impl_callRecoveryUI(sal_Bool bEmergencySave,sal_Bool bCrashed,sal_Bool bExistsRecoveryData)1592 sal_Bool impl_callRecoveryUI(sal_Bool bEmergencySave ,
1593 sal_Bool bCrashed ,
1594 sal_Bool bExistsRecoveryData)
1595 {
1596 static ::rtl::OUString SERVICENAME_RECOVERYUI = ::rtl::OUString::createFromAscii("com.sun.star.comp.svx.RecoveryUI" );
1597 static ::rtl::OUString SERVICENAME_URLPARSER = ::rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" );
1598 static ::rtl::OUString COMMAND_EMERGENCYSAVE = ::rtl::OUString::createFromAscii("vnd.sun.star.autorecovery:/doEmergencySave");
1599 static ::rtl::OUString COMMAND_RECOVERY = ::rtl::OUString::createFromAscii("vnd.sun.star.autorecovery:/doAutoRecovery" );
1600 static ::rtl::OUString COMMAND_CRASHREPORT = ::rtl::OUString::createFromAscii("vnd.sun.star.autorecovery:/doCrashReport" );
1601
1602 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory();
1603
1604 css::uno::Reference< css::frame::XSynchronousDispatch > xRecoveryUI(
1605 xSMGR->createInstance(SERVICENAME_RECOVERYUI),
1606 css::uno::UNO_QUERY_THROW);
1607
1608 css::uno::Reference< css::util::XURLTransformer > xURLParser(
1609 xSMGR->createInstance(SERVICENAME_URLPARSER),
1610 css::uno::UNO_QUERY_THROW);
1611
1612 css::util::URL aURL;
1613 if (bEmergencySave)
1614 aURL.Complete = COMMAND_EMERGENCYSAVE;
1615 else
1616 {
1617 if (bExistsRecoveryData)
1618 aURL.Complete = COMMAND_RECOVERY;
1619 else
1620 if (bCrashed && Desktop::isCrashReporterEnabled() )
1621 aURL.Complete = COMMAND_CRASHREPORT;
1622 }
1623
1624 sal_Bool bRet = sal_False;
1625 if ( aURL.Complete.getLength() > 0 )
1626 {
1627 xURLParser->parseStrict(aURL);
1628
1629 css::uno::Any aRet = xRecoveryUI->dispatchWithReturnValue(aURL, css::uno::Sequence< css::beans::PropertyValue >());
1630 aRet >>= bRet;
1631 }
1632 return bRet;
1633 }
1634
1635 /*
1636 * Save all open documents so they will be reopened
1637 * the next time the application is started
1638 *
1639 * returns sal_True if at least one document could be saved...
1640 *
1641 */
1642
1643 sal_Bool Desktop::_bTasksSaved = sal_False;
1644
SaveTasks()1645 sal_Bool Desktop::SaveTasks()
1646 {
1647 return impl_callRecoveryUI(
1648 sal_True , // sal_True => force emergency save
1649 sal_False, // 2. and 3. param not used if 1. = true!
1650 sal_False);
1651 }
1652
1653 namespace {
1654
restartOnMac(bool passArguments)1655 void restartOnMac(bool passArguments) {
1656 #if defined MACOSX
1657 OfficeIPCThread::DisableOfficeIPCThread();
1658 rtl::OUString execUrl;
1659 OSL_VERIFY(osl_getExecutableFile(&execUrl.pData) == osl_Process_E_None);
1660 rtl::OUString execPath;
1661 rtl::OString execPath8;
1662 if ((osl::FileBase::getSystemPathFromFileURL(execUrl, execPath)
1663 != osl::FileBase::E_None) ||
1664 !execPath.convertToString(
1665 &execPath8, osl_getThreadTextEncoding(),
1666 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
1667 RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
1668 {
1669 std::abort();
1670 }
1671 std::vector< rtl::OString > args;
1672 args.push_back(execPath8);
1673 bool wait = false;
1674 if (passArguments) {
1675 sal_uInt32 n = osl_getCommandArgCount();
1676 for (sal_uInt32 i = 0; i < n; ++i) {
1677 rtl::OUString arg;
1678 OSL_VERIFY(osl_getCommandArg(i, &arg.pData) == osl_Process_E_None);
1679 if (arg.matchAsciiL(RTL_CONSTASCII_STRINGPARAM("-accept="))) {
1680 wait = true;
1681 }
1682 rtl::OString arg8;
1683 if (!arg.convertToString(
1684 &arg8, osl_getThreadTextEncoding(),
1685 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
1686 RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
1687 {
1688 std::abort();
1689 }
1690 args.push_back(arg8);
1691 }
1692 }
1693 std::vector< char const * > argPtrs;
1694 for (std::vector< rtl::OString >::iterator i(args.begin()); i != args.end();
1695 ++i)
1696 {
1697 argPtrs.push_back(i->getStr());
1698 }
1699 argPtrs.push_back(0);
1700 execv(execPath8.getStr(), const_cast< char ** >(&argPtrs[0]));
1701 if (errno == ENOTSUP) { // happens when multithreaded on OS X < 10.6
1702 pid_t pid = fork();
1703 if (pid == 0) {
1704 execv(execPath8.getStr(), const_cast< char ** >(&argPtrs[0]));
1705 } else if (pid > 0) {
1706 // Two simultaneously running soffice processes lead to two dock
1707 // icons, so avoid waiting here unless it must be assumed that the
1708 // process invoking soffice itself wants to wait for soffice to
1709 // finish:
1710 if (!wait) {
1711 return;
1712 }
1713 int stat;
1714 if (waitpid(pid, &stat, 0) == pid && WIFEXITED(stat)) {
1715 _exit(WEXITSTATUS(stat));
1716 }
1717 }
1718 }
1719 std::abort();
1720 #else
1721 (void) passArguments; // avoid warnings
1722 #endif
1723 }
1724
1725 }
1726
Exception(sal_uInt16 nError)1727 sal_uInt16 Desktop::Exception(sal_uInt16 nError)
1728 {
1729 // protect against recursive calls
1730 static sal_Bool bInException = sal_False;
1731
1732 sal_uInt16 nOldMode = Application::GetSystemWindowMode();
1733 Application::SetSystemWindowMode( nOldMode & ~SYSTEMWINDOW_MODE_NOAUTOMODE );
1734 Application::SetDefDialogParent( NULL );
1735
1736 if ( bInException )
1737 {
1738 String aDoubleExceptionString;
1739 Application::Abort( aDoubleExceptionString );
1740 }
1741
1742 bInException = sal_True;
1743 CommandLineArgs* pArgs = GetCommandLineArgs();
1744
1745 // save all modified documents ... if it's allowed doing so.
1746 sal_Bool bRestart = sal_False;
1747 sal_Bool bAllowRecoveryAndSessionManagement = (
1748 ( !pArgs->IsNoRestore() ) && // some use cases of office must work without recovery
1749 ( !pArgs->IsHeadless() ) &&
1750 ( !pArgs->IsServer() ) &&
1751 (( nError & EXC_MAJORTYPE ) != EXC_DISPLAY ) && // recovery can't work without UI ... but UI layer seems to be the reason for this crash
1752 ( Application::IsInExecute() ) // crashes during startup and shutdown should be ignored (they indicates a corrupt installation ...)
1753 );
1754 if ( bAllowRecoveryAndSessionManagement )
1755 bRestart = SaveTasks();
1756
1757 FlushConfiguration();
1758
1759 switch( nError & EXC_MAJORTYPE )
1760 {
1761 case EXC_RSCNOTLOADED:
1762 {
1763 String aResExceptionString;
1764 Application::Abort( aResExceptionString );
1765 break;
1766 }
1767
1768 case EXC_SYSOBJNOTCREATED:
1769 {
1770 String aSysResExceptionString;
1771 Application::Abort( aSysResExceptionString );
1772 break;
1773 }
1774
1775 default:
1776 {
1777 if (m_pLockfile != NULL) {
1778 m_pLockfile->clean();
1779 }
1780 if( bRestart )
1781 {
1782 OfficeIPCThread::DisableOfficeIPCThread();
1783 if( pSignalHandler )
1784 DELETEZ( pSignalHandler );
1785 restartOnMac(false);
1786 _exit( ExitHelper::E_CRASH_WITH_RESTART );
1787 }
1788 else
1789 {
1790 Application::Abort( String() );
1791 }
1792
1793 break;
1794 }
1795 }
1796
1797 OSL_ASSERT(false); // unreachable
1798 return 0;
1799 }
1800
AppEvent(const ApplicationEvent & rAppEvent)1801 void Desktop::AppEvent( const ApplicationEvent& rAppEvent )
1802 {
1803 HandleAppEvent( rAppEvent );
1804 }
1805
1806 struct ExecuteGlobals
1807 {
1808 Reference < css::document::XEventListener > xGlobalBroadcaster;
1809 sal_Bool bRestartRequested;
1810 sal_Bool bUseSystemFileDialog;
1811 std::auto_ptr<SvtLanguageOptions> pLanguageOptions;
1812 std::auto_ptr<SvtPathOptions> pPathOptions;
1813
ExecuteGlobalsdesktop::ExecuteGlobals1814 ExecuteGlobals()
1815 : bRestartRequested( sal_False )
1816 , bUseSystemFileDialog( sal_True )
1817 {}
1818 };
1819
1820 static ExecuteGlobals* pExecGlobals = NULL;
1821
Main()1822 void Desktop::Main()
1823 {
1824 pExecGlobals = new ExecuteGlobals();
1825
1826 RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::Main" );
1827
1828 // Remember current context object
1829 com::sun::star::uno::ContextLayer layer(
1830 com::sun::star::uno::getCurrentContext() );
1831
1832 BootstrapError eError = GetBootstrapError();
1833 if ( eError != BE_OK )
1834 {
1835 HandleBootstrapErrors( eError );
1836 return;
1837 }
1838
1839 BootstrapStatus eStatus = GetBootstrapStatus();
1840 if (eStatus == BS_TERMINATE) {
1841 return;
1842 }
1843
1844 // Detect desktop environment - need to do this as early as possible
1845 com::sun::star::uno::setCurrentContext(
1846 new DesktopContext( com::sun::star::uno::getCurrentContext() ) );
1847
1848 CommandLineArgs* pCmdLineArgs = GetCommandLineArgs();
1849
1850 // setup configuration error handling
1851 ConfigurationErrorHandler aConfigErrHandler;
1852 if (!ShouldSuppressUI(pCmdLineArgs))
1853 aConfigErrHandler.activate();
1854
1855 ResMgr::SetReadStringHook( ReplaceStringHookProc );
1856
1857 // Startup screen
1858 RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109) Desktop::Main { OpenSplashScreen" );
1859 OpenSplashScreen();
1860 RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109) Desktop::Main } OpenSplashScreen" );
1861
1862 {
1863 UserInstall::UserInstallError instErr_fin = UserInstall::finalize();
1864 if ( instErr_fin != UserInstall::E_None)
1865 {
1866 OSL_ENSURE(sal_False, "userinstall failed");
1867 if ( instErr_fin == UserInstall::E_NoDiskSpace )
1868 HandleBootstrapErrors( BE_USERINSTALL_NOTENOUGHDISKSPACE );
1869 else if ( instErr_fin == UserInstall::E_NoWriteAccess )
1870 HandleBootstrapErrors( BE_USERINSTALL_NOWRITEACCESS );
1871 else
1872 HandleBootstrapErrors( BE_USERINSTALL_FAILED );
1873 return;
1874 }
1875 // refresh path information
1876 utl::Bootstrap::reloadData();
1877 SetSplashScreenProgress(25);
1878 }
1879
1880 Reference< XMultiServiceFactory > xSMgr =
1881 ::comphelper::getProcessServiceFactory();
1882
1883 Reference< ::com::sun::star::task::XRestartManager > xRestartManager;
1884 int nAcquireCount( 0 );
1885 try
1886 {
1887 RegisterServices( xSMgr );
1888
1889 //SetSplashScreenProgress(15);
1890
1891 #ifndef UNX
1892 if ( pCmdLineArgs->IsHelp() ) {
1893 displayCmdlineHelp();
1894 return;
1895 }
1896 #endif
1897
1898 // check user installation directory for lockfile so we can be sure
1899 // there is no other instance using our data files from a remote host
1900 RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109) Desktop::Main -> Lockfile" );
1901 m_pLockfile = new Lockfile;
1902 if ( !pCmdLineArgs->IsHeadless() && !pCmdLineArgs->IsInvisible() &&
1903 !pCmdLineArgs->IsNoLockcheck() && !m_pLockfile->check( Lockfile_execWarning )) {
1904 // Lockfile exists, and user clicked 'no'
1905 return;
1906 }
1907 RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109) Desktop::Main <- Lockfile" );
1908
1909 // check if accessibility is enabled but not working and allow to quit
1910 RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ GetEnableATToolSupport" );
1911 if( Application::GetSettings().GetMiscSettings().GetEnableATToolSupport() )
1912 {
1913 sal_Bool bQuitApp (sal_False);
1914
1915 if( !InitAccessBridge( true, bQuitApp ) )
1916 if( bQuitApp )
1917 return;
1918 }
1919 RTL_LOGFILE_CONTEXT_TRACE( aLog, "} GetEnableATToolSupport" );
1920
1921 // terminate if requested...
1922 if( pCmdLineArgs->IsTerminateAfterInit() ) return;
1923
1924 // Read the common configuration items for optimization purpose
1925 if ( !InitializeConfiguration() ) return;
1926
1927 //SetSplashScreenProgress(20);
1928
1929 // set static variable to enabled/disable crash reporter
1930 retrieveCrashReporterState();
1931 const bool bCrashReporterEnabled = isCrashReporterEnabled();
1932 osl_setErrorReporting( !bCrashReporterEnabled );
1933
1934 // create title string
1935 sal_Bool bCheckOk = sal_False;
1936 ::com::sun::star::lang::Locale aLocale;
1937 const char* pMgrName = "ofa";
1938 ResMgr* pLabelResMgr = ResMgr::SearchCreateResMgr( pMgrName, aLocale );
1939 String aTitle = pLabelResMgr ? String( ResId( RID_APPTITLE, *pLabelResMgr ) ) : String();
1940 delete pLabelResMgr;
1941
1942 // Check for StarOffice/Suite specific extensions runs also with OpenOffice installation sets
1943 OUString aTitleString( aTitle );
1944 bCheckOk = CheckInstallation( aTitleString );
1945 if ( !bCheckOk )
1946 return;
1947 else
1948 aTitle = aTitleString;
1949
1950 #ifdef DBG_UTIL
1951 //include version ID in non product builds
1952 ::rtl::OUString aDefault;
1953 aTitle += DEFINE_CONST_UNICODE(" [");
1954 String aVerId( utl::Bootstrap::getBuildIdData( aDefault ));
1955 aTitle += aVerId;
1956 aTitle += ']';
1957 #endif
1958
1959 SetDisplayName( aTitle );
1960 RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ create SvtPathOptions and SvtLanguageOptions" );
1961 pExecGlobals->pPathOptions.reset( new SvtPathOptions);
1962 SetSplashScreenProgress(40);
1963 RTL_LOGFILE_CONTEXT_TRACE( aLog, "} create SvtPathOptions and SvtLanguageOptions" );
1964
1965 // Check special env variable #111015#
1966 std::vector< String > aUnrestrictedFolders;
1967 svt::getUnrestrictedFolders( aUnrestrictedFolders );
1968
1969 if ( aUnrestrictedFolders.size() > 0 )
1970 {
1971 // Set different working directory. The first entry is
1972 // the new work path.
1973 String aWorkPath = aUnrestrictedFolders[0];
1974 SvtPathOptions().SetWorkPath( aWorkPath );
1975 }
1976
1977 // create service for loading SFX (still needed in startup)
1978 pExecGlobals->xGlobalBroadcaster = Reference < css::document::XEventListener >
1979 ( xSMgr->createInstance(
1980 DEFINE_CONST_UNICODE( "com.sun.star.frame.GlobalEventBroadcaster" ) ), UNO_QUERY );
1981
1982 /* ensure existence of a default window that messages can be dispatched to
1983 This is for the benefit of testtool which uses PostUserEvent extensively
1984 and else can deadlock while creating this window from another tread while
1985 the main thread is not yet in the event loop.
1986 */
1987 Application::GetDefaultDevice();
1988
1989 // initialize test-tool library (if available)
1990 RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ tools::InitTestToolLib" );
1991 tools::InitTestToolLib();
1992 RTL_LOGFILE_CONTEXT_TRACE( aLog, "} tools::InitTestToolLib" );
1993
1994 // Check if bundled or shared extensions were added /removed
1995 // and process those extensions (has to be done before checking
1996 // the extension dependencies!
1997 SynchronizeExtensionRepositories();
1998 bool bAbort = CheckExtensionDependencies();
1999 if ( bAbort )
2000 return;
2001
2002 {
2003 ::comphelper::ComponentContext aContext( xSMgr );
2004 xRestartManager.set( aContext.getSingleton( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.OfficeRestartManager" ) ) ), UNO_QUERY );
2005 }
2006
2007 // check whether the shutdown is caused by restart
2008 pExecGlobals->bRestartRequested = ( xRestartManager.is() && xRestartManager->isRestartRequested( sal_True ) );
2009
2010 // First Start Wizard allowed ?
2011 if ( ! pCmdLineArgs->IsNoFirstStartWizard() && !pExecGlobals->bRestartRequested )
2012 {
2013 RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ FirstStartWizard" );
2014
2015 if (IsFirstStartWizardNeeded())
2016 {
2017 Reference< XJob > xFirstStartJob( xSMgr->createInstance(
2018 DEFINE_CONST_UNICODE( "com.sun.star.comp.desktop.FirstStart" ) ), UNO_QUERY );
2019 if (xFirstStartJob.is())
2020 {
2021 sal_Bool bDone = sal_False;
2022 Sequence< NamedValue > lArgs(2);
2023 lArgs[0].Name = ::rtl::OUString::createFromAscii("LicenseNeedsAcceptance");
2024 lArgs[0].Value <<= LicenseNeedsAcceptance();
2025 lArgs[1].Name = ::rtl::OUString::createFromAscii("LicensePath");
2026 lArgs[1].Value <<= GetLicensePath();
2027
2028 xFirstStartJob->execute(lArgs) >>= bDone;
2029 if ( !bDone )
2030 {
2031 doShutdown();
2032 return;
2033 }
2034 // mark first start as done
2035 FinishFirstStart();
2036 }
2037 }
2038
2039 RTL_LOGFILE_CONTEXT_TRACE( aLog, "} FirstStartWizard" );
2040 }
2041
2042 // process non-pre-registered extensions
2043 installBundledExtensionBlobs();
2044
2045 // keep a language options instance...
2046 pExecGlobals->pLanguageOptions.reset( new SvtLanguageOptions(sal_True));
2047
2048 if (pExecGlobals->xGlobalBroadcaster.is())
2049 {
2050 css::document::EventObject aEvent;
2051 aEvent.EventName = ::rtl::OUString::createFromAscii("OnStartApp");
2052 pExecGlobals->xGlobalBroadcaster->notifyEvent(aEvent);
2053 }
2054
2055 SetSplashScreenProgress(50);
2056
2057 // Backing Component
2058 sal_Bool bCrashed = sal_False;
2059 sal_Bool bExistsRecoveryData = sal_False;
2060 sal_Bool bExistsSessionData = sal_False;
2061
2062 RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ impl_checkRecoveryState" );
2063 impl_checkRecoveryState(bCrashed, bExistsRecoveryData, bExistsSessionData);
2064 RTL_LOGFILE_CONTEXT_TRACE( aLog, "} impl_checkRecoveryState" );
2065
2066 {
2067 ::comphelper::ComponentContext aContext( xSMgr );
2068 xRestartManager.set( aContext.getSingleton( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.OfficeRestartManager" ) ) ), UNO_QUERY );
2069 }
2070
2071 // check whether the shutdown is caused by restart
2072 pExecGlobals->bRestartRequested = ( xRestartManager.is() && xRestartManager->isRestartRequested( sal_True ) );
2073
2074 if ( pCmdLineArgs->IsHeadless() )
2075 {
2076 // Ensure that we use not the system file dialogs as
2077 // headless mode relies on Application::EnableHeadlessMode()
2078 // which does only work for VCL dialogs!!
2079 SvtMiscOptions aMiscOptions;
2080 pExecGlobals->bUseSystemFileDialog = aMiscOptions.UseSystemFileDialog();
2081 aMiscOptions.SetUseSystemFileDialog( sal_False );
2082 }
2083
2084 if ( !pExecGlobals->bRestartRequested )
2085 {
2086 if ((!pCmdLineArgs->IsNoDefault() &&
2087 !pCmdLineArgs->WantsToLoadDocument() &&
2088 !pCmdLineArgs->IsInvisible() &&
2089 !pCmdLineArgs->IsHeadless() &&
2090 !pCmdLineArgs->IsQuickstart()) &&
2091 (SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::E_SSTARTMODULE)) &&
2092 (!bExistsRecoveryData ) &&
2093 (!bExistsSessionData ) &&
2094 (!Application::AnyInput( INPUT_APPEVENT ) ))
2095 {
2096 RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ create BackingComponent" );
2097 Reference< XFrame > xDesktopFrame( xSMgr->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ))), UNO_QUERY );
2098 if (xDesktopFrame.is())
2099 {
2100 Reference< XFrame > xBackingFrame;
2101 Reference< ::com::sun::star::awt::XWindow > xContainerWindow;
2102
2103 xBackingFrame = xDesktopFrame->findFrame(OUString( RTL_CONSTASCII_USTRINGPARAM( "_blank" )), 0);
2104 if (xBackingFrame.is())
2105 xContainerWindow = xBackingFrame->getContainerWindow();
2106 if (xContainerWindow.is())
2107 {
2108 // set the WB_EXT_DOCUMENT style. Normally, this is done by the TaskCreator service when a "_blank"
2109 // frame/window is created. Since we do not use the TaskCreator here, we need to mimic its behavior,
2110 // otherwise documents loaded into this frame will later on miss functionality depending on the style.
2111 Window* pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
2112 OSL_ENSURE( pContainerWindow, "Desktop::Main: no implementation access to the frame's container window!" );
2113 pContainerWindow->SetExtendedStyle( pContainerWindow->GetExtendedStyle() | WB_EXT_DOCUMENT );
2114
2115 SetSplashScreenProgress(75);
2116 Sequence< Any > lArgs(1);
2117 lArgs[0] <<= xContainerWindow;
2118
2119 Reference< XController > xBackingComp(
2120 xSMgr->createInstanceWithArguments(OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.StartModule") ), lArgs), UNO_QUERY);
2121 if (xBackingComp.is())
2122 {
2123 Reference< ::com::sun::star::awt::XWindow > xBackingWin(xBackingComp, UNO_QUERY);
2124 // Attention: You MUST(!) call setComponent() before you call attachFrame().
2125 // Because the backing component set the property "IsBackingMode" of the frame
2126 // to true inside attachFrame(). But setComponent() reset this state everytimes ...
2127 xBackingFrame->setComponent(xBackingWin, xBackingComp);
2128 SetSplashScreenProgress(100);
2129 xBackingComp->attachFrame(xBackingFrame);
2130 CloseSplashScreen();
2131 xContainerWindow->setVisible(sal_True);
2132 }
2133 }
2134 }
2135 RTL_LOGFILE_CONTEXT_TRACE( aLog, "} create BackingComponent" );
2136 }
2137 }
2138 }
2139 catch ( com::sun::star::lang::WrappedTargetException& wte )
2140 {
2141 com::sun::star::uno::Exception te;
2142 wte.TargetException >>= te;
2143 FatalError( MakeStartupConfigAccessErrorMessage(wte.Message + te.Message) );
2144 return;
2145 }
2146 catch ( com::sun::star::uno::Exception& e )
2147 {
2148 FatalError( MakeStartupErrorMessage(e.Message) );
2149 return;
2150 }
2151
2152 SvtFontSubstConfig().Apply();
2153
2154 SvtTabAppearanceCfg aAppearanceCfg;
2155 aAppearanceCfg.SetInitialized();
2156 aAppearanceCfg.SetApplicationDefaults( this );
2157 SvtAccessibilityOptions aOptions;
2158 aOptions.SetVCLSettings();
2159
2160 if ( !pExecGlobals->bRestartRequested )
2161 {
2162 Application::SetFilterHdl( LINK( this, Desktop, ImplInitFilterHdl ) );
2163 sal_Bool bTerminateRequested = sal_False;
2164
2165 // Preload function depends on an initialized sfx application!
2166 SetSplashScreenProgress(75);
2167
2168 // use system window dialogs
2169 Application::SetSystemWindowMode( SYSTEMWINDOW_MODE_DIALOG );
2170
2171 // SetSplashScreenProgress(80);
2172
2173 if ( !bTerminateRequested && !pCmdLineArgs->IsInvisible() &&
2174 !pCmdLineArgs->IsNoQuickstart() )
2175 InitializeQuickstartMode( xSMgr );
2176
2177 RTL_LOGFILE_CONTEXT( aLog2, "desktop (cd100003) createInstance com.sun.star.frame.Desktop" );
2178 try
2179 {
2180 Reference< XDesktop > xDesktop( xSMgr->createInstance(
2181 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ))), UNO_QUERY );
2182 if ( xDesktop.is() )
2183 xDesktop->addTerminateListener( new OfficeIPCThreadController );
2184 SetSplashScreenProgress(100);
2185 }
2186 catch ( com::sun::star::uno::Exception& e )
2187 {
2188 FatalError( MakeStartupErrorMessage(e.Message) );
2189 return;
2190 }
2191
2192 // Post user event to startup first application component window
2193 // We have to send this OpenClients message short before execute() to
2194 // minimize the risk that this message overtakes type detection construction!!
2195 Application::PostUserEvent( LINK( this, Desktop, OpenClients_Impl ) );
2196
2197 // Post event to enable acceptors
2198 Application::PostUserEvent( LINK( this, Desktop, EnableAcceptors_Impl) );
2199
2200 // The configuration error handler currently is only for startup
2201 aConfigErrHandler.deactivate();
2202
2203 // Acquire solar mutex just before we enter our message loop
2204 if ( nAcquireCount )
2205 Application::AcquireSolarMutex( nAcquireCount );
2206
2207 // call Application::Execute to process messages in vcl message loop
2208 RTL_LOGFILE_PRODUCT_TRACE( "PERFORMANCE - enter Application::Execute()" );
2209
2210 try
2211 {
2212 // The JavaContext contains an interaction handler which is used when
2213 // the creation of a Java Virtual Machine fails
2214 com::sun::star::uno::ContextLayer layer2(
2215 new svt::JavaContext( com::sun::star::uno::getCurrentContext() ) );
2216
2217 // check whether the shutdown is caused by restart just before entering the Execute
2218 pExecGlobals->bRestartRequested = pExecGlobals->bRestartRequested || ( xRestartManager.is() && xRestartManager->isRestartRequested( sal_True ) );
2219
2220 if ( !pExecGlobals->bRestartRequested )
2221 {
2222 // if this run of the office is triggered by restart, some additional actions should be done
2223 DoRestartActionsIfNecessary( !pCmdLineArgs->IsInvisible() && !pCmdLineArgs->IsNoQuickstart() );
2224
2225 Execute();
2226 }
2227 }
2228 catch(const com::sun::star::document::CorruptedFilterConfigurationException& exFilterCfg)
2229 {
2230 OfficeIPCThread::SetDowning();
2231 FatalError( MakeStartupErrorMessage(exFilterCfg.Message) );
2232 }
2233 catch(const com::sun::star::configuration::CorruptedConfigurationException& exAnyCfg)
2234 {
2235 OfficeIPCThread::SetDowning();
2236 FatalError( MakeStartupErrorMessage(exAnyCfg.Message) );
2237 }
2238 catch( const ::com::sun::star::uno::Exception& exUNO)
2239 {
2240 OfficeIPCThread::SetDowning();
2241 FatalError( exUNO.Message);
2242 }
2243 catch( const std::exception& exSTD)
2244 {
2245 OfficeIPCThread::SetDowning();
2246 FatalError( OUString::createFromAscii( exSTD.what()));
2247 }
2248 catch( ...)
2249 {
2250 OfficeIPCThread::SetDowning();
2251 FatalError( OUString(RTL_CONSTASCII_USTRINGPARAM( "Caught Unknown Exception: Aborting!")));
2252 }
2253 }
2254 // CAUTION: you do not necessarily get here e.g. on the Mac.
2255 // please put all deinitialization code into doShutdown
2256 doShutdown();
2257 }
2258
doShutdown()2259 void Desktop::doShutdown()
2260 {
2261 if( ! pExecGlobals )
2262 return;
2263
2264 if ( pExecGlobals->bRestartRequested )
2265 SetRestartState();
2266
2267 if (pExecGlobals->xGlobalBroadcaster.is())
2268 {
2269 css::document::EventObject aEvent;
2270 aEvent.EventName = ::rtl::OUString::createFromAscii("OnCloseApp");
2271 pExecGlobals->xGlobalBroadcaster->notifyEvent(aEvent);
2272 }
2273
2274 delete pResMgr, pResMgr = NULL;
2275 // Restore old value
2276 CommandLineArgs* pCmdLineArgs = GetCommandLineArgs();
2277 if ( pCmdLineArgs->IsHeadless() )
2278 SvtMiscOptions().SetUseSystemFileDialog( pExecGlobals->bUseSystemFileDialog );
2279
2280 // remove temp directory
2281 RemoveTemporaryDirectory();
2282 FlushConfiguration();
2283 // The acceptors in the AcceptorMap must be released (in DeregisterServices)
2284 // with the solar mutex unlocked, to avoid deadlock:
2285 sal_uLong nAcquireCount = Application::ReleaseSolarMutex();
2286 DeregisterServices();
2287 Application::AcquireSolarMutex(nAcquireCount);
2288 tools::DeInitTestToolLib();
2289 // be sure that path/language options gets destroyed before
2290 // UCB is deinitialized
2291 RTL_LOGFILE_CONTEXT_TRACE( aLog, "-> dispose path/language options" );
2292 pExecGlobals->pLanguageOptions.reset( 0 );
2293 pExecGlobals->pPathOptions.reset( 0 );
2294 RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- dispose path/language options" );
2295
2296 RTL_LOGFILE_CONTEXT_TRACE( aLog, "-> deinit ucb" );
2297 ::ucbhelper::ContentBroker::deinitialize();
2298 RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- deinit ucb" );
2299
2300 sal_Bool bRR = pExecGlobals->bRestartRequested;
2301 delete pExecGlobals, pExecGlobals = NULL;
2302
2303 RTL_LOGFILE_CONTEXT_TRACE( aLog, "FINISHED WITH Destop::Main" );
2304 if ( bRR )
2305 {
2306 restartOnMac(true);
2307 // wouldn't the solution be more clean if SalMain returns the exit code to the system?
2308 _exit( ExitHelper::E_NORMAL_RESTART );
2309 }
2310 }
2311
IMPL_LINK(Desktop,ImplInitFilterHdl,ConvertData *,pData)2312 IMPL_LINK( Desktop, ImplInitFilterHdl, ConvertData*, pData )
2313 {
2314 return GraphicFilter::GetGraphicFilter()->GetFilterCallback().Call( pData );
2315 }
2316
InitializeConfiguration()2317 sal_Bool Desktop::InitializeConfiguration()
2318 {
2319 sal_Bool bOk = sal_False;
2320
2321 try
2322 {
2323 bOk = InitConfiguration();
2324 }
2325 catch( ::com::sun::star::lang::ServiceNotRegisteredException& )
2326 {
2327 this->HandleBootstrapErrors( Desktop::BE_UNO_SERVICE_CONFIG_MISSING );
2328 }
2329 catch( ::com::sun::star::configuration::MissingBootstrapFileException& e )
2330 {
2331 OUString aMsg( CreateErrorMsgString( utl::Bootstrap::MISSING_BOOTSTRAP_FILE,
2332 e.BootstrapFileURL ));
2333 HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_USER_INSTALL, aMsg );
2334 }
2335 catch( ::com::sun::star::configuration::InvalidBootstrapFileException& e )
2336 {
2337 OUString aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY,
2338 e.BootstrapFileURL ));
2339 HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL, aMsg );
2340 }
2341 catch( ::com::sun::star::configuration::InstallationIncompleteException& )
2342 {
2343 OUString aVersionFileURL;
2344 OUString aMsg;
2345 utl::Bootstrap::PathStatus aPathStatus = utl::Bootstrap::locateVersionFile( aVersionFileURL );
2346 if ( aPathStatus == utl::Bootstrap::PATH_EXISTS )
2347 aMsg = CreateErrorMsgString( utl::Bootstrap::MISSING_VERSION_FILE_ENTRY, aVersionFileURL );
2348 else
2349 aMsg = CreateErrorMsgString( utl::Bootstrap::MISSING_VERSION_FILE, aVersionFileURL );
2350
2351 HandleBootstrapPathErrors( ::utl::Bootstrap::MISSING_USER_INSTALL, aMsg );
2352 }
2353 catch ( com::sun::star::configuration::backend::BackendAccessException& exception)
2354 {
2355 // [cm122549] It is assumed in this case that the message
2356 // coming from InitConfiguration (in fact CreateApplicationConf...)
2357 // is suitable for display directly.
2358 FatalError( MakeStartupErrorMessage( exception.Message ) );
2359 }
2360 catch ( com::sun::star::configuration::backend::BackendSetupException& exception)
2361 {
2362 // [cm122549] It is assumed in this case that the message
2363 // coming from InitConfiguration (in fact CreateApplicationConf...)
2364 // is suitable for display directly.
2365 FatalError( MakeStartupErrorMessage( exception.Message ) );
2366 }
2367 catch ( ::com::sun::star::configuration::CannotLoadConfigurationException& )
2368 {
2369 OUString aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_DATA,
2370 OUString() ));
2371 HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL, aMsg );
2372 }
2373 catch( ::com::sun::star::uno::Exception& )
2374 {
2375 OUString aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_DATA,
2376 OUString() ));
2377 HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL, aMsg );
2378 }
2379
2380 return bOk;
2381 }
2382
FlushConfiguration()2383 void Desktop::FlushConfiguration()
2384 {
2385 Reference < XFlushable > xCFGFlush( ::utl::ConfigManager::GetConfigManager()->GetConfigurationProvider(), UNO_QUERY );
2386 if (xCFGFlush.is())
2387 {
2388 xCFGFlush->flush();
2389 }
2390 else
2391 {
2392 // because there is no method to flush the configuration data, we must dispose the ConfigManager
2393 Reference < XComponent > xCFGDispose( ::utl::ConfigManager::GetConfigManager()->GetConfigurationProvider(), UNO_QUERY );
2394 if (xCFGDispose.is())
2395 xCFGDispose->dispose();
2396 }
2397 }
2398
InitializeQuickstartMode(Reference<XMultiServiceFactory> & rSMgr)2399 sal_Bool Desktop::InitializeQuickstartMode( Reference< XMultiServiceFactory >& rSMgr )
2400 {
2401 try
2402 {
2403 // the shutdown icon sits in the systray and allows the user to keep
2404 // the office instance running for quicker restart
2405 // this will only be activated if -quickstart was specified on cmdline
2406 RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) createInstance com.sun.star.office.Quickstart" );
2407
2408 sal_Bool bQuickstart = GetCommandLineArgs()->IsQuickstart();
2409 if ( !bQuickstart )
2410 {
2411 SfxItemSet aOptSet( SFX_APP()->GetPool(), SID_ATTR_QUICKLAUNCHER, SID_ATTR_QUICKLAUNCHER );
2412 SFX_APP()->GetOptions(aOptSet);
2413 const SfxPoolItem* pItem;
2414 if ( SFX_ITEM_SET == aOptSet.GetItemState( SID_ATTR_QUICKLAUNCHER, sal_False, &pItem ) )
2415 bQuickstart = ((const SfxBoolItem*)pItem)->GetValue();
2416 }
2417
2418 Sequence< Any > aSeq( 1 );
2419 aSeq[0] <<= bQuickstart;
2420
2421 // Try to instantiate quickstart service. This service is not mandatory, so
2422 // do nothing if service is not available
2423
2424 // #i105753# the following if was invented for performance
2425 // unfortunately this broke the QUARTZ behavior which is to always run
2426 // in quickstart mode since Mac applications do not usually quit
2427 // when the last document closes
2428 #ifndef QUARTZ
2429 if ( bQuickstart )
2430 #endif
2431 {
2432 Reference < XComponent > xQuickstart( rSMgr->createInstanceWithArguments(
2433 DEFINE_CONST_UNICODE( "com.sun.star.office.Quickstart" ), aSeq ),
2434 UNO_QUERY );
2435 }
2436 return sal_True;
2437 }
2438 catch( ::com::sun::star::uno::Exception& )
2439 {
2440 return sal_False;
2441 }
2442 }
2443
SystemSettingsChanging(AllSettings & rSettings,Window *)2444 void Desktop::SystemSettingsChanging( AllSettings& rSettings, Window* )
2445 {
2446 if ( !SvtTabAppearanceCfg::IsInitialized () )
2447 return;
2448
2449 # define DRAGFULL_OPTION_ALL \
2450 ( DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE \
2451 | DRAGFULL_OPTION_OBJECTMOVE | DRAGFULL_OPTION_OBJECTSIZE \
2452 | DRAGFULL_OPTION_DOCKING | DRAGFULL_OPTION_SPLIT \
2453 | DRAGFULL_OPTION_SCROLL )
2454 # define DRAGFULL_OPTION_NONE ((sal_uInt32)~DRAGFULL_OPTION_ALL)
2455
2456 StyleSettings hStyleSettings = rSettings.GetStyleSettings();
2457 MouseSettings hMouseSettings = rSettings.GetMouseSettings();
2458
2459 sal_uInt32 nDragFullOptions = hStyleSettings.GetDragFullOptions();
2460
2461 SvtTabAppearanceCfg aAppearanceCfg;
2462 sal_uInt16 nGet = aAppearanceCfg.GetDragMode();
2463 switch ( nGet )
2464 {
2465 case DragFullWindow:
2466 nDragFullOptions |= DRAGFULL_OPTION_ALL;
2467 break;
2468 case DragFrame:
2469 nDragFullOptions &= DRAGFULL_OPTION_NONE;
2470 break;
2471 case DragSystemDep:
2472 default:
2473 break;
2474 }
2475
2476 sal_uInt32 nFollow = hMouseSettings.GetFollow();
2477 hMouseSettings.SetFollow( aAppearanceCfg.IsMenuMouseFollow() ? (nFollow|MOUSE_FOLLOW_MENU) : (nFollow&~MOUSE_FOLLOW_MENU));
2478 rSettings.SetMouseSettings(hMouseSettings);
2479
2480 sal_Bool bUseImagesInMenus = hStyleSettings.GetUseImagesInMenus();
2481
2482 SvtMenuOptions aMenuOpt;
2483 nGet = aMenuOpt.GetMenuIconsState();
2484 switch ( nGet )
2485 {
2486 case 0:
2487 bUseImagesInMenus = sal_False;
2488 break;
2489 case 1:
2490 bUseImagesInMenus = sal_True;
2491 break;
2492 case 2:
2493 default:
2494 break;
2495 }
2496 hStyleSettings.SetUseImagesInMenus(bUseImagesInMenus);
2497
2498 hStyleSettings.SetDragFullOptions( nDragFullOptions );
2499 rSettings.SetStyleSettings ( hStyleSettings );
2500 }
2501
2502 // ========================================================================
IMPL_LINK(Desktop,AsyncInitFirstRun,void *,EMPTYARG)2503 IMPL_LINK( Desktop, AsyncInitFirstRun, void*, EMPTYARG )
2504 {
2505 DoFirstRunInitializations();
2506 return 0L;
2507 }
2508
2509 // ========================================================================
2510
2511 class ExitTimer : public Timer
2512 {
2513 public:
ExitTimer()2514 ExitTimer()
2515 {
2516 SetTimeout(500);
2517 Start();
2518 }
Timeout()2519 virtual void Timeout()
2520 {
2521 exit(42);
2522 }
2523 };
2524
IMPL_LINK(Desktop,OpenClients_Impl,void *,EMPTYARG)2525 IMPL_LINK( Desktop, OpenClients_Impl, void*, EMPTYARG )
2526 {
2527 RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "PERFORMANCE - DesktopOpenClients_Impl()" );
2528
2529 // #114963#
2530 // Enable IPC thread before OpenClients
2531 //
2532 // This is because it is possible for another client to connect during the OpenClients() call.
2533 // This can happen on Windows when document is printed (not opened) and another client wants to print (when printing multiple documents).
2534 // If the IPC thread is enabled after OpenClients, then the client will not be processed because the application will exit after printing. i.e OfficeIPCThread::AreRequestsPending() will always return false
2535 //
2536 // ALSO:
2537 //
2538 // Multiple clients may request simultaneous connections.
2539 // When this server closes down it attempts to recreate the pipe (in DisableOfficeIPCThread()).
2540 // It's possible that the client has a pending connection request.
2541 // When the IPC thread is not running, this connection locks (because maPipe.accept()) is never called
2542 OfficeIPCThread::SetReady();
2543 OpenClients();
2544
2545 // CloseStartupScreen();
2546 CloseSplashScreen();
2547 CheckFirstRun( );
2548 EnableOleAutomation();
2549
2550 if (getenv ("OOO_EXIT_POST_STARTUP"))
2551 new ExitTimer();
2552 return 0;
2553 }
2554
2555 // enable acceptors
IMPL_LINK(Desktop,EnableAcceptors_Impl,void *,EMPTYARG)2556 IMPL_LINK( Desktop, EnableAcceptors_Impl, void*, EMPTYARG )
2557 {
2558 enableAcceptors();
2559 return 0;
2560 }
2561
2562
2563 // Registers a COM class factory of the service manager with the Windows operating system.
EnableOleAutomation()2564 void Desktop::EnableOleAutomation()
2565 {
2566 RTL_LOGFILE_CONTEXT( aLog, "desktop (jl97489) ::Desktop::EnableOleAutomation" );
2567 #ifdef WNT
2568 Reference< XMultiServiceFactory > xSMgr= comphelper::getProcessServiceFactory();
2569 xSMgr->createInstance(DEFINE_CONST_UNICODE("com.sun.star.bridge.OleApplicationRegistration"));
2570 xSMgr->createInstance(DEFINE_CONST_UNICODE("com.sun.star.comp.ole.EmbedServer"));
2571 #endif
2572 }
2573
CheckOEM()2574 sal_Bool Desktop::CheckOEM()
2575 {
2576 Reference<XMultiServiceFactory> rFactory = ::comphelper::getProcessServiceFactory();
2577 Reference<XJob> rOemJob(rFactory->createInstance(
2578 OUString::createFromAscii("com.sun.star.office.OEMPreloadJob")),
2579 UNO_QUERY );
2580 Sequence<NamedValue> args;
2581 sal_Bool bResult = sal_False;
2582 if (rOemJob.is()) {
2583 Any aResult = rOemJob->execute(args);
2584 aResult >>= bResult;
2585 return bResult;
2586 } else {
2587 return sal_True;
2588 }
2589 }
2590
PreloadModuleData(CommandLineArgs * pArgs)2591 void Desktop::PreloadModuleData( CommandLineArgs* pArgs )
2592 {
2593 Reference< XMultiServiceFactory > rFactory = ::comphelper::getProcessServiceFactory();
2594
2595 Sequence < com::sun::star::beans::PropertyValue > args(1);
2596 args[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Hidden"));
2597 args[0].Value <<= sal_True;
2598 Reference < XComponentLoader > xLoader( ::comphelper::getProcessServiceFactory()->createInstance(
2599 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), UNO_QUERY );
2600
2601 if ( !xLoader.is() )
2602 return;
2603
2604 if ( pArgs->IsWriter() )
2605 {
2606 try
2607 {
2608 Reference < ::com::sun::star::util::XCloseable > xDoc( xLoader->loadComponentFromURL( DEFINE_CONST_UNICODE("private:factory/swriter"),
2609 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, args ), UNO_QUERY_THROW );
2610 xDoc->close( sal_False );
2611 }
2612 catch ( com::sun::star::uno::Exception& )
2613 {
2614 }
2615 }
2616 if ( pArgs->IsCalc() )
2617 {
2618 try
2619 {
2620 Reference < ::com::sun::star::util::XCloseable > xDoc( xLoader->loadComponentFromURL( DEFINE_CONST_UNICODE("private:factory/scalc"),
2621 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, args ), UNO_QUERY_THROW );
2622 xDoc->close( sal_False );
2623 }
2624 catch ( com::sun::star::uno::Exception& )
2625 {
2626 }
2627 }
2628 if ( pArgs->IsDraw() )
2629 {
2630 try
2631 {
2632 Reference < ::com::sun::star::util::XCloseable > xDoc( xLoader->loadComponentFromURL( DEFINE_CONST_UNICODE("private:factory/sdraw"),
2633 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, args ), UNO_QUERY_THROW );
2634 xDoc->close( sal_False );
2635 }
2636 catch ( com::sun::star::uno::Exception& )
2637 {
2638 }
2639 }
2640 if ( pArgs->IsImpress() )
2641 {
2642 try
2643 {
2644 Reference < ::com::sun::star::util::XCloseable > xDoc( xLoader->loadComponentFromURL( DEFINE_CONST_UNICODE("private:factory/simpress"),
2645 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, args ), UNO_QUERY_THROW );
2646 xDoc->close( sal_False );
2647 }
2648 catch ( com::sun::star::uno::Exception& )
2649 {
2650 }
2651 }
2652 }
2653
PreloadConfigurationData()2654 void Desktop::PreloadConfigurationData()
2655 {
2656 Reference< XMultiServiceFactory > rFactory = ::comphelper::getProcessServiceFactory();
2657 Reference< XNameAccess > xNameAccess( rFactory->createInstance(
2658 DEFINE_CONST_UNICODE( "com.sun.star.frame.UICommandDescription" )), UNO_QUERY );
2659
2660 rtl::OUString aWriterDoc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.TextDocument" ));
2661 rtl::OUString aCalcDoc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.SpreadsheetDocument" ));
2662 rtl::OUString aDrawDoc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.DrawingDocument" ));
2663 rtl::OUString aImpressDoc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.PresentationDocument" ));
2664
2665 // preload commands configuration
2666 if ( xNameAccess.is() )
2667 {
2668 Any a;
2669 Reference< XNameAccess > xCmdAccess;
2670
2671 try
2672 {
2673 a = xNameAccess->getByName( aWriterDoc );
2674 a >>= xCmdAccess;
2675 if ( xCmdAccess.is() )
2676 {
2677 xCmdAccess->getByName( DEFINE_CONST_UNICODE( ".uno:BasicShapes" ));
2678 xCmdAccess->getByName( DEFINE_CONST_UNICODE( ".uno:EditGlossary" ));
2679 }
2680 }
2681 catch ( ::com::sun::star::uno::Exception& )
2682 {
2683 }
2684
2685 try
2686 {
2687 a = xNameAccess->getByName( aCalcDoc );
2688 a >>= xCmdAccess;
2689 if ( xCmdAccess.is() )
2690 xCmdAccess->getByName( DEFINE_CONST_UNICODE( ".uno:InsertObjectStarMath" ));
2691 }
2692 catch ( ::com::sun::star::uno::Exception& )
2693 {
2694 }
2695
2696 try
2697 {
2698 // draw and impress share the same configuration file (DrawImpressCommands.xcu)
2699 a = xNameAccess->getByName( aDrawDoc );
2700 a >>= xCmdAccess;
2701 if ( xCmdAccess.is() )
2702 xCmdAccess->getByName( DEFINE_CONST_UNICODE( ".uno:Polygon" ));
2703 }
2704 catch ( ::com::sun::star::uno::Exception& )
2705 {
2706 }
2707 }
2708
2709 // preload window state configuration
2710 xNameAccess = Reference< XNameAccess >( rFactory->createInstance(
2711 DEFINE_CONST_UNICODE( "com.sun.star.ui.WindowStateConfiguration" )), UNO_QUERY );
2712 if ( xNameAccess.is() )
2713 {
2714 Any a;
2715 Reference< XNameAccess > xWindowAccess;
2716 try
2717 {
2718 a = xNameAccess->getByName( aWriterDoc );
2719 a >>= xWindowAccess;
2720 if ( xWindowAccess.is() )
2721 xWindowAccess->getByName( DEFINE_CONST_UNICODE( "private:resource/toolbar/standardbar" ));
2722 }
2723 catch ( ::com::sun::star::uno::Exception& )
2724 {
2725 }
2726 try
2727 {
2728 a = xNameAccess->getByName( aCalcDoc );
2729 a >>= xWindowAccess;
2730 if ( xWindowAccess.is() )
2731 xWindowAccess->getByName( DEFINE_CONST_UNICODE( "private:resource/toolbar/standardbar" ));
2732 }
2733 catch ( ::com::sun::star::uno::Exception& )
2734 {
2735 }
2736 try
2737 {
2738 a = xNameAccess->getByName( aDrawDoc );
2739 a >>= xWindowAccess;
2740 if ( xWindowAccess.is() )
2741 xWindowAccess->getByName( DEFINE_CONST_UNICODE( "private:resource/toolbar/standardbar" ));
2742 }
2743 catch ( ::com::sun::star::uno::Exception& )
2744 {
2745 }
2746 try
2747 {
2748 a = xNameAccess->getByName( aImpressDoc );
2749 a >>= xWindowAccess;
2750 if ( xWindowAccess.is() )
2751 xWindowAccess->getByName( DEFINE_CONST_UNICODE( "private:resource/toolbar/standardbar" ));
2752 }
2753 catch ( ::com::sun::star::uno::Exception& )
2754 {
2755 }
2756 }
2757
2758 // preload user interface element factories
2759 Sequence< Sequence< css::beans::PropertyValue > > aSeqSeqPropValue;
2760 Reference< ::com::sun::star::ui::XUIElementFactoryRegistration > xUIElementFactory(
2761 rFactory->createInstance(
2762 DEFINE_CONST_UNICODE( "com.sun.star.ui.UIElementFactoryManager" )),
2763 UNO_QUERY );
2764 if ( xUIElementFactory.is() )
2765 {
2766 try
2767 {
2768 aSeqSeqPropValue = xUIElementFactory->getRegisteredFactories();
2769 }
2770 catch ( ::com::sun::star::uno::Exception& )
2771 {
2772 }
2773 }
2774
2775 // preload popup menu controller factories. As all controllers are in the same
2776 // configuration file they also get preloaded!
2777 Reference< ::com::sun::star::frame::XUIControllerRegistration > xPopupMenuControllerFactory(
2778 rFactory->createInstance(
2779 DEFINE_CONST_UNICODE( "com.sun.star.frame.PopupMenuControllerFactory" )),
2780 UNO_QUERY );
2781 if ( xPopupMenuControllerFactory.is() )
2782 {
2783 try
2784 {
2785 xPopupMenuControllerFactory->hasController(
2786 DEFINE_CONST_UNICODE( ".uno:CharFontName" ),
2787 OUString() );
2788 }
2789 catch ( ::com::sun::star::uno::Exception& )
2790 {
2791 }
2792 }
2793
2794 // preload filter configuration
2795 Sequence< OUString > aSeq;
2796 xNameAccess = Reference< XNameAccess >( rFactory->createInstance(
2797 DEFINE_CONST_UNICODE( "com.sun.star.document.FilterFactory" )), UNO_QUERY );
2798 if ( xNameAccess.is() )
2799 {
2800 try
2801 {
2802 aSeq = xNameAccess->getElementNames();
2803 }
2804 catch ( ::com::sun::star::uno::Exception& )
2805 {
2806 }
2807 }
2808
2809 // preload type detection configuration
2810 xNameAccess = Reference< XNameAccess >( rFactory->createInstance(
2811 DEFINE_CONST_UNICODE( "com.sun.star.document.TypeDetection" )), UNO_QUERY );
2812 if ( xNameAccess.is() )
2813 {
2814 try
2815 {
2816 aSeq = xNameAccess->getElementNames();
2817 }
2818 catch ( ::com::sun::star::uno::Exception& )
2819 {
2820 }
2821 }
2822
2823 static const OUString sConfigSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ) );
2824 static const OUString sAccessSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationAccess" ) );
2825
2826 // get configuration provider
2827 Reference< XMultiServiceFactory > xConfigProvider;
2828 xConfigProvider = Reference< XMultiServiceFactory > (
2829 rFactory->createInstance( sConfigSrvc ),UNO_QUERY );
2830
2831 if ( xConfigProvider.is() )
2832 {
2833 // preload writer configuration
2834 Sequence< Any > theArgs(1);
2835 theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Writer/MailMergeWizard" );
2836 try
2837 {
2838 xNameAccess = Reference< XNameAccess >(
2839 xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY );
2840 }
2841 catch (::com::sun::star::uno::Exception& )
2842 {
2843 }
2844
2845 // WriterWeb
2846 theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.WriterWeb/Content" );
2847 try
2848 {
2849 xNameAccess = Reference< XNameAccess >(
2850 xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY );
2851 }
2852 catch (::com::sun::star::uno::Exception& )
2853 {
2854 }
2855
2856 // preload compatibility
2857 theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Compatibility/WriterCompatibilityVersion" );
2858 try
2859 {
2860 xNameAccess = Reference< XNameAccess >(
2861 xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY );
2862 }
2863 catch (::com::sun::star::uno::Exception& )
2864 {
2865 }
2866
2867 // preload calc configuration
2868 theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Calc/Content" );
2869 try
2870 {
2871 xNameAccess = Reference< XNameAccess >(
2872 xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY );
2873 }
2874 catch (::com::sun::star::uno::Exception& )
2875 {
2876 }
2877
2878 // preload impress configuration
2879 theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.UI.Effects/UserInterface" );
2880 try
2881 {
2882 xNameAccess = Reference< XNameAccess >(
2883 xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY );
2884 }
2885 catch (::com::sun::star::uno::Exception& )
2886 {
2887 }
2888
2889 theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Impress/Layout" );
2890 try
2891 {
2892 xNameAccess = Reference< XNameAccess >(
2893 xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY );
2894 }
2895 catch (::com::sun::star::uno::Exception& )
2896 {
2897 }
2898
2899 // preload draw configuration
2900 theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Draw/Layout" );
2901 try
2902 {
2903 xNameAccess = Reference< XNameAccess >(
2904 xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY );
2905 }
2906 catch (::com::sun::star::uno::Exception& )
2907 {
2908 }
2909
2910 // preload ui configuration
2911 theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.UI/FilterClassification" );
2912 try
2913 {
2914 xNameAccess = Reference< XNameAccess >(
2915 xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY );
2916 }
2917 catch (::com::sun::star::uno::Exception& )
2918 {
2919 }
2920
2921 // preload addons configuration
2922 theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Addons/AddonUI" );
2923 try
2924 {
2925 xNameAccess = Reference< XNameAccess >(
2926 xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY );
2927 }
2928 catch (::com::sun::star::uno::Exception& )
2929 {
2930 }
2931 }
2932 }
2933
OpenClients()2934 void Desktop::OpenClients()
2935 {
2936
2937 // check if a document has been recovered - if there is one or if a document was loaded by cmdline, no default document
2938 // should be created
2939 Reference < XComponent > xFirst;
2940 sal_Bool bLoaded = sal_False;
2941
2942 CommandLineArgs* pArgs = GetCommandLineArgs();
2943 SvtInternalOptions aInternalOptions;
2944
2945 Reference<XMultiServiceFactory> rFactory = ::comphelper::getProcessServiceFactory();
2946
2947 if (!pArgs->IsQuickstart()) {
2948 sal_Bool bShowHelp = sal_False;
2949 ::rtl::OUStringBuffer aHelpURLBuffer;
2950 if (pArgs->IsHelpWriter()) {
2951 bShowHelp = sal_True;
2952 aHelpURLBuffer.appendAscii("vnd.sun.star.help://swriter/start");
2953 } else if (pArgs->IsHelpCalc()) {
2954 bShowHelp = sal_True;
2955 aHelpURLBuffer.appendAscii("vnd.sun.star.help://scalc/start");
2956 } else if (pArgs->IsHelpDraw()) {
2957 bShowHelp = sal_True;
2958 aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdraw/start");
2959 } else if (pArgs->IsHelpImpress()) {
2960 bShowHelp = sal_True;
2961 aHelpURLBuffer.appendAscii("vnd.sun.star.help://simpress/start");
2962 } else if (pArgs->IsHelpBase()) {
2963 bShowHelp = sal_True;
2964 aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdatabase/start");
2965 } else if (pArgs->IsHelpBasic()) {
2966 bShowHelp = sal_True;
2967 aHelpURLBuffer.appendAscii("vnd.sun.star.help://sbasic/start");
2968 } else if (pArgs->IsHelpMath()) {
2969 bShowHelp = sal_True;
2970 aHelpURLBuffer.appendAscii("vnd.sun.star.help://smath/start");
2971 }
2972 if (bShowHelp) {
2973 Help *pHelp = Application::GetHelp();
2974
2975 Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::LOCALE );
2976 rtl::OUString aTmp;
2977 aRet >>= aTmp;
2978 aHelpURLBuffer.appendAscii("?Language=");
2979 aHelpURLBuffer.append(aTmp);
2980 #if defined UNX
2981 aHelpURLBuffer.appendAscii("&System=UNX");
2982 #elif defined WNT
2983 aHelpURLBuffer.appendAscii("&System=WIN");
2984 #elif defined OS2
2985 aHelpURLBuffer.appendAscii("&System=OS2");
2986 #endif
2987 pHelp->Start(aHelpURLBuffer.makeStringAndClear(), NULL);
2988 return;
2989 }
2990 }
2991 else
2992 {
2993 OUString aIniName;
2994 ::vos::OStartupInfo aInfo;
2995
2996 aInfo.getExecutableFile( aIniName );
2997 sal_uInt32 lastIndex = aIniName.lastIndexOf('/');
2998 if ( lastIndex > 0 )
2999 {
3000 aIniName = aIniName.copy( 0, lastIndex+1 );
3001 aIniName += OUString( RTL_CONSTASCII_USTRINGPARAM( "perftune" ));
3002 #if defined(WNT) || defined(OS2)
3003 aIniName += OUString( RTL_CONSTASCII_USTRINGPARAM( ".ini" ));
3004 #else
3005 aIniName += OUString( RTL_CONSTASCII_USTRINGPARAM( "rc" ));
3006 #endif
3007 }
3008
3009 rtl::Bootstrap aPerfTuneIniFile( aIniName );
3010
3011 OUString aDefault( RTL_CONSTASCII_USTRINGPARAM( "0" ));
3012 OUString aPreloadData;
3013
3014 aPerfTuneIniFile.getFrom( OUString( RTL_CONSTASCII_USTRINGPARAM( "QuickstartPreloadConfiguration" )), aPreloadData, aDefault );
3015 if ( aPreloadData.equalsAscii( "1" ))
3016 {
3017 if ( pArgs->IsWriter() ||
3018 pArgs->IsCalc() ||
3019 pArgs->IsDraw() ||
3020 pArgs->IsImpress() )
3021 {
3022 PreloadModuleData( pArgs );
3023 }
3024
3025 PreloadConfigurationData();
3026 }
3027 }
3028
3029 // Disable AutoSave feature in case "-norestore" or a similar command line switch is set on the command line.
3030 // The reason behind: AutoSave/EmergencySave/AutoRecovery share the same data.
3031 // But the require that all documents, which are saved as backup should exists inside
3032 // memory. May be this mechanism will be inconsistent if the configuration exists ...
3033 // but no document inside memory correspond to this data.
3034 // Further it's not acceptable to recover such documents without any UI. It can
3035 // need some time, where the user won't see any results and wait for finishing the office startup ...
3036 sal_Bool bAllowRecoveryAndSessionManagement = (
3037 ( !pArgs->IsNoRestore() ) &&
3038 ( !pArgs->IsHeadless() ) &&
3039 ( !pArgs->IsServer() )
3040 );
3041
3042 if ( ! bAllowRecoveryAndSessionManagement )
3043 {
3044 try
3045 {
3046 Reference< XDispatch > xRecovery(
3047 ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.AutoRecovery")) ),
3048 ::com::sun::star::uno::UNO_QUERY_THROW );
3049
3050 Reference< XURLTransformer > xParser(
3051 ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer")) ),
3052 ::com::sun::star::uno::UNO_QUERY_THROW );
3053
3054 css::util::URL aCmd;
3055 aCmd.Complete = ::rtl::OUString::createFromAscii("vnd.sun.star.autorecovery:/disableRecovery");
3056 xParser->parseStrict(aCmd);
3057
3058 xRecovery->dispatch(aCmd, css::uno::Sequence< css::beans::PropertyValue >());
3059 }
3060 catch(const css::uno::Exception& e)
3061 {
3062 OUString aMessage = OUString::createFromAscii("Could not disable AutoRecovery.\n")
3063 + e.Message;
3064 OSL_ENSURE(sal_False, OUStringToOString(aMessage, RTL_TEXTENCODING_ASCII_US).getStr());
3065 }
3066 }
3067 else
3068 {
3069 sal_Bool bCrashed = sal_False;
3070 sal_Bool bExistsRecoveryData = sal_False;
3071 sal_Bool bExistsSessionData = sal_False;
3072
3073 impl_checkRecoveryState(bCrashed, bExistsRecoveryData, bExistsSessionData);
3074
3075 if ( !getenv ("OOO_DISABLE_RECOVERY") &&
3076 ( ! bLoaded ) &&
3077 (
3078 ( bExistsRecoveryData ) || // => crash with files => recovery
3079 ( bCrashed ) // => crash without files => error report
3080 )
3081 )
3082 {
3083 try
3084 {
3085 impl_callRecoveryUI(
3086 sal_False , // false => force recovery instead of emergency save
3087 bCrashed ,
3088 bExistsRecoveryData);
3089 /* TODO we can't be sure, that at least one document could be recovered here successfully
3090 So we set bLoaded=sal_True to suppress opening of the default document.
3091 But we should make it more safe. Otherwise we have an office without an UI ...
3092 ...
3093 Maybe we can check the desktop if some documents are existing there.
3094 */
3095 Reference< XFramesSupplier > xTasksSupplier(
3096 ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ),
3097 ::com::sun::star::uno::UNO_QUERY_THROW );
3098 Reference< XElementAccess > xList( xTasksSupplier->getFrames(), UNO_QUERY_THROW );
3099 if ( xList->hasElements() )
3100 bLoaded = sal_True;
3101 }
3102 catch(const css::uno::Exception& e)
3103 {
3104 OUString aMessage = OUString::createFromAscii("Error during recovery\n")
3105 + e.Message;
3106 OSL_ENSURE(sal_False, OUStringToOString(aMessage, RTL_TEXTENCODING_ASCII_US).getStr());
3107 }
3108 }
3109
3110 Reference< XInitialization > xSessionListener;
3111 try
3112 {
3113 xSessionListener = Reference< XInitialization >(::comphelper::getProcessServiceFactory()->createInstance(
3114 OUString::createFromAscii("com.sun.star.frame.SessionListener")), UNO_QUERY_THROW);
3115
3116 // specifies whether the UI-interaction on Session shutdown is allowed
3117 sal_Bool bAllowUI = isUIOnSessionShutdownAllowed();
3118 css::beans::NamedValue aProperty( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AllowUserInteractionOnQuit" ) ),
3119 css::uno::makeAny( bAllowUI ) );
3120 css::uno::Sequence< css::uno::Any > aArgs( 1 );
3121 aArgs[0] <<= aProperty;
3122
3123 xSessionListener->initialize( aArgs );
3124 }
3125 catch(const com::sun::star::uno::Exception& e)
3126 {
3127 OUString aMessage = OUString::createFromAscii("Registration of session listener failed\n")
3128 + e.Message;
3129 OSL_ENSURE(sal_False, OUStringToOString(aMessage, RTL_TEXTENCODING_ASCII_US).getStr());
3130 }
3131
3132 if (
3133 ( ! bLoaded ) &&
3134 ( bExistsSessionData )
3135 )
3136 {
3137 // session management
3138 try
3139 {
3140 Reference< XSessionManagerListener > r(xSessionListener, UNO_QUERY_THROW);
3141 bLoaded = r->doRestore();
3142 }
3143 catch(const com::sun::star::uno::Exception& e)
3144 {
3145 OUString aMessage = OUString::createFromAscii("Error in session management\n")
3146 + e.Message;
3147 OSL_ENSURE(sal_False, OUStringToOString(aMessage, RTL_TEXTENCODING_ASCII_US).getStr());
3148 }
3149 }
3150 }
3151
3152 OfficeIPCThread::EnableRequests();
3153
3154 sal_Bool bShutdown( sal_False );
3155 if ( !pArgs->IsServer() )
3156 {
3157 ProcessDocumentsRequest aRequest(pArgs->getCwdUrl());
3158 aRequest.pcProcessed = NULL;
3159
3160 pArgs->GetOpenList( aRequest.aOpenList );
3161 pArgs->GetViewList( aRequest.aViewList );
3162 pArgs->GetStartList( aRequest.aStartList );
3163 pArgs->GetPrintList( aRequest.aPrintList );
3164 pArgs->GetPrintToList( aRequest.aPrintToList );
3165 pArgs->GetPrinterName( aRequest.aPrinterName );
3166 pArgs->GetForceOpenList( aRequest.aForceOpenList );
3167 pArgs->GetForceNewList( aRequest.aForceNewList );
3168
3169 if ( aRequest.aOpenList.getLength() > 0 ||
3170 aRequest.aViewList.getLength() > 0 ||
3171 aRequest.aStartList.getLength() > 0 ||
3172 aRequest.aPrintList.getLength() > 0 ||
3173 aRequest.aForceOpenList.getLength() > 0 ||
3174 aRequest.aForceNewList.getLength() > 0 ||
3175 ( aRequest.aPrintToList.getLength() > 0 && aRequest.aPrinterName.getLength() > 0 ))
3176 {
3177 bLoaded = sal_True;
3178
3179 if ( pArgs->HasModuleParam() )
3180 {
3181 SvtModuleOptions aOpt;
3182
3183 // Support command line parameters to start a module (as preselection)
3184 if ( pArgs->IsWriter() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
3185 aRequest.aModule = aOpt.GetFactoryName( SvtModuleOptions::E_WRITER );
3186 else if ( pArgs->IsCalc() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) )
3187 aRequest.aModule = aOpt.GetFactoryName( SvtModuleOptions::E_CALC );
3188 else if ( pArgs->IsImpress() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) )
3189 aRequest.aModule= aOpt.GetFactoryName( SvtModuleOptions::E_IMPRESS );
3190 else if ( pArgs->IsDraw() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) )
3191 aRequest.aModule= aOpt.GetFactoryName( SvtModuleOptions::E_DRAW );
3192 }
3193
3194 // check for printing disabled
3195 if( ( aRequest.aPrintList.getLength() || aRequest.aPrintToList.getLength() )
3196 && Application::GetSettings().GetMiscSettings().GetDisablePrinting() )
3197 {
3198 aRequest.aPrintList = rtl::OUString();
3199 aRequest.aPrintToList = rtl::OUString();
3200 ResMgr* pDtResMgr = GetDesktopResManager();
3201 if( pDtResMgr )
3202 {
3203 ErrorBox aBox( NULL, ResId( EBX_ERR_PRINTDISABLED, *pDtResMgr ) );
3204 aBox.Execute();
3205 }
3206 }
3207
3208 // Process request
3209 bShutdown = OfficeIPCThread::ExecuteCmdLineRequests( aRequest );
3210 }
3211 }
3212
3213 // Don't do anything if we have successfully called terminate at desktop
3214 if ( bShutdown )
3215 return;
3216
3217 // no default document if a document was loaded by recovery or by command line or if soffice is used as server
3218 Reference< XFramesSupplier > xTasksSupplier(
3219 ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ),
3220 ::com::sun::star::uno::UNO_QUERY_THROW );
3221 Reference< XElementAccess > xList( xTasksSupplier->getFrames(), UNO_QUERY_THROW );
3222 if ( xList->hasElements() || pArgs->IsServer() )
3223 return;
3224
3225 if ( pArgs->IsQuickstart() || pArgs->IsInvisible() || pArgs->IsBean() || Application::AnyInput( INPUT_APPEVENT ) )
3226 // soffice was started as tray icon ...
3227 return;
3228 {
3229 OpenDefault();
3230 }
3231 }
3232
OpenDefault()3233 void Desktop::OpenDefault()
3234 {
3235
3236 RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::OpenDefault" );
3237
3238 ::rtl::OUString aName;
3239 SvtModuleOptions aOpt;
3240
3241 CommandLineArgs* pArgs = GetCommandLineArgs();
3242 if ( pArgs->IsNoDefault() ) return;
3243 if ( pArgs->HasModuleParam() )
3244 {
3245 // Support new command line parameters to start a module
3246 if ( pArgs->IsWriter() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
3247 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITER );
3248 else if ( pArgs->IsCalc() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) )
3249 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_CALC );
3250 else if ( pArgs->IsImpress() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) )
3251 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_IMPRESS );
3252 else if ( pArgs->IsBase() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SDATABASE ) )
3253 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DATABASE );
3254 else if ( pArgs->IsDraw() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) )
3255 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DRAW );
3256 else if ( pArgs->IsMath() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SMATH ) )
3257 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_MATH );
3258 else if ( pArgs->IsGlobal() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
3259 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITERGLOBAL );
3260 else if ( pArgs->IsWeb() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
3261 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITERWEB );
3262 }
3263
3264 if ( !aName.getLength() )
3265 {
3266 // Old way to create a default document
3267 if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
3268 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITER );
3269 else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) )
3270 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_CALC );
3271 else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) )
3272 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_IMPRESS );
3273 else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SDATABASE ) )
3274 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DATABASE );
3275 else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) )
3276 aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DRAW );
3277 else
3278 return;
3279 }
3280
3281 ProcessDocumentsRequest aRequest(pArgs->getCwdUrl());
3282 aRequest.pcProcessed = NULL;
3283 aRequest.aOpenList = aName;
3284 OfficeIPCThread::ExecuteCmdLineRequests( aRequest );
3285 }
3286
3287
GetURL_Impl(const String & rName,boost::optional<rtl::OUString> const & cwdUrl)3288 String GetURL_Impl(
3289 const String& rName, boost::optional< rtl::OUString > const & cwdUrl )
3290 {
3291 // if rName is a vnd.sun.star.script URL do not attempt to parse it
3292 // as INetURLObj does not handle their URLs
3293 if (rName.CompareToAscii("vnd.sun.star.script" , 19) == COMPARE_EQUAL)
3294 {
3295 return rName;
3296 }
3297
3298 // don't touch file urls, those should already be in internal form
3299 // they won't get better here (#112849#)
3300 if (rName.CompareToAscii("file:" , 5) == COMPARE_EQUAL)
3301 {
3302 return rName;
3303 }
3304
3305 if ( rName.CompareToAscii("service:" , 8) == COMPARE_EQUAL )
3306 {
3307 return rName;
3308 }
3309
3310 // Add path seperator to these directory and make given URL (rName) absolute by using of current working directory
3311 // Attention: "setFianlSlash()" is necessary for calling "smartRel2Abs()"!!!
3312 // Otherwise last part will be ignored and wrong result will be returned!!!
3313 // "smartRel2Abs()" interpret given URL as file not as path. So he truncate last element to get the base path ...
3314 // But if we add a seperator - he doesn't do it anymore.
3315 INetURLObject aObj;
3316 if (cwdUrl) {
3317 aObj.SetURL(*cwdUrl);
3318 aObj.setFinalSlash();
3319 }
3320
3321 // Use the provided parameters for smartRel2Abs to support the usage of '%' in system paths.
3322 // Otherwise this char won't get encoded and we are not able to load such files later,
3323 // see #110156#
3324 bool bWasAbsolute;
3325 INetURLObject aURL = aObj.smartRel2Abs( rName, bWasAbsolute, false, INetURLObject::WAS_ENCODED,
3326 RTL_TEXTENCODING_UTF8, true );
3327 String aFileURL = aURL.GetMainURL(INetURLObject::NO_DECODE);
3328
3329 ::osl::FileStatus aStatus( FileStatusMask_FileURL );
3330 ::osl::DirectoryItem aItem;
3331 if( ::osl::FileBase::E_None == ::osl::DirectoryItem::get( aFileURL, aItem ) &&
3332 ::osl::FileBase::E_None == aItem.getFileStatus( aStatus ) )
3333 aFileURL = aStatus.getFileURL();
3334
3335 return aFileURL;
3336 }
3337
HandleAppEvent(const ApplicationEvent & rAppEvent)3338 void Desktop::HandleAppEvent( const ApplicationEvent& rAppEvent )
3339 {
3340 if ( rAppEvent.GetEvent() == "APPEAR" && !GetCommandLineArgs()->IsInvisible() )
3341 {
3342 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory();
3343
3344 // find active task - the active task is always a visible task
3345 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFramesSupplier >
3346 xDesktop( xSMGR->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ),
3347 ::com::sun::star::uno::UNO_QUERY );
3348 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xTask = xDesktop->getActiveFrame();
3349 if ( !xTask.is() )
3350 {
3351 // get any task if there is no active one
3352 ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess > xList( xDesktop->getFrames(), ::com::sun::star::uno::UNO_QUERY );
3353 if ( xList->getCount()>0 )
3354 xList->getByIndex(0) >>= xTask;
3355 }
3356
3357 if ( xTask.is() )
3358 {
3359 Reference< com::sun::star::awt::XTopWindow > xTop( xTask->getContainerWindow(), UNO_QUERY );
3360 xTop->toFront();
3361 }
3362 else
3363 {
3364 // no visible task that could be activated found
3365 Reference< XFrame > xBackingFrame;
3366 Reference< ::com::sun::star::awt::XWindow > xContainerWindow;
3367 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xDesktopFrame( xDesktop, UNO_QUERY );
3368
3369 xBackingFrame = xDesktopFrame->findFrame(OUString( RTL_CONSTASCII_USTRINGPARAM( "_blank" )), 0);
3370 if (xBackingFrame.is())
3371 xContainerWindow = xBackingFrame->getContainerWindow();
3372 if (xContainerWindow.is())
3373 {
3374 Sequence< Any > lArgs(1);
3375 lArgs[0] <<= xContainerWindow;
3376 Reference< XController > xBackingComp(
3377 xSMGR->createInstanceWithArguments(OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.StartModule") ), lArgs),
3378 UNO_QUERY);
3379 if (xBackingComp.is())
3380 {
3381 Reference< ::com::sun::star::awt::XWindow > xBackingWin(xBackingComp, UNO_QUERY);
3382 // Attention: You MUST(!) call setComponent() before you call attachFrame().
3383 // Because the backing component set the property "IsBackingMode" of the frame
3384 // to true inside attachFrame(). But setComponent() reset this state everytimes ...
3385 xBackingFrame->setComponent(xBackingWin, xBackingComp);
3386 xBackingComp->attachFrame(xBackingFrame);
3387 xContainerWindow->setVisible(sal_True);
3388
3389 Window* pCompWindow = VCLUnoHelper::GetWindow(xBackingFrame->getComponentWindow());
3390 if (pCompWindow)
3391 pCompWindow->Update();
3392 }
3393 }
3394 }
3395 }
3396 else if ( rAppEvent.GetEvent() == "QUICKSTART" && !GetCommandLineArgs()->IsInvisible() )
3397 {
3398 // If the office has been started the second time its command line arguments are sent through a pipe
3399 // connection to the first office. We want to reuse the quickstart option for the first office.
3400 // NOTICE: The quickstart service must be initialized inside the "main thread", so we use the
3401 // application events to do this (they are executed inside main thread)!!!
3402 // Don't start quickstart service if the user specified "-invisible" on the command line!
3403 sal_Bool bQuickstart( sal_True );
3404 Sequence< Any > aSeq( 1 );
3405 aSeq[0] <<= bQuickstart;
3406
3407 Reference < XInitialization > xQuickstart( ::comphelper::getProcessServiceFactory()->createInstance(
3408 DEFINE_CONST_UNICODE( "com.sun.star.office.Quickstart" )),
3409 UNO_QUERY );
3410 if ( xQuickstart.is() )
3411 xQuickstart->initialize( aSeq );
3412 }
3413 else if ( rAppEvent.GetEvent() == "ACCEPT" )
3414 {
3415 // every time an accept parameter is used we create an acceptor
3416 // with the corresponding accept-string
3417 OUString aAcceptString(rAppEvent.GetData().GetBuffer());
3418 createAcceptor(aAcceptString);
3419 }
3420 else if ( rAppEvent.GetEvent() == "UNACCEPT" )
3421 {
3422 // try to remove corresponding acceptor
3423 OUString aUnAcceptString(rAppEvent.GetData().GetBuffer());
3424 destroyAcceptor(aUnAcceptString);
3425 }
3426 else if ( rAppEvent.GetEvent() == "SaveDocuments" )
3427 {
3428 Desktop::_bTasksSaved = sal_False;
3429 Desktop::_bTasksSaved = SaveTasks();
3430 }
3431 else if ( rAppEvent.GetEvent() == "OPENHELPURL" )
3432 {
3433 // start help for a specific URL
3434 OUString aHelpURL(rAppEvent.GetData().GetBuffer());
3435 Help *pHelp = Application::GetHelp();
3436 pHelp->Start(aHelpURL, NULL);
3437 }
3438 else if ( rAppEvent.GetEvent() == APPEVENT_OPEN_STRING )
3439 {
3440 OUString aOpenURL(rAppEvent.GetData().GetBuffer());
3441
3442 CommandLineArgs* pCmdLine = GetCommandLineArgs();
3443 if ( !pCmdLine->IsInvisible() && !pCmdLine->IsTerminateAfterInit() )
3444 {
3445 ProcessDocumentsRequest* pDocsRequest = new ProcessDocumentsRequest(
3446 pCmdLine->getCwdUrl());
3447 pDocsRequest->aOpenList = aOpenURL;
3448 pDocsRequest->pcProcessed = NULL;
3449
3450 OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest );
3451 delete pDocsRequest;
3452 }
3453 }
3454 else if ( rAppEvent.GetEvent() == APPEVENT_PRINT_STRING )
3455 {
3456 OUString aPrintURL(rAppEvent.GetData().GetBuffer());
3457
3458 CommandLineArgs* pCmdLine = GetCommandLineArgs();
3459 if ( !pCmdLine->IsInvisible() && !pCmdLine->IsTerminateAfterInit() )
3460 {
3461 ProcessDocumentsRequest* pDocsRequest = new ProcessDocumentsRequest(
3462 pCmdLine->getCwdUrl());
3463 pDocsRequest->aPrintList = aPrintURL;
3464 pDocsRequest->pcProcessed = NULL;
3465
3466 OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest );
3467 delete pDocsRequest;
3468 }
3469 }
3470 #ifndef UNX
3471 else if ( rAppEvent.GetEvent() == "HELP" )
3472 {
3473 // in non unix version allow showing of cmdline help window
3474 displayCmdlineHelp();
3475 }
3476 #endif
3477 else if ( rAppEvent.GetEvent() == "SHOWDIALOG" )
3478 {
3479 // ignore all errors here. It's clicking a menu entry only ...
3480 // The user will try it again, in case nothing happens .-)
3481 try
3482 {
3483 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory();
3484
3485 com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider >
3486 xDesktop( xSMGR->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ),
3487 ::com::sun::star::uno::UNO_QUERY );
3488
3489 // check provider ... we know it's weak reference only
3490 if ( ! xDesktop.is())
3491 return;
3492
3493 css::uno::Reference< css::util::XURLTransformer > xParser(xSMGR->createInstance(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer"))), css::uno::UNO_QUERY_THROW);
3494 css::util::URL aCommand;
3495 if( rAppEvent.GetData().EqualsAscii( "PREFERENCES" ) )
3496 aCommand.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:OptionsTreeDialog" ) );
3497 else if( rAppEvent.GetData().EqualsAscii( "ABOUT" ) )
3498 aCommand.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:About" ) );
3499 if( aCommand.Complete.getLength() )
3500 {
3501 xParser->parseStrict(aCommand);
3502
3503 css::uno::Reference< css::frame::XDispatch > xDispatch = xDesktop->queryDispatch(aCommand, rtl::OUString(), 0);
3504 if (xDispatch.is())
3505 xDispatch->dispatch(aCommand, css::uno::Sequence< css::beans::PropertyValue >());
3506 }
3507 }
3508 catch(const css::uno::Exception&)
3509 {}
3510 }
3511 else if( rAppEvent.GetEvent() == "PRIVATE:DOSHUTDOWN" )
3512 {
3513 Desktop* pD = dynamic_cast<Desktop*>(GetpApp());
3514 OSL_ENSURE( pD, "no desktop ?!?" );
3515 if( pD )
3516 pD->doShutdown();
3517 }
3518 }
3519
OpenSplashScreen()3520 void Desktop::OpenSplashScreen()
3521 {
3522 ::rtl::OUString aTmpString;
3523 CommandLineArgs* pCmdLine = GetCommandLineArgs();
3524 sal_Bool bVisible = sal_False;
3525 // Show intro only if this is normal start (e.g. no server, no quickstart, no printing )
3526 if ( !pCmdLine->IsInvisible() &&
3527 !pCmdLine->IsHeadless() &&
3528 !pCmdLine->IsQuickstart() &&
3529 !pCmdLine->IsMinimized() &&
3530 !pCmdLine->IsNoLogo() &&
3531 !pCmdLine->IsTerminateAfterInit() &&
3532 !pCmdLine->GetPrintList( aTmpString ) &&
3533 !pCmdLine->GetPrintToList( aTmpString ) )
3534 {
3535 // Determine application name from command line parameters
3536 OUString aAppName;
3537 if ( pCmdLine->IsWriter() )
3538 aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "writer" ));
3539 else if ( pCmdLine->IsCalc() )
3540 aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "calc" ));
3541 else if ( pCmdLine->IsDraw() )
3542 aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "draw" ));
3543 else if ( pCmdLine->IsImpress() )
3544 aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "impress" ));
3545 else if ( pCmdLine->IsBase() )
3546 aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "base" ));
3547 else if ( pCmdLine->IsGlobal() )
3548 aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "global" ));
3549 else if ( pCmdLine->IsMath() )
3550 aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "math" ));
3551 else if ( pCmdLine->IsWeb() )
3552 aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "web" ));
3553
3554 bVisible = sal_True;
3555 Sequence< Any > aSeq( 2 );
3556 aSeq[0] <<= bVisible;
3557 aSeq[1] <<= aAppName;
3558 m_rSplashScreen = Reference<XStatusIndicator>(
3559 comphelper::getProcessServiceFactory()->createInstanceWithArguments(
3560 OUString::createFromAscii("com.sun.star.office.SplashScreen"),
3561 aSeq), UNO_QUERY);
3562
3563 if(m_rSplashScreen.is())
3564 m_rSplashScreen->start(OUString::createFromAscii("SplashScreen"), 100);
3565 }
3566
3567 }
3568
SetSplashScreenProgress(sal_Int32 iProgress)3569 void Desktop::SetSplashScreenProgress(sal_Int32 iProgress)
3570 {
3571 if(m_rSplashScreen.is())
3572 {
3573 m_rSplashScreen->setValue(iProgress);
3574 }
3575 }
3576
SetSplashScreenText(const::rtl::OUString & rText)3577 void Desktop::SetSplashScreenText( const ::rtl::OUString& rText )
3578 {
3579 if( m_rSplashScreen.is() )
3580 {
3581 m_rSplashScreen->setText( rText );
3582 }
3583 }
3584
CloseSplashScreen()3585 void Desktop::CloseSplashScreen()
3586 {
3587 if(m_rSplashScreen.is())
3588 {
3589 m_rSplashScreen->end();
3590 m_rSplashScreen = NULL;
3591 }
3592 }
3593
3594 // ========================================================================
DoFirstRunInitializations()3595 void Desktop::DoFirstRunInitializations()
3596 {
3597 try
3598 {
3599 Reference< XJobExecutor > xExecutor( ::comphelper::getProcessServiceFactory()->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.task.JobExecutor" ) ), UNO_QUERY );
3600 if( xExecutor.is() )
3601 xExecutor->trigger( ::rtl::OUString::createFromAscii("onFirstRunInitialization") );
3602 }
3603 catch(const ::com::sun::star::uno::Exception&)
3604 {
3605 OSL_ENSURE( sal_False, "Desktop::DoFirstRunInitializations: caught an exception while trigger job executor ..." );
3606 }
3607 }
3608
3609 // ========================================================================
CheckFirstRun()3610 void Desktop::CheckFirstRun( )
3611 {
3612 const ::rtl::OUString sCommonMiscNodeName = ::rtl::OUString::createFromAscii( "/org.openoffice.Office.Common/Misc" );
3613 const ::rtl::OUString sFirstRunNodeName = ::rtl::OUString::createFromAscii( "FirstRun" );
3614
3615 // --------------------------------------------------------------------
3616 // check if this is the first office start
3617
3618 // for this, open the Common/Misc node where this info is stored
3619 ::utl::OConfigurationTreeRoot aCommonMisc = ::utl::OConfigurationTreeRoot::createWithServiceFactory(
3620 ::comphelper::getProcessServiceFactory( ),
3621 sCommonMiscNodeName,
3622 2,
3623 ::utl::OConfigurationTreeRoot::CM_UPDATABLE
3624 );
3625
3626 // read the flag
3627 OSL_ENSURE( aCommonMisc.isValid(), "Desktop::CheckFirstRun: could not open the config node needed!" );
3628 sal_Bool bIsFirstRun = sal_False;
3629 aCommonMisc.getNodeValue( sFirstRunNodeName ) >>= bIsFirstRun;
3630
3631 if ( !bIsFirstRun )
3632 // nothing to do ....
3633 return;
3634
3635 // --------------------------------------------------------------------
3636 // it is the first run
3637 // this has once been done using a vos timer. this could lead to problems when
3638 // the timer would trigger when the app is already going down again, since VCL would
3639 // no longer be available. Since the old handler would do a postUserEvent to the main
3640 // thread anyway, we can use a vcl timer here to prevent the race contition (#107197#)
3641 m_firstRunTimer.SetTimeout(3000); // 3 sec.
3642 m_firstRunTimer.SetTimeoutHdl(LINK(this, Desktop, AsyncInitFirstRun));
3643 m_firstRunTimer.Start();
3644
3645 // --------------------------------------------------------------------
3646 // reset the config flag
3647
3648 // set the value
3649 aCommonMisc.setNodeValue( sFirstRunNodeName, makeAny( (sal_Bool)sal_False ) );
3650 // commit the changes
3651 aCommonMisc.commit();
3652 }
3653
3654 }
3655