khmel | 8c1f662 | 2017-05-11 19:14:50 | [diff] [blame] | 1 | // Copyright 2017 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_EXTENSIONS_CHROME_APP_ICON_SERVICE_H_ |
| 6 | #define CHROME_BROWSER_EXTENSIONS_CHROME_APP_ICON_SERVICE_H_ |
| 7 | |
| 8 | #include <map> |
| 9 | #include <memory> |
| 10 | #include <set> |
| 11 | |
Vladislav Kaznacheev | 6ae79b4 | 2018-09-13 06:11:11 | [diff] [blame] | 12 | #include "base/callback.h" |
khmel | 8c1f662 | 2017-05-11 19:14:50 | [diff] [blame] | 13 | #include "base/macros.h" |
| 14 | #include "base/memory/weak_ptr.h" |
| 15 | #include "base/scoped_observer.h" |
| 16 | #include "components/keyed_service/core/keyed_service.h" |
Evan Stade | 75872a6 | 2019-09-06 21:17:38 | [diff] [blame] | 17 | #include "extensions/browser/extension_registry.h" |
khmel | 8c1f662 | 2017-05-11 19:14:50 | [diff] [blame] | 18 | #include "extensions/browser/extension_registry_observer.h" |
| 19 | |
| 20 | #if defined(OS_CHROMEOS) |
| 21 | #include "chrome/browser/ui/ash/launcher/launcher_extension_app_updater.h" |
| 22 | #endif |
| 23 | |
| 24 | namespace content { |
| 25 | class BrowserContext; |
| 26 | } |
| 27 | |
Vladislav Kaznacheev | 6ae79b4 | 2018-09-13 06:11:11 | [diff] [blame] | 28 | namespace gfx { |
| 29 | class ImageSkia; |
| 30 | class Size; |
| 31 | } // namespace gfx |
| 32 | |
khmel | 8c1f662 | 2017-05-11 19:14:50 | [diff] [blame] | 33 | namespace extensions { |
| 34 | |
| 35 | class ChromeAppIcon; |
| 36 | class ChromeAppIconDelegate; |
| 37 | |
| 38 | // Factory for ChromeAppIcon. Each created icon is tracked by this service. |
| 39 | // Once some condition that affects how extension app icon should look is |
| 40 | // changed then corresponded app icons are automatically updated. This service |
| 41 | // is bound to content::BrowserContext. |
| 42 | // Usage: ChromeAppIconService::Get(context)->CreateIcon(). |
| 43 | class ChromeAppIconService : public KeyedService, |
| 44 | #if defined(OS_CHROMEOS) |
| 45 | public LauncherAppUpdater::Delegate, |
| 46 | #endif |
| 47 | public ExtensionRegistryObserver { |
| 48 | public: |
Vladislav Kaznacheev | 6ae79b4 | 2018-09-13 06:11:11 | [diff] [blame] | 49 | using ResizeFunction = |
| 50 | base::RepeatingCallback<void(const gfx::Size&, gfx::ImageSkia*)>; |
| 51 | |
khmel | 8c1f662 | 2017-05-11 19:14:50 | [diff] [blame] | 52 | explicit ChromeAppIconService(content::BrowserContext* context); |
| 53 | |
| 54 | ~ChromeAppIconService() override; |
| 55 | |
| 56 | // Convenience function to get the ChromeAppIconService for a |
| 57 | // BrowserContext. |
| 58 | static ChromeAppIconService* Get(content::BrowserContext* context); |
| 59 | |
| 60 | // Creates extension app icon for requested app and size. Icon updates are |
| 61 | // dispatched via |delegate|. |
Vladislav Kaznacheev | 6ae79b4 | 2018-09-13 06:11:11 | [diff] [blame] | 62 | // |resize_function| overrides icon resizing behavior if non-null. Otherwise |
| 63 | // IconLoader with perform the resizing. In both cases |resource_size_in_dip| |
| 64 | // is used to pick the correct icon representation from resources. |
| 65 | std::unique_ptr<ChromeAppIcon> CreateIcon( |
| 66 | ChromeAppIconDelegate* delegate, |
| 67 | const std::string& app_id, |
| 68 | int resource_size_in_dip, |
| 69 | const ResizeFunction& resize_function); |
| 70 | |
khmel | 8c1f662 | 2017-05-11 19:14:50 | [diff] [blame] | 71 | std::unique_ptr<ChromeAppIcon> CreateIcon(ChromeAppIconDelegate* delegate, |
| 72 | const std::string& app_id, |
| 73 | int resource_size_in_dip); |
| 74 | |
| 75 | // KeyedService: |
| 76 | void Shutdown() override; |
| 77 | |
| 78 | private: |
| 79 | class Updater; |
| 80 | |
| 81 | // System may have multiple icons for the same app id with different |
| 82 | // dimensions. For example icon in shelf and app launcher. |
| 83 | using IconMap = std::map<std::string, std::set<ChromeAppIcon*>>; |
| 84 | |
| 85 | // Called from ChromeAppIcon DTOR. |
| 86 | void OnIconDestroyed(ChromeAppIcon* icon); |
| 87 | |
| 88 | // Called from Updater when corresponded app icons need to be updated. |
| 89 | void OnAppUpdated(const std::string& app_id); |
| 90 | |
| 91 | // ExtensionRegistryObserver: |
| 92 | void OnExtensionLoaded(content::BrowserContext* browser_context, |
| 93 | const Extension* extension) override; |
| 94 | void OnExtensionUnloaded(content::BrowserContext* browser_context, |
| 95 | const Extension* extension, |
| 96 | UnloadedExtensionReason reason) override; |
| 97 | |
| 98 | #if defined(OS_CHROMEOS) |
| 99 | // LauncherAppUpdater::Delegate: |
| 100 | void OnAppUpdated(content::BrowserContext* browser_context, |
| 101 | const std::string& app_id) override; |
| 102 | #endif |
| 103 | |
| 104 | // Unowned pointer. |
| 105 | content::BrowserContext* context_; |
| 106 | |
| 107 | #if defined(OS_CHROMEOS) |
| 108 | // On Chrome OS this handles Chrome app life-cycle events that may change how |
| 109 | // extension based app icon looks like. |
| 110 | std::unique_ptr<LauncherExtensionAppUpdater> app_updater_; |
| 111 | #endif |
| 112 | |
khmel | 0df82202 | 2017-06-23 02:02:56 | [diff] [blame] | 113 | // Deletes the icon set for |app_id| from the map if it is empty. |
| 114 | void MaybeCleanupIconSet(const std::string& app_id); |
| 115 | |
khmel | 8c1f662 | 2017-05-11 19:14:50 | [diff] [blame] | 116 | IconMap icon_map_; |
| 117 | |
Evan Stade | 75872a6 | 2019-09-06 21:17:38 | [diff] [blame] | 118 | ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> observer_{this}; |
khmel | 8c1f662 | 2017-05-11 19:14:50 | [diff] [blame] | 119 | |
Jeremy Roman | 495db68 | 2019-07-12 16:03:24 | [diff] [blame] | 120 | base::WeakPtrFactory<ChromeAppIconService> weak_ptr_factory_{this}; |
khmel | 8c1f662 | 2017-05-11 19:14:50 | [diff] [blame] | 121 | |
| 122 | DISALLOW_COPY_AND_ASSIGN(ChromeAppIconService); |
| 123 | }; |
| 124 | |
| 125 | } // namespace extensions |
| 126 | |
| 127 | #endif // CHROME_BROWSER_EXTENSIONS_CHROME_APP_ICON_SERVICE_H_ |