1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CHROME_BROWSER_UI_ASH_LAUNCHER_SHELF_SPINNER_CONTROLLER_H_
6 #define CHROME_BROWSER_UI_ASH_LAUNCHER_SHELF_SPINNER_CONTROLLER_H_
7 
8 #include <stdint.h>
9 
10 #include <map>
11 #include <memory>
12 #include <string>
13 #include <utility>
14 
15 #include "ash/public/cpp/shelf_model_observer.h"
16 #include "base/macros.h"
17 #include "base/memory/weak_ptr.h"
18 #include "base/time/time.h"
19 #include "components/account_id/account_id.h"
20 
21 class ShelfItemDelegate;
22 class ShelfSpinnerItemController;
23 class ChromeLauncherController;
24 class Profile;
25 
26 namespace gfx {
27 class ImageSkia;
28 }  // namespace gfx
29 
30 // ShelfSpinnerController displays visual feedback that the application the user
31 // has just activated will not be immediately available, as it is for example
32 // waiting for ARC or Crostini to be ready.
33 class ShelfSpinnerController : public ash::ShelfModelObserver {
34  public:
35   // ShelfSpinnerData holds the information used to draw the spinner, including
36   // animating the spinner after it has been dismissed.
37   class ShelfSpinnerData;
38 
39   explicit ShelfSpinnerController(ChromeLauncherController* owner);
40   ~ShelfSpinnerController() override;
41 
42   bool HasApp(const std::string& app_id) const;
43 
44   base::TimeDelta GetActiveTime(const std::string& app_id) const;
45 
46   // Adds a spinner to the shelf unless the app is already running.
47   void AddSpinnerToShelf(
48       const std::string& app_id,
49       std::unique_ptr<ShelfSpinnerItemController> controller);
50 
51   // Applies spinning effect if requested app is handled by spinner controller.
52   void MaybeApplySpinningEffect(const std::string& app_id,
53                                 gfx::ImageSkia* image);
54 
55   // Finishes spinning on an icon. If an icon is pinned it will be kept on the
56   // shelf as a shortcut, otherwise it will be removed without storing the
57   // delegate.
58   void CloseSpinner(const std::string& app_id);
59 
60   // Closes all Crostini spinner shelf items.
61   // This should be avoided when possible.
62   void CloseCrostiniSpinners();
63 
64   Profile* OwnerProfile();
65 
66   // Hide all the spinners associated with the old user, and restore to the
67   // shelf any spinners associated with the new active user. Called by
68   // ChromeLauncherController when the active user is changed.
69   void ActiveUserChanged(const AccountId& account_id);
70 
71   // ash::ShelfModelObserver:
72   void ShelfItemDelegateChanged(const ash::ShelfID& id,
73                                 ash::ShelfItemDelegate* old_delegate,
74                                 ash::ShelfItemDelegate* delegate) override;
75 
76  private:
77   // Defines mapping of a shelf app id to a corresponding controller's data.
78   // Shelf app id is optional mapping (for example, Play Store to ARC Host
79   // Support).
80   using AppControllerMap = std::map<std::string, ShelfSpinnerData>;
81   // Defines a mapping from account id to (app id, ShelfSpinnerItemController)
82   // for spinners that are not currently on the shelf. Taking ownership of these
83   // delegates allows us to reuse them if we need to add the spinner back on to
84   // the shelf.
85   using HiddenAppControllerMap = std::multimap<
86       AccountId,
87       std::pair<std::string, std::unique_ptr<ShelfSpinnerItemController>>>;
88 
89   void UpdateApps();
90   void UpdateShelfItemIcon(const std::string& app_id);
91   void RegisterNextUpdate();
92   // Removes the spinner with id |app_id| from |app_controller_map_| and returns
93   // true if it was present, false otherwise.
94   bool RemoveSpinnerFromControllerMap(const std::string& app_id);
95 
96   // Removes a spinner from the shelf and stores the delegate for later
97   // restoration. Used when the user switches from one profile to another.
98   void HideSpinner(const std::string& app_id);
99 
100   // Unowned pointers.
101   ChromeLauncherController* owner_;
102 
103   AccountId current_account_id_;
104 
105   AppControllerMap app_controller_map_;
106 
107   HiddenAppControllerMap hidden_app_controller_map_;
108 
109   // Always keep this the last member of this class.
110   base::WeakPtrFactory<ShelfSpinnerController> weak_ptr_factory_{this};
111 
112   DISALLOW_COPY_AND_ASSIGN(ShelfSpinnerController);
113 };
114 
115 #endif  // CHROME_BROWSER_UI_ASH_LAUNCHER_SHELF_SPINNER_CONTROLLER_H_
116