Kaydet (Commit) b78209ae authored tarafından Markus Mohrhard's avatar Markus Mohrhard

work on adding crash report UI

Change-Id: I66f4dca3cd32381ecd52cc36490e7ee1dddf3699
Reviewed-on: https://gerrit.libreoffice.org/22566Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarMarkus Mohrhard <markus.mohrhard@googlemail.com>
üst 65694793
...@@ -105,6 +105,7 @@ ...@@ -105,6 +105,7 @@
#include <svl/itemset.hxx> #include <svl/itemset.hxx>
#include <svl/eitem.hxx> #include <svl/eitem.hxx>
#include <basic/sbstar.hxx> #include <basic/sbstar.hxx>
#include <desktop/crashreport.hxx>
#include <svtools/fontsubstconfig.hxx> #include <svtools/fontsubstconfig.hxx>
#include <svtools/accessibilityoptions.hxx> #include <svtools/accessibilityoptions.hxx>
...@@ -119,6 +120,10 @@ ...@@ -119,6 +120,10 @@
#include <tubes/manager.hxx> #include <tubes/manager.hxx>
#endif #endif
#if HAVE_FEATURE_BREAKPAD
#include <fstream>
#endif
#if defined MACOSX #if defined MACOSX
#include <errno.h> #include <errno.h>
#include <sys/wait.h> #include <sys/wait.h>
...@@ -1017,6 +1022,50 @@ bool Desktop::isUIOnSessionShutdownAllowed() ...@@ -1017,6 +1022,50 @@ bool Desktop::isUIOnSessionShutdownAllowed()
::get(); ::get();
} }
namespace {
bool crashReportInfoExists()
{
#if HAVE_FEATURE_BREAKPAD
std::string path = CrashReporter::getIniFileName();
std::ifstream aFile(path);
while (!aFile.eof())
{
std::string line;
std::getline(aFile, line);
int sep = line.find('=');
if (sep >= 0)
{
std::string key = line.substr(0, sep);
std::string value = line.substr(sep + 1);
if (key == "DumpFile")
return true;
}
}
#endif
return false;
}
#if HAVE_FEATURE_BREAKPAD
void handleCrashReport()
{
static const char SERVICENAME_CRASHREPORT[] = "com.sun.star.comp.svx.CrashReportUI";
css::uno::Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
Reference< css::frame::XSynchronousDispatch > xRecoveryUI(
xContext->getServiceManager()->createInstanceWithContext(SERVICENAME_CRASHREPORT, xContext),
css::uno::UNO_QUERY_THROW);
Reference< css::util::XURLTransformer > xURLParser =
css::util::URLTransformer::create(::comphelper::getProcessComponentContext());
css::util::URL aURL;
css::uno::Any aRet = xRecoveryUI->dispatchWithReturnValue(aURL, css::uno::Sequence< css::beans::PropertyValue >());
bool bRet = false;
aRet >>= bRet;
}
#endif
/** @short check if recovery must be started or not. /** @short check if recovery must be started or not.
...@@ -1038,7 +1087,7 @@ void impl_checkRecoveryState(bool& bCrashed , ...@@ -1038,7 +1087,7 @@ void impl_checkRecoveryState(bool& bCrashed ,
bool& bRecoveryDataExists, bool& bRecoveryDataExists,
bool& bSessionDataExists ) bool& bSessionDataExists )
{ {
bCrashed = officecfg::Office::Recovery::RecoveryInfo::Crashed::get(); bCrashed = officecfg::Office::Recovery::RecoveryInfo::Crashed::get() || crashReportInfoExists();
bool elements = officecfg::Office::Recovery::RecoveryList::get()-> bool elements = officecfg::Office::Recovery::RecoveryList::get()->
hasElements(); hasElements();
bool session bool session
...@@ -1085,6 +1134,8 @@ bool impl_callRecoveryUI(bool bEmergencySave , ...@@ -1085,6 +1134,8 @@ bool impl_callRecoveryUI(bool bEmergencySave ,
return !bEmergencySave || bRet; return !bEmergencySave || bRet;
} }
}
/* /*
* Save all open documents so they will be reopened * Save all open documents so they will be reopened
* the next time the application is started * the next time the application is started
...@@ -1092,7 +1143,6 @@ bool impl_callRecoveryUI(bool bEmergencySave , ...@@ -1092,7 +1143,6 @@ bool impl_callRecoveryUI(bool bEmergencySave ,
* returns sal_True if at least one document could be saved... * returns sal_True if at least one document could be saved...
* *
*/ */
bool Desktop::SaveTasks() bool Desktop::SaveTasks()
{ {
return impl_callRecoveryUI( return impl_callRecoveryUI(
...@@ -2218,6 +2268,11 @@ void Desktop::OpenClients() ...@@ -2218,6 +2268,11 @@ void Desktop::OpenClients()
// need some time, where the user won't see any results and wait for finishing the office startup... // need some time, where the user won't see any results and wait for finishing the office startup...
bool bAllowRecoveryAndSessionManagement = ( !rArgs.IsNoRestore() ) && ( !rArgs.IsHeadless() ); bool bAllowRecoveryAndSessionManagement = ( !rArgs.IsNoRestore() ) && ( !rArgs.IsHeadless() );
#if HAVE_FEATURE_BREAKPAD
if (crashReportInfoExists())
handleCrashReport();
#endif
if ( ! bAllowRecoveryAndSessionManagement ) if ( ! bAllowRecoveryAndSessionManagement )
{ {
try try
...@@ -2292,6 +2347,9 @@ void Desktop::OpenClients() ...@@ -2292,6 +2347,9 @@ void Desktop::OpenClients()
} }
} }
} }
#if HAVE_FEATURE_BREAKPAD
CrashReporter::writeCommonInfo();
#endif
OfficeIPCThread::EnableRequests(); OfficeIPCThread::EnableRequests();
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include <desktop/crashreport.hxx> #include <desktop/crashreport.hxx>
#include <config_version.h>
#include <string> #include <string>
#include <fstream> #include <fstream>
...@@ -27,7 +29,18 @@ void CrashReporter::AddKeyValue(const OUString& rKey, const OUString& rValue) ...@@ -27,7 +29,18 @@ void CrashReporter::AddKeyValue(const OUString& rKey, const OUString& rValue)
#endif #endif
const char* CrashReporter::getIniFileName() void CrashReporter::writeCommonInfo()
{
// limit the amount of code that needs to be executed before the crash reporting
std::string ini_path = CrashReporter::getIniFileName();
std::ofstream minidump_file(ini_path, std::ios_base::trunc);
minidump_file << "ProductName=LibreOffice\n";
minidump_file << "Version=" << LIBO_VERSION_DOTTED << "\n";
minidump_file << "URL=" << "http://127.0.0.1:8000/submit" << "\n";
minidump_file.close();
}
std::string CrashReporter::getIniFileName()
{ {
// TODO: we need a generic solution for the location // TODO: we need a generic solution for the location
return "/tmp/dump.ini"; return "/tmp/dump.ini";
......
...@@ -65,14 +65,6 @@ ...@@ -65,14 +65,6 @@
#if HAVE_FEATURE_BREAKPAD #if HAVE_FEATURE_BREAKPAD
OString getLibDir()
{
OUString aOriginal = "$BRAND_BASE_DIR/" LIBO_LIBEXEC_FOLDER;
rtl::Bootstrap::expandMacros(aOriginal);
return rtl::OUStringToOString(aOriginal, RTL_TEXTENCODING_UTF8);
}
#if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID #if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* /*context*/, bool succeeded) static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* /*context*/, bool succeeded)
{ {
...@@ -80,11 +72,7 @@ static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, ...@@ -80,11 +72,7 @@ static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,
std::ofstream minidump_file(ini_path, std::ios_base::app); std::ofstream minidump_file(ini_path, std::ios_base::app);
minidump_file << "DumpFile=" << descriptor.path() << "\n";; minidump_file << "DumpFile=" << descriptor.path() << "\n";;
minidump_file.close(); minidump_file.close();
// send the minidump to the server (not yet implemented) SAL_WARN("crashreport", "minidump generated: " << descriptor.path());
SAL_WARN("destkop.crashreport", "minidump generated: " << descriptor.path());
OString aCommand = getLibDir().copy(7) + "/minidump_upload " + ini_path.c_str();
int retVal = std::system(aCommand.getStr());
SAL_WARN_IF(retVal != 0, "destkop.crashreport", "Failed to upload minidump. Error Code: " << retVal);
return succeeded; return succeeded;
} }
#endif #endif
...@@ -93,14 +81,6 @@ static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, ...@@ -93,14 +81,6 @@ static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,
extern "C" int DESKTOP_DLLPUBLIC soffice_main() extern "C" int DESKTOP_DLLPUBLIC soffice_main()
{ {
#if HAVE_FEATURE_BREAKPAD #if HAVE_FEATURE_BREAKPAD
//limit the amount of code that needs to be executed before the crash reporting
std::string ini_path = CrashReporter::getIniFileName();
std::ofstream minidump_file(ini_path, std::ios_base::trunc);
minidump_file << "ProductName=LibreOffice\n";
minidump_file << "Version=" LIBO_VERSION_DOTTED "\n";
minidump_file << "URL=http://127.0.0.1:8000/submit\n";
minidump_file.close();
#if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID #if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
google_breakpad::MinidumpDescriptor descriptor("/tmp"); google_breakpad::MinidumpDescriptor descriptor("/tmp");
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <config_features.h> #include <config_features.h>
#include <map> #include <map>
#include <string>
/** /**
* Provides access to the crash reporter service. * Provides access to the crash reporter service.
...@@ -32,7 +33,9 @@ class CRASHREPORT_DLLPUBLIC CrashReporter ...@@ -32,7 +33,9 @@ class CRASHREPORT_DLLPUBLIC CrashReporter
public: public:
static void AddKeyValue(const OUString& rKey, const OUString& rValue); static void AddKeyValue(const OUString& rKey, const OUString& rValue);
static const char* getIniFileName(); static std::string getIniFileName();
static void writeCommonInfo();
private: private:
......
...@@ -46,6 +46,8 @@ $(eval $(call gb_Library_use_libraries,svx,\ ...@@ -46,6 +46,8 @@ $(eval $(call gb_Library_use_libraries,svx,\
comphelper \ comphelper \
cppuhelper \ cppuhelper \
cppu \ cppu \
$(call gb_Helper_optional,BREAKPAD, \
crashreport) \
$(call gb_Helper_optional,DBCONNECTIVITY, \ $(call gb_Helper_optional,DBCONNECTIVITY, \
dbtools) \ dbtools) \
drawinglayer \ drawinglayer \
...@@ -108,6 +110,9 @@ $(eval $(call gb_Library_add_exception_objects,svx,\ ...@@ -108,6 +110,9 @@ $(eval $(call gb_Library_add_exception_objects,svx,\
svx/source/dialog/_contdlg \ svx/source/dialog/_contdlg \
svx/source/dialog/contwnd \ svx/source/dialog/contwnd \
svx/source/dialog/compressgraphicdialog \ svx/source/dialog/compressgraphicdialog \
$(call gb_Helper_optional,BREAKPAD, \
svx/source/dialog/crashreportdlg \
svx/source/dialog/crashreportui) \
svx/source/dialog/ctredlin \ svx/source/dialog/ctredlin \
svx/source/dialog/databaseregistrationui \ svx/source/dialog/databaseregistrationui \
svx/source/dialog/dialcontrol \ svx/source/dialog/dialcontrol \
......
...@@ -22,6 +22,7 @@ $(eval $(call gb_UIConfig_add_uifiles,svx,\ ...@@ -22,6 +22,7 @@ $(eval $(call gb_UIConfig_add_uifiles,svx,\
svx/uiconfig/ui/chinesedictionary \ svx/uiconfig/ui/chinesedictionary \
svx/uiconfig/ui/colorwindow \ svx/uiconfig/ui/colorwindow \
svx/uiconfig/ui/compressgraphicdialog \ svx/uiconfig/ui/compressgraphicdialog \
svx/uiconfig/ui/crashreportdlg \
svx/uiconfig/ui/datanavigator \ svx/uiconfig/ui/datanavigator \
svx/uiconfig/ui/deleteheaderdialog \ svx/uiconfig/ui/deleteheaderdialog \
svx/uiconfig/ui/deletefooterdialog \ svx/uiconfig/ui/deletefooterdialog \
......
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "crashreportdlg.hxx"
#include <config_folders.h>
#include <rtl/bootstrap.hxx>
#include <desktop/crashreport.hxx>
CrashReportDialog::CrashReportDialog(vcl::Window* pParent):
Dialog(pParent, "CrashReportDialog",
"svx/ui/crashreportdlg.ui")
{
get(mpBtnSend, "btn_send");
get(mpBtnCancel, "btn_cancel");
mpBtnSend->SetClickHdl(LINK(this, CrashReportDialog, BtnHdl));
mpBtnCancel->SetClickHdl(LINK(this, CrashReportDialog, BtnHdl));
}
CrashReportDialog::~CrashReportDialog()
{
disposeOnce();
}
void CrashReportDialog::dispose()
{
mpBtnSend.clear();
mpBtnCancel.clear();
Dialog::dispose();
}
namespace {
OString getLibDir()
{
OUString aOriginal = "$BRAND_BASE_DIR/" LIBO_LIBEXEC_FOLDER;
rtl::Bootstrap::expandMacros(aOriginal);
return rtl::OUStringToOString(aOriginal, RTL_TEXTENCODING_UTF8);
}
}
IMPL_LINK_TYPED(CrashReportDialog, BtnHdl, Button*, pBtn, void)
{
if (pBtn == mpBtnSend.get())
{
std::string ini_path = CrashReporter::getIniFileName();
OString aCommand = getLibDir().copy(7) + "/minidump_upload " + ini_path.c_str();
int retVal = std::system(aCommand.getStr());
SAL_WARN_IF(retVal != 0, "crashreport", "Failed to upload minidump. Error Code: " << retVal);
Close();
}
else if (pBtn == mpBtnCancel.get())
{
Close();
}
else
{
assert(false);
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef INCLUDED_SVX_SOURCE_DIALOG_CRASHREPORTDLG_HXX
#define INCLUDED_SVX_SOURCE_DIALOG_CRASHREPORTDLG_HXX
#include <vcl/dialog.hxx>
#include <vcl/button.hxx>
class CrashReportDialog : public Dialog
{
public:
CrashReportDialog(vcl::Window* pParent);
~CrashReportDialog();
virtual void dispose() override;
private:
VclPtr<Button> mpBtnSend;
VclPtr<Button> mpBtnCancel;
DECL_LINK_TYPED(BtnHdl, Button*, void);
};
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <cppuhelper/implbase.hxx>
#include <com/sun/star/frame/XSynchronousDispatch.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <comphelper/processfactory.hxx>
#include <cppuhelper/supportsservice.hxx>
#include <vcl/svapp.hxx>
#include "crashreportdlg.hxx"
namespace {
class CrashReportUI : public ::cppu::WeakImplHelper< css::lang::XServiceInfo ,
css::frame::XSynchronousDispatch > // => XDispatch!
{
public:
CrashReportUI(const css::uno::Reference< css::uno::XComponentContext >& xContext);
virtual ~CrashReportUI();
// css.lang.XServiceInfo
virtual OUString SAL_CALL getImplementationName()
throw(css::uno::RuntimeException, std::exception) override;
virtual sal_Bool SAL_CALL supportsService(const OUString& sServiceName)
throw(css::uno::RuntimeException, std::exception) override;
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames()
throw(css::uno::RuntimeException, std::exception) override;
virtual css::uno::Any SAL_CALL dispatchWithReturnValue(const css::util::URL& aURL,
const css::uno::Sequence< css::beans::PropertyValue >& lArguments )
throw(css::uno::RuntimeException, std::exception) override;
private:
css::uno::Reference< css::uno::XComponentContext > mxContext;
};
CrashReportUI::CrashReportUI(const css::uno::Reference<css::uno::XComponentContext>& xContext):
mxContext(xContext)
{
}
CrashReportUI::~CrashReportUI()
{
}
OUString SAL_CALL CrashReportUI::getImplementationName()
throw(css::uno::RuntimeException, std::exception)
{
return OUString("com.sun.star.comp.svx.CrashReportUI");
}
sal_Bool SAL_CALL CrashReportUI::supportsService(const OUString& sServiceName)
throw(css::uno::RuntimeException, std::exception)
{
return cppu::supportsService(this, sServiceName);
}
css::uno::Sequence< OUString > SAL_CALL CrashReportUI::getSupportedServiceNames()
throw(css::uno::RuntimeException, std::exception)
{
css::uno::Sequence< OUString > lServiceNames { "com.sun.star.dialog.CrashReportUI" };
return lServiceNames;
}
css::uno::Any SAL_CALL CrashReportUI::dispatchWithReturnValue(const css::util::URL&,
const css::uno::Sequence< css::beans::PropertyValue >& )
throw(css::uno::RuntimeException, std::exception)
{
SolarMutexGuard aGuard;
css::uno::Any aRet;
ScopedVclPtrInstance<CrashReportDialog> xDialog(new CrashReportDialog(nullptr));
xDialog->Execute();
return aRet;
}
}
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
com_sun_star_comp_svx_CrashReportUI_get_implementation(
css::uno::XComponentContext *context,
css::uno::Sequence<css::uno::Any> const &)
{
return cppu::acquire(new CrashReportUI(context));
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<interface>
<requires lib="gtk+" version="3.12"/>
<object class="GtkDialog" id="CrashReportDialog">
<property name="can_focus">False</property>
<property name="type_hint">dialog</property>
<child internal-child="vbox">
<object class="GtkBox" id="dialog-vbox1">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="dialog-action_area1">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="btn_send">
<property name="label" translatable="yes">Send report</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btn_cancel">
<property name="label" translatable="yes">Don't send report</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">We are sorry but it seems that LibreOffice crashed the last time.
You can help us fix this issue by sending the crash report to the
LibreOffice crash reporting server.</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
...@@ -32,6 +32,10 @@ ...@@ -32,6 +32,10 @@
constructor="com_sun_star_comp_svx_RecoveryUI_get_implementation"> constructor="com_sun_star_comp_svx_RecoveryUI_get_implementation">
<service name="com.sun.star.dialog.RecoveryUI"/> <service name="com.sun.star.dialog.RecoveryUI"/>
</implementation> </implementation>
<implementation name="com.sun.star.comp.svx.CrashReportUI"
constructor="com_sun_star_comp_svx_CrashReportUI_get_implementation">
<service name="com.sun.star.dialog.CrashReportUI"/>
</implementation>
<implementation name="com.sun.star.drawing.EnhancedCustomShapeEngine" <implementation name="com.sun.star.drawing.EnhancedCustomShapeEngine"
constructor="com_sun_star_drawing_EnhancedCustomShapeEngine_get_implementation"> constructor="com_sun_star_drawing_EnhancedCustomShapeEngine_get_implementation">
<service name="com.sun.star.drawing.CustomShapeEngine"/> <service name="com.sun.star.drawing.CustomShapeEngine"/>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment