merge conflicts
[accounts-sso:libaccounts-ui.git] / lib / AccountsUI / provider-plugin-process.cpp
1 /*
2  * This file is part of accounts-ui
3  *
4  * Copyright (C) 2009-2010 Nokia Corporation.
5  *
6  * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * version 2.1 as published by the Free Software Foundation.
11  *
12  * This library is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA
21  */
22
23 #include "provider-plugin-process.h"
24 #include "add-account-page.h"
25 #include "accountsettingspage.h"
26 #include "generic-account-setup-context.h"
27 #include "provider-plugin-process-priv.h"
28
29 #include <Accounts/Account>
30 #include <Accounts/Manager>
31 #include <MComponentCache>
32 #include <MApplication>
33 #include <MApplicationWindow>
34
35 #include <QDebug>
36 #include <QFile>
37 #include <QLocalSocket>
38 #include <QProcess>
39
40 namespace AccountsUI {
41
42 static ProviderPluginProcess *plugin_instance = 0;
43
44 void ProviderPluginProcessPrivate::printAccountId()
45 {
46     Accounts::Account *account = context()->account();
47
48     QByteArray ba = QString("%1 %2").arg(account->id()).arg(QString::number(returnToApp)).toAscii();
49     if (!serverName.isEmpty()) {
50         QLocalSocket *socket = new QLocalSocket();
51         connect(socket, SIGNAL(error(QLocalSocket::LocalSocketError)),
52                 this, SLOT(socketConnectionError(QLocalSocket::LocalSocketError)));
53         socket->connectToServer(serverName);
54         socket->write(ba);
55         socket->flush();
56         socket->close();
57     } else {
58         QFile output;
59         output.open(STDOUT_FILENO, QIODevice::WriteOnly);
60         output.write(ba.constData());
61         output.close();
62     }
63 }
64
65 void ProviderPluginProcessPrivate::socketConnectionError(QLocalSocket::LocalSocketError status)
66 {
67     qDebug() << Q_FUNC_INFO << status;
68 }
69
70
71 AbstractAccountSetupContext *ProviderPluginProcessPrivate::context() const
72 {
73     if (!m_context) {
74         m_context = q_ptr->accountSetupContext(account, setupType, q_ptr);
75         m_context->setServiceType(serviceType);
76     }
77     return m_context;
78 }
79
80 void ProviderPluginProcessPrivate::serviceEnabled(Accounts::Service *service)
81 {
82     qDebug() << Q_FUNC_INFO << service->name();
83
84     QDomElement root = service->domDocument().documentElement();
85     QDomElement handler = root.firstChildElement("handler");
86     if (!handler.isNull()) {
87         QString type = handler.attribute("type");
88         if (type == "command") {
89             /* Syntax for the service file:
90              *
91              *   <handler type="command">/usr/bin/appname [args]...</handler>
92              */
93             QString command = handler.text();
94             qDebug() << "Executing" << command;
95
96             /* The account plugin process is going to die very soon; the
97              * handler must be started as a detached process, for it to
98              * continue to live. */
99             bool ok = QProcess::startDetached(command);
100             if (!ok)
101                 qWarning() << "Could not execute:" << command;
102         }
103         /* support more types (e.g., D-Bus services) here */
104     }
105 }
106
107 void ProviderPluginProcessPrivate::accountSaved()
108 {
109     qDebug() << Q_FUNC_INFO;
110
111     account->selectService();
112     if (account->enabled()) {
113         /* Go through the enabled services and run the activation command, if
114          * present */
115         foreach (Accounts::Service *service, account->services()) {
116             account->selectService(service);
117             if (account->enabled() && !enabledServices.contains(service))
118                 serviceEnabled(service);
119         }
120     }
121 }
122
123 void ProviderPluginProcessPrivate::monitorServices()
124 {
125     connect(account, SIGNAL(synced()), this, SLOT(accountSaved()));
126
127     /* If we are editing an account, get the list of services initially
128      * enabled, to avoid starting up their handlers for no reason */
129     account->selectService();
130     if (setupType == EditExisting && account->enabled()) {
131         foreach (Accounts::Service *service, account->services()) {
132             account->selectService(service);
133             if (account->enabled())
134                 enabledServices.append(service);
135         }
136     }
137 }
138
139 ProviderPluginProcess::ProviderPluginProcess(AccountPluginInterface *plugin,
140                                              int &argc, char **argv)
141     : d_ptr(new ProviderPluginProcessPrivate(plugin, argc, argv))
142 {
143     Q_D(ProviderPluginProcess);
144     init(argc, argv);
145     d->m_context = plugin->accountSetupContext(d->account, d->setupType, this);
146     d->m_context->setServiceType(d->serviceType);
147 }
148
149 ProviderPluginProcess::ProviderPluginProcess(int &argc, char **argv)
150     : d_ptr(new ProviderPluginProcessPrivate(argc, argv))
151 {
152     init(argc, argv);
153 }
154
155 void ProviderPluginProcess::init(int &argc, char **argv)
156 {
157     Q_UNUSED(argc);
158     Q_UNUSED(argv);
159     Q_D(ProviderPluginProcess);
160     d->q_ptr = this;
161     if (plugin_instance != 0)
162         qWarning() << "ProviderPluginProcess already instantiated";
163     plugin_instance = this;
164 }
165
166 ProviderPluginProcess::~ProviderPluginProcess()
167 {
168     Q_D(ProviderPluginProcess);
169     delete d;
170 }
171
172 ProviderPluginProcess *ProviderPluginProcess::instance()
173 {
174     return plugin_instance;
175 }
176
177 MApplicationPage * ProviderPluginProcess::mainPage()
178 {
179     Q_D(ProviderPluginProcess);
180     AbstractAccountSetupContext *context = d->context();
181
182     if (context->setupType() == CreateNew)
183         return new AddAccountPage(context);
184
185     if (context->setupType() == EditExisting)
186         return new AccountSettingsPage(context);
187
188     /* we should never come to this point */
189     Q_ASSERT(false);
190     return 0;
191 }
192
193 int ProviderPluginProcess::exec()
194 {
195     Q_D(ProviderPluginProcess);
196
197     /* if we the account is invalid (either because it does not exists or
198      * couldn't be loaded because of some DB error), return immediately */
199     if (d->account == 0) {
200         qWarning() << Q_FUNC_INFO << "account() is NULL";
201         return 1;
202     }
203
204     d->window->show();
205     MApplicationPage *page = mainPage();
206
207     if (page == 0) {
208         qWarning() << Q_FUNC_INFO << "The mainPage() returned 0";
209         return 1;
210     }
211
212     page->appear(d->window);
213
214     int result = d->application->exec();
215 <<<<<<< HEAD
216 =======
217     delete page;
218     delete d->window;
219     delete d->application;
220 >>>>>>> d20944132c0db7bd293806be0353ae0113afb028
221     return result;
222 }
223
224 void ProviderPluginProcess::quit()
225 {
226     Q_D(ProviderPluginProcess);
227
228     d->printAccountId();
229
230     QCoreApplication::exit(0);
231 }
232
233 AbstractAccountSetupContext *ProviderPluginProcess::setupContext() const
234 {
235     Q_D(const ProviderPluginProcess);
236     return d->context();
237 }
238
239 AbstractAccountSetupContext *ProviderPluginProcess::accountSetupContext(
240             Accounts::Account *account,
241             SetupType type,
242             QObject *parent)
243 {
244     return new GenericAccountSetupContext(account, type, parent);
245 }
246
247 void ProviderPluginProcess::setReturnToApp(bool returnToApp)
248 {
249     Q_D(ProviderPluginProcess);
250     d->returnToApp = returnToApp;
251 }
252
253 const LastPageActions &ProviderPluginProcess::lastPageActions() const
254 {
255     Q_D(const ProviderPluginProcess);
256     return d->lastPageActions;
257 }
258
259 } // namespace