LibreOffice Module desktop (master)  1
crashreport.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  */
9 
10 #include <desktop/crashreport.hxx>
11 #include <rtl/bootstrap.hxx>
12 #include <osl/file.hxx>
15 #include <unotools/bootstrap.hxx>
17 #include <desktop/minidump.hxx>
18 
19 #include <config_version.h>
20 #include <config_folders.h>
21 
22 #include <string>
23 
24 
25 #if HAVE_FEATURE_BREAKPAD
26 
27 #include <fstream>
28 #if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
29 #include <client/linux/handler/exception_handler.h>
30 #elif defined WNT
31 #if defined __clang__
32 #pragma clang diagnostic push
33 #pragma clang diagnostic ignored "-Wmicrosoft-enum-value"
34 #endif
35 #include <client/windows/handler/exception_handler.h>
36 #if defined __clang__
37 #pragma clang diagnostic pop
38 #endif
39 #endif
40 
41 osl::Mutex CrashReporter::maMutex;
42 google_breakpad::ExceptionHandler* CrashReporter::mpExceptionHandler = nullptr;
43 bool CrashReporter::mbInit = false;
44 CrashReporter::vmaKeyValues CrashReporter::maKeyValues;
45 
46 
47 void CrashReporter::writeToFile(std::ios_base::openmode Openmode)
48 {
49  std::ofstream ini_file(getIniFileName(), Openmode);
50 
51  for (auto& keyValue : maKeyValues)
52  {
53  ini_file << OUStringToOString(keyValue.first, RTL_TEXTENCODING_UTF8) << "=";
54  ini_file << OUStringToOString(keyValue.second, RTL_TEXTENCODING_UTF8) << "\n";
55  }
56 
57  maKeyValues.clear();
58  ini_file.close();
59 }
60 
61 void CrashReporter::addKeyValue(const OUString& rKey, const OUString& rValue, tAddKeyHandling AddKeyHandling)
62 {
63  osl::MutexGuard aGuard(maMutex);
64 
65  if (IsDumpEnable())
66  {
67  if (!rKey.isEmpty())
68  maKeyValues.push_back(mpair(rKey, rValue));
69 
70  if (AddKeyHandling != AddItem)
71  {
72  if (mbInit)
73  writeToFile(std::ios_base::app);
74  else if (AddKeyHandling == Create)
75  writeCommonInfo();
76  }
77  }
78 }
79 
80 void CrashReporter::writeCommonInfo()
81 {
83 
84  const OUString protocol = "https";
85  const OUString url = "crashreport.libreoffice.org";
86  const sal_Int32 port = 443;
87 
88  const ucbhelper::InternetProxyServer proxy_server = proxy_decider.getProxy(protocol, url, port);
89 
90  // save the new Keys
91  vmaKeyValues atlast = maKeyValues;
92  // clear the keys, the following Keys should be at the begin
93  maKeyValues.clear();
94 
95  // limit the amount of code that needs to be executed before the crash reporting
96  addKeyValue("ProductName", "LibreOffice", AddItem);
97  addKeyValue("Version", LIBO_VERSION_DOTTED, AddItem);
99  addKeyValue("URL", protocol + "://" + url + "/submit/", AddItem);
100 
101  if (proxy_server.aName != OUString())
102  {
103  addKeyValue("Proxy", proxy_server.aName + ":" + OUString::number(proxy_server.nPort), AddItem);
104  }
105 
106  // write the new keys at the end
107  maKeyValues.insert(maKeyValues.end(), atlast.begin(), atlast.end());
108 
109  mbInit = true;
110 
111  writeToFile(std::ios_base::trunc);
112 
113  updateMinidumpLocation();
114 }
115 
116 
117 namespace {
118 
119 OUString getCrashDirectory()
120 {
121  OUString aCrashURL;
122  rtl::Bootstrap::get("CrashDirectory", aCrashURL);
123  // Need to convert to URL in case of user-defined path
124  osl::FileBase::getFileURLFromSystemPath(aCrashURL, aCrashURL);
125 
126  if (aCrashURL.isEmpty()) { // Fall back to user profile
127  aCrashURL = "${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/crash/";
128  rtl::Bootstrap::expandMacros(aCrashURL);
129  }
130 
131  if (!aCrashURL.endsWith("/"))
132  aCrashURL += "/";
133 
134  osl::Directory::create(aCrashURL);
135  OUString aCrashPath;
136  osl::FileBase::getSystemPathFromFileURL(aCrashURL, aCrashPath);
137  return aCrashPath;
138 }
139 
140 }
141 
142 void CrashReporter::updateMinidumpLocation()
143 {
144 #if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
145  OUString aURL = getCrashDirectory();
146  OString aOStringUrl = OUStringToOString(aURL, RTL_TEXTENCODING_UTF8);
147  google_breakpad::MinidumpDescriptor descriptor(aOStringUrl.getStr());
148  mpExceptionHandler->set_minidump_descriptor(descriptor);
149 #elif defined WNT
150  OUString aURL = getCrashDirectory();
151  mpExceptionHandler->set_dump_path(o3tl::toW(aURL.getStr()));
152 #endif
153 }
154 
155 bool CrashReporter::crashReportInfoExists()
156 {
157  static bool first = true;
158  static bool InfoExist = false;
159 
160  if (first)
161  {
162  first = false;
163  InfoExist = crashreport::readConfig(CrashReporter::getIniFileName(), nullptr);
164  }
165 
166  return InfoExist;
167 }
168 
169 bool CrashReporter::readSendConfig(std::string& response)
170 {
171  return crashreport::readConfig(CrashReporter::getIniFileName(), &response);
172 }
173 
174 void CrashReporter::storeExceptionHandler(google_breakpad::ExceptionHandler* pExceptionHandler)
175 {
176  if(IsDumpEnable())
177  mpExceptionHandler = pExceptionHandler;
178 }
179 
180 
181 
182 bool CrashReporter::IsDumpEnable()
183 {
184  OUString sToken;
185  OString sEnvVar(std::getenv("CRASH_DUMP_ENABLE"));
186  bool bEnable = true; // default, always on
187  // read configuration item 'CrashDumpEnable' -> bool on/off
188  if (rtl::Bootstrap::get("CrashDumpEnable", sToken) && sEnvVar.isEmpty())
189  {
190  bEnable = sToken.toBoolean();
191  }
192 
193  return bEnable;
194 }
195 
196 
197 std::string CrashReporter::getIniFileName()
198 {
199  OUString url = getCrashDirectory() + "dump.ini";
200  OString aUrl = OUStringToOString(url, RTL_TEXTENCODING_UTF8);
201  std::string aRet(aUrl.getStr());
202  return aRet;
203 }
204 
205 
206 #endif //HAVE_FEATURE_BREAKPAD
207 
208 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::deployment::XPackageRegistry > create(css::uno::Reference< css::deployment::XPackageRegistry > const &xRootRegistry, OUString const &context, OUString const &cachePath, css::uno::Reference< css::uno::XComponentContext > const &xComponentContext)
bool readConfig(const std::string &iniPath, std::string *response)
Read+Send, Test and send info from the Dump.ini .
Definition: minidump.cxx:194
#define SAL_CONFIGFILE(name)
OString OUStringToOString(const OUString &str, ConnectionSettings const *settings)
Reference< XComponentContext > getProcessComponentContext()
void SAL_CALL first(const css::awt::SpinEvent &rEvent) override
static OUString getBuildIdData(OUString const &_sDefault)
static void addKeyValue(SAL_UNUSED_PARAMETER const OUString &, SAL_UNUSED_PARAMETER const OUString &, SAL_UNUSED_PARAMETER tAddKeyHandling)
Definition: crashreport.hxx:87