[Libreoffice-commits] core.git: Branch 'feature/profilesafemode' - comphelper/source configmgr/source desktop/source desktop/uiconfig include/comphelper
Armin Le Grand
Armin.Le.Grand at cib.de
Thu Sep 15 10:48:59 UTC 2016
comphelper/source/misc/backupfilehelper.cxx | 11 +
configmgr/source/components.cxx | 43 ++++-
desktop/source/app/app.cxx | 93 +++++++++++-
desktop/uiconfig/ui/querytrytorestoreconfigurationdialog.ui | 37 ++++
include/comphelper/backupfilehelper.hxx | 14 +
5 files changed, 182 insertions(+), 16 deletions(-)
New commits:
commit 2b80416bcb49b61e0ee7764193b965bd92ba02ea
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date: Thu Sep 15 12:27:28 2016 +0200
profilesafe: Added adaptions
Added code to detect/test exceptions, tested execution,
added code to detect if _exit() was already called on all
systems to avoid writing config and creating backup in that
state (win calls destructors of static objects on _exit(),
linux does not which is intended)
Change-Id: I01df80c714ee964646da23cc3b2b081b74ecfb4b
diff --git a/comphelper/source/misc/backupfilehelper.cxx b/comphelper/source/misc/backupfilehelper.cxx
index 778f0a0..7a353b8 100644
--- a/comphelper/source/misc/backupfilehelper.cxx
+++ b/comphelper/source/misc/backupfilehelper.cxx
@@ -15,6 +15,7 @@
namespace comphelper
{
sal_uInt16 BackupFileHelper::mnMaxAllowedBackups = 10;
+ bool BackupFileHelper::mbExitWasCalled = false;
BackupFileHelper::BackupFileHelper(
const OUString& rBaseURL,
@@ -28,6 +29,16 @@ namespace comphelper
{
}
+ void BackupFileHelper::setExitWasCalled()
+ {
+ mbExitWasCalled = true;
+ }
+
+ bool BackupFileHelper::getExitWasCalled()
+ {
+ return mbExitWasCalled;
+ }
+
bool BackupFileHelper::tryPush()
{
if (isDifferentOrNew())
diff --git a/configmgr/source/components.cxx b/configmgr/source/components.cxx
index b560b0d..7790ab0 100644
--- a/configmgr/source/components.cxx
+++ b/configmgr/source/components.cxx
@@ -614,25 +614,48 @@ Components::Components(
Components::~Components()
{
- flushModifications();
+ SAL_WARN("configmgr", "################# Components::~Components() #####################");
+
+ // get flag if _exit was already called which is a sign to not to secure user config
+ const bool bExitWasCalled(comphelper::BackupFileHelper::getExitWasCalled());
+
+#ifndef WNT
+ // we can add a SAL_WARN here for other systems where the destructor gets called after
+ // an _exit() call - which should not happen. Still safe - the getExitWasCalled() is
+ // used, but a hint that _exit behaves different on a system
+ SAL_WARN_IF(bExitWasCalled, "configmgr", "Components::~Components() called after _exit() call");
+#endif
+
+ if (bExitWasCalled)
+ {
+ osl::MutexGuard g(*lock_);
+
+ if (writeThread_.is())
+ {
+ writeThread_->join();
+ }
+ }
+ else
+ {
+ flushModifications();
+ }
+
for (WeakRootSet::iterator i(roots_.begin()); i != roots_.end(); ++i) {
(*i)->setAlive(false);
}
- // test backup of registrymodifications (currently off)
- static bool bFeatureSecureUserConfig(false);
+ // test backup of registrymodifications
+ static bool bFeatureSecureUserConfig(true);
- if (bFeatureSecureUserConfig && ModificationTarget::File == modificationTarget_ && !modificationFileUrl_.isEmpty())
+ if (!bExitWasCalled &&
+ bFeatureSecureUserConfig &&
+ ModificationTarget::File == modificationTarget_ &&
+ !modificationFileUrl_.isEmpty())
{
static sal_uInt16 nNumCopies(5);
comphelper::BackupFileHelper aBackupFileHelper(modificationFileUrl_, nNumCopies);
- aBackupFileHelper.tryPush();
- static bool bTryPop(false);
- if (bTryPop)
- {
- aBackupFileHelper.tryPop();
- }
+ aBackupFileHelper.tryPush();
}
}
diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx
index 7628c7a..c2fe950 100644
--- a/desktop/source/app/app.cxx
+++ b/desktop/source/app/app.cxx
@@ -81,6 +81,7 @@
#include <comphelper/configuration.hxx>
#include <comphelper/fileurl.hxx>
#include <comphelper/processfactory.hxx>
+#include <comphelper/backupfilehelper.hxx>
#include <unotools/bootstrap.hxx>
#include <unotools/configmgr.hxx>
#include <unotools/moduleoptions.hxx>
@@ -567,6 +568,14 @@ void Desktop::Init()
{
SetBootstrapError( BE_OFFICECONFIG_BROKEN, e.Message );
}
+
+ static bool bTryHardOfficeconfigBroken(false);
+
+ if (bTryHardOfficeconfigBroken)
+ {
+ SAL_WARN("configmgr", "################# Desktop::Init() #####################");
+ SetBootstrapError(BE_OFFICECONFIG_BROKEN, OUString());
+ }
}
if ( true )
@@ -938,15 +947,87 @@ void Desktop::HandleBootstrapErrors(
}
else if ( aBootstrapError == BE_OFFICECONFIG_BROKEN )
{
- OUString msg(
- GetMsgString(
+ // test restore of registrymodifications
+ static bool bFeatureSecureUserConfig(true);
+ static sal_uInt16 nNumCopies(5);
+ bool bFireOriginalError(true);
+
+ if (bFeatureSecureUserConfig)
+ {
+ // try to asccess user layer configuration file
+ OUString conf("${CONFIGURATION_LAYERS}");
+ rtl::Bootstrap::expandMacros(conf);
+ const OUString aTokenUser("user:");
+ sal_Int32 nStart(conf.indexOf(aTokenUser));
+ OUString aUser;
+
+ if (-1 != nStart)
+ {
+ nStart += aTokenUser.getLength();
+ sal_Int32 nEnd(conf.indexOf(' ', nStart));
+
+ if (-1 == nEnd)
+ {
+ nEnd = conf.getLength();
+ }
+
+ aUser = conf.copy(nStart, nEnd - nStart);
+ aUser.startsWith("!", &aUser);
+ }
+
+ if (!aUser.isEmpty())
+ {
+ comphelper::BackupFileHelper aBackupFileHelper(aUser, nNumCopies);
+
+ if (aBackupFileHelper.isPopPossible())
+ {
+ ScopedVclPtrInstance< MessageDialog > aQueryShouldRestore(
+ Application::GetDefDialogParent(),
+ "QueryTryToRestoreConfigurationDialog",
+ "desktop/ui/querytrytorestoreconfigurationdialog.ui");
+
+ if (aQueryShouldRestore.get())
+ {
+ if (!aErrorMessage.isEmpty())
+ {
+ OUString aPrimaryText(aQueryShouldRestore->get_primary_text());
+
+ aPrimaryText += "\n(\"" + aErrorMessage + "\")";
+ aQueryShouldRestore->set_primary_text(aPrimaryText);
+ }
+
+ if (RET_YES == aQueryShouldRestore->Execute())
+ {
+ aBackupFileHelper.tryPop();
+ bFireOriginalError = false;
+ }
+ }
+ }
+ }
+ }
+
+ // set flag at BackupFileHelper to be able to know if _exit was called and
+ // actions are executed after this
+ comphelper::BackupFileHelper::setExitWasCalled();
+
+ if (bFireOriginalError)
+ {
+ OUString msg(
+ GetMsgString(
STR_CONFIG_ERR_ACCESS_GENERAL,
("A general error occurred while accessing your central"
- " configuration.")));
- if (!aErrorMessage.isEmpty()) {
- msg += "\n(\"" + aErrorMessage + "\")";
+ " configuration.")));
+ if (!aErrorMessage.isEmpty()) {
+ msg += "\n(\"" + aErrorMessage + "\")";
+ }
+ FatalError(MakeStartupErrorMessage(msg));
+ }
+ else
+ {
+ // Already presented all information to the user.
+ // just do what FatalError does at it's end
+ _exit(EXITHELPER_FATAL_ERROR);
}
- FatalError(MakeStartupErrorMessage(msg));
}
else if ( aBootstrapError == BE_USERINSTALL_FAILED )
{
diff --git a/desktop/uiconfig/ui/querytrytorestoreconfigurationdialog.ui b/desktop/uiconfig/ui/querytrytorestoreconfigurationdialog.ui
new file mode 100644
index 0000000..4c332d1
--- /dev/null
+++ b/desktop/uiconfig/ui/querytrytorestoreconfigurationdialog.ui
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkMessageDialog" id="QueryTryToRestoreConfigurationDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes">LibreOffice Startup: General Configuration Error</property>
+ <property name="resizable">False</property>
+ <property name="type_hint">dialog</property>
+ <property name="skip_taskbar_hint">True</property>
+ <property name="message_type">question</property>
+ <property name="buttons">yes-no</property>
+ <property name="text" translatable="yes">A general error occurred during startup while accessing the central configuration.</property>
+ <property name="secondary_text" translatable="yes">A Backup of your configuration was detected. Restoring the configuration might solve this problem, but is not guaranteed to work. A restart of the Program is needed.
+
+Do you want to restore the configuration?</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="messagedialog-vbox5">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="messagedialog-action_area5">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/include/comphelper/backupfilehelper.hxx b/include/comphelper/backupfilehelper.hxx
index 3061254..f407d2b 100644
--- a/include/comphelper/backupfilehelper.hxx
+++ b/include/comphelper/backupfilehelper.hxx
@@ -14,6 +14,7 @@
#include <comphelper/comphelperdllapi.h>
#include <rtl/ustring.hxx>
+#include <osl/file.hxx>
namespace comphelper
{
@@ -51,6 +52,15 @@ namespace comphelper
osl::File maBaseFile;
bool mbBaseFileIsOpen;
+ // internal flag if _exit() was called already - a hint to evtl.
+ // not create copies of potentially not well-defined data. This
+ // may be used in destructors of static instances - which unfortunately
+ // get called on WNT but not on linux. Thus I thought about encapsulating
+ // in some '#ifdefs', but it's just more safe to always do it and
+ // allows to add a SAL_WARN when one of these destructors is called
+ // after _exit()
+ static bool mbExitWasCalled;
+
// internal upper limit (max) of allowed backups
static sal_uInt16 mnMaxAllowedBackups;
@@ -69,6 +79,10 @@ namespace comphelper
*/
BackupFileHelper(const OUString& rBaseURL, sal_uInt16 nNumBackups = 5);
+ // allow to set flag when app had to call _exit()
+ static void setExitWasCalled();
+ static bool getExitWasCalled();
+
/** tries to create a new backup, if there is none yet, or if the
* last differs from the base file. It will then put a new verion
* on the 'stack' of copies and evtl. delete the oldest backup.
More information about the Libreoffice-commits
mailing list