00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "provider-plugin-proxy.h"
00024 #include "provider-plugin-proxy-priv.h"
00025
00026 #include <Accounts/Manager>
00027
00028 #include <QDebug>
00029 #include <QLocalServer>
00030 #include <QLocalSocket>
00031
00032 using namespace Accounts;
00033 using namespace AccountSetup;
00034
00035
00036 ProviderPluginProxyPrivate::~ProviderPluginProxyPrivate()
00037 {
00038 qDebug() << Q_FUNC_INFO;
00039 if (process) {
00040 process->disconnect();
00041 process->close();
00042 delete process;
00043 }
00044 }
00045
00046 void ProviderPluginProxyPrivate::startProcess(Provider *provider,
00047 AccountId accountId,
00048 const QString &serviceType)
00049 {
00050 Q_Q(ProviderPluginProxy);
00051
00052 error = ProviderPluginProxy::NoError;
00053 createdAccountId = 0;
00054 pluginOutput.clear();
00055
00056 QString processName;
00057 QString pluginFileName;
00058
00059 if (!findPlugin(provider, processName, pluginFileName)) {
00060 error = ProviderPluginProxy::PluginNotFound;
00061 emit q->finished();
00062 return;
00063 }
00064 providerName = provider->name();
00065 pid_t pid = getpid();
00066 socketName = provider->name() + QString::number(pid);
00067
00068 QStringList arguments;
00069 arguments << QLatin1String("--socketName") << socketName;
00070
00071 if (parentWidget != 0) {
00072 WId windowId = parentWidget->effectiveWinId();
00073 arguments << QLatin1String("--windowId") << QString::number(windowId);
00074 }
00075
00076 if (accountId != 0) {
00077 arguments << QLatin1String("--edit") << QString::number(accountId);
00078 setupType = EditExisting;
00079 } else {
00080 arguments << QLatin1String("--create") << provider->name();
00081 setupType = CreateNew;
00082 }
00083
00084 if (!serviceType.isEmpty())
00085 arguments << QLatin1String("--serviceType") << serviceType;
00086
00087 arguments += additionalParameters;
00088
00089 #ifndef QT_NO_DEBUG_OUTPUT
00090 arguments << QLatin1String("-output-level") << QLatin1String("debug");
00091 #endif
00092
00093 if (!process)
00094 process = new QProcess();
00095
00096 pluginName = pluginFileName;
00097
00098 qDebug() << Q_FUNC_INFO << processName << arguments;
00099
00100 connect(process, SIGNAL(readyReadStandardError()),
00101 this, SLOT(onReadStandardError()));
00102 connect(process, SIGNAL(error(QProcess::ProcessError)),
00103 this, SLOT(onError(QProcess::ProcessError)));
00104 connect(process, SIGNAL(finished(int, QProcess::ExitStatus)),
00105 this, SLOT(onFinished(int, QProcess::ExitStatus)));
00106 connect(process, SIGNAL(started()), this, SLOT(setCommunicationChannel()));
00107
00108 process->start(processName, arguments);
00109 }
00110
00111 bool ProviderPluginProxyPrivate::findPlugin(Provider *provider,
00112 QString &pluginPath,
00113 QString &pluginFileName)
00114 {
00115 static const char pluginNamePattern[] = "%1plugin";
00116 bool pluginTagExists = true;
00117
00118 QDomElement root(provider->domDocument().documentElement());
00119 QString pluginName(root.
00120 firstChildElement(QString::fromLatin1("plugin")).
00121 text());
00122 if (pluginName.isEmpty()) {
00123 pluginName = provider->name();
00124 pluginTagExists = false;
00125 }
00126
00127 QStringList pluginFileNames;
00128 pluginFileNames << QString::fromLatin1(pluginNamePattern).arg(pluginName);
00129
00130
00131
00132
00133
00134 if (!pluginTagExists) {
00135 pluginFileNames << QString::fromLatin1(pluginNamePattern).
00136 arg(QLatin1String("generic"));
00137 }
00138
00139 foreach (QString name, pluginFileNames) {
00140 foreach (QString pluginDir, pluginDirs) {
00141 QFileInfo pluginFileInfo(pluginDir, name);
00142
00143 if (pluginFileInfo.exists()) {
00144 pluginPath = pluginFileInfo.canonicalFilePath();
00145 pluginFileName = name;
00146 return true;
00147 }
00148 }
00149 }
00150
00151 return false;
00152 }
00153
00154 void ProviderPluginProxyPrivate::setCommunicationChannel()
00155 {
00156 QLocalServer *server = new QLocalServer();
00157 QLocalServer::removeServer(socketName);
00158 if (!server->listen(socketName))
00159 qWarning() << "Server not up";
00160 else
00161 connect(server, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
00162 }
00163
00164 void ProviderPluginProxyPrivate::onNewConnection()
00165 {
00166 QLocalServer *server = qobject_cast<QLocalServer*>(sender());
00167 QLocalSocket *socket = server->nextPendingConnection();
00168 if (!socket->waitForConnected()) {
00169 qWarning() << "Server Connection not established";
00170 return;
00171 }
00172 if (!socket->waitForReadyRead()) {
00173 qWarning() << "Server data not available for reading";
00174 return;
00175 }
00176 pluginOutput = socket->readAll();
00177 socket->close();
00178 }
00179
00180
00181 void ProviderPluginProxyPrivate::onReadStandardError()
00182 {
00183 qDebug() << QString::fromLatin1(process->readAllStandardError());
00184 }
00185
00186 void ProviderPluginProxyPrivate::onError(QProcess::ProcessError err)
00187 {
00188 Q_Q(ProviderPluginProxy);
00189
00190 if (err == QProcess::FailedToStart) {
00191 pluginName.clear();
00192 error = ProviderPluginProxy::PluginCrashed;
00193
00194 emit q->finished();
00195 if (process) {
00196 process->deleteLater();
00197 process = NULL;
00198 }
00199 }
00200
00201 qDebug() << "Error: " << err;
00202 }
00203
00204 void ProviderPluginProxyPrivate::onFinished(int exitCode,
00205 QProcess::ExitStatus exitStatus)
00206 {
00207 Q_Q(ProviderPluginProxy);
00208 Q_UNUSED(exitCode);
00209
00210 pluginName.clear();
00211
00212 if (exitStatus == QProcess::CrashExit) {
00213 error = ProviderPluginProxy::PluginCrashed;
00214 emit q->finished();
00215 process->deleteLater();
00216 process = NULL;
00217 return;
00218 }
00219
00220 QString value;
00221 if (!pluginOutput.isEmpty()) {
00222 QDataStream stream(pluginOutput);
00223 stream.device()->seek(0);
00224 stream >> createdAccountId >> exitData;
00225 }
00226
00227 if (process) {
00228 process->deleteLater();
00229 process = NULL;
00230 }
00231
00232 emit q->finished();
00233 }
00234
00235 ProviderPluginProxy::ProviderPluginProxy(QObject *parent):
00236 QObject(parent),
00237 d_ptr(new ProviderPluginProxyPrivate(this))
00238 {
00239 }
00240
00241 ProviderPluginProxy::~ProviderPluginProxy()
00242 {
00243 Q_D(ProviderPluginProxy);
00244 delete d;
00245 }
00246
00247 void ProviderPluginProxy::createAccount(Accounts::Provider *provider,
00248 const QString &serviceType)
00249 {
00250 Q_D(ProviderPluginProxy);
00251
00252 if (!provider) {
00253 qCritical() << " NULL pointer to provider";
00254 d->error = ProviderPluginProxy::PluginNotFound;
00255 emit finished();
00256 return;
00257 }
00258
00259 d->startProcess(provider, 0, serviceType);
00260 }
00261
00262 void ProviderPluginProxy::editAccount(Accounts::Account *account,
00263 const QString &serviceType)
00264 {
00265 Q_D(ProviderPluginProxy);
00266
00267 if (!account) {
00268 qCritical() << " NULL pointer to account";
00269 d->error = ProviderPluginProxy::AccountNotFound;
00270 emit finished();
00271 return;
00272 }
00273
00274 Manager *manager = account->manager();
00275 Provider *provider = manager->provider(account->providerName());
00276 d->startProcess(provider, account->id(), serviceType);
00277 }
00278
00279 void ProviderPluginProxy::setParentWidget(QWidget *parent)
00280 {
00281 Q_D(ProviderPluginProxy);
00282 d->parentWidget = parent;
00283 }
00284
00285 void ProviderPluginProxy::setPluginDirectories(const QStringList &pluginDirs)
00286 {
00287 Q_D(ProviderPluginProxy);
00288 d->pluginDirs = pluginDirs;
00289 }
00290
00291 QStringList ProviderPluginProxy::pluginDirectories() const
00292 {
00293 Q_D(const ProviderPluginProxy);
00294 return d->pluginDirs;
00295 }
00296
00297 bool ProviderPluginProxy::accountCreated() const
00298 {
00299 Q_D(const ProviderPluginProxy);
00300 return d->createdAccountId != 0;
00301 }
00302
00303 ProviderPluginProxy::Error ProviderPluginProxy::error() const
00304 {
00305 Q_D(const ProviderPluginProxy);
00306 return d->error;
00307 }
00308
00309 Accounts::AccountId ProviderPluginProxy::createdAccountId() const
00310 {
00311 Q_D(const ProviderPluginProxy);
00312 return d->createdAccountId;
00313 }
00314
00315 bool ProviderPluginProxy::isPluginRunning()
00316 {
00317 Q_D(ProviderPluginProxy);
00318 return d->process != 0;
00319 }
00320
00321 SetupType ProviderPluginProxy::setupType() const
00322 {
00323 Q_D(const ProviderPluginProxy);
00324 return d->setupType;
00325 }
00326
00327 QString ProviderPluginProxy::pluginName()
00328 {
00329 if (!isPluginRunning())
00330 return QString();
00331
00332 Q_D(ProviderPluginProxy);
00333 return d->pluginName;
00334 }
00335
00336 QString ProviderPluginProxy::providerName()
00337 {
00338 if (!isPluginRunning())
00339 return QString();
00340 Q_D(ProviderPluginProxy);
00341 return d->providerName;
00342 }
00343
00344 void ProviderPluginProxy::setAdditionalParameters(const QStringList ¶meters)
00345 {
00346 Q_D(ProviderPluginProxy);
00347 d->additionalParameters = parameters;
00348 }
00349
00350 QStringList ProviderPluginProxy::additionalParameters() const
00351 {
00352 Q_D(const ProviderPluginProxy);
00353 return d->additionalParameters;
00354 }
00355
00356 bool ProviderPluginProxy::killRunningPlugin()
00357 {
00358 Q_D(ProviderPluginProxy);
00359
00360 if (d->process == 0)
00361 return false;
00362
00363 d->process->disconnect();
00364 d->process->close();
00365 delete d->process;
00366 d->process = 0;
00367
00368 return true;
00369 }
00370
00371 QVariant ProviderPluginProxy::exitData()
00372 {
00373 Q_D(ProviderPluginProxy);
00374 return d->exitData;
00375 }
00376