1
/**************************************************************************
3
** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
5
** Contact: BlackBerry (qt@blackberry.com)
6
** Contact: KDAB (info@kdab.com)
8
** This file is part of Qt Creator.
10
** Commercial License Usage
11
** Licensees holding valid commercial Qt licenses may use this file in
12
** accordance with the commercial license agreement provided with the
13
** Software or, alternatively, in accordance with the terms contained in
14
** a written agreement between you and Digia. For licensing terms and
15
** conditions see http://qt.digia.com/licensing. For further information
16
** use the contact form at http://qt.digia.com/contact-us.
18
** GNU Lesser General Public License Usage
19
** Alternatively, this file may be used under the terms of the GNU Lesser
20
** General Public License version 2.1 as published by the Free Software
21
** Foundation and appearing in the file LICENSE.LGPL included in the
22
** packaging of this file. Please review the following information to
23
** ensure the GNU Lesser General Public License version 2.1 requirements
24
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
26
** In addition, as a special exception, Digia gives you certain additional
27
** rights. These rights are described in the Digia Qt LGPL Exception
28
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
30
****************************************************************************/
32
#include "blackberrysetupwizard.h"
33
#include "blackberrysetupwizardpages.h"
34
#include "blackberrydeviceconfiguration.h"
35
#include "blackberrycertificate.h"
36
#include "blackberryconfigurationmanager.h"
37
#include "blackberrydebugtokenrequester.h"
38
#include "blackberrydebugtokenuploader.h"
39
#include "blackberrydeviceinformation.h"
40
#include "blackberrysigningutils.h"
41
#include "qnxconstants.h"
43
#include <projectexplorer/devicesupport/devicemanager.h>
44
#include <projectexplorer/devicesupport/idevice.h>
45
#include <ssh/sshconnection.h>
46
#include <ssh/sshkeygenerator.h>
47
#include <utils/fileutils.h>
48
#include <coreplugin/icore.h>
51
#include <QMessageBox>
53
#include <QAbstractButton>
55
using namespace ProjectExplorer;
57
using namespace Qnx::Internal;
59
BlackBerrySetupWizard::BlackBerrySetupWizard(QWidget *parent) :
60
Utils::Wizard(parent),
69
m_utils(BlackBerrySigningUtils::instance()),
74
setWindowTitle(tr("BlackBerry Development Environment Setup Wizard"));
75
setOption(QWizard::IndependentPages, true);
77
m_welcomePage = new BlackBerrySetupWizardWelcomePage(this);
78
m_ndkPage = new BlackBerrySetupWizardNdkPage(this);
79
m_keysPage = new BlackBerrySetupWizardKeysPage(this);
80
m_certificatePage = new BlackBerrySetupWizardCertificatePage(this);
81
m_devicePage = new BlackBerrySetupWizardDevicePage(this);
82
m_finishPage = new BlackBerrySetupWizardFinishPage(this);
84
setPage(WelcomePageId, m_welcomePage);
85
setPage(NdkPageId, m_ndkPage);
86
setPage(KeysPageId, m_keysPage);
87
setPage(CertificatePageId, m_certificatePage);
88
setPage(DevicePageId, m_devicePage);
89
setPage(FinishPageId, m_finishPage);
91
m_deviceInfo = new BlackBerryDeviceInformation(this);
92
m_requester = new BlackBerryDebugTokenRequester(this);
93
m_uploader = new BlackBerryDebugTokenUploader(this);
94
m_keyGenerator = new QSsh::SshKeyGenerator;
96
connect(m_ndkPage, SIGNAL(targetsUpdated()),
97
this, SIGNAL(ndkTargetsUpdated()));
98
connect(m_deviceInfo, SIGNAL(finished(int)),
99
this, SLOT(deviceInfoFinished(int)));
100
connect(m_requester, SIGNAL(finished(int)),
101
this, SLOT(debugTokenArrived(int)));
102
connect(m_uploader, SIGNAL(finished(int)),
103
this, SLOT(uploaderFinished(int)));
104
connect(this, SIGNAL(stepFinished()),
105
this, SLOT(processNextStep()));
107
registerStep("requestDevicePin", tr("Reading device PIN..."));
108
registerStep("generateDeveloperCertificate", tr("Generating developer certificate..."));
109
registerStep("generateSshKeys", tr("Generating SSH keys..."));
110
registerStep("requestDebugToken", tr("Requesting a debug token for the device..."));
111
registerStep("uploadDebugToken", tr("Now uploading the debug token..."));
112
registerStep("writeDeviceInformation", tr("Writing device information..."));
115
BlackBerrySetupWizard::~BlackBerrySetupWizard()
117
delete m_keyGenerator;
119
foreach (Step *s, m_stepList)
125
void BlackBerrySetupWizard::accept()
131
void BlackBerrySetupWizard::processNextStep()
135
if (m_currentStep >= m_stepList.size())
138
const Step *step = m_stepList.at(m_currentStep);
140
m_finishPage->setProgress(step->message, m_currentStep * m_stepOffset);
141
QMetaObject::invokeMethod(this, step->slot);
144
void BlackBerrySetupWizard::deviceInfoFinished(int status)
146
const QString errorString = tr("Error reading device PIN. "
147
"Please make sure that the specified device IP address is correct.");
149
if (status != BlackBerryDeviceInformation::Success) {
150
QMessageBox::critical(this, tr("Error"), errorString);
155
m_devicePin = m_deviceInfo->devicePin();
157
if (m_devicePin.isEmpty()) {
158
QMessageBox::critical(this, tr("Error"), errorString);
166
void BlackBerrySetupWizard::certificateCreated(int status)
168
if (status == BlackBerryCertificate::Error) {
169
QMessageBox::critical(this, tr("Error"), tr("Error creating developer certificate."));
170
m_certificate->deleteLater();
179
void BlackBerrySetupWizard::debugTokenArrived(int status)
181
QString errorString = tr("Failed to request debug token:") + QLatin1Char(' ');
184
case BlackBerryDebugTokenRequester::Success:
187
case BlackBerryDebugTokenRequester::WrongCskPassword:
188
m_utils.clearCskPassword();
189
errorString += tr("Wrong CSK password.");
191
case BlackBerryDebugTokenRequester::WrongKeystorePassword:
192
errorString += tr("Wrong keystore password.");
194
case BlackBerryDebugTokenRequester::NetworkUnreachable:
195
errorString += tr("Network unreachable.");
197
case BlackBerryDebugTokenRequester::IllegalPin:
198
errorString += tr("Illegal device PIN.");
200
case BlackBerryDebugTokenRequester::FailedToStartInferiorProcess:
201
errorString += tr("Failed to start inferior process.");
203
case BlackBerryDebugTokenRequester::InferiorProcessTimedOut:
204
errorString += tr("Inferior processes timed out.");
206
case BlackBerryDebugTokenRequester::InferiorProcessCrashed:
207
errorString += tr("Inferior process has crashed.");
209
case BlackBerryDebugTokenRequester::InferiorProcessReadError:
210
case BlackBerryDebugTokenRequester::InferiorProcessWriteError:
211
errorString += tr("Failed to communicate with the inferior process.");
213
case BlackBerryDebugTokenRequester::UnknownError:
215
m_utils.clearCskPassword();
216
errorString += tr("An unknwon error has occurred.");
220
QMessageBox::critical(this, tr("Error"), errorString);
225
void BlackBerrySetupWizard::uploaderFinished(int status)
227
QString errorString = tr("Failed to upload debug token:") + QLatin1Char(' ');
230
case BlackBerryDebugTokenUploader::Success:
233
case BlackBerryDebugTokenUploader::NoRouteToHost:
234
errorString += tr("No route to host.");
236
case BlackBerryDebugTokenUploader::AuthenticationFailed:
237
errorString += tr("Authentication failed.");
239
case BlackBerryDebugTokenUploader::DevelopmentModeDisabled:
240
errorString += tr("Development mode is disabled on the device.");
242
case BlackBerryDebugTokenUploader::FailedToStartInferiorProcess:
243
errorString += tr("Failed to start inferior process.");
245
case BlackBerryDebugTokenUploader::InferiorProcessTimedOut:
246
errorString += tr("Inferior processes timed out.");
248
case BlackBerryDebugTokenUploader::InferiorProcessCrashed:
249
errorString += tr("Inferior process has crashed.");
251
case BlackBerryDebugTokenUploader::InferiorProcessReadError:
252
case BlackBerryDebugTokenUploader::InferiorProcessWriteError:
253
errorString += tr("Failed to communicate with the inferior process.");
255
case BlackBerryDebugTokenUploader::UnknownError:
256
errorString += tr("An unknwon error has happened.");
260
QMessageBox::critical(this, tr("Error"), errorString);
265
void BlackBerrySetupWizard::registerStep(const QByteArray &slot, const QString &message)
269
s->message = message;
272
m_stepOffset = 100/m_stepList.size();
275
void BlackBerrySetupWizard::setBusy(bool busy)
277
button(QWizard::BackButton)->setEnabled(!busy);
278
button(QWizard::NextButton)->setEnabled(!busy);
279
button(QWizard::FinishButton)->setEnabled(!busy);
280
button(QWizard::CancelButton)->setEnabled(!busy);
283
m_finishPage->setProgress(QString(), -1);
286
void BlackBerrySetupWizard::cleanupFiles() const
288
BlackBerryConfigurationManager &configuration = BlackBerryConfigurationManager::instance();
292
f.setFileName(configuration.defaultKeystorePath());
295
f.setFileName(configuration.defaultDebugTokenPath());
298
f.setFileName(privateKeyPath());
301
f.setFileName(publicKeyPath());
304
QDir::root().rmpath(storeLocation());
307
void BlackBerrySetupWizard::reset()
314
m_certificate->deleteLater();
319
void BlackBerrySetupWizard::requestDevicePin()
321
if (!isPhysicalDevice()) {
326
m_deviceInfo->setDeviceTarget(hostName(), devicePassword());
329
void BlackBerrySetupWizard::generateDeveloperCertificate()
331
BlackBerryConfigurationManager &configuration = BlackBerryConfigurationManager::instance();
333
m_certificate = new BlackBerryCertificate(configuration.defaultKeystorePath(),
334
certificateAuthor(), certificatePassword());
336
connect(m_certificate, SIGNAL(finished(int)), this, SLOT(certificateCreated(int)));
338
m_certificate->store();
341
void BlackBerrySetupWizard::generateSshKeys()
343
const bool success = m_keyGenerator->generateKeys(QSsh::SshKeyGenerator::Rsa,
344
QSsh::SshKeyGenerator::Mixed, 4096,
345
QSsh::SshKeyGenerator::DoNotOfferEncryption);
348
QMessageBox::critical(this, tr("Key Generation Failed"), m_keyGenerator->error());
353
if (!QDir::root().mkpath(storeLocation())) {
354
QMessageBox::critical(this, tr("Failure to Save Key File"),
355
tr("Failed to create directory: '%1'.").arg(storeLocation()));
360
if (QFileInfo(privateKeyPath()).exists()) {
361
QMessageBox::critical(this, tr("Failure to Save Key File"),
362
tr("Private key file already exists: '%1'").arg(privateKeyPath()));
367
if (QFileInfo(publicKeyPath()).exists()) {
368
QMessageBox::critical(this, tr("Failure to Save Key File"),
369
tr("Public key file already exists: '%1'").arg(publicKeyPath()));
374
Utils::FileSaver privateKeySaver(privateKeyPath());
375
privateKeySaver.write(m_keyGenerator->privateKey());
377
if (!privateKeySaver.finalize(this)) {
379
return; // finalize shows an error message if necessary
382
QFile::setPermissions(privateKeyPath(), QFile::ReadOwner | QFile::WriteOwner);
384
Utils::FileSaver publicKeySaver(publicKeyPath());
386
// blackberry-connect requires an @ character to be included in the RSA comment
387
const QString atHost = QLatin1Char('@') + QHostInfo::localHostName();
388
QByteArray publicKeyContent = m_keyGenerator->publicKey();
389
publicKeyContent.append(atHost.toLocal8Bit());
391
publicKeySaver.write(publicKeyContent);
393
if (!publicKeySaver.finalize(this)) {
401
void BlackBerrySetupWizard::requestDebugToken()
403
if (!isPhysicalDevice()) {
408
BlackBerryConfigurationManager &configuration = BlackBerryConfigurationManager::instance();
410
m_requester->requestDebugToken(configuration.defaultDebugTokenPath(),
411
m_utils.cskPassword(), configuration.defaultKeystorePath(), certificatePassword(), m_devicePin);
414
void BlackBerrySetupWizard::uploadDebugToken()
416
if (!isPhysicalDevice()) {
421
BlackBerryConfigurationManager &configuration = BlackBerryConfigurationManager::instance();
423
m_uploader->uploadDebugToken(configuration.defaultDebugTokenPath(),
424
hostName(), devicePassword());
427
void BlackBerrySetupWizard::writeDeviceInformation()
429
DeviceManager * const deviceManager = DeviceManager::instance();
430
deviceManager->addDevice(device());
432
m_utils.setDefaultCertificate(m_certificate);
437
QString BlackBerrySetupWizard::privateKeyPath() const
439
return storeLocation() + QLatin1String("/id_rsa");
442
QString BlackBerrySetupWizard::publicKeyPath() const
444
return storeLocation() + QLatin1String("/id_rsa.pub");
447
QString BlackBerrySetupWizard::deviceName() const
449
return field(QLatin1String(BlackBerrySetupWizardDevicePage::NameField)).toString();
452
QString BlackBerrySetupWizard::storeLocation() const
454
return Core::ICore::userResourcePath() + QLatin1String("/qnx/") + deviceName();
457
QString BlackBerrySetupWizard::certificatePassword() const
459
return field(QLatin1String(BlackBerrySetupWizardCertificatePage::PasswordField)).toString();
462
QString BlackBerrySetupWizard::certificateAuthor() const
464
return field(QLatin1String(BlackBerrySetupWizardCertificatePage::AuthorField)).toString();
467
QString BlackBerrySetupWizard::hostName() const
469
return field(QLatin1String(BlackBerrySetupWizardDevicePage::IpAddressField)).toString();
472
QString BlackBerrySetupWizard::devicePassword() const
474
return field(QLatin1String(BlackBerrySetupWizardDevicePage::PasswordField)).toString();
477
bool BlackBerrySetupWizard::isPhysicalDevice() const
479
return field(QLatin1String(BlackBerrySetupWizardDevicePage::PhysicalDeviceField)).toBool();
482
IDevice::Ptr BlackBerrySetupWizard::device()
484
QSsh::SshConnectionParameters sshParams;
485
sshParams.options = QSsh::SshIgnoreDefaultProxy;
486
sshParams.host = hostName();
487
sshParams.password = devicePassword();
488
sshParams.authenticationType = QSsh::SshConnectionParameters::AuthenticationTypePublicKey;
489
sshParams.privateKeyFile = privateKeyPath();
490
sshParams.userName = QLatin1String("devuser");
491
sshParams.timeout = 10;
494
IDevice::MachineType machineType = (isPhysicalDevice()) ? IDevice::Hardware : IDevice::Emulator;
496
BlackBerryDeviceConfiguration::Ptr configuration = BlackBerryDeviceConfiguration::create(
497
deviceName(), Core::Id(Constants::QNX_BB_OS_TYPE), machineType);
499
configuration->setSshParameters(sshParams);
500
configuration->setDebugToken(BlackBerryConfigurationManager::instance().defaultDebugTokenPath());
502
return configuration;