diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2012-08-09 13:29:22 +0200 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2012-08-09 14:36:54 +0200 |
commit | 5300f6f711c2167931d45248c1b72dbce3a7df38 (patch) | |
tree | 6d58ac854c58fed61b26c43942990ae0b7110361 /desktop | |
parent | Related fdo#53006: Do not instantiate service manager too early (diff) | |
download | core-5300f6f711c2167931d45248c1b72dbce3a7df38.tar.gz core-5300f6f711c2167931d45248c1b72dbce3a7df38.zip |
fdo#53006: Remove user/extensions/bundled cache after upgrade
... to clean out all sorts of inconsitencies that can have accrued there over
time apparently due to how the mechanism of copying share/prereg/bundled worked,
and to work around stale $BUNDLED_EXTENSIONS_PREREG references in a better way
than the previous 81fd6b084b0f3c0eb5a97c77592f5ceb21d2dfb1 "fdo#53006 Force
reinstall of all bundled extensions on upgrade."
See the comment on refreshBundledExtensionsDir for how, at least in theory, that
functionality could be removed again in the future.
This effectively reverts 2d2b19dea1ab401b1b4971ff5b12b87bb11fd666 "Force
ExtensionManager resync when the implementation changes" and
81fd6b084b0f3c0eb5a97c77592f5ceb21d2dfb1 "fdo#53006 Force reinstall of all
bundled extensions on upgrade" (the latter at least on master; it had never been
cherry-picked to libreoffice-3-6), which it obsoletes.
Change-Id: I8f80c07a06ec9d53b03813338eeff7d7757c9d4d
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 | 9 | ||||
-rw-r--r-- | desktop/source/deployment/manager/dp_extensionmanager.hxx | 1 | ||||
-rw-r--r-- | desktop/source/deployment/manager/dp_manager.cxx | 22 | ||||
-rw-r--r-- | desktop/source/deployment/manager/dp_manager.h | 2 | ||||
-rw-r--r-- | desktop/source/deployment/misc/dp_misc.cxx | 7 | ||||
-rw-r--r-- | desktop/source/pkgchk/unopkg/unopkg_app.cxx | 2 |
11 files changed, 176 insertions, 48 deletions
diff --git a/desktop/inc/app.hxx b/desktop/inc/app.hxx index 06dc4c76d027..22866ef6b689 100644 --- a/desktop/inc/app.hxx +++ b/desktop/inc/app.hxx @@ -126,14 +126,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 c3152ee79805..84f60b8eef55 100644 --- a/desktop/source/app/app.cxx +++ b/desktop/source/app/app.cxx @@ -152,6 +152,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 >()); + } + 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() @@ -633,6 +772,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 @@ -1607,14 +1748,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 df358d791a69..2410c1ba8670 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 290df139a250..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)); @@ -1278,7 +1278,7 @@ void ExtensionManager::synchronizeBundledPrereg( Reference<deploy::XPackageManager> xMgr = xPackageManagerFactory->getPackageManager(OUSTR("bundled_prereg")); - xMgr->synchronize(false, xAbortChannel, xCmdEnv); + xMgr->synchronize(xAbortChannel, xCmdEnv); progressBundled.update(OUSTR("\n\n")); uno::Sequence<Reference<deploy::XPackage> > extensions = xMgr->getDeployedPackages( @@ -1317,7 +1317,6 @@ void ExtensionManager::synchronizeBundledPrereg( } sal_Bool ExtensionManager::synchronize( - sal_Bool forceBundled, Reference<task::XAbortChannel> const & xAbortChannel, Reference<ucb::XCommandEnvironment> const & xCmdEnv ) throw (deploy::DeploymentException, @@ -1334,13 +1333,13 @@ sal_Bool ExtensionManager::synchronize( String sSynchronizingShared(StrSyncRepository::get()); sSynchronizingShared.SearchAndReplaceAllAscii( "%NAME", OUSTR("shared")); dp_misc::ProgressLevel progressShared(xCmdEnv, sSynchronizingShared); - bModified = getSharedRepository()->synchronize(false, xAbortChannel, xCmdEnv); + bModified = getSharedRepository()->synchronize(xAbortChannel, xCmdEnv); progressShared.update(OUSTR("\n\n")); String sSynchronizingBundled(StrSyncRepository::get()); sSynchronizingBundled.SearchAndReplaceAllAscii( "%NAME", OUSTR("bundled")); dp_misc::ProgressLevel progressBundled(xCmdEnv, sSynchronizingBundled); - bModified |= getBundledRepository()->synchronize(forceBundled, xAbortChannel, xCmdEnv); + bModified |= getBundledRepository()->synchronize(xAbortChannel, xCmdEnv); progressBundled.update(OUSTR("\n\n")); //Always determine the active extension. This is necessary for the diff --git a/desktop/source/deployment/manager/dp_extensionmanager.hxx b/desktop/source/deployment/manager/dp_extensionmanager.hxx index 05fcde825fbf..800d91f437b6 100644 --- a/desktop/source/deployment/manager/dp_extensionmanager.hxx +++ b/desktop/source/deployment/manager/dp_extensionmanager.hxx @@ -193,7 +193,6 @@ public: css::uno::RuntimeException); virtual sal_Bool SAL_CALL synchronize( - sal_Bool forceBundled, css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) throw (css::deployment::DeploymentException, diff --git a/desktop/source/deployment/manager/dp_manager.cxx b/desktop/source/deployment/manager/dp_manager.cxx index d7c8a2a3a154..a088f516c8a7 100644 --- a/desktop/source/deployment/manager/dp_manager.cxx +++ b/desktop/source/deployment/manager/dp_manager.cxx @@ -1248,7 +1248,6 @@ void PackageManagerImpl::reinstallDeployedPackages( return m_readOnly; } bool PackageManagerImpl::synchronizeRemovedExtensions( - bool force, Reference<task::XAbortChannel> const & xAbortChannel, Reference<css::ucb::XCommandEnvironment> const & xCmdEnv) { @@ -1272,19 +1271,15 @@ bool PackageManagerImpl::synchronizeRemovedExtensions( if (bShared) url = makeURLAppendSysPathSegment( url + OUSTR("_"), i->second.fileName); - bool bRemoved = force; - + bool bRemoved = false; //Check if the URL to the extension is still the same - if (!bRemoved) - { - ::ucbhelper::Content contentExtension; + ::ucbhelper::Content contentExtension; - if (!create_ucb_content( - &contentExtension, url, - Reference<XCommandEnvironment>(), false)) - { - bRemoved = true; - } + if (!create_ucb_content( + &contentExtension, url, + Reference<XCommandEnvironment>(), false)) + { + bRemoved = true; } //The folder is in the extension database, but it can still be deleted. @@ -1469,7 +1464,6 @@ bool PackageManagerImpl::synchronizeAddedExtensions( } sal_Bool PackageManagerImpl::synchronize( - sal_Bool force, Reference<task::XAbortChannel> const & xAbortChannel, Reference<css::ucb::XCommandEnvironment> const & xCmdEnv) throw (css::deployment::DeploymentException, @@ -1482,7 +1476,7 @@ sal_Bool PackageManagerImpl::synchronize( if (m_context.equals(OUSTR("user"))) return bModified; bModified |= - synchronizeRemovedExtensions(force, xAbortChannel, xCmdEnv); + synchronizeRemovedExtensions(xAbortChannel, xCmdEnv); bModified |= synchronizeAddedExtensions(xAbortChannel, xCmdEnv); return bModified; diff --git a/desktop/source/deployment/manager/dp_manager.h b/desktop/source/deployment/manager/dp_manager.h index cb3cbe82357b..b88b51111062 100644 --- a/desktop/source/deployment/manager/dp_manager.h +++ b/desktop/source/deployment/manager/dp_manager.h @@ -82,7 +82,6 @@ class PackageManagerImpl : private ::dp_misc::MutexHolder, public t_pm_helper css::uno::Reference<css::deployment::XPackage> const & package); bool synchronizeRemovedExtensions( - bool force, css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); @@ -240,7 +239,6 @@ public: throw (::com::sun::star::uno::RuntimeException); virtual ::sal_Bool SAL_CALL synchronize( - sal_Bool force, css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) throw (css::deployment::DeploymentException, diff --git a/desktop/source/deployment/misc/dp_misc.cxx b/desktop/source/deployment/misc/dp_misc.cxx index 6f47e3df9c2c..ba9c98384c1d 100644 --- a/desktop/source/deployment/misc/dp_misc.cxx +++ b/desktop/source/deployment/misc/dp_misc.cxx @@ -546,7 +546,7 @@ void TRACE(::rtl::OUString 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() ); @@ -557,8 +557,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 = @@ -568,7 +567,7 @@ void syncRepositories( if (xExtensionManager.is()) { bModified = xExtensionManager->synchronize( - force, Reference<task::XAbortChannel>(), xCmdEnv); + Reference<task::XAbortChannel>(), xCmdEnv); } } 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" ) { |