1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25 
26 #pragma once
27 
28 #include "../projectexplorer_export.h"
29 
30 #include <utils/id.h>
31 #include <utils/hostosinfo.h>
32 
33 #include <QAbstractSocket>
34 #include <QCoreApplication>
35 #include <QDir>
36 #include <QList>
37 #include <QObject>
38 #include <QSharedPointer>
39 #include <QUrl>
40 #include <QVariantMap>
41 
42 #include <functional>
43 #include <memory>
44 
45 QT_BEGIN_NAMESPACE
46 class QWidget;
47 QT_END_NAMESPACE
48 
49 namespace QSsh { class SshConnectionParameters; }
50 
51 namespace Utils {
52 class CommandLine;
53 class Environment;
54 class FilePath;
55 class Icon;
56 class PortList;
57 class Port;
58 class QtcProcess;
59 } // Utils
60 
61 namespace ProjectExplorer {
62 
63 class Connection;
64 class DeviceProcess;
65 class DeviceProcessList;
66 class Kit;
67 class Runnable;
68 
69 namespace Internal { class IDevicePrivate; }
70 
71 class IDeviceWidget;
72 class DeviceTester;
73 
74 class PROJECTEXPLORER_EXPORT DeviceProcessSignalOperation : public QObject
75 {
76     Q_OBJECT
77 public:
78     using Ptr = QSharedPointer<DeviceProcessSignalOperation>;
79 
80     virtual void killProcess(qint64 pid) = 0;
81     virtual void killProcess(const QString &filePath) = 0;
82     virtual void interruptProcess(qint64 pid) = 0;
83     virtual void interruptProcess(const QString &filePath) = 0;
84 
85     void setDebuggerCommand(const QString &cmd);
86 
87 signals:
88     // If the error message is empty the operation was successful
89     void finished(const QString &errorMessage);
90 
91 protected:
92     explicit DeviceProcessSignalOperation();
93 
94     QString m_debuggerCommand;
95     QString m_errorMessage;
96 };
97 
98 class PROJECTEXPLORER_EXPORT DeviceEnvironmentFetcher : public QObject
99 {
100     Q_OBJECT
101 public:
102     using Ptr = QSharedPointer<DeviceEnvironmentFetcher>;
103 
104     virtual void start() = 0;
105 
106 signals:
107     void finished(const Utils::Environment &env, bool success);
108 
109 protected:
110     explicit DeviceEnvironmentFetcher();
111 };
112 
113 class PROJECTEXPLORER_EXPORT PortsGatheringMethod
114 {
115 public:
116     using Ptr = QSharedPointer<const PortsGatheringMethod>;
117 
118     virtual ~PortsGatheringMethod() = default;
119     virtual Runnable runnable(QAbstractSocket::NetworkLayerProtocol protocol) const = 0;
120     virtual QList<Utils::Port> usedPorts(const QByteArray &commandOutput) const = 0;
121 };
122 
123 // See cpp file for documentation.
124 class PROJECTEXPLORER_EXPORT IDevice : public QEnableSharedFromThis<IDevice>
125 {
126     friend class Internal::IDevicePrivate;
127 public:
128     using Ptr = QSharedPointer<IDevice>;
129     using ConstPtr = QSharedPointer<const IDevice>;
130 
131     enum Origin { ManuallyAdded, AutoDetected };
132     enum MachineType { Hardware, Emulator };
133 
134     virtual ~IDevice();
135 
136     Ptr clone() const;
137 
138     QString displayName() const;
139     void setDisplayName(const QString &name);
140     void setDefaultDisplayName(const QString &name);
141 
142     // Provide some information on the device suitable for formated
143     // output, e.g. in tool tips. Get a list of name value pairs.
144     class DeviceInfoItem {
145     public:
DeviceInfoItem(const QString & k,const QString & v)146         DeviceInfoItem(const QString &k, const QString &v) : key(k), value(v) { }
147 
148         QString key;
149         QString value;
150     };
151     using DeviceInfo = QList<DeviceInfoItem>;
152     virtual DeviceInfo deviceInformation() const;
153 
154     Utils::Id type() const;
155     void setType(Utils::Id type);
156 
157     bool isAutoDetected() const;
158     Utils::Id id() const;
159 
160     virtual bool isCompatibleWith(const Kit *k) const;
161 
162     QString displayType() const;
163     Utils::OsType osType() const;
164 
165     virtual IDeviceWidget *createWidget() = 0;
166 
167     struct DeviceAction {
168         QString display;
169         std::function<void(const IDevice::Ptr &device, QWidget *parent)> execute;
170     };
171     void addDeviceAction(const DeviceAction &deviceAction);
172     const QList<DeviceAction> deviceActions() const;
173 
174     // Devices that can auto detect ports need not return a ports gathering method. Such devices can
175     // obtain a free port on demand. eg: Desktop device.
canAutoDetectPorts()176     virtual bool canAutoDetectPorts() const { return false; }
177     virtual PortsGatheringMethod::Ptr portsGatheringMethod() const;
canCreateProcessModel()178     virtual bool canCreateProcessModel() const { return false; }
179     virtual DeviceProcessList *createProcessListModel(QObject *parent = nullptr) const;
hasDeviceTester()180     virtual bool hasDeviceTester() const { return false; }
181     virtual DeviceTester *createDeviceTester() const;
182 
canCreateProcess()183     virtual bool canCreateProcess() const { return false; }
184     virtual DeviceProcess *createProcess(QObject *parent) const;
185     virtual DeviceProcessSignalOperation::Ptr signalOperation() const = 0;
186     virtual DeviceEnvironmentFetcher::Ptr environmentFetcher() const;
187 
188     enum DeviceState { DeviceReadyToUse, DeviceConnected, DeviceDisconnected, DeviceStateUnknown };
189     DeviceState deviceState() const;
190     void setDeviceState(const DeviceState state);
191     QString deviceStateToString() const;
192 
193     virtual void fromMap(const QVariantMap &map);
194     virtual QVariantMap toMap() const;
195 
196     static Utils::Id typeFromMap(const QVariantMap &map);
197     static Utils::Id idFromMap(const QVariantMap &map);
198 
199     static QString defaultPrivateKeyFilePath();
200     static QString defaultPublicKeyFilePath();
201 
202     QSsh::SshConnectionParameters sshParameters() const;
203     void setSshParameters(const QSsh::SshConnectionParameters &sshParameters);
204 
205     enum ControlChannelHint { QmlControlChannel };
206     virtual QUrl toolControlChannel(const ControlChannelHint &) const;
207 
208     Utils::PortList freePorts() const;
209     void setFreePorts(const Utils::PortList &freePorts);
210 
211     MachineType machineType() const;
212     void setMachineType(MachineType machineType);
213 
214     QString debugServerPath() const;
215     void setDebugServerPath(const QString &path);
216 
217     QString qmlRunCommand() const;
218     void setQmlRunCommand(const QString &path);
219 
220     void setExtraData(Utils::Id kind, const QVariant &data);
221     QVariant extraData(Utils::Id kind) const;
222 
223     void setupId(Origin origin, Utils::Id id = Utils::Id());
224 
225     bool canOpenTerminal() const;
226     void openTerminal(const Utils::Environment &env, const QString &workingDir) const;
227 
228     bool isEmptyCommandAllowed() const;
229     void setAllowEmptyCommand(bool allow);
230 
isWindowsDevice()231     bool isWindowsDevice() const { return osType() == Utils::OsTypeWindows; }
isLinuxDevice()232     bool isLinuxDevice() const { return osType() == Utils::OsTypeLinux; }
isMacDevice()233     bool isMacDevice() const { return osType() == Utils::OsTypeMac; }
234     bool isAnyUnixDevice() const;
235 
236     virtual Utils::FilePath mapToGlobalPath(const Utils::FilePath &pathOnDevice) const;
237 
238     virtual bool handlesFile(const Utils::FilePath &filePath) const;
239     virtual bool isExecutableFile(const Utils::FilePath &filePath) const;
240     virtual bool isReadableFile(const Utils::FilePath &filePath) const;
241     virtual bool isWritableFile(const Utils::FilePath &filePath) const;
242     virtual bool isReadableDirectory(const Utils::FilePath &filePath) const;
243     virtual bool isWritableDirectory(const Utils::FilePath &filePath) const;
244     virtual bool isFile(const Utils::FilePath &filePath) const;
245     virtual bool isDirectory(const Utils::FilePath &filePath) const;
246     virtual bool ensureWritableDirectory(const Utils::FilePath &filePath) const;
247     virtual bool ensureExistingFile(const Utils::FilePath &filePath) const;
248     virtual bool createDirectory(const Utils::FilePath &filePath) const;
249     virtual bool exists(const Utils::FilePath &filePath) const;
250     virtual bool removeFile(const Utils::FilePath &filePath) const;
251     virtual bool removeRecursively(const Utils::FilePath &filePath) const;
252     virtual bool copyFile(const Utils::FilePath &filePath, const Utils::FilePath &target) const;
253     virtual bool renameFile(const Utils::FilePath &filePath, const Utils::FilePath &target) const;
254     virtual Utils::FilePath searchExecutableInPath(const QString &fileName) const;
255     virtual Utils::FilePath searchExecutable(const QString &fileName,
256                                              const QList<Utils::FilePath> &dirs) const;
257     virtual Utils::FilePath symLinkTarget(const Utils::FilePath &filePath) const;
258     virtual QList<Utils::FilePath> directoryEntries(const Utils::FilePath &filePath,
259                                                     const QStringList &nameFilters,
260                                                     QDir::Filters filters,
261                                                     QDir::SortFlags sort = QDir::NoSort) const;
262     virtual QByteArray fileContents(const Utils::FilePath &filePath,
263                                     qint64 limit,
264                                     qint64 offset) const;
265     virtual bool writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const;
266     virtual QDateTime lastModified(const Utils::FilePath &filePath) const;
267     virtual QFile::Permissions permissions(const Utils::FilePath &filePath) const;
268     virtual void runProcess(Utils::QtcProcess &process) const;
269     virtual Utils::Environment systemEnvironment() const;
270 
aboutToBeRemoved()271     virtual void aboutToBeRemoved() const {}
272 
273 protected:
274     IDevice();
275 
276     using OpenTerminal = std::function<void(const Utils::Environment &, const QString &)>;
277     void setOpenTerminal(const OpenTerminal &openTerminal);
278     void setDisplayType(const QString &type);
279     void setOsType(Utils::OsType osType);
280 
281 private:
282     IDevice(const IDevice &) = delete;
283     IDevice &operator=(const IDevice &) = delete;
284 
285     int version() const;
286 
287     const std::unique_ptr<Internal::IDevicePrivate> d;
288     friend class DeviceManager;
289 };
290 
291 
292 class PROJECTEXPLORER_EXPORT DeviceTester : public QObject
293 {
294     Q_OBJECT
295 
296 public:
297     enum TestResult { TestSuccess, TestFailure };
298 
299     virtual void testDevice(const ProjectExplorer::IDevice::Ptr &deviceConfiguration) = 0;
300     virtual void stopTest() = 0;
301 
302 signals:
303     void progressMessage(const QString &message);
304     void errorMessage(const QString &message);
305     void finished(ProjectExplorer::DeviceTester::TestResult result);
306 
307 protected:
308     explicit DeviceTester(QObject *parent = nullptr);
309 };
310 
311 } // namespace ProjectExplorer
312