File: crostini_package_service.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (209 lines) | stat: -rw-r--r-- 8,915 bytes parent folder | download | duplicates (6)
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
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_ASH_CROSTINI_CROSTINI_PACKAGE_SERVICE_H_
#define CHROME_BROWSER_ASH_CROSTINI_CROSTINI_PACKAGE_SERVICE_H_

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

#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/ash/crostini/crostini_manager.h"
#include "chrome/browser/ash/crostini/crostini_package_notification.h"
#include "chrome/browser/ash/crostini/crostini_package_operation_status.h"
#include "chrome/browser/ash/crostini/crostini_util.h"
#include "chrome/browser/ash/guest_os/guest_os_registry_service.h"
#include "components/keyed_service/core/keyed_service.h"
#include "storage/browser/file_system/file_system_url.h"

namespace crostini {

class CrostiniPackageService : public KeyedService,
                               public LinuxPackageOperationProgressObserver,
                               public PendingAppListUpdatesObserver,
                               public ash::VmShutdownObserver {
 public:
  using StateChangeCallback =
      base::RepeatingCallback<void(PackageOperationStatus)>;

  explicit CrostiniPackageService(Profile* profile);

  CrostiniPackageService(const CrostiniPackageService&) = delete;
  CrostiniPackageService& operator=(const CrostiniPackageService&) = delete;

  ~CrostiniPackageService() override;

  // For testing: Set a callback that will be called each time a notification
  // is set to a new state.
  void SetNotificationStateChangeCallbackForTesting(
      StateChangeCallback state_change_callback);

  // KeyedService:
  void Shutdown() override;

  void NotificationCompleted(CrostiniPackageNotification* notification);

  void GetLinuxPackageInfo(
      const guest_os::GuestId& container_id,
      const storage::FileSystemURL& package_url,
      CrostiniManager::GetLinuxPackageInfoCallback callback);

  // LinuxPackageOperationProgressObserver:
  void OnInstallLinuxPackageProgress(const guest_os::GuestId& container_id,
                                     InstallLinuxPackageProgressStatus status,
                                     int progress_percent,
                                     const std::string& error_message) override;

  void OnUninstallPackageProgress(const guest_os::GuestId& container_id,
                                  UninstallPackageProgressStatus status,
                                  int progress_percent) override;

  // PendingAppListUpdatesObserver:
  void OnPendingAppListUpdates(const guest_os::GuestId& container_id,
                               int count) override;

  // ash::VmShutdownObserver
  void OnVmShutdown(const std::string& vm_name) override;

  // (Eventually) install a Linux package. If successfully started, a system
  // notification will be used to display further updates.
  void QueueInstallLinuxPackage(
      const guest_os::GuestId& container_id,
      const storage::FileSystemURL& package_url,
      CrostiniManager::InstallLinuxPackageCallback callback);

  // (Eventually) uninstall the package identified by |app_id|. If successfully
  // started, a system notification will be used to display further updates.
  void QueueUninstallApplication(const std::string& app_id);

  CrostiniManager::RestartId GetRestartIdForTesting();

 private:
  // The user can request new operations while a different operation is in
  // progress. Rather than sending a request which will fail, just queue the
  // request until the previous one is done.
  struct QueuedInstall;
  struct QueuedUninstall;

  bool ContainerHasRunningOperation(
      const guest_os::GuestId& container_id) const;
  bool ContainerHasQueuedOperation(const guest_os::GuestId& container_id) const;

  // Creates a new notification and adds it to running_notifications_.
  // |app_name| is the name of the application being modified, if any -- for
  // installs, it will be blank, but for uninstalls, it will have the localized
  // name of the application in UTF8.
  // If there is a running notification, it will be set to error state. Caller
  // should check before calling this if a different behavior is desired.
  void CreateRunningNotification(
      const guest_os::GuestId& container_id,
      CrostiniPackageNotification::NotificationType notification_type,
      const std::string& app_name);

  // Creates a new uninstall notification and adds it to queued_uninstalls_.
  void CreateQueuedUninstall(const guest_os::GuestId& container_id,
                             const std::string& app_id,
                             const std::string& app_name);

  // Creates a new install notification and adds it to queued_installs_.
  void CreateQueuedInstall(
      const guest_os::GuestId& container_id,
      const std::string& package,
      CrostiniManager::InstallLinuxPackageCallback callback);

  // Sets the operation status of the current operation. Sets the notification
  // window's current state and updates containers_with_running_operations_.
  // Note that if status is |SUCCEEDED| or |FAILED|, this may kick off another
  // operation from the queued_uninstalls_ list. When status is |FAILED|, the
  // |error_message| will contain an error reported by the installation process.
  void UpdatePackageOperationStatus(const guest_os::GuestId& container_id,
                                    PackageOperationStatus status,
                                    int progress_percent,
                                    const std::string& error_message = {});

  // Callback between sharing and invoking GetLinuxPackageInfo().
  void OnSharePathForGetLinuxPackageInfo(
      const guest_os::GuestId& container_id,
      const storage::FileSystemURL& package_url,
      const base::FilePath& package_path,
      CrostiniManager::GetLinuxPackageInfoCallback callback,
      CrostiniResult result);

  // Wraps the callback provided in GetLinuxPackageInfo().
  void OnGetLinuxPackageInfo(
      const guest_os::GuestId& container_id,
      CrostiniManager::GetLinuxPackageInfoCallback callback,
      const LinuxPackageInfo& linux_package_info);

  // Wraps the callback provided in InstallLinuxPackage().
  void OnInstallLinuxPackage(
      const guest_os::GuestId& container_id,
      CrostiniManager::InstallLinuxPackageCallback callback,
      CrostiniResult result);

  // Kicks off an uninstall of the given app. Never queues the operation. Helper
  // for QueueUninstallApplication (if the operation can be performed
  // immediately) and StartQueuedOperation.
  void UninstallApplication(
      const guest_os::GuestOsRegistryService::Registration& registration,
      const std::string& app_id);

  // Callback when the Crostini container is up and ready to accept messages.
  // Used by the uninstall flow only.
  void OnCrostiniRunningForUninstall(const guest_os::GuestId& container_id,
                                     const std::string& desktop_file_id,
                                     CrostiniResult result);

  // Callback for CrostiniManager::UninstallPackageOwningFile().
  void OnUninstallPackageOwningFile(const guest_os::GuestId& container_id,
                                    CrostiniResult result);

  // Kick off the next operation in the queue for the given container.
  void StartQueuedOperation(const guest_os::GuestId& container_id);

  std::string GetUniqueNotificationId();

  raw_ptr<Profile> profile_;

  // The notifications in the RUNNING state for each container.
  std::map<guest_os::GuestId, std::unique_ptr<CrostiniPackageNotification>>
      running_notifications_;

  // Installs we want to run when the current operation is done.
  std::map<guest_os::GuestId, std::queue<QueuedInstall>> queued_installs_;

  // Uninstalls we want to run when the current operation is done.
  std::map<guest_os::GuestId, std::queue<QueuedUninstall>> queued_uninstalls_;

  // Notifications in a finished state (either SUCCEEDED or FAILED). We need
  // to keep notifications around until they are dismissed even if we don't
  // update them any more.
  std::vector<std::unique_ptr<CrostiniPackageNotification>>
      finished_notifications_;

  // A map storing which containers have currently pending app list update
  // operations. If a container is not present in the map, we assume no pending
  // updates.
  std::set<guest_os::GuestId> has_pending_app_list_updates_;

  // Called each time a notification is set to a new state.
  StateChangeCallback testing_state_change_callback_;

  int next_notification_id_ = 0;

  CrostiniManager::RestartId restart_id_for_testing_;

  base::WeakPtrFactory<CrostiniPackageService> weak_ptr_factory_{this};
};

}  // namespace crostini

#endif  // CHROME_BROWSER_ASH_CROSTINI_CROSTINI_PACKAGE_SERVICE_H_