summaryrefslogtreecommitdiffstats
path: root/xbmc/addons/AddonInstaller.h
blob: 727e9e957ab83a8437dad8ac8d1f9a1b08a7433f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
/*
 *  Copyright (C) 2011-2018 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 */

#pragma once

#include "threads/Event.h"
#include "utils/Job.h"

#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>

class CFileItemList;

namespace ADDON
{

class CAddonVersion;

class CAddonDatabase;

class CRepository;
using RepositoryPtr = std::shared_ptr<CRepository>;

class IAddon;
using AddonPtr = std::shared_ptr<IAddon>;
using VECADDONS = std::vector<AddonPtr>;

enum class BackgroundJob : bool
{
  CHOICE_YES = true,
  CHOICE_NO = false,
};

enum class ModalJob : bool
{
  CHOICE_YES = true,
  CHOICE_NO = false,
};

enum class AutoUpdateJob : bool
{
  CHOICE_YES = true,
  CHOICE_NO = false,
};

enum class DependencyJob : bool
{
  CHOICE_YES = true,
  CHOICE_NO = false,
};

enum class InstallModalPrompt : bool
{
  CHOICE_YES = true,
  CHOICE_NO = false,
};

enum class AllowCheckForUpdates : bool
{
  CHOICE_YES = true,
  CHOICE_NO = false,
};

enum class RecurseOrphaned : bool
{
  CHOICE_YES = true,
  CHOICE_NO = false,
};

class CAddonInstaller : public IJobCallback
{
public:
  static CAddonInstaller &GetInstance();

  bool IsDownloading() const;
  void GetInstallList(ADDON::VECADDONS &addons) const;
  bool GetProgress(const std::string& addonID, unsigned int& percent, bool& downloadFinshed) const;
  bool Cancel(const std::string &addonID);

  /*! \brief Installs the addon while showing a modal progress dialog
   \param addonID the addon ID of the item to install.
   \param addon [out] the installed addon for later use.
   \param promptForInstall Whether or not to prompt the user before installing the addon.
   \return true on successful install, false otherwise.
   \sa Install
   */
  bool InstallModal(const std::string& addonID,
                    ADDON::AddonPtr& addon,
                    InstallModalPrompt promptForInstall);

  /*! \brief Install an addon if it is available in a repository
   \param addonID the addon ID of the item to install
   \param background whether to install in the background or not.
   \param modal whether to show a modal dialog when not installing in background
   \return true on successful install, false on failure.
   \sa DoInstall
   */
  bool InstallOrUpdate(const std::string& addonID, BackgroundJob background, ModalJob modal);

  /*! \brief Install a dependency from a specific repository
   \param dependsId the dependency to install
   \param repo the repository to install the addon from
   \return true on successful install, false on failure.
   \sa DoInstall
   */
  bool InstallOrUpdateDependency(const ADDON::AddonPtr& dependsId,
                                 const ADDON::RepositoryPtr& repo);

  /*! \brief Remove a single dependency from the system
   \param dependsId the dependency to remove
   \return true on successful uninstall, false on failure.
   */
  bool RemoveDependency(const std::shared_ptr<IAddon>& dependsId) const;

  /*!
   * \brief Removes all orphaned add-ons recursively. Removal may orphan further
   *        add-ons/dependencies, so loop until no orphaned is left on the system
   * \return Names of add-ons that have effectively been removed
   */
  std::vector<std::string> RemoveOrphanedDepsRecursively() const;

  /*! \brief Installs a vector of addons
   *  \param addons the list of addons to install
   *  \param wait if the method should wait for all the DoInstall jobs to finish or if it should return right away
   *  \param allowCheckForUpdates indicates if content update checks are allowed
   *         after installation of a repository addon from the vector
   *  \sa DoInstall
   */
  void InstallAddons(const ADDON::VECADDONS& addons,
                     bool wait,
                     AllowCheckForUpdates allowCheckForUpdates);

  /*! \brief Install an addon from the given zip path
   \param path the zip file to install from
   \return true if successful, false otherwise
   \sa DoInstall
   */
  bool InstallFromZip(const std::string &path);

   /*! Install an addon with a specific version and repository */
  bool Install(const std::string& addonId,
               const ADDON::CAddonVersion& version,
               const std::string& repoId);

  /*! Uninstall an addon, remove addon data if requested */
  bool UnInstall(const ADDON::AddonPtr& addon, bool removeData);

  /*! \brief Check whether dependencies of an addon exist or are installable.
  Iterates through the addon's dependencies, checking they're installed or installable.
  Each dependency must also satisfies CheckDependencies in turn.
  \param addon the addon to check
  \param database the database instance to update. Defaults to NULL.
  \return true if dependencies are available, false otherwise.
  */
  bool CheckDependencies(const ADDON::AddonPtr& addon, CAddonDatabase* database = nullptr);

  /*! \brief Check whether dependencies of an addon exist or are installable.
   Iterates through the addon's dependencies, checking they're installed or installable.
   Each dependency must also satisfies CheckDependencies in turn.
   \param addon the addon to check
   \param failedDep Dependency addon that isn't available
   \param database the database instance to update. Defaults to NULL.
   \return true if dependencies are available, false otherwise.
   */
  bool CheckDependencies(const ADDON::AddonPtr& addon,
                         std::pair<std::string, std::string>& failedDep,
                         CAddonDatabase* database = nullptr);

  /*! \brief Check if an installation job for a given add-on is already queued up
   *  \param ID The ID of the add-on
   *  \return true if a job exists, false otherwise
   */
  bool HasJob(const std::string& ID) const;

  void OnJobComplete(unsigned int jobID, bool success, CJob* job) override;
  void OnJobProgress(unsigned int jobID, unsigned int progress, unsigned int total, const CJob *job) override;

  class CDownloadJob
  {
  public:
    explicit CDownloadJob(unsigned int id) : jobID(id) { }

    unsigned int jobID;
    unsigned int progress = 0;
    bool downloadFinshed = false;
  };

  typedef std::map<std::string, CDownloadJob> JobMap;

private:
  // private construction, and no assignments; use the provided singleton methods
  CAddonInstaller();
  CAddonInstaller(const CAddonInstaller&) = delete;
  CAddonInstaller const& operator=(CAddonInstaller const&) = delete;
  ~CAddonInstaller() override;

  /*! \brief Install an addon from a repository or zip
   *  \param addon the AddonPtr describing the addon
   *  \param repo the repository to install addon from
   *  \param background whether to install in the background or not.
   *  \param modal whether to install in modal mode or not.
   *  \param autoUpdate whether the addon is installed in auto update mode.
   *         (i.e. no notification)
   *  \param dependsInstall whether this is the installation of a dependency addon
   *  \param allowCheckForUpdates whether content update check after installation of
   *         a repository addon is allowed
   *  \return true on successful install, false on failure.
   */
  bool DoInstall(const ADDON::AddonPtr& addon,
                 const ADDON::RepositoryPtr& repo,
                 BackgroundJob background,
                 ModalJob modal,
                 AutoUpdateJob autoUpdate,
                 DependencyJob dependsInstall,
                 AllowCheckForUpdates allowCheckForUpdates);

  /*! \brief Check whether dependencies of an addon exist or are installable.
   Iterates through the addon's dependencies, checking they're installed or installable.
   Each dependency must also satisfies CheckDependencies in turn.
   \param addon the addon to check
   \param preDeps previous dependencies encountered during recursion. aids in avoiding infinite recursion
   \param database database instance to update
   \param failedDep Dependency addon that isn't available
   \return true if dependencies are available, false otherwise.
   */
  bool CheckDependencies(const ADDON::AddonPtr &addon, std::vector<std::string>& preDeps, CAddonDatabase &database, std::pair<std::string, std::string> &failedDep);

  void PrunePackageCache();
  int64_t EnumeratePackageFolder(std::map<std::string, std::unique_ptr<CFileItemList>>& result);

  mutable CCriticalSection m_critSection;
  JobMap m_downloadJobs;
  CEvent m_idle;
};

}; // namespace ADDON