/src/breakpad/CrashReporter/CrashReporter.cpp

http://github.com/tomahawk-player/tomahawk · C++ · 203 lines · 142 code · 39 blank · 22 comment · 4 complexity · b98c56d3af9fdaf1c6274518a25795b4 MD5 · raw file

  1. /* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
  2. *
  3. * Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
  4. *
  5. * Tomahawk is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * Tomahawk is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "CrashReporter.h"
  19. #include <QIcon>
  20. #include <QDebug>
  21. #include <QTimer>
  22. #include <QDir>
  23. #include <QDateTime>
  24. #include <QHttp>
  25. #include "utils/TomahawkUtils.h"
  26. #define LOGFILE TomahawkUtils::appLogDir().filePath( "Tomahawk.log" ).toLocal8Bit()
  27. #define RESPATH ":/data/"
  28. CrashReporter::CrashReporter( const QStringList& args )
  29. {
  30. setWindowIcon( QIcon( RESPATH "icons/tomahawk-icon-128x128.png" ) );
  31. ui.setupUi( this );
  32. ui.logoLabel->setPixmap( QPixmap( RESPATH "icons/tomahawk-icon-128x128.png" ).scaled( QSize( 55, 55 ), Qt::KeepAspectRatio, Qt::SmoothTransformation ) );
  33. ui.progressBar->setRange( 0, 100 );
  34. ui.progressBar->setValue( 0 );
  35. ui.progressLabel->setPalette( Qt::gray );
  36. #ifdef Q_WS_MAC
  37. QFont f = ui.bottomLabel->font();
  38. f.setPointSize( 10 );
  39. ui.bottomLabel->setFont( f );
  40. f.setPointSize( 11 );
  41. ui.progressLabel->setFont( f );
  42. ui.progressLabel->setIndent( 3 );
  43. #else
  44. ui.vboxLayout->setSpacing( 16 );
  45. ui.hboxLayout1->setSpacing( 16 );
  46. ui.progressBar->setTextVisible( false );
  47. ui.progressLabel->setIndent( 1 );
  48. ui.bottomLabel->setDisabled( true );
  49. ui.bottomLabel->setIndent( 1 );
  50. #endif //Q_WS_MAC
  51. m_http = new QHttp( "oops.tomahawk-player.org", 80, this );
  52. connect( m_http, SIGNAL( done( bool ) ), SLOT( onDone() ), Qt::QueuedConnection );
  53. connect( m_http, SIGNAL( dataSendProgress( int, int ) ), SLOT( onProgress( int, int ) ) );
  54. m_dir = args.value( 1 );
  55. m_minidump = m_dir + '/' + args.value( 2 ) + ".dmp";
  56. m_product_name = args.value( 3 );
  57. //hide until "send report" has been clicked
  58. ui.progressBar->setVisible( false );
  59. ui.button->setVisible( false );
  60. ui.progressLabel->setVisible( false );
  61. connect( ui.sendButton, SIGNAL( clicked() ), SLOT( onSendButton() ) );
  62. adjustSize();
  63. setFixedSize( size() );
  64. }
  65. CrashReporter::~CrashReporter()
  66. {
  67. delete m_http;
  68. }
  69. static QByteArray
  70. contents( const QString& path )
  71. {
  72. QFile f( path );
  73. f.open( QFile::ReadOnly );
  74. return f.readAll();
  75. }
  76. void
  77. CrashReporter::send()
  78. {
  79. QByteArray body;
  80. // socorro expects a 10 digit build id
  81. QRegExp rx( "(\\d+\\.\\d+\\.\\d+).(\\d+)" );
  82. rx.exactMatch( TomahawkUtils::appFriendlyVersion() );
  83. QString const version = rx.cap( 1 );
  84. QString const buildId = rx.cap( 2 ).leftJustified( 10, '0' );
  85. // add parameters
  86. typedef QPair<QByteArray, QByteArray> Pair;
  87. QList<Pair> pairs;
  88. pairs << Pair( "BuildID", buildId.toUtf8() )
  89. << Pair( "ProductName", m_product_name.toUtf8() )
  90. << Pair( "Version", TomahawkUtils::appFriendlyVersion().toLocal8Bit() )
  91. << Pair( "Vendor", "Tomahawk" )
  92. << Pair( "timestamp", QByteArray::number( QDateTime::currentDateTime().toTime_t() ) );
  93. foreach ( Pair const pair, pairs )
  94. {
  95. body += "--thkboundary\r\n";
  96. body += "Content-Disposition: form-data; name=\"" +
  97. pair.first + "\"\r\n\r\n" +
  98. pair.second + "\r\n";
  99. }
  100. // add minidump file
  101. body += "--thkboundary\r\n";
  102. body += "Content-Disposition: form-data; name=\"upload_file_minidump\"; filename=\""
  103. + QFileInfo( m_minidump ).fileName() + "\"\r\n";
  104. body += "Content-Type: application/octet-stream\r\n";
  105. body += "\r\n";
  106. body += contents( m_minidump );
  107. body += "\r\n";
  108. // add logfile
  109. body += "--thkboundary\r\n";
  110. body += "Content-Disposition: form-data; name=\"upload_file_tomahawklog\"; filename=\"Tomahawk.log\"\r\n";
  111. body += "Content-Type: application/x-gzip\r\n";
  112. body += "\r\n";
  113. body += qCompress( contents( LOGFILE ) );
  114. body += "\r\n";
  115. body += "--thkboundary--\r\n";
  116. QHttpRequestHeader header( "POST", "/addreport.php" );
  117. header.setContentType( "multipart/form-data; boundary=thkboundary" );
  118. header.setValue( "HOST", "oops.tomahawk-player.org" );
  119. m_http->request( header, body );
  120. }
  121. void
  122. CrashReporter::onProgress( int done, int total )
  123. {
  124. if ( total )
  125. {
  126. QString const msg = tr( "Uploaded %L1 of %L2 KB." ).arg( done / 1024 ).arg( total / 1024 );
  127. ui.progressBar->setMaximum( total );
  128. ui.progressBar->setValue( done );
  129. ui.progressLabel->setText( msg );
  130. }
  131. }
  132. void
  133. CrashReporter::onDone()
  134. {
  135. QByteArray data = m_http->readAll();
  136. ui.progressBar->setValue( ui.progressBar->maximum() );
  137. ui.button->setText( tr( "Close" ) );
  138. QString const response = QString::fromUtf8( data );
  139. if ( m_http->error() != QHttp::NoError || !response.startsWith( "CrashID=" ) )
  140. {
  141. onFail( m_http->error(), m_http->errorString() );
  142. }
  143. else
  144. ui.progressLabel->setText( tr( "Sent! <b>Many thanks</b>." ) );
  145. }
  146. void
  147. CrashReporter::onFail( int error, const QString& errorString )
  148. {
  149. ui.button->setText( tr( "Close" ) );
  150. ui.progressLabel->setText( tr( "Failed to send crash info." ) );
  151. qDebug() << "Error:" << error << errorString;
  152. }
  153. void
  154. CrashReporter::onSendButton()
  155. {
  156. ui.progressBar->setVisible( true );
  157. ui.button->setVisible( true );
  158. ui.progressLabel->setVisible( true );
  159. ui.sendButton->setEnabled( false );
  160. ui.dontSendButton->setEnabled( false );
  161. adjustSize();
  162. setFixedSize( size() );
  163. QTimer::singleShot( 0, this, SLOT( send() ) );
  164. }