File: side_panel_service.h

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (168 lines) | stat: -rw-r--r-- 7,275 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
// Copyright 2022 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_EXTENSIONS_API_SIDE_PANEL_SIDE_PANEL_SERVICE_H_
#define CHROME_BROWSER_EXTENSIONS_API_SIDE_PANEL_SIDE_PANEL_SERVICE_H_

#include "base/containers/flat_map.h"
#include "base/memory/raw_ptr.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "base/scoped_observation.h"
#include "base/types/expected.h"
#include "chrome/common/extensions/api/side_panel.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_registry_observer.h"
#include "extensions/common/extension_id.h"

namespace extensions {

// The single responsibility of this service is to be the source of truth for
// side panel options. Extensions can interact with this service using the API
// and side panel UI updates can rely on the response of GetOptions(tab_id).
class SidePanelService : public BrowserContextKeyedAPI,
                         public ExtensionRegistryObserver {
 public:
  class Observer : public base::CheckedObserver {
   public:
    virtual void OnPanelOptionsChanged(
        const ExtensionId& extension_id,
        const api::side_panel::PanelOptions& updated_options) = 0;
    virtual void OnSidePanelServiceShutdown() = 0;
  };

  explicit SidePanelService(content::BrowserContext* context);

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

  ~SidePanelService() override;

  // Convenience method to get the SidePanelService for a profile.
  static SidePanelService* Get(content::BrowserContext* context);

  // BrowserContextKeyedAPI implementation.
  static BrowserContextKeyedAPIFactory<SidePanelService>* GetFactoryInstance();

  using TabId = int;

  // Returns if there is an action to toggle the side panel for the given
  // `extension` and `tab_id`.
  bool HasSidePanelActionForTab(const Extension& extension, TabId tab_id);

  // Returns if there is an action to toggle the side panel from the extension
  // context menu for the given `extension` and `tab_id`.
  bool HasSidePanelContextMenuActionForTab(const Extension& extension,
                                           TabId tab_id);

  // Get options for `tab_id`. Options are loaded in order first from service
  // storage, manifest, or an empty object will be returned, if they're unset.
  api::side_panel::PanelOptions GetOptions(const Extension& extension,
                                           std::optional<TabId> tab_id);

  // Get options that were set for `tab_id`. If no options were specifically
  // set, returns an empty object instead of falling back to default options.
  api::side_panel::PanelOptions GetSpecificOptionsForTab(
      const Extension& extension,
      TabId tab_id);

  // Set options for tab_id if specified. Otherwise set default options.
  void SetOptions(const Extension& extension,
                  api::side_panel::PanelOptions set_options);

  // Determine if panel options have been set for extension id. Used in tests.
  bool HasExtensionPanelOptionsForTest(const ExtensionId& id);

  // Returns whether the extension will open its side panel entry when its icon
  // in the toolbar is clicked.
  bool OpenSidePanelOnIconClick(const ExtensionId& extension_id);

  // Updates whether the extension will open its side panel entry when its icon
  // in the toolbar is clicked.
  void SetOpenSidePanelOnIconClick(const ExtensionId& extension_id,
                                   bool open_side_panel_on_icon_click);

  // Opens the `extension`'s side panel for the specified `tab_id` and profile
  // specified by `context`. Handles properly determining if the side panel to
  // be opened is a global or contextual panel. `include_incognito_information`
  // indicates whether the registry should allow crossing incognito contexts
  // when looking up `tab_id`. If `window_id` is specified, checks that the
  // given `tab_id` belongs to the `window_id`. Returns true on success; returns
  // an error string on failure.
  // TODO(crbug.com/40064601): Return an enum here to indicate if the
  // panel was newly-opened vs already-opened in order to support waiting for
  // the panel to open?
  base::expected<bool, std::string> OpenSidePanelForTab(
      const Extension& extension,
      content::BrowserContext* context,
      int tab_id,
      std::optional<int> window_id,
      bool include_incognito_information);

  // Opens the `extension`'s side panel for the specified `window_id` and
  // profile specified by `context`. This is only valid if the extension has a
  // registered global side panel. This will not override any contextual panels
  // in the window. `include_incognito_information` indicates whether the
  // registry should allow crossing incognito contexts when looking up `tab_id`.
  // Returns true on success; returns an error string on failure.
  // TODO(crbug.com/40064601): Return an enum here to indicate if the
  // panel was newly-opened vs already-opened in order to support waiting for
  // the panel to open?
  base::expected<bool, std::string> OpenSidePanelForWindow(
      const Extension& extension,
      content::BrowserContext* context,
      int window_id,
      bool include_incognito_information);

  // Adds or removes observers.
  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);

 private:
  friend class BrowserContextKeyedAPIFactory<SidePanelService>;

  const raw_ptr<content::BrowserContext> browser_context_;

  // BrowserContextKeyedAPI implementation.
  static const char* service_name() { return "SidePanelService"; }
  static const bool kServiceRedirectedInIncognito = true;
  static const bool kServiceIsNULLWhileTesting = true;

  // Returns if there is an extension side panel for `tab_id`.
  bool HasSidePanelAvailableForTab(const Extension& extension, TabId tab_id);

  // Remove extension id and associated options from `panels_`.
  void RemoveExtensionOptions(const ExtensionId& id);

  // ExtensionRegistry:
  void OnExtensionUnloaded(content::BrowserContext* browser_context,
                           const Extension* extension,
                           UnloadedExtensionReason reason) override;

  // ExtensionRegistry:
  void OnExtensionUninstalled(content::BrowserContext* browser_context,
                              const Extension* extension,
                              UninstallReason reason) override;

  // KeyedService implementation.
  void Shutdown() override;

  // The associated observers.
  base::ObserverList<Observer> observers_;

  // ExtensionRegistry observer.
  base::ScopedObservation<extensions::ExtensionRegistry,
                          extensions::ExtensionRegistryObserver>
      extension_registry_observation_{this};

  // Extension and tab panel options.
  using TabPanelOptions = base::flat_map<TabId, api::side_panel::PanelOptions>;
  using ExtensionPanelOptions = base::flat_map<ExtensionId, TabPanelOptions>;
  ExtensionPanelOptions panels_;
};

}  // namespace extensions

#endif  // CHROME_BROWSER_EXTENSIONS_API_SIDE_PANEL_SIDE_PANEL_SERVICE_H_