1 /*
2  * SingleApplicationDBus.cpp
3  * Copyright (C) 2017  Belledonne Communications, Grenoble, France
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program 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 this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  *  Created on: June 20, 2017
20  *      Author: Ghislain MARY
21  */
22 
23 #include <cstdlib>
24 #include <iostream>
25 
26 #include <QtCore/QByteArray>
27 #include <QtDBus/QtDBus>
28 
29 #include "SingleApplication.hpp"
30 #include "SingleApplicationDBusPrivate.hpp"
31 
32 // =============================================================================
33 
34 const char *SERVICE_NAME = "org.linphone.SingleApplication";
35 
SingleApplicationPrivate(SingleApplication * q_ptr)36 SingleApplicationPrivate::SingleApplicationPrivate (SingleApplication *q_ptr)
37   : QDBusAbstractAdaptor(q_ptr), q_ptr(q_ptr) {}
38 
getBus() const39 QDBusConnection SingleApplicationPrivate::getBus () const {
40   if (options & SingleApplication::Mode::User)
41     return QDBusConnection::sessionBus();
42 
43   return QDBusConnection::systemBus();
44 }
45 
startPrimary()46 void SingleApplicationPrivate::startPrimary () {
47   if (!getBus().registerObject("/", this, QDBusConnection::ExportAllSlots))
48     qWarning() << QStringLiteral("Failed to register single application object on DBus.");
49   instanceNumber = 0;
50 }
51 
startSecondary()52 void SingleApplicationPrivate::startSecondary () {
53   instanceNumber = 1;
54 }
55 
SingleApplication(int & argc,char * argv[],bool allowSecondary,Options options,int)56 SingleApplication::SingleApplication (int &argc, char *argv[], bool allowSecondary, Options options, int)
57   : QApplication(argc, argv), d_ptr(new SingleApplicationPrivate(this)) {
58   Q_D(SingleApplication);
59 
60   // Store the current mode of the program
61   d->options = options;
62 
63   if (!d->getBus().isConnected()) {
64     qWarning() << QStringLiteral("Cannot connect to the D-Bus session bus.");
65     delete d;
66     ::exit(EXIT_FAILURE);
67   }
68 
69   if (d->getBus().registerService(SERVICE_NAME)) {
70     d->startPrimary();
71     return;
72   }
73 
74   if (allowSecondary) {
75     d->startSecondary();
76     return;
77   }
78 
79   delete d;
80   ::exit(EXIT_SUCCESS);
81 }
82 
~SingleApplication()83 SingleApplication::~SingleApplication () {
84   Q_D(SingleApplication);
85   delete d;
86 }
87 
isPrimary()88 bool SingleApplication::isPrimary () {
89   Q_D(SingleApplication);
90   return d->instanceNumber == 0;
91 }
92 
isSecondary()93 bool SingleApplication::isSecondary () {
94   Q_D(SingleApplication);
95   return d->instanceNumber != 0;
96 }
97 
instanceId()98 quint32 SingleApplication::instanceId () {
99   Q_D(SingleApplication);
100   return d->instanceNumber;
101 }
102 
sendMessage(QByteArray message,int timeout)103 bool SingleApplication::sendMessage (QByteArray message, int timeout) {
104   Q_D(SingleApplication);
105 
106   if (isPrimary()) return false;
107 
108   QDBusInterface iface(SERVICE_NAME, "/", "", d->getBus());
109   if (iface.isValid()) {
110     iface.setTimeout(timeout);
111     QDBusMessage msg = iface.call(QDBus::Block, "messageReceived", instanceId(), message);
112     return true;
113   }
114 
115   return false;
116 }
117 
messageReceived(quint32 instanceId,QByteArray message)118 void SingleApplicationPrivate::messageReceived (quint32 instanceId, QByteArray message) {
119   Q_Q(SingleApplication);
120   Q_EMIT q->receivedMessage(instanceId, message);
121 }
122 
quit()123 void SingleApplication::quit () {
124   QCoreApplication::quit();
125 }
126