Vidalia  0.3.1
PluginWrapper.cpp
Go to the documentation of this file.
1 /*
2 ** This file is part of Vidalia, and is subject to the license terms in the
3 ** LICENSE file, found in the top level directory of this distribution. If
4 ** you did not receive the LICENSE file with this file, you may obtain it
5 ** from the Vidalia source package distributed by the Vidalia Project at
6 ** http://www.torproject.org/projects/vidalia.html. No part of Vidalia,
7 ** including this file, may be copied, modified, propagated, or distributed
8 ** except according to the terms described in the LICENSE file.
9 */
10 
11 /*
12 ** \file PluginWrapper.cpp
13 ** \brief Wrapper for the plugin scripts
14 */
15 
16 #include "PluginWrapper.h"
17 #include "PluginEngine.h"
18 #include "DebugDialog.h"
19 #include "Vidalia.h"
20 
21 #include <QtXml>
22 
23 PluginWrapper::PluginWrapper(const QString &info_path, PluginEngine *engine, QObject *parent)
24  : QObject(parent), _engine(engine)
25 {
26  _action = 0;
27  _gui = false;
28  _persistent = false;
29  processInfo(info_path);
30 
31  foreach(QString path, _files) {
32  DebugDialog::outputDebug(tr("%1: Processing...").arg(name()));
33 
34  QFile file(path);
35  if(file.open(QIODevice::ReadOnly)) {
36  QString contents = file.readAll();
37  QScriptSyntaxCheckResult res = QScriptEngine::checkSyntax(contents);
38  if(res.state() == QScriptSyntaxCheckResult::Valid) {
39  DebugDialog::outputDebug("Everything's ok, evaluating...");
40  _engine->evaluate(contents);
42  } else {
43  DebugDialog::syntaxDebug(tr("%4: ERROR: Line: %1 - Column: %2\n%3")
44  .arg(res.errorLineNumber())
45  .arg(res.errorColumnNumber())
46  .arg(res.errorMessage())
47  .arg(name()));
48  }
49  } else
50  DebugDialog::outputDebug(tr("%1: Error opening file %2")
51  .arg(name()).arg(path));
52  }
53 }
54 
56 
57 void
58 PluginWrapper::processInfo(const QString &path)
59 {
60  QDomDocument info("Plugin Info");
61  QFile file(path);
62  if(!file.open(QIODevice::ReadOnly)) {
63  DebugDialog::outputDebug(tr("%2: ERROR: Cannot open %1")
64  .arg(path).arg(name()));
65  return;
66  }
67 
68  QString errMsg;
69  int errLine, errCol;
70 
71  if(!info.setContent(&file, false, &errMsg, &errLine, &errCol)) {
72  DebugDialog::syntaxDebug(tr("%2: ERROR: Parsing %1")
73  .arg(file.fileName()).arg(name()));
74  DebugDialog::syntaxDebug(tr("Line: %1 - Column: %2\nMessage: %3")
75  .arg(errLine).arg(errCol).arg(errMsg));
76 
77  file.close();
78  return;
79  }
80 
81  QDomElement root = info.documentElement();
82 
83  if(root.tagName() != "VidaliaPlugin") {
84  return;
85  }
86 
87  QDomNode n = root.firstChild();
88  while(!n.isNull()) {
89  QDomElement e = n.toElement();
90  if(!e.isNull()) {
91  if(e.tagName() == "name")
92  _name = e.text();
93  else if(e.tagName() == "author")
94  _author = e.text();
95  else if(e.tagName() == "date")
96  _date = e.text();
97  else if(e.tagName() == "type") {
98  _persistent = (e.attribute("persistent", "false") == "true");
99  _gui = (e.attribute("gui", "false") == "true");
100  } else if(e.tagName() == "files") {
101  QDomNode froot = e.firstChild();
102  while(!froot.isNull()) {
103  QDomElement fe = froot.toElement();
104  if(fe.tagName() == "file")
105  _files << QString("%1%2%3").arg(QFileInfo(path).path()).arg(QDir::separator()).arg(fe.text());
106  froot = froot.nextSibling();
107  }
108  } else if(e.tagName() == "namespace") {
109  _nspace = e.text();
110  }
111  }
112  n = n.nextSibling();
113  }
114 
115  file.close();
116 }
117 
118 void
120 {
121  DebugDialog::outputDebug(tr("%1: Starting...").arg(name()));
122  _engine->evaluate(QString("%1.start()").arg(nspace()));
123  checkExceptions();
124 }
125 
126 void
128 {
129  DebugDialog::outputDebug(tr("%1: Stoping...").arg(name()));
130  _engine->evaluate(QString("%1.stop()").arg(nspace()));
131  checkExceptions();
132 }
133 
134 VidaliaTab *
136 {
137  if(!hasGUI()) {
138  DebugDialog::outputDebug(tr("%1: WARNING: doesn't have a GUI, and buildGUI() was called")
139  .arg(name()));
140  if(checkExceptions())
141  return NULL;
142  }
143 
144  VidaliaTab *tab = qscriptvalue_cast<VidaliaTab *>(
145  _engine->evaluate(QString("%1.buildGUI()").arg(nspace())));
146 
147  if(checkExceptions())
148  return NULL;
149 
150  return tab;
151 }
152 
153 bool
155 {
156  if(_engine->hasUncaughtException()) {
157  DebugDialog::exceptDebug(tr("%2:\n*** Exception in line %1")
158  .arg(_engine->uncaughtExceptionLineNumber())
159  .arg(_engine->uncaughtException().toString()));
160  DebugDialog::exceptDebug(tr("*** Backtrace:"));
161  foreach(QString line, _engine->uncaughtExceptionBacktrace()) {
162  vInfo(line);
164  }
165 
166  _engine->clearExceptions();
167 
168  return true;
169  }
170 
171  return false;
172 }
173 
174 bool
176 {
177  return _gui;
178 }
179 
180 bool
182 {
183  return _persistent;
184 }
185 
186 QString
188 {
189  if(_name.isEmpty())
190  return tr("(untitled)");
191  return _name;
192 }
193 
194 QString
196 {
197  return _date;
198 }
199 
200 QString
202 {
203  return _author;
204 }
205 
206 QString
208 {
209  return _nspace;
210 }
211 
212 QStringList
214 {
215  return _files;
216 }
217 
218 QAction *
220 {
221  _action = new QAction(_name, this);
222 
223  if(hasGUI()) {
224  connect(_action, SIGNAL(triggered()), this, SLOT(emitPluginTab()));
225  }
226 
227  // if it hasn't been started yet
228  if(!isPersistent()) {
229  connect(_action, SIGNAL(triggered()), this, SLOT(start()));
230  }
231 
232  return _action;
233 }
234 
235 void
237 {
238  VidaliaTab *tab = buildGUI();
239  if(tab)
240  emit pluginTab(tab);
241  else
242  DebugDialog::exceptDebug(tr("Error: buildGUI() failed for plugin %1")
243  .arg(name()));
244 }
QString _nspace
Definition: PluginWrapper.h:62
QString nspace() const
QString _author
Definition: PluginWrapper.h:59
static void exceptDebug(const QString &msg)
Definition: DebugDialog.cpp:58
void pluginTab(VidaliaTab *)
#define vInfo(fmt)
Definition: Vidalia.h:40
VidaliaTab * buildGUI()
QAction * _action
Definition: PluginWrapper.h:64
QStringList _files
Definition: PluginWrapper.h:61
static void syntaxDebug(const QString &msg)
Definition: DebugDialog.cpp:52
PluginEngine * _engine
Definition: PluginWrapper.h:58
stop errmsg connect(const QHostAddress &address, quint16 port)
PluginWrapper(const QString &info_path, PluginEngine *engine, QObject *parent=0)
QAction * menuAction()
static void outputDebug(const QString &msg)
Definition: DebugDialog.cpp:46
QString author() const
QString date() const
QString name() const
bool checkExceptions()
void processInfo(const QString &path)
QStringList files() const