summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2012-08-09 13:29:22 +0200
committerPetr Mladek <pmladek@suse.cz>2012-08-10 17:02:09 +0200
commitfd75125424b3dda0e77076d5b1709224ec22a345 (patch)
tree4b304cd598373a8d2b3715189a392a94857f0010
parent006e90e29c6ca768e3a5d8d2a558a63b04817c4b (diff)
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 Signed-off-by: Petr Mladek <pmladek@suse.cz>
-rw-r--r--desktop/inc/app.hxx4
-rw-r--r--desktop/source/app/app.cxx153
-rw-r--r--desktop/source/app/check_ext_deps.cxx19
-rw-r--r--desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx2
-rw-r--r--desktop/source/deployment/inc/dp_misc.h3
-rw-r--r--desktop/source/deployment/manager/dp_extensionmanager.cxx2
-rw-r--r--desktop/source/deployment/misc/dp_misc.cxx5
-rw-r--r--desktop/source/pkgchk/unopkg/unopkg_app.cxx2
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" )
{