diff --git a/.gitignore b/.gitignore index 93a8fbca1ae..6369b049a28 100644 --- a/.gitignore +++ b/.gitignore @@ -58,7 +58,6 @@ CMakeLists.txt.user* /src/plugins/**/*.json !/src/plugins/**/wizard.json /src/plugins/coreplugin/ide_version.h -/src/libs/qt-breakpad/bin /.cmake/ /.vs/ app_version.h diff --git a/src/app/main.cpp b/src/app/main.cpp index db5b46c437a..b875850722a 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -46,10 +46,6 @@ #include #include -#ifdef ENABLE_QT_BREAKPAD -#include -#endif - #ifdef ENABLE_CRASHPAD #define NOMINMAX #include "client/crashpad_client.h" @@ -698,13 +694,11 @@ int main(int argc, char **argv) const QString libexecPath = QCoreApplication::applicationDirPath() + '/' + RELATIVE_LIBEXEC_PATH; -#ifdef ENABLE_QT_BREAKPAD - QtSystemExceptionHandler systemExceptionHandler(libexecPath); -#else + // Display a backtrace once a serious signal is delivered (Linux only). CrashHandlerSetup setupCrashHandler(Core::Constants::IDE_DISPLAY_NAME, - CrashHandlerSetup::EnableRestart, libexecPath); -#endif + CrashHandlerSetup::EnableRestart, + libexecPath); #ifdef ENABLE_CRASHPAD bool crashReportingEnabled = settings->value("CrashReportingEnabled", false).toBool(); diff --git a/src/libs/qt-breakpad/poster/__init__.py b/src/libs/qt-breakpad/poster/__init__.py deleted file mode 100644 index e963d70b960..00000000000 --- a/src/libs/qt-breakpad/poster/__init__.py +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (c) 2010 Chris AtLee -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -"""poster module - -Support for streaming HTTP uploads, and multipart/form-data encoding - -```poster.version``` is a 3-tuple of integers representing the version number. -New releases of poster will always have a version number that compares greater -than an older version of poster. -New in version 0.6.""" - -import poster.streaminghttp -import poster.encode - -version = (0, 8, 0) # Thanks JP! diff --git a/src/libs/qt-breakpad/poster/encode.py b/src/libs/qt-breakpad/poster/encode.py deleted file mode 100644 index fbc4e764527..00000000000 --- a/src/libs/qt-breakpad/poster/encode.py +++ /dev/null @@ -1,433 +0,0 @@ -# Copyright (c) 2010 Chris AtLee -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -"""multipart/form-data encoding module - -This module provides functions that faciliate encoding name/value pairs -as multipart/form-data suitable for a HTTP POST or PUT request. - -multipart/form-data is the standard way to upload files over HTTP""" - -__all__ = ['gen_boundary', 'encode_and_quote', 'MultipartParam', - 'encode_string', 'encode_file_header', 'get_body_size', 'get_headers', - 'multipart_encode'] - -try: - import uuid - def gen_boundary(): - """Returns a random string to use as the boundary for a message""" - return uuid.uuid4().hex -except ImportError: - import random, sha - def gen_boundary(): - """Returns a random string to use as the boundary for a message""" - bits = random.getrandbits(160) - return sha.new(str(bits)).hexdigest() - -import urllib, re, os, mimetypes -try: - from email.header import Header -except ImportError: - # Python 2.4 - from email.Header import Header - -def encode_and_quote(data): - """If ``data`` is unicode, return urllib.quote_plus(data.encode("utf-8")) - otherwise return urllib.quote_plus(data)""" - if data is None: - return None - - if isinstance(data, unicode): - data = data.encode("utf-8") - return urllib.quote_plus(data) - -def _strify(s): - """If s is a unicode string, encode it to UTF-8 and return the results, - otherwise return str(s), or None if s is None""" - if s is None: - return None - if isinstance(s, unicode): - return s.encode("utf-8") - return str(s) - -class MultipartParam(object): - """Represents a single parameter in a multipart/form-data request - - ``name`` is the name of this parameter. - - If ``value`` is set, it must be a string or unicode object to use as the - data for this parameter. - - If ``filename`` is set, it is what to say that this parameter's filename - is. Note that this does not have to be the actual filename any local file. - - If ``filetype`` is set, it is used as the Content-Type for this parameter. - If unset it defaults to "text/plain; charset=utf8" - - If ``filesize`` is set, it specifies the length of the file ``fileobj`` - - If ``fileobj`` is set, it must be a file-like object that supports - .read(). - - Both ``value`` and ``fileobj`` must not be set, doing so will - raise a ValueError assertion. - - If ``fileobj`` is set, and ``filesize`` is not specified, then - the file's size will be determined first by stat'ing ``fileobj``'s - file descriptor, and if that fails, by seeking to the end of the file, - recording the current position as the size, and then by seeking back to the - beginning of the file. - - ``cb`` is a callable which will be called from iter_encode with (self, - current, total), representing the current parameter, current amount - transferred, and the total size. - """ - def __init__(self, name, value=None, filename=None, filetype=None, - filesize=None, fileobj=None, cb=None): - self.name = Header(name).encode() - self.value = _strify(value) - if filename is None: - self.filename = None - else: - if isinstance(filename, unicode): - # Encode with XML entities - self.filename = filename.encode("ascii", "xmlcharrefreplace") - else: - self.filename = str(filename) - self.filename = self.filename.encode("string_escape").\ - replace('"', '\\"') - self.filetype = _strify(filetype) - - self.filesize = filesize - self.fileobj = fileobj - self.cb = cb - - if self.value is not None and self.fileobj is not None: - raise ValueError("Only one of value or fileobj may be specified") - - if fileobj is not None and filesize is None: - # Try and determine the file size - try: - self.filesize = os.fstat(fileobj.fileno()).st_size - except (OSError, AttributeError): - try: - fileobj.seek(0, 2) - self.filesize = fileobj.tell() - fileobj.seek(0) - except: - raise ValueError("Could not determine filesize") - - def __cmp__(self, other): - attrs = ['name', 'value', 'filename', 'filetype', 'filesize', 'fileobj'] - myattrs = [getattr(self, a) for a in attrs] - oattrs = [getattr(other, a) for a in attrs] - return cmp(myattrs, oattrs) - - def reset(self): - if self.fileobj is not None: - self.fileobj.seek(0) - elif self.value is None: - raise ValueError("Don't know how to reset this parameter") - - @classmethod - def from_file(cls, paramname, filename): - """Returns a new MultipartParam object constructed from the local - file at ``filename``. - - ``filesize`` is determined by os.path.getsize(``filename``) - - ``filetype`` is determined by mimetypes.guess_type(``filename``)[0] - - ``filename`` is set to os.path.basename(``filename``) - """ - - return cls(paramname, filename=os.path.basename(filename), - filetype=mimetypes.guess_type(filename)[0], - filesize=os.path.getsize(filename), - fileobj=open(filename, "rb")) - - @classmethod - def from_params(cls, params): - """Returns a list of MultipartParam objects from a sequence of - name, value pairs, MultipartParam instances, - or from a mapping of names to values - - The values may be strings or file objects, or MultipartParam objects. - MultipartParam object names must match the given names in the - name,value pairs or mapping, if applicable.""" - if hasattr(params, 'items'): - params = params.items() - - retval = [] - for item in params: - if isinstance(item, cls): - retval.append(item) - continue - name, value = item - if isinstance(value, cls): - assert value.name == name - retval.append(value) - continue - if hasattr(value, 'read'): - # Looks like a file object - filename = getattr(value, 'name', None) - if filename is not None: - filetype = mimetypes.guess_type(filename)[0] - else: - filetype = None - - retval.append(cls(name=name, filename=filename, - filetype=filetype, fileobj=value)) - else: - retval.append(cls(name, value)) - return retval - - def encode_hdr(self, boundary): - """Returns the header of the encoding of this parameter""" - boundary = encode_and_quote(boundary) - - headers = ["--%s" % boundary] - - if self.filename: - disposition = 'form-data; name="%s"; filename="%s"' % (self.name, - self.filename) - else: - disposition = 'form-data; name="%s"' % self.name - - headers.append("Content-Disposition: %s" % disposition) - - if self.filetype: - filetype = self.filetype - else: - filetype = "text/plain; charset=utf-8" - - headers.append("Content-Type: %s" % filetype) - - headers.append("") - headers.append("") - - return "\r\n".join(headers) - - def encode(self, boundary): - """Returns the string encoding of this parameter""" - if self.value is None: - value = self.fileobj.read() - else: - value = self.value - - if re.search("^--%s$" % re.escape(boundary), value, re.M): - raise ValueError("boundary found in encoded string") - - return "%s%s\r\n" % (self.encode_hdr(boundary), value) - - def iter_encode(self, boundary, blocksize=4096): - """Yields the encoding of this parameter - If self.fileobj is set, then blocks of ``blocksize`` bytes are read and - yielded.""" - total = self.get_size(boundary) - current = 0 - if self.value is not None: - block = self.encode(boundary) - current += len(block) - yield block - if self.cb: - self.cb(self, current, total) - else: - block = self.encode_hdr(boundary) - current += len(block) - yield block - if self.cb: - self.cb(self, current, total) - last_block = "" - encoded_boundary = "--%s" % encode_and_quote(boundary) - boundary_exp = re.compile("^%s$" % re.escape(encoded_boundary), - re.M) - while True: - block = self.fileobj.read(blocksize) - if not block: - current += 2 - yield "\r\n" - if self.cb: - self.cb(self, current, total) - break - last_block += block - if boundary_exp.search(last_block): - raise ValueError("boundary found in file data") - last_block = last_block[-len(encoded_boundary)-2:] - current += len(block) - yield block - if self.cb: - self.cb(self, current, total) - - def get_size(self, boundary): - """Returns the size in bytes that this param will be when encoded - with the given boundary.""" - if self.filesize is not None: - valuesize = self.filesize - else: - valuesize = len(self.value) - - return len(self.encode_hdr(boundary)) + 2 + valuesize - -def encode_string(boundary, name, value): - """Returns ``name`` and ``value`` encoded as a multipart/form-data - variable. ``boundary`` is the boundary string used throughout - a single request to separate variables.""" - - return MultipartParam(name, value).encode(boundary) - -def encode_file_header(boundary, paramname, filesize, filename=None, - filetype=None): - """Returns the leading data for a multipart/form-data field that contains - file data. - - ``boundary`` is the boundary string used throughout a single request to - separate variables. - - ``paramname`` is the name of the variable in this request. - - ``filesize`` is the size of the file data. - - ``filename`` if specified is the filename to give to this field. This - field is only useful to the server for determining the original filename. - - ``filetype`` if specified is the MIME type of this file. - - The actual file data should be sent after this header has been sent. - """ - - return MultipartParam(paramname, filesize=filesize, filename=filename, - filetype=filetype).encode_hdr(boundary) - -def get_body_size(params, boundary): - """Returns the number of bytes that the multipart/form-data encoding - of ``params`` will be.""" - size = sum(p.get_size(boundary) for p in MultipartParam.from_params(params)) - return size + len(boundary) + 6 - -def get_headers(params, boundary): - """Returns a dictionary with Content-Type and Content-Length headers - for the multipart/form-data encoding of ``params``.""" - headers = {} - boundary = urllib.quote_plus(boundary) - headers['Content-Type'] = "multipart/form-data; boundary=%s" % boundary - headers['Content-Length'] = str(get_body_size(params, boundary)) - return headers - -class multipart_yielder: - def __init__(self, params, boundary, cb): - self.params = params - self.boundary = boundary - self.cb = cb - - self.i = 0 - self.p = None - self.param_iter = None - self.current = 0 - self.total = get_body_size(params, boundary) - - def __iter__(self): - return self - - def next(self): - """generator function to yield multipart/form-data representation - of parameters""" - if self.param_iter is not None: - try: - block = self.param_iter.next() - self.current += len(block) - if self.cb: - self.cb(self.p, self.current, self.total) - return block - except StopIteration: - self.p = None - self.param_iter = None - - if self.i is None: - raise StopIteration - elif self.i >= len(self.params): - self.param_iter = None - self.p = None - self.i = None - block = "--%s--\r\n" % self.boundary - self.current += len(block) - if self.cb: - self.cb(self.p, self.current, self.total) - return block - - self.p = self.params[self.i] - self.param_iter = self.p.iter_encode(self.boundary) - self.i += 1 - return self.next() - - def reset(self): - self.i = 0 - self.current = 0 - for param in self.params: - param.reset() - -def multipart_encode(params, boundary=None, cb=None): - """Encode ``params`` as multipart/form-data. - - ``params`` should be a sequence of (name, value) pairs or MultipartParam - objects, or a mapping of names to values. - Values are either strings parameter values, or file-like objects to use as - the parameter value. The file-like objects must support .read() and either - .fileno() or both .seek() and .tell(). - - If ``boundary`` is set, then it as used as the MIME boundary. Otherwise - a randomly generated boundary will be used. In either case, if the - boundary string appears in the parameter values a ValueError will be - raised. - - If ``cb`` is set, it should be a callback which will get called as blocks - of data are encoded. It will be called with (param, current, total), - indicating the current parameter being encoded, the current amount encoded, - and the total amount to encode. - - Returns a tuple of `datagen`, `headers`, where `datagen` is a - generator that will yield blocks of data that make up the encoded - parameters, and `headers` is a dictionary with the assoicated - Content-Type and Content-Length headers. - - Examples: - - >>> datagen, headers = multipart_encode( [("key", "value1"), ("key", "value2")] ) - >>> s = "".join(datagen) - >>> assert "value2" in s and "value1" in s - - >>> p = MultipartParam("key", "value2") - >>> datagen, headers = multipart_encode( [("key", "value1"), p] ) - >>> s = "".join(datagen) - >>> assert "value2" in s and "value1" in s - - >>> datagen, headers = multipart_encode( {"key": "value1"} ) - >>> s = "".join(datagen) - >>> assert "value2" not in s and "value1" in s - - """ - if boundary is None: - boundary = gen_boundary() - else: - boundary = urllib.quote_plus(boundary) - - headers = get_headers(params, boundary) - params = MultipartParam.from_params(params) - - return multipart_yielder(params, boundary, cb), headers diff --git a/src/libs/qt-breakpad/poster/streaminghttp.py b/src/libs/qt-breakpad/poster/streaminghttp.py deleted file mode 100644 index eb3b4661d36..00000000000 --- a/src/libs/qt-breakpad/poster/streaminghttp.py +++ /dev/null @@ -1,216 +0,0 @@ -# Copyright (c) 2010 Chris AtLee -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -"""Streaming HTTP uploads module. - -This module extends the standard httplib and urllib2 objects so that -iterable objects can be used in the body of HTTP requests. - -In most cases all one should have to do is call :func:`register_openers()` -to register the new streaming http handlers which will take priority over -the default handlers, and then you can use iterable objects in the body -of HTTP requests. - -**N.B.** You must specify a Content-Length header if using an iterable object -since there is no way to determine in advance the total size that will be -yielded, and there is no way to reset an interator. - -Example usage: - ->>> from StringIO import StringIO ->>> import urllib2, poster.streaminghttp - ->>> opener = poster.streaminghttp.register_openers() - ->>> s = "Test file data" ->>> f = StringIO(s) - ->>> req = urllib2.Request("http://localhost:5000", f, -... {'Content-Length': str(len(s))}) -""" - -import httplib, urllib2, socket -from httplib import NotConnected - -__all__ = ['StreamingHTTPConnection', 'StreamingHTTPRedirectHandler', - 'StreamingHTTPHandler', 'register_openers'] - -if hasattr(httplib, 'HTTPS'): - __all__.extend(['StreamingHTTPSHandler', 'StreamingHTTPSConnection']) - -class _StreamingHTTPMixin: - """Mixin class for HTTP and HTTPS connections that implements a streaming - send method.""" - def send(self, value): - """Send ``value`` to the server. - - ``value`` can be a string object, a file-like object that supports - a .read() method, or an iterable object that supports a .next() - method. - """ - # Based on python 2.6's httplib.HTTPConnection.send() - if self.sock is None: - if self.auto_open: - self.connect() - else: - raise NotConnected() - - # send the data to the server. if we get a broken pipe, then close - # the socket. we want to reconnect when somebody tries to send again. - # - # NOTE: we DO propagate the error, though, because we cannot simply - # ignore the error... the caller will know if they can retry. - if self.debuglevel > 0: - print "send:", repr(value) - try: - blocksize = 8192 - if hasattr(value, 'read') : - if hasattr(value, 'seek'): - value.seek(0) - if self.debuglevel > 0: - print "sendIng a read()able" - data = value.read(blocksize) - while data: - self.sock.sendall(data) - data = value.read(blocksize) - elif hasattr(value, 'next'): - if hasattr(value, 'reset'): - value.reset() - if self.debuglevel > 0: - print "sendIng an iterable" - for data in value: - self.sock.sendall(data) - else: - self.sock.sendall(value) - except socket.error, v: - if v[0] == 32: # Broken pipe - self.close() - raise - -class StreamingHTTPConnection(_StreamingHTTPMixin, httplib.HTTPConnection): - """Subclass of `httplib.HTTPConnection` that overrides the `send()` method - to support iterable body objects""" - -class StreamingHTTPRedirectHandler(urllib2.HTTPRedirectHandler): - """Subclass of `urllib2.HTTPRedirectHandler` that overrides the - `redirect_request` method to properly handle redirected POST requests - - This class is required because python 2.5's HTTPRedirectHandler does - not remove the Content-Type or Content-Length headers when requesting - the new resource, but the body of the original request is not preserved. - """ - - handler_order = urllib2.HTTPRedirectHandler.handler_order - 1 - - # From python2.6 urllib2's HTTPRedirectHandler - def redirect_request(self, req, fp, code, msg, headers, newurl): - """Return a Request or None in response to a redirect. - - This is called by the http_error_30x methods when a - redirection response is received. If a redirection should - take place, return a new Request to allow http_error_30x to - perform the redirect. Otherwise, raise HTTPError if no-one - else should try to handle this url. Return None if you can't - but another Handler might. - """ - m = req.get_method() - if (code in (301, 302, 303, 307) and m in ("GET", "HEAD") - or code in (301, 302, 303) and m == "POST"): - # Strictly (according to RFC 2616), 301 or 302 in response - # to a POST MUST NOT cause a redirection without confirmation - # from the user (of urllib2, in this case). In practice, - # essentially all clients do redirect in this case, so we - # do the same. - # be conciliant with URIs containing a space - newurl = newurl.replace(' ', '%20') - newheaders = dict((k, v) for k, v in req.headers.items() - if k.lower() not in ( - "content-length", "content-type") - ) - return urllib2.Request(newurl, - headers=newheaders, - origin_req_host=req.get_origin_req_host(), - unverifiable=True) - else: - raise urllib2.HTTPError(req.get_full_url(), code, msg, headers, fp) - -class StreamingHTTPHandler(urllib2.HTTPHandler): - """Subclass of `urllib2.HTTPHandler` that uses - StreamingHTTPConnection as its http connection class.""" - - handler_order = urllib2.HTTPHandler.handler_order - 1 - - def http_open(self, req): - """Open a StreamingHTTPConnection for the given request""" - return self.do_open(StreamingHTTPConnection, req) - - def http_request(self, req): - """Handle a HTTP request. Make sure that Content-Length is specified - if we're using an interable value""" - # Make sure that if we're using an iterable object as the request - # body, that we've also specified Content-Length - if req.has_data(): - data = req.get_data() - if hasattr(data, 'read') or hasattr(data, 'next'): - if not req.has_header('Content-length'): - raise ValueError( - "No Content-Length specified for iterable body") - return urllib2.HTTPHandler.do_request_(self, req) - -if hasattr(httplib, 'HTTPS'): - class StreamingHTTPSConnection(_StreamingHTTPMixin, - httplib.HTTPSConnection): - """Subclass of `httplib.HTTSConnection` that overrides the `send()` - method to support iterable body objects""" - - class StreamingHTTPSHandler(urllib2.HTTPSHandler): - """Subclass of `urllib2.HTTPSHandler` that uses - StreamingHTTPSConnection as its http connection class.""" - - handler_order = urllib2.HTTPSHandler.handler_order - 1 - - def https_open(self, req): - return self.do_open(StreamingHTTPSConnection, req) - - def https_request(self, req): - # Make sure that if we're using an iterable object as the request - # body, that we've also specified Content-Length - if req.has_data(): - data = req.get_data() - if hasattr(data, 'read') or hasattr(data, 'next'): - if not req.has_header('Content-length'): - raise ValueError( - "No Content-Length specified for iterable body") - return urllib2.HTTPSHandler.do_request_(self, req) - - -def register_openers(): - """Register the streaming http handlers in the global urllib2 default - opener object. - - Returns the created OpenerDirector object.""" - handlers = [StreamingHTTPHandler, StreamingHTTPRedirectHandler] - if hasattr(httplib, "HTTPS"): - handlers.append(StreamingHTTPSHandler) - - opener = urllib2.build_opener(*handlers) - - urllib2.install_opener(opener) - - return opener diff --git a/src/libs/qt-breakpad/qtbreakpad/qtsystemexceptionhandler.cpp b/src/libs/qt-breakpad/qtbreakpad/qtsystemexceptionhandler.cpp deleted file mode 100644 index 5ca079c0183..00000000000 --- a/src/libs/qt-breakpad/qtbreakpad/qtsystemexceptionhandler.cpp +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "qtsystemexceptionhandler.h" - -#include -#include - -#include -#include -#include -#include - -#if defined(Q_OS_LINUX) -# include "client/linux/handler/exception_handler.h" -#elif defined(Q_OS_WIN) -# include "client/windows/handler/exception_handler.h" -#elif defined(Q_OS_MACOS) -# include "client/mac/handler/exception_handler.h" -#endif - -#if defined(Q_OS_LINUX) -static bool exceptionHandlerCallback(const google_breakpad::MinidumpDescriptor& descriptor, - void* /*context*/, - bool succeeded) -{ - if (!succeeded) - return succeeded; - - const QStringList argumentList = { - QString::fromLocal8Bit(descriptor.path()), - QString::number(QtSystemExceptionHandler::startTime().toTime_t()), - QCoreApplication::applicationName(), - QCoreApplication::applicationVersion(), - QtSystemExceptionHandler::plugins(), - QtSystemExceptionHandler::buildVersion(), - QCoreApplication::applicationFilePath() - }; - - return !QProcess::execute(QtSystemExceptionHandler::crashHandlerPath(), argumentList); -} -#elif defined(Q_OS_MACOS) -static bool exceptionHandlerCallback(const char *dump_dir, - const char *minidump_id, - void *context, - bool succeeded) -{ - Q_UNUSED(context); - - if (!succeeded) - return succeeded; - - const QString path = QString::fromLocal8Bit(dump_dir) + '/' - + QString::fromLocal8Bit(minidump_id) + ".dmp"; - const QStringList argumentList = { - path, - QString::number(QtSystemExceptionHandler::startTime().toTime_t()), - QCoreApplication::applicationName(), - QCoreApplication::applicationVersion(), - QtSystemExceptionHandler::plugins(), - QtSystemExceptionHandler::buildVersion(), - QCoreApplication::applicationFilePath() - }; - - return !QProcess::execute(QtSystemExceptionHandler::crashHandlerPath(), argumentList); -} -#elif defined(Q_OS_WIN) -static bool exceptionHandlerCallback(const wchar_t* dump_path, - const wchar_t* minidump_id, - void* context, - EXCEPTION_POINTERS* exinfo, - MDRawAssertionInfo* assertion, - bool succeeded) -{ - Q_UNUSED(assertion); - Q_UNUSED(exinfo); - Q_UNUSED(context); - - if (!succeeded) - return succeeded; - - const QString path = QString::fromWCharArray(dump_path, int(wcslen(dump_path))) + '/' - + QString::fromWCharArray(minidump_id, int(wcslen(minidump_id))) + ".dmp"; - const QStringList argumentList = { - path, - QString::number(QtSystemExceptionHandler::startTime().toTime_t()), - QCoreApplication::applicationName(), - QCoreApplication::applicationVersion(), - QtSystemExceptionHandler::plugins(), - QtSystemExceptionHandler::buildVersion(), - QCoreApplication::applicationFilePath() - }; - - return !QProcess::execute(QtSystemExceptionHandler::crashHandlerPath(), argumentList); -} -#endif - -static QDateTime s_startTime; -static QString s_plugins; -static QString s_buildVersion; -static QString s_crashHandlerPath; - -#if defined(Q_OS_LINUX) -QtSystemExceptionHandler::QtSystemExceptionHandler(const QString &libexecPath) - : exceptionHandler(new google_breakpad::ExceptionHandler( - google_breakpad::MinidumpDescriptor(QDir::tempPath().toStdString()), - NULL, - exceptionHandlerCallback, - NULL, - true, - -1)) -{ - init(libexecPath); -} -#elif defined(Q_OS_MACOS) -QtSystemExceptionHandler::QtSystemExceptionHandler(const QString &libexecPath) - : exceptionHandler(new google_breakpad::ExceptionHandler( - QDir::tempPath().toStdString(), - NULL, - exceptionHandlerCallback, - NULL, - true, - NULL)) -{ - init(libexecPath); -} -#elif defined(Q_OS_WIN) -QtSystemExceptionHandler::QtSystemExceptionHandler(const QString &libexecPath) - : exceptionHandler(new google_breakpad::ExceptionHandler( - QDir::tempPath().toStdWString(), - NULL, - exceptionHandlerCallback, - NULL, - google_breakpad::ExceptionHandler::HANDLER_ALL)) -{ - init(libexecPath); -} -#else -QtSystemExceptionHandler::QtSystemExceptionHandler(const QString & /*libexecPath*/) - : exceptionHandler(0) -{ - -} -#endif - -void QtSystemExceptionHandler::init(const QString &libexecPath) -{ - s_startTime = QDateTime::currentDateTime(); - s_crashHandlerPath = libexecPath + Utils::HostOsInfo::withExecutableSuffix("/qtcrashhandler"); -} - -QtSystemExceptionHandler::~QtSystemExceptionHandler() -{ -#ifdef ENABLE_QT_BREAKPAD - delete exceptionHandler; -#endif -} - -void QtSystemExceptionHandler::setPlugins(const QStringList &pluginNameList) -{ - s_plugins = QString("{%1}").arg(pluginNameList.join(",")); -} - -void QtSystemExceptionHandler::setBuildVersion(const QString &version) -{ - s_buildVersion = version; -} - -QString QtSystemExceptionHandler::buildVersion() -{ - return s_buildVersion; -} - -QString QtSystemExceptionHandler::plugins() -{ - return s_plugins; -} - -void QtSystemExceptionHandler::setCrashHandlerPath(const QString &crashHandlerPath) -{ - s_crashHandlerPath = crashHandlerPath; -} - -QString QtSystemExceptionHandler::crashHandlerPath() -{ - return s_crashHandlerPath; -} - -void QtSystemExceptionHandler::crash() -{ - int *a = (int*)0x42; - - fprintf(stdout, "Going to crash...\n"); - fprintf(stdout, "A = %d", *a); -} - -QDateTime QtSystemExceptionHandler::startTime() -{ - return s_startTime; -} diff --git a/src/libs/qt-breakpad/qtbreakpad/qtsystemexceptionhandler.h b/src/libs/qt-breakpad/qtbreakpad/qtsystemexceptionhandler.h deleted file mode 100644 index 6bc5949ee2b..00000000000 --- a/src/libs/qt-breakpad/qtbreakpad/qtsystemexceptionhandler.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -#include - -namespace google_breakpad { - class ExceptionHandler; -} - -class QtSystemExceptionHandler -{ -public: - QtSystemExceptionHandler(const QString &libexecPath); - ~QtSystemExceptionHandler(); - - static void crash(); - static void setPlugins(const QStringList &pluginNameList); - static void setBuildVersion(const QString &version); - static void setCrashHandlerPath(const QString &crashHandlerPath); - - static QString plugins(); - static QString buildVersion(); - static QString crashHandlerPath(); - - static QDateTime startTime(); - -protected: - void init(const QString &libexecPath); - -private: - google_breakpad::ExceptionHandler *exceptionHandler = nullptr; -}; diff --git a/src/libs/qt-breakpad/qtbreakpadsymbols b/src/libs/qt-breakpad/qtbreakpadsymbols deleted file mode 100755 index 3b7c5af8ffc..00000000000 --- a/src/libs/qt-breakpad/qtbreakpadsymbols +++ /dev/null @@ -1,271 +0,0 @@ -#!/usr/bin/python - -import sys -import os -import os.path -import subprocess -import shlex -import shutil -import base64 - -from poster.encode import multipart_encode -from poster.encode import MultipartParam -from poster.streaminghttp import register_openers -import urllib2 - -from optparse import OptionParser - -register_openers() - -breakpadSourceDir = os.environ['BREAKPAD_SOURCE_DIR'] -breakpadUploadUrl = os.environ['BREAKPAD_UPLOAD_URL'] -breakpadUserName = os.environ['BREAKPAD_USER_NAME'] -breakpadUserPassword = os.environ['BREAKPAD_USER_PASSWORD'] - -if sys.platform == 'win32': - nullfilename = 'nul:' -else: - nullfilename = '/dev/null' -nullfile = open(nullfilename, 'r+b') - - -def stdoutFromProcess(process): - (stdout, stderr) = process.communicate() - if stderr: - print stderr - raise SystemError() - sys.exit(1) - return stdout - -def toolPath(): - if sys.platform == 'linux2': - dumpsymsPath = os.path.join(breakpadSourceDir, 'src/tools/linux/dump_syms/dump_syms') - elif sys.platform == 'darwin': - dumpsymsPath = os.path.join(breakpadSourceDir, 'src/tools/mac/dump_syms/build/Release/dump_syms') - elif sys.platform == 'win32': - dumpsymsPath = os.path.join(breakpadSourceDir,'src\\tools\\windows\\binaries\\dump_syms.exe') - else: - sys.exit(1) - return dumpsymsPath - -gitRootDirectoryCache = {} - -def gitRootDirectory(path): - directory = os.path.dirname(path) - if directory in gitRootDirectoryCache: - return gitRootDirectoryCache[directory] - directoryList = directory.split(os.sep) - while len(directoryList) > 0: - gitDirectory = os.sep.join(directoryList + ['.git']) - if os.path.exists(gitDirectory): - gitDirectory = os.sep.join(directoryList) - gitRootDirectoryCache[directory] = gitDirectory - return gitDirectory - directoryList.pop() - - return None - - -gitCommitShaCache = {} - - -def gitCommitSha(gitRootPath): - if gitRootPath in gitCommitShaCache: - return gitCommitShaCache[gitRootPath] - gitProcess = subprocess.Popen(shlex.split('git rev-parse HEAD'), - stdout=subprocess.PIPE, - stderr=nullfile, cwd=gitRootPath) - commitSha = stdoutFromProcess(gitProcess).strip('\n') - gitCommitShaCache[gitRootPath] = commitSha - return commitSha - - -gitRemoteRepositoryCache = {} - - -def gitRemoteRepository(gitRootPath): - if gitRootPath in gitRemoteRepositoryCache: - return gitRemoteRepositoryCache[gitRootPath] - gitProcess = \ - subprocess.Popen(shlex.split('git config remote.origin.url'), - stdout=subprocess.PIPE, stderr=nullfile, - cwd=gitRootPath) - repository = stdoutFromProcess(gitProcess).strip('\n') - gitRemoteRepositoryCache[gitRootPath] = repository - return repository - - -gitFilePathCache = {} - - -def populateFilePathCache(gitRootPath): - if gitRootPath not in gitFilePathCache: - gitProcess = \ - subprocess.Popen(shlex.split('git ls-files --full-name'), - stdout=subprocess.PIPE, stderr=nullfile, - cwd=gitRootPath) - fileNameList = stdoutFromProcess(gitProcess).split('\n') - filePathCache = {} - for fileName in fileNameList: - baseFileName = os.path.basename(fileName) - filePathCache[baseFileName] = fileName - gitFilePathCache[gitRootPath] = filePathCache - - -def gitFilePath(path, gitRootPath): - if not gitRootPath: - return path - - populateFilePathCache(gitRootPath) - - baseFileName = os.path.basename(path) - filePathCache = gitFilePathCache[gitRootPath] - if baseFileName in filePathCache: - return filePathCache[baseFileName] - else: - return os.path.relpath(path, gitRootPath) - - -def isInRepository(path): - gitRootPath = gitRootDirectory(path) - if not gitRootPath: - return False - - populateFilePathCache(gitRootPath) - baseFileName = os.path.basename(path) - if baseFileName in gitFilePathCache[gitRootPath]: - return True - else: - return False - - -def sendSymbolsToServer( - breakpadUploadUrl, - symbolText, - codeFile, - debugFile, - debugIdentifier, - operatingSystem, - cpu, - ): - (data, headers) = multipart_encode({ - 'symbol_file': MultipartParam('symbol_file', value=symbolText, - filename='symbol_file'), - 'code_file': codeFile, - 'debug_file': debugFile, - 'debug_identifier': debugIdentifier, - 'os': operatingSystem, - 'cpu': cpu, - }) - request = urllib2.Request(breakpadUploadUrl, data, headers) - auth = base64.encodestring('%s:%s' % (breakpadUserName, - breakpadUserPassword))[:-1] # This is just standard un/pw encoding - request.add_header('Authorization', 'Basic %s' % auth) # Add Auth header to request - result = urllib2.urlopen(request).read() - - -def generateSymbolFilesAndSend(binaryPath, projectPath): - dumpsymsPath = toolPath() - - originalBinaryPath = binaryPath - - if sys.platform == 'darwin': - dsymutilProcess = \ - subprocess.Popen(shlex.split('/usr/bin/dsymutil "' - + binaryPath + '"'), stdout=nullfile, - stderr=nullfile) - dsymutilProcess.wait() - binaryPath += os.path.join('.dSYM/Contents/Resources/DWARF/', - os.path.basename(binaryPath)) - - binaryPath = os.path.normpath(binaryPath) - - dumpsymsProcess = subprocess.Popen(shlex.split('"' + dumpsymsPath - + '" "' + binaryPath + '"'), stdout=subprocess.PIPE, - stderr=nullfile, cwd=projectPath) - symbolList = stdoutFromProcess(dumpsymsProcess).split('\n') - - outputTextList = [] - codeFile = os.path.basename(binaryPath) - debugFile = '' - debugIdentifier = '' - operatingSystem = '' - cpu = '' - moduleNotParsed = True - for line in symbolList: - line = line.strip('\n').strip('\r') - if line[:4] == 'FILE': - (marker, idnumber, filepath) = line.split(' ', 2) - filepath = os.path.normpath(os.path.join(projectPath, - filepath)) - - if isInRepository(filepath): - gitRootPath = gitRootDirectory(filepath) - commitSha = gitCommitSha(gitRootPath) - repository = \ - gitRemoteRepository(gitRootPath).replace(':', '/') - relativeFilePath = gitFilePath(filepath, - gitRootPath).replace('\\', '/') - outputTextList.append('FILE ' + idnumber + ' git:' - + repository + ':' + relativeFilePath + ':' - + commitSha) - else: - outputTextList.append(line) - elif moduleNotParsed and line[:6] == 'MODULE': - (operatingSystem, cpu, debugIdentifier, debugFile) = \ - line[7:].split(' ', 3) - moduleNotParsed = False - elif line: - outputTextList.append(line) - - if moduleNotParsed: - print 'Module not parsed' - sys.exit(1) - - sendSymbolsToServer( - breakpadUploadUrl, - '\n'.join(outputTextList), - codeFile, - debugFile, - debugIdentifier, - operatingSystem, - cpu, - ) - - if sys.platform == 'darwin': - shutil.rmtree(originalBinaryPath + '.dSYM') - - -def testForBreakpad(): - try: - dumpsymsPath = toolPath() - if not dumpsymsPath: - sys.exit(1) - subprocess.Popen([dumpsymsPath], stdout=nullfile, - stderr=nullfile) - except (OSError, KeyError): - print 'No dumpsyms can be executed. Maybe BREAKPAD_SOURCE_DIR is wrong.' - sys.exit(1) - sys.exit(0) - - -def main(): - usage = 'usage: %prog [options] binary projectpath' - parser = OptionParser(usage=usage) - parser.add_option('-v', '--verbose', action='store_true', - dest='verbose') - parser.add_option('-e', '--breakpad-exists', action='store_true', - dest='testForBreakpad') - - (options, args) = parser.parse_args() - - if options.testForBreakpad == True: - testForBreakpad() - if len(args) > 1: - generateSymbolFilesAndSend(args[0], args[1]) - else: - parser.print_help() - - -if __name__ == '__main__': - main() diff --git a/src/libs/qt-breakpad/qtbreakpadsymbols.bat b/src/libs/qt-breakpad/qtbreakpadsymbols.bat deleted file mode 100644 index aad26594d66..00000000000 --- a/src/libs/qt-breakpad/qtbreakpadsymbols.bat +++ /dev/null @@ -1 +0,0 @@ -@python qtbreakpadsymbols %* diff --git a/src/libs/qt-breakpad/qtcrashhandler/detaildialog.cpp b/src/libs/qt-breakpad/qtcrashhandler/detaildialog.cpp deleted file mode 100644 index b767359a588..00000000000 --- a/src/libs/qt-breakpad/qtcrashhandler/detaildialog.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "detaildialog.h" - -#include -#include -#include - -DetailDialog::DetailDialog(QWidget *parent) : - QDialog(parent) -{ - resize(640, 480); - QVBoxLayout *verticalLayout = new QVBoxLayout(this); - textBrowser = new QTextBrowser(this); - verticalLayout->addWidget(textBrowser); - buttonBox = new QDialogButtonBox(this); - buttonBox->setOrientation(Qt::Horizontal); - buttonBox->setStandardButtons(QDialogButtonBox::Close); - - verticalLayout->addWidget(buttonBox); - connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); - connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); -} - -DetailDialog::~DetailDialog() -{ -} - -void DetailDialog::setText(const QString &text) -{ - textBrowser->setPlainText(text); -} diff --git a/src/libs/qt-breakpad/qtcrashhandler/detaildialog.h b/src/libs/qt-breakpad/qtcrashhandler/detaildialog.h deleted file mode 100644 index bfde7d755b9..00000000000 --- a/src/libs/qt-breakpad/qtcrashhandler/detaildialog.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -#include - -QT_BEGIN_NAMESPACE -class QTextBrowser; -class QDialogButtonBox; -QT_END_NAMESPACE - -class DetailDialog : public QDialog -{ - Q_OBJECT - -public: - explicit DetailDialog(QWidget *parent = nullptr); - ~DetailDialog(); - - void setText(const QString &text); - -private: - QTextBrowser *textBrowser = nullptr; - QDialogButtonBox *buttonBox = nullptr; -}; diff --git a/src/libs/qt-breakpad/qtcrashhandler/dumpsender.cpp b/src/libs/qt-breakpad/qtcrashhandler/dumpsender.cpp deleted file mode 100644 index fe9aa29ac32..00000000000 --- a/src/libs/qt-breakpad/qtcrashhandler/dumpsender.cpp +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "dumpsender.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -DumpSender::DumpSender(QObject *parent) : - QObject(parent), - m_httpMultiPart(QHttpMultiPart::FormDataType) -{ - const QString dumpPath = QCoreApplication::arguments().at(1); - const QByteArray startupTime = QCoreApplication::arguments().at(2).toLocal8Bit(); - const QByteArray applicationName = QCoreApplication::arguments().at(3).toLocal8Bit(); - QByteArray applicationVersion = QCoreApplication::arguments().at(4).toLocal8Bit(); - const QByteArray plugins = QCoreApplication::arguments().at(5).toLocal8Bit(); - // QByteArray ideRevision = QCoreApplication::arguments().at(6).toLocal8Bit(); - m_applicationFilePath = QCoreApplication::arguments().at(7); - - if (applicationVersion.isEmpty()) - applicationVersion = "1.0.0"; - - QFile dumpFile(dumpPath, this); - const bool isOpen = dumpFile.open(QIODevice::ReadOnly); - Q_ASSERT(isOpen); - Q_UNUSED(isOpen); - - const QList > pairList = { - { "StartupTime", startupTime }, - { "Vendor", "Qt Project" }, - { "InstallTime", "0" }, - { "Add-ons", plugins }, - { "BuildID", "" }, - { "SecondsSinceLastCrash", "0" }, - { "ProductName", applicationName }, - { "URL", "" }, - { "Theme", "" }, - { "Version", applicationVersion }, - { "CrashTime", QByteArray::number(QDateTime::currentDateTime().toTime_t()) }, - { "Throttleable", "0" } - }; - - const QByteArray boundary = m_httpMultiPart.boundary(); - m_formData.append("--" + boundary + "\r\n"); - for (const auto &pair : pairList) { - m_formData.append("Content-Disposition: form-data; name=\"" + pair.first + "\"\r\n\r\n"); - m_formData.append(pair.second + "\r\n"); - m_formData.append("--" + boundary + "\r\n"); - } - - - QByteArray dumpArray = dumpFile.readAll(); - m_formData.append("Content-Type: application/octet-stream\r\n"); - m_formData.append("Content-Disposition: form-data; name=\"upload_file_minidump\"; filename=\"" - + QFileInfo(dumpPath).baseName().toUtf8() + "\r\n"); - m_formData.append("Content-Transfer-Encoding: binary\r\n\r\n"); - m_formData.append(dumpArray); - - m_formData.append("--" + boundary + "--\r\n"); - - for (const auto &pair : pairList) { - QHttpPart httpPart; - httpPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"" + pair.first + "\""); - httpPart.setBody(pair.second); - m_httpMultiPart.append(httpPart); - } - - QHttpPart dumpPart; - dumpPart.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream"); - dumpPart.setHeader(QNetworkRequest::ContentDispositionHeader, - "form-data; name=\"upload_file_minidump\"; filename=\"" - + QFileInfo(dumpPath).baseName().toUtf8() + "\""); - dumpPart.setRawHeader("Content-Transfer-Encoding:", "binary"); - dumpPart.setBody(dumpArray); - m_httpMultiPart.append(dumpPart); -} - -void DumpSender::sendDumpAndQuit() -{ - QNetworkAccessManager *manager = new QNetworkAccessManager(this); - - QNetworkRequest request(QUrl("http://crashes.qt.io/submit")); - - const QByteArray boundary = m_httpMultiPart.boundary(); - request.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data; boundary=" + boundary); - - QList> pairList; - - if (!m_emailAddress.isEmpty()) - pairList.append({ "Email", m_emailAddress.toLocal8Bit() }); - - if (!m_commentText.isEmpty()) - pairList.append({ "Comments", m_commentText.toLocal8Bit() }); - - for (const auto &pair : pairList) { - m_formData.append("Content-Disposition: form-data; name=\"" + pair.first + "\"\r\n\r\n"); - m_formData.append(pair.second + "\r\n"); - m_formData.append("--" + boundary + "\r\n"); - } - - for (const auto &pair : pairList) { - QHttpPart httpPart; - httpPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"" + pair.first + "\""); - httpPart.setBody(pair.second); - m_httpMultiPart.append(httpPart); - } - - QNetworkReply *reply = manager->post(request, &m_httpMultiPart); - - m_httpMultiPart.setParent(reply); - - connect(reply, &QNetworkReply::uploadProgress, this, &DumpSender::uploadProgress); - connect(reply, &QNetworkReply::finished, QCoreApplication::instance(), &QCoreApplication::quit); - connect(reply, QOverload::of(&QNetworkReply::error), - QCoreApplication::instance(), &QCoreApplication::quit); -} - -void DumpSender::restartCrashedApplicationAndSendDump() -{ - QProcess::startDetached(m_applicationFilePath); - sendDumpAndQuit(); -} - -void DumpSender::restartCrashedApplication() -{ - QProcess::startDetached(m_applicationFilePath); - QCoreApplication::quit(); -} - -void DumpSender::setEmailAddress(const QString &email) -{ - m_emailAddress = email; -} - -void DumpSender::setCommentText(const QString &comment) -{ - m_commentText = comment; -} - -int DumpSender::dumperSize() const -{ - return m_formData.size(); -} diff --git a/src/libs/qt-breakpad/qtcrashhandler/dumpsender.h b/src/libs/qt-breakpad/qtcrashhandler/dumpsender.h deleted file mode 100644 index 0f60663fbba..00000000000 --- a/src/libs/qt-breakpad/qtcrashhandler/dumpsender.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -#include -#include - -class DumpSender : public QObject -{ - Q_OBJECT - -public: - explicit DumpSender(QObject *parent = nullptr); - - int dumperSize() const; - - void sendDumpAndQuit(); - void restartCrashedApplication(); - void restartCrashedApplicationAndSendDump(); - void setEmailAddress(const QString &email); - void setCommentText(const QString &comment); - -signals: - void uploadProgress(qint64 bytesSent, qint64 bytesTotal); - -private: - QHttpMultiPart m_httpMultiPart; - QByteArray m_formData; - QString m_applicationFilePath; - QString m_emailAddress; - QString m_commentText; -}; diff --git a/src/libs/qt-breakpad/qtcrashhandler/main.cpp b/src/libs/qt-breakpad/qtcrashhandler/main.cpp deleted file mode 100644 index 6cb04abecd1..00000000000 --- a/src/libs/qt-breakpad/qtcrashhandler/main.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "mainwidget.h" -#include "dumpsender.h" - -#include -#include -#include -#include - -int main(int argc, char *argv[]) -{ - QApplication application(argc, argv); - - if (application.arguments().count() <= 1) - return 0; - - const QString dumpPath = QApplication::arguments().at(1); - if (!QFileInfo(dumpPath).exists()) - return 0; - - QNetworkProxyFactory::setUseSystemConfiguration(true); - - QHostInfo hostInfo = QHostInfo::fromName("crashes.qt.io"); - -// if (hostInfo.error() != QHostInfo::NoError) -// return 0; - - DumpSender dumpSender; - - MainWidget mainWindow; - - mainWindow.setProgressbarMaximum(dumpSender.dumperSize()); - - QObject::connect(&mainWindow, &MainWidget::restartCrashedApplication, - &dumpSender, &DumpSender::restartCrashedApplication); - QObject::connect(&mainWindow, &MainWidget::restartCrashedApplicationAndSendDump, - &dumpSender, &DumpSender::restartCrashedApplicationAndSendDump); - QObject::connect(&mainWindow, &MainWidget::sendDump, - &dumpSender, &DumpSender::sendDumpAndQuit); - QObject::connect(&mainWindow, &MainWidget::commentChanged, - &dumpSender, &DumpSender::setCommentText); - QObject::connect(&mainWindow, &MainWidget::emailAdressChanged, - &dumpSender, &DumpSender::setEmailAddress); - QObject::connect(&dumpSender, &DumpSender::uploadProgress, - &mainWindow, &MainWidget::updateProgressBar); - - mainWindow.show(); - return application.exec(); -} diff --git a/src/libs/qt-breakpad/qtcrashhandler/mainwidget.cpp b/src/libs/qt-breakpad/qtcrashhandler/mainwidget.cpp deleted file mode 100644 index e70e316a9d5..00000000000 --- a/src/libs/qt-breakpad/qtcrashhandler/mainwidget.cpp +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "mainwidget.h" -#include "ui_mainwidget.h" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MainWidget::MainWidget(QWidget *parent) : - QWidget(parent), - ui(new Ui::MainWidget) -{ - ui->setupUi(this); - - const QString applicationName = QApplication::arguments().at(3); - ui->mainWidgetTopLabel.setText(tr("%1 has crashed").arg(applicationName)); - - connect(ui->restartButton, &QAbstractButton::clicked, this, &MainWidget::restartApplication); - connect(ui->quitButton, &QAbstractButton::clicked, this, &MainWidget::quitApplication); - connect(ui->detailButton, &QAbstractButton::clicked, this, &MainWidget::showDetails); - connect(ui->commentTextEdit, &QTextEdit::textChanged, this, &MainWidget::commentIsProvided); - connect(ui->emailLineEdit, &QLineEdit::textEdited, this, &MainWidget::emailAdressChanged); -} - -MainWidget::~MainWidget() -{ - delete ui; -} - -void MainWidget::setProgressbarMaximum(int maximum) -{ - ui->progressBar->setMaximum(maximum); -} - -void MainWidget::changeEvent(QEvent *e) -{ - QWidget::changeEvent(e); - if (e->type() == QEvent::LanguageChange) - ui->retranslateUi(this); -} - -void MainWidget::updateProgressBar(qint64 progressCount, qint64 fullCount) -{ - ui->progressBar->setValue(static_cast(progressCount)); - ui->progressBar->setMaximum(static_cast(fullCount)); -} - -void MainWidget::showError(QNetworkReply::NetworkError error) -{ - QNetworkReply *reply = qobject_cast(sender()); - if (error != QNetworkReply::NoError && reply) { - ui->commentTextEdit->setReadOnly(true); - ui->commentTextEdit->setPlainText(reply->errorString()); - } -} - -void MainWidget::restartApplication() -{ - if (ui->sendDumpCheckBox->isChecked()) - emit restartCrashedApplicationAndSendDump(); - else - emit restartCrashedApplication(); -} - -void MainWidget::quitApplication() -{ - ui->quitButton->setEnabled(false); - if (ui->sendDumpCheckBox->isChecked()) - emit sendDump(); - else - QCoreApplication::quit(); -} - -void MainWidget::commentIsProvided() -{ - m_commentIsProvided = true; - emit commentChanged(ui->commentTextEdit->toPlainText()); -} - -void MainWidget::showDetails() -{ - if (m_detailDialog.isNull()) { - m_detailDialog = new DetailDialog(this); - - QString detailText; - - detailText.append(tr("We specifically send the following information:\n\n")); - - QString dumpPath = QApplication::arguments().at(1); - QString startupTime = QApplication::arguments().at(2); - QString applicationName = QApplication::arguments().at(3); - QString applicationVersion = QApplication::arguments().at(4); - QString plugins = QApplication::arguments().at(5); - QString ideRevision = QApplication::arguments().at(6); - - detailText.append(QString("StartupTime: %1\n").arg(startupTime)); - detailText.append(QString("Vendor: %1\n").arg("Qt Project")); - detailText.append(QString("InstallTime: %1\n").arg("0")); - detailText.append(QString("Add-ons: %1\n").arg(plugins)); - detailText.append(QString("BuildID: %1\n").arg("0")); - detailText.append(QString("SecondsSinceLastCrash: %1\n").arg("0")); - detailText.append(QString("ProductName: %1\n").arg(applicationName)); - detailText.append(QString("URL: %1\n").arg("")); - detailText.append(QString("Theme: %1\n").arg("")); - detailText.append(QString("Version: %1\n").arg(applicationVersion)); - detailText.append(QString("CrashTime: %1\n").arg(QString::number(QDateTime::currentDateTime().toTime_t()))); - - if (!ui->emailLineEdit->text().isEmpty()) - detailText.append(tr("Email: %1\n").arg(ui->emailLineEdit->text())); - - if (m_commentIsProvided) - detailText.append(tr("Comments: %1\n").arg(ui->commentTextEdit->toPlainText())); - - detailText.append( - tr("In addition, we send a Microsoft Minidump file, which contains information " - "about this computer, such as the operating system and CPU, and most " - "importantly, it contains the stacktrace, which is an internal structure that " - "shows where the program crashed. This information will help us to identify " - "the cause of the crash and to fix it.")); - - m_detailDialog.data()->setText(detailText); - } - if (m_detailDialog->isVisible()) - m_detailDialog->showNormal(); - else - m_detailDialog->show(); -} diff --git a/src/libs/qt-breakpad/qtcrashhandler/mainwidget.h b/src/libs/qt-breakpad/qtcrashhandler/mainwidget.h deleted file mode 100644 index 6845205c072..00000000000 --- a/src/libs/qt-breakpad/qtcrashhandler/mainwidget.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -#include "detaildialog.h" - -#include -#include -#include -#include - -namespace Ui { class MainWidget; } - -class MainWidget : public QWidget -{ - Q_OBJECT - -public: - explicit MainWidget(QWidget *parent = nullptr); - ~MainWidget(); - - void setProgressbarMaximum(int maximum); - void updateProgressBar(qint64 progressCount, qint64 fullCount); - -signals: - void restartCrashedApplication(); - void sendDump(); - void restartCrashedApplicationAndSendDump(); - void emailAdressChanged(const QString &email); - void commentChanged(const QString &comment); - -protected: - void changeEvent(QEvent *e); - -private: - void restartApplication(); - void quitApplication(); - void showError(QNetworkReply::NetworkError error); - void showDetails(); - void commentIsProvided(); - -private: - Ui::MainWidget *ui; - - QPointer m_detailDialog; - bool m_commentIsProvided = false; -}; diff --git a/src/libs/qt-breakpad/qtcrashhandler/mainwidget.ui b/src/libs/qt-breakpad/qtcrashhandler/mainwidget.ui deleted file mode 100644 index e5a06027090..00000000000 --- a/src/libs/qt-breakpad/qtcrashhandler/mainwidget.ui +++ /dev/null @@ -1,143 +0,0 @@ - - - MainWidget - - - - 0 - 0 - 422 - 510 - - - - Crash Handler - - - - - - - 20 - - - - Qt Creator has crashed - - - false - - - - - - - You can send us a crash report in order to help us diagnose and fix the problem. - - - true - - - - - - - - - Email: - - - - - - - Enter here your email (optional) - - - - - - - - - Tell The Qt Company about this crash so they can fix it - - - true - - - - - - - Details - - - - - - - true - - - Please describe what you did before it crashed (comments are publicly visible) - - - - - - - Your crash report will be submitted before you quit or restart. - - - - - - - 0 - - - %v/%m Bytes - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - false - - - Restart - - - - - - - Quit - - - - - - - - - - - diff --git a/src/libs/qt-breakpad/testapp/main.cpp b/src/libs/qt-breakpad/testapp/main.cpp deleted file mode 100644 index 2e8ef1d7dba..00000000000 --- a/src/libs/qt-breakpad/testapp/main.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include - -#include -#include - -int main(int argc, char *argv[]) -{ - QCoreApplication a(argc, argv); - - a.setApplicationName("testapp"); - a.setApplicationVersion("1.0.0"); - - QtSystemExceptionHandler exceptionHandler; - - QTimer::singleShot(100, [] { QtSystemExceptionHandler::crash(); }); - - return a.exec(); -} diff --git a/src/tools/qml2puppet/qml2puppet/configcrashpad.h b/src/tools/qml2puppet/qml2puppet/configcrashpad.h index af82ffca165..70cbfc5f4a5 100644 --- a/src/tools/qml2puppet/qml2puppet/configcrashpad.h +++ b/src/tools/qml2puppet/qml2puppet/configcrashpad.h @@ -4,10 +4,6 @@ #include -#ifdef ENABLE_QT_BREAKPAD -#include -#endif - #if defined(ENABLE_CRASHPAD) && defined(Q_OS_WIN) #define NOMINMAX #include "client/crash_report_database.h" @@ -60,11 +56,6 @@ namespace { return success; } -#ifdef ENABLE_QT_BREAKPAD - const QString libexecPath = QCoreApplication::applicationDirPath() + '/' - + RELATIVE_LIBEXEC_PATH; - QtSystemExceptionHandler systemExceptionHandler(libexecPath); -#endif //#ifdef ENABLE_QT_BREAKPAD #else //#if defined(ENABLE_CRASHPAD) && defined(Q_OS_WIN) bool startCrashpad(const QString&, const QString&) {