diff options
Diffstat (limited to 'desktop')
-rw-r--r-- | desktop/inc/app.hxx | 4 | ||||
-rw-r--r-- | desktop/source/app/app.cxx | 153 | ||||
-rw-r--r-- | desktop/source/app/check_ext_deps.cxx | 19 | ||||
-rw-r--r-- | desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx | 2 | ||||
-rw-r--r-- | desktop/source/deployment/inc/dp_misc.h | 3 | ||||
-rw-r--r-- | desktop/source/deployment/manager/dp_extensionmanager.cxx | 2 | ||||
-rw-r--r-- | desktop/source/deployment/misc/dp_misc.cxx | 5 | ||||
-rw-r--r-- | desktop/source/pkgchk/unopkg/unopkg_app.cxx | 2 |
8 files changed, 164 insertions, 26 deletions
diff --git a/desktop/inc/app.hxx b/desktop/inc/app.hxx index ea107e801ff2..25b635254f82 100644 --- a/desktop/inc/app.hxx +++ b/desktop/inc/app.hxx @@ -130,14 +130,12 @@ class Desktop : public Application static sal_Bool isCrashReporterEnabled(); // first-start (ever) related methods - static bool newInstallation(); - static sal_Bool CheckExtensionDependencies(); static void DoRestartActionsIfNecessary( sal_Bool bQuickStart ); static void SetRestartState(); - void SynchronizeExtensionRepositories(bool force); + void SynchronizeExtensionRepositories(); void SetSplashScreenText( const ::rtl::OUString& rText ); void SetSplashScreenProgress( sal_Int32 ); diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx index 991577f10dfa..6efc9f46acde 100644 --- a/desktop/source/app/app.cxx +++ b/desktop/source/app/app.cxx @@ -147,6 +147,145 @@ static sal_Bool _bCrashReporterEnabled = sal_True; static ::rtl::OUString getBrandSharePreregBundledPathURL(); #endif +namespace { + +void removeTree(OUString const & url) { + osl::Directory dir(url); + switch (dir.open()) { + case osl::FileBase::E_None: + break; + case osl::FileBase::E_NOENT: + return; //TODO: SAL_WARN if recursive + default: + throw css::uno::RuntimeException( + "cannot open directory " + url, + css::uno::Reference< css::uno::XInterface >()); + } + for (;;) { + osl::DirectoryItem i; + osl::FileBase::RC rc = dir.getNextItem(i, SAL_MAX_UINT32); + if (rc == osl::FileBase::E_NOENT) { + break; + } + if (rc != osl::FileBase::E_None) { + throw css::uno::RuntimeException( + "cannot iterate directory " + url, + css::uno::Reference< css::uno::XInterface >()); + } + osl::FileStatus stat( + osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName | + osl_FileStatus_Mask_FileURL); + if (i.getFileStatus(stat) != osl::FileBase::E_None) { + throw css::uno::RuntimeException( + "cannot stat in directory " + url, + css::uno::Reference< css::uno::XInterface >()); + } + if (stat.getFileType() == osl::FileStatus::Directory) { //TODO: symlinks + removeTree(stat.getFileURL()); + } else { + if (osl::File::remove(stat.getFileURL()) != osl::FileBase::E_None) { + throw css::uno::RuntimeException( + "cannot remove " + stat.getFileURL(), + css::uno::Reference< css::uno::XInterface >()); + } + } + } +} + +// Remove any existing UserInstallation's user/extensions/bundled cache +// remaining from old installations. Apparently due to the old +// share/prereg/bundled mechanism (disabled since +// 5c47e5f63a79a9e72ec4a100786b1bbf65137ed4 "fdo#51252 Disable copying +// share/prereg/bundled to avoid startup crashes"), that cache could contain +// corrupted information (like a UNO component registered twice, which got +// changed from active to passive registration in one LO version, but the +// version of the corresponding bundled extension only incremented in a later LO +// version). At least in theory, this function could be removed again once no +// UserInstallation can be poisoned by that old share/prereg/bundled mechanism +// any more. (But then Desktop::SynchronizeExtensionRepositories might need to +// be revisited, see 2d2b19dea1ab401b1b4971ff5b12b87bb11fd666 "Force +// ExtensionManager resync when the implementation changes" which effectively +// got reverted again now. Now, a mismatch between a UserInstallation's +// user/extensions/bundled and an installation's share/extensions will always be +// detected here and lead to a removal of user/extensions/bundled, so that +// Desktop::SynchronizeExtensionRepositories will then definitely resync +// share/extensions.) +void refreshBundledExtensionsDir() { + OUString buildId( + "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") ":buildid}"); + rtl::Bootstrap::expandMacros(buildId); //TODO: detect failure + OUString dir("$BUNDLED_EXTENSIONS_USER"); + rtl::Bootstrap::expandMacros(dir); //TODO: detect failure + OUString url(dir + "/buildid"); + osl::File f(url); + switch (f.open(osl_File_OpenFlag_Read)) { + case osl::FileBase::E_None: + { + rtl::ByteSequence s1; + osl::FileBase::RC rc = f.readLine(s1); + if (f.close() != osl::FileBase::E_None) { + SAL_WARN("desktop", "cannot close " + url + " after reading"); + } + if (rc != osl::FileBase::E_None) { + throw css::uno::RuntimeException( + "cannot read from " + url, + css::uno::Reference< css::uno::XInterface >()); + } + OUString s2( + reinterpret_cast< char const * >(s1.getConstArray()), + s1.getLength(), RTL_TEXTENCODING_ISO_8859_1); + // using ISO 8859-1 avoids any and all conversion errors; the + // content should only be a subset of ASCII, anyway + if (s2 == buildId) { + return; + } + break; + } + case osl::FileBase::E_NOENT: + break; + default: + throw css::uno::RuntimeException( + "cannot open " + url + " for reading", + css::uno::Reference< css::uno::XInterface >()); + } + removeTree(dir); + switch (osl::Directory::createPath(dir)) { + case osl::FileBase::E_None: + case osl::FileBase::E_EXIST: + break; + default: + throw css::uno::RuntimeException( + "cannot create path " + dir, + css::uno::Reference< css::uno::XInterface >()); + } + if (f.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Create) != + osl::FileBase::E_None) + { + throw css::uno::RuntimeException( + "cannot open " + url + " for writing", + css::uno::Reference< css::uno::XInterface >()); + } + rtl::OString buf(OUStringToOString(buildId, RTL_TEXTENCODING_UTF8)); + // using UTF-8 avoids almost all conversion errors (and buildid + // containing single surrogate halves should never happen, anyway); the + // content should only be a subset of ASCII, anyway + sal_uInt64 n; + if (f.write(buf.getStr(), buf.getLength(), n) != osl::FileBase::E_None + || n != static_cast< sal_uInt32 >(buf.getLength())) + { + throw css::uno::RuntimeException( + "cannot write to " + url, + css::uno::Reference< css::uno::XInterface >()); + } + if (f.close() != osl::FileBase::E_None) { + throw css::uno::RuntimeException( + "cannot close " + url + " after writing", + css::uno::Reference< css::uno::XInterface >()); + } +} + +} + // ---------------------------------------------------------------------------- ResMgr* Desktop::GetDesktopResManager() @@ -625,6 +764,8 @@ void Desktop::Init() RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::Init" ); SetBootstrapStatus(BS_OK); + refreshBundledExtensionsDir(); + // Check for lastsynchronized file for bundled extensions in the user directory // and test if synchronzation is necessary! #ifndef ANDROID @@ -1616,14 +1757,10 @@ int Desktop::Main() // Check if bundled or shared extensions were added /removed // and process those extensions (has to be done before checking // the extension dependencies! - bool newInst = newInstallation(); - SynchronizeExtensionRepositories(newInst); - if ( newInst ) - { - bool bAbort = CheckExtensionDependencies(); - if ( bAbort ) - return EXIT_FAILURE; - } + SynchronizeExtensionRepositories(); + bool bAbort = CheckExtensionDependencies(); + if ( bAbort ) + return EXIT_FAILURE; { ::comphelper::ComponentContext aContext( xSMgr ); diff --git a/desktop/source/app/check_ext_deps.cxx b/desktop/source/app/check_ext_deps.cxx index 04b5cd75b1d6..dd01d9bbf4e5 100644 --- a/desktop/source/app/check_ext_deps.cxx +++ b/desktop/source/app/check_ext_deps.cxx @@ -347,9 +347,9 @@ static void impl_setNeedsCompatCheck() // to check if we need checking the dependencies of the extensions again, we compare // the build id of the office with the one of the last check //------------------------------------------------------------------------------ -bool Desktop::newInstallation() +static bool impl_needsCompatCheck() { - bool bNewInst = false; + bool bNeedsCheck = false; rtl::OUString aLastCheckBuildID; rtl::OUString aCurrentBuildID( UNISTRING( "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") ":buildid}" ) ); rtl::Bootstrap::expandMacros( aCurrentBuildID ); @@ -371,18 +371,18 @@ bool Desktop::newInstallation() result >>= aLastCheckBuildID; if ( aLastCheckBuildID != aCurrentBuildID ) { - bNewInst = true; + bNeedsCheck = true; result <<= aCurrentBuildID; pset->setPropertyValue( OUString("LastCompatibilityCheckID"), result ); Reference< util::XChangesBatch >( pset, UNO_QUERY_THROW )->commitChanges(); } #ifdef DEBUG - bNewInst = true; + bNeedsCheck = true; #endif } catch (const com::sun::star::uno::Exception&) {} - return bNewInst; + return bNeedsCheck; } //------------------------------------------------------------------------------ @@ -390,6 +390,11 @@ bool Desktop::newInstallation() // When there are unresolved issues, we can't continue with startup sal_Bool Desktop::CheckExtensionDependencies() { + if (!impl_needsCompatCheck()) + { + return false; + } + uno::Reference< uno::XComponentContext > xContext = comphelper_getProcessComponentContext(); bool bDependenciesValid = impl_checkDependencies( xContext ); @@ -408,10 +413,10 @@ sal_Bool Desktop::CheckExtensionDependencies() return false; } -void Desktop::SynchronizeExtensionRepositories(bool force) +void Desktop::SynchronizeExtensionRepositories() { RTL_LOGFILE_CONTEXT(aLog,"desktop (jl) ::Desktop::SynchronizeExtensionRepositories"); - dp_misc::syncRepositories( force, new SilentCommandEnv( this ) ); + dp_misc::syncRepositories( new SilentCommandEnv( this ) ); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx b/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx index 7795e3093cc3..29ded177175a 100644 --- a/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx +++ b/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx @@ -1124,7 +1124,7 @@ void ExtensionCmdQueue::acceptLicense( const uno::Reference< deployment::XPackag void ExtensionCmdQueue::syncRepositories( const uno::Reference< uno::XComponentContext > &xContext ) { - dp_misc::syncRepositories( false, new ProgressCmdEnv( xContext, NULL, OUSTR("Extension Manager") ) ); + dp_misc::syncRepositories( new ProgressCmdEnv( xContext, NULL, OUSTR("Extension Manager") ) ); } void ExtensionCmdQueue::stop() diff --git a/desktop/source/deployment/inc/dp_misc.h b/desktop/source/deployment/inc/dp_misc.h index e9ad4a2b1d24..29fd14007d71 100644 --- a/desktop/source/deployment/inc/dp_misc.h +++ b/desktop/source/deployment/inc/dp_misc.h @@ -154,8 +154,7 @@ void TRACE(::rtl::OUString const & sText); recently added or removed. */ DESKTOP_DEPLOYMENTMISC_DLLPUBLIC -void syncRepositories(bool force, - ::com::sun::star::uno::Reference< +void syncRepositories(::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment> const & xCmdEnv); } diff --git a/desktop/source/deployment/manager/dp_extensionmanager.cxx b/desktop/source/deployment/manager/dp_extensionmanager.cxx index e5a16b7f6a0c..f2a6fce0a0ff 100644 --- a/desktop/source/deployment/manager/dp_extensionmanager.cxx +++ b/desktop/source/deployment/manager/dp_extensionmanager.cxx @@ -1223,7 +1223,7 @@ void ExtensionManager::reinstallDeployedExtensions( xPackageManager->reinstallDeployedPackages(xAbortChannel, xCmdEnv); //We must sync here, otherwise we will get exceptions when extensions //are removed. - dp_misc::syncRepositories(false, xCmdEnv); + dp_misc::syncRepositories(xCmdEnv); const uno::Sequence< Reference<deploy::XPackage> > extensions( xPackageManager->getDeployedPackages(xAbortChannel, xCmdEnv)); diff --git a/desktop/source/deployment/misc/dp_misc.cxx b/desktop/source/deployment/misc/dp_misc.cxx index 9ed579fbb97c..b225db620b5c 100644 --- a/desktop/source/deployment/misc/dp_misc.cxx +++ b/desktop/source/deployment/misc/dp_misc.cxx @@ -591,7 +591,7 @@ void TRACE(::rtl::OString const & sText) } void syncRepositories( - bool force, Reference<ucb::XCommandEnvironment> const & xCmdEnv) + Reference<ucb::XCommandEnvironment> const & xCmdEnv) { OUString sDisable; ::rtl::Bootstrap::get( OUSTR( "DISABLE_EXTENSION_SYNCHRONIZATION" ), sDisable, OUString() ); @@ -602,8 +602,7 @@ void syncRepositories( //synchronize shared before bundled otherewise there are //more revoke and registration calls. sal_Bool bModified = false; - if (force - || needToSyncRepostitory(OUString(RTL_CONSTASCII_USTRINGPARAM("shared"))) + if (needToSyncRepostitory(OUString(RTL_CONSTASCII_USTRINGPARAM("shared"))) || needToSyncRepostitory(OUString(RTL_CONSTASCII_USTRINGPARAM("bundled")))) { xExtensionManager = diff --git a/desktop/source/pkgchk/unopkg/unopkg_app.cxx b/desktop/source/pkgchk/unopkg/unopkg_app.cxx index 205e6ef82a31..2bd4d1b99214 100644 --- a/desktop/source/pkgchk/unopkg/unopkg_app.cxx +++ b/desktop/source/pkgchk/unopkg/unopkg_app.cxx @@ -432,7 +432,7 @@ extern "C" DESKTOP_DLLPUBLIC int unopkg_main() if (!subcmd_gui && ! subCommand.equals(OUSTR("reinstall")) && ! subCommand.equals(OUSTR("sync")) && ! dp_misc::office_is_running()) - dp_misc::syncRepositories(false, xCmdEnv); + dp_misc::syncRepositories(xCmdEnv); if ( subcmd_add || subCommand == "remove" ) { |