[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