PageRenderTime 367ms CodeModel.GetById 40ms app.highlight 203ms RepoModel.GetById 60ms app.codeStats 0ms

/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
 19#include "CrashReporter.h"
 20
 21#include <QIcon>
 22#include <QDebug>
 23#include <QTimer>
 24#include <QDir>
 25#include <QDateTime>
 26#include <QHttp>
 27
 28#include "utils/TomahawkUtils.h"
 29
 30#define LOGFILE TomahawkUtils::appLogDir().filePath( "Tomahawk.log" ).toLocal8Bit()
 31#define RESPATH ":/data/"
 32
 33
 34CrashReporter::CrashReporter( const QStringList& args )
 35{
 36    setWindowIcon( QIcon( RESPATH "icons/tomahawk-icon-128x128.png" ) );
 37
 38    ui.setupUi( this );
 39    ui.logoLabel->setPixmap( QPixmap( RESPATH "icons/tomahawk-icon-128x128.png" ).scaled( QSize( 55, 55 ), Qt::KeepAspectRatio, Qt::SmoothTransformation ) );
 40    ui.progressBar->setRange( 0, 100 );
 41    ui.progressBar->setValue( 0 );
 42    ui.progressLabel->setPalette( Qt::gray );
 43
 44  #ifdef Q_WS_MAC
 45    QFont f = ui.bottomLabel->font();
 46    f.setPointSize( 10 );
 47    ui.bottomLabel->setFont( f );
 48    f.setPointSize( 11 );
 49    ui.progressLabel->setFont( f );
 50    ui.progressLabel->setIndent( 3 );
 51  #else
 52    ui.vboxLayout->setSpacing( 16 );
 53    ui.hboxLayout1->setSpacing( 16 );
 54    ui.progressBar->setTextVisible( false );
 55    ui.progressLabel->setIndent( 1 );
 56    ui.bottomLabel->setDisabled( true );
 57    ui.bottomLabel->setIndent( 1 );
 58  #endif //Q_WS_MAC
 59
 60    m_http = new QHttp( "oops.tomahawk-player.org", 80, this );
 61
 62    connect( m_http, SIGNAL( done( bool ) ), SLOT( onDone() ), Qt::QueuedConnection );
 63    connect( m_http, SIGNAL( dataSendProgress( int, int ) ), SLOT( onProgress( int, int ) ) );
 64
 65    m_dir = args.value( 1 );
 66    m_minidump = m_dir + '/' + args.value( 2 ) + ".dmp";
 67    m_product_name = args.value( 3 );
 68
 69    //hide until "send report" has been clicked
 70    ui.progressBar->setVisible( false );
 71    ui.button->setVisible( false );
 72    ui.progressLabel->setVisible( false );
 73    connect( ui.sendButton, SIGNAL( clicked() ), SLOT( onSendButton() ) );
 74
 75    adjustSize();
 76    setFixedSize( size() );
 77}
 78
 79
 80CrashReporter::~CrashReporter()
 81{
 82    delete m_http;
 83}
 84
 85
 86static QByteArray
 87contents( const QString& path )
 88{
 89    QFile f( path );
 90    f.open( QFile::ReadOnly );
 91    return f.readAll();
 92}
 93
 94
 95void
 96CrashReporter::send()
 97{
 98    QByteArray body;
 99
100    // socorro expects a 10 digit build id
101    QRegExp rx( "(\\d+\\.\\d+\\.\\d+).(\\d+)" );
102    rx.exactMatch( TomahawkUtils::appFriendlyVersion() );
103    QString const version = rx.cap( 1 );
104    QString const buildId = rx.cap( 2 ).leftJustified( 10, '0' );
105
106    // add parameters
107    typedef QPair<QByteArray, QByteArray> Pair;
108    QList<Pair> pairs;
109    pairs << Pair( "BuildID", buildId.toUtf8() )
110          << Pair( "ProductName", m_product_name.toUtf8() )
111          << Pair( "Version", TomahawkUtils::appFriendlyVersion().toLocal8Bit() )
112          << Pair( "Vendor", "Tomahawk" )
113          << Pair( "timestamp", QByteArray::number( QDateTime::currentDateTime().toTime_t() ) );
114
115    foreach ( Pair const pair, pairs )
116    {
117        body += "--thkboundary\r\n";
118        body += "Content-Disposition: form-data; name=\"" +
119                           pair.first  + "\"\r\n\r\n" +
120                           pair.second + "\r\n";
121    }
122
123    // add minidump file
124    body += "--thkboundary\r\n";
125    body += "Content-Disposition: form-data; name=\"upload_file_minidump\"; filename=\""
126          + QFileInfo( m_minidump ).fileName() + "\"\r\n";
127    body += "Content-Type: application/octet-stream\r\n";
128    body += "\r\n";
129    body += contents( m_minidump );
130    body += "\r\n";
131
132    // add logfile
133    body += "--thkboundary\r\n";
134    body += "Content-Disposition: form-data; name=\"upload_file_tomahawklog\"; filename=\"Tomahawk.log\"\r\n";
135    body += "Content-Type: application/x-gzip\r\n";
136    body += "\r\n";
137    body += qCompress( contents( LOGFILE ) );
138    body += "\r\n";
139    body += "--thkboundary--\r\n";
140
141    QHttpRequestHeader header( "POST", "/addreport.php" );
142    header.setContentType( "multipart/form-data; boundary=thkboundary" );
143    header.setValue( "HOST", "oops.tomahawk-player.org" );
144
145    m_http->request( header, body );
146}
147
148
149void
150CrashReporter::onProgress( int done, int total )
151{
152    if ( total )
153    {
154        QString const msg = tr( "Uploaded %L1 of %L2 KB." ).arg( done / 1024 ).arg( total / 1024 );
155
156        ui.progressBar->setMaximum( total );
157        ui.progressBar->setValue( done );
158        ui.progressLabel->setText( msg );
159    }
160}
161
162
163void
164CrashReporter::onDone()
165{
166    QByteArray data = m_http->readAll();
167    ui.progressBar->setValue( ui.progressBar->maximum() );
168    ui.button->setText( tr( "Close" ) );
169
170    QString const response = QString::fromUtf8( data );
171
172    if ( m_http->error() != QHttp::NoError || !response.startsWith( "CrashID=" ) )
173    {
174        onFail( m_http->error(), m_http->errorString() );
175    }
176    else
177        ui.progressLabel->setText( tr( "Sent! <b>Many thanks</b>." ) );
178}
179
180
181void
182CrashReporter::onFail( int error, const QString& errorString )
183{
184    ui.button->setText( tr( "Close" ) );
185    ui.progressLabel->setText( tr( "Failed to send crash info." ) );
186    qDebug() << "Error:" << error << errorString;
187}
188
189
190void
191CrashReporter::onSendButton()
192{
193    ui.progressBar->setVisible( true );
194    ui.button->setVisible( true );
195    ui.progressLabel->setVisible( true );
196    ui.sendButton->setEnabled( false );
197    ui.dontSendButton->setEnabled( false );
198
199    adjustSize();
200    setFixedSize( size() );
201
202    QTimer::singleShot( 0, this, SLOT( send() ) );
203}