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 "pluginspec.h"
29 #include "pluginmanager.h"
30 
31 #include <utils/algorithm.h>
32 
33 #include <QElapsedTimer>
34 #include <QMutex>
35 #include <QObject>
36 #include <QReadWriteLock>
37 #include <QScopedPointer>
38 #include <QSet>
39 #include <QStringList>
40 #include <QWaitCondition>
41 
42 #include <queue>
43 
44 QT_BEGIN_NAMESPACE
45 class QTime;
46 class QTimer;
47 class QEventLoop;
48 QT_END_NAMESPACE
49 
50 namespace Utils {
51 class QtcSettings;
52 }
53 
54 namespace ExtensionSystem {
55 
56 class PluginManager;
57 
58 namespace Internal {
59 
60 class PluginSpecPrivate;
61 
62 class EXTENSIONSYSTEM_EXPORT PluginManagerPrivate : public QObject
63 {
64     Q_OBJECT
65 public:
66     PluginManagerPrivate(PluginManager *pluginManager);
67     ~PluginManagerPrivate() override;
68 
69     // Object pool operations
70     void addObject(QObject *obj);
71     void removeObject(QObject *obj);
72 
73     // Plugin operations
74     void checkForProblematicPlugins();
75     void loadPlugins();
76     void shutdown();
77     void setPluginPaths(const QStringList &paths);
78     const QVector<ExtensionSystem::PluginSpec *> loadQueue();
79     void loadPlugin(PluginSpec *spec, PluginSpec::State destState);
80     void resolveDependencies();
81     void enableDependenciesIndirectly();
82     void initProfiling();
83     void profilingSummary() const;
84     void profilingReport(const char *what, const PluginSpec *spec = nullptr);
85     void setSettings(Utils::QtcSettings *settings);
86     void setGlobalSettings(Utils::QtcSettings *settings);
87     void readSettings();
88     void writeSettings();
89 
90     class TestSpec {
91     public:
92         TestSpec(PluginSpec *pluginSpec, const QStringList &testFunctionsOrObjects = QStringList())
pluginSpec(pluginSpec)93             : pluginSpec(pluginSpec)
94             , testFunctionsOrObjects(testFunctionsOrObjects)
95         {}
96         PluginSpec *pluginSpec = nullptr;
97         QStringList testFunctionsOrObjects;
98     };
99 
containsTestSpec(PluginSpec * pluginSpec)100     bool containsTestSpec(PluginSpec *pluginSpec) const
101     {
102         return Utils::contains(testSpecs, [pluginSpec](const TestSpec &s) { return s.pluginSpec == pluginSpec; });
103     }
104 
removeTestSpec(PluginSpec * pluginSpec)105     void removeTestSpec(PluginSpec *pluginSpec)
106     {
107         testSpecs = Utils::filtered(testSpecs, [pluginSpec](const TestSpec &s) { return s.pluginSpec != pluginSpec; });
108     }
109 
110     QHash<QString, QVector<PluginSpec *>> pluginCategories;
111     QVector<PluginSpec *> pluginSpecs;
112     std::vector<TestSpec> testSpecs;
113     QStringList pluginPaths;
114     QString pluginIID;
115     QVector<QObject *> allObjects;      // ### make this a QVector<QPointer<QObject> > > ?
116     QStringList defaultDisabledPlugins; // Plugins/Ignored from install settings
117     QStringList defaultEnabledPlugins; // Plugins/ForceEnabled from install settings
118     QStringList disabledPlugins;
119     QStringList forceEnabledPlugins;
120     // delayed initialization
121     QTimer *delayedInitializeTimer = nullptr;
122     std::queue<PluginSpec *> delayedInitializeQueue;
123     // ansynchronous shutdown
124     QSet<PluginSpec *> asynchronousPlugins;  // plugins that have requested async shutdown
125     QEventLoop *shutdownEventLoop = nullptr; // used for async shutdown
126 
127     QStringList arguments;
128     QStringList argumentsForRestart;
129     QScopedPointer<QElapsedTimer> m_profileTimer;
130     QHash<const PluginSpec *, int> m_profileTotal;
131     int m_profileElapsedMS = 0;
132     unsigned m_profilingVerbosity = 0;
133     Utils::QtcSettings *settings = nullptr;
134     Utils::QtcSettings *globalSettings = nullptr;
135 
136     // Look in argument descriptions of the specs for the option.
137     PluginSpec *pluginForOption(const QString &option, bool *requiresArgument) const;
138     PluginSpec *pluginByName(const QString &name) const;
139 
140     // used by tests
141     static PluginSpec *createSpec();
142     static PluginSpecPrivate *privateSpec(PluginSpec *spec);
143 
144     mutable QReadWriteLock m_lock;
145 
146     bool m_isInitializationDone = false;
147     bool enableCrashCheck = true;
148 
149     QHash<QString, std::function<bool()>> m_scenarios;
150     QString m_requestedScenario;
151     std::atomic_bool m_isScenarioRunning = false; // if it's running, the running one is m_requestedScenario
152     std::atomic_bool m_isScenarioFinished = false; // if it's running, the running one is m_requestedScenario
153     bool m_scenarioFullyInitialized = false;
154     QMutex m_scenarioMutex;
155     QWaitCondition m_scenarioWaitCondition;
156 
157     PluginManager::ProcessData m_creatorProcessData;
158 
159 private:
160     PluginManager *q;
161 
162     void nextDelayedInitialize();
163     void asyncShutdownFinished();
164 
165     void readPluginPaths();
166     bool loadQueue(PluginSpec *spec,
167                    QVector<ExtensionSystem::PluginSpec *> &queue,
168                    QVector<ExtensionSystem::PluginSpec *> &circularityCheckQueue);
169     void stopAll();
170     void deleteAll();
171 
172 #ifdef WITH_TESTS
173     void startTests();
174 #endif
175 };
176 
177 } // namespace Internal
178 } // namespace ExtensionSystem
179