File: permission_context_base.h

package info (click to toggle)
chromium 120.0.6099.224-1~deb11u1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 6,112,112 kB
  • sloc: cpp: 32,907,025; ansic: 8,148,123; javascript: 3,679,536; python: 2,031,248; asm: 959,718; java: 804,675; xml: 617,256; sh: 111,417; objc: 100,835; perl: 88,443; cs: 53,032; makefile: 29,579; fortran: 24,137; php: 21,162; tcl: 21,147; sql: 20,809; ruby: 17,735; pascal: 12,864; yacc: 8,045; lisp: 3,388; lex: 1,323; ada: 727; awk: 329; jsp: 267; csh: 117; exp: 43; sed: 37
file content (249 lines) | stat: -rw-r--r-- 11,049 bytes parent folder | download
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
245
246
247
248
249
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_PERMISSIONS_PERMISSION_CONTEXT_BASE_H_
#define COMPONENTS_PERMISSIONS_PERMISSION_CONTEXT_BASE_H_

#include <memory>
#include <unordered_map>

#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/content_settings/core/browser/content_settings_observer.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/permissions/permission_request.h"
#include "components/permissions/permission_request_data.h"
#include "content/public/browser/permission_result.h"
#include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-forward.h"

class GURL;

namespace permissions {
class PermissionRequestID;
}

namespace content {
class BrowserContext;
class RenderFrameHost;
class WebContents;
}  // namespace content

namespace permissions {

class Observer : public base::CheckedObserver {
 public:
  // Called whenever there is a potential permission status change for the
  // specified patterns. This function being called does not necessarily mean
  // that the result of |GetPermissionStatus| has changed for any particular
  // origin.
  virtual void OnPermissionChanged(
      const ContentSettingsPattern& primary_pattern,
      const ContentSettingsPattern& secondary_pattern,
      ContentSettingsTypeSet content_type_set) = 0;
};

// A one time grant will never last longer than this value.
static constexpr base::TimeDelta kOneTimePermissionMaximumLifetime =
    base::Hours(16);

using BrowserPermissionCallback = base::OnceCallback<void(ContentSetting)>;

// This base class contains common operations for granting permissions.
// It offers the following functionality:
//   - Creates a permission request when needed.
//   - If accepted/denied the permission is saved in content settings for
//     future uses (for the domain that requested it).
//   - If dismissed the permission is not saved but it's considered denied for
//     this one request
//   - In any case the BrowserPermissionCallback is executed once a decision
//     about the permission is made by the user.
// The bare minimum you need to create a new permission request is
//   - Define your new permission in the ContentSettingsType enum.
//   - Create a class that inherits from PermissionContextBase and passes the
//     new permission.
//   - Edit the PermissionRequest methods to add the new text.
//   - Hit several asserts for the missing plumbing and fix them :)
// After this you can override several other methods to customize behavior,
// in particular it is advised to override UpdateTabContext in order to manage
// the permission from the omnibox.
// See midi_permission_context.h/cc or push_permission_context.cc/h for some
// examples.

class PermissionContextBase : public content_settings::Observer {
 public:
  PermissionContextBase(
      content::BrowserContext* browser_context,
      ContentSettingsType content_settings_type,
      blink::mojom::PermissionsPolicyFeature permissions_policy_feature);
  ~PermissionContextBase() override;

  // A field trial used to enable the global permissions kill switch.
  // This is public so permissions that don't yet inherit from
  // PermissionContextBase can use it.
  static const char kPermissionsKillSwitchFieldStudy[];

  // The field trial param to enable the global permissions kill switch.
  // This is public so permissions that don't yet inherit from
  // PermissionContextBase can use it.
  static const char kPermissionsKillSwitchBlockedValue[];

  // |callback| is called upon resolution of the request, but not if a prompt
  // is shown and ignored.
  virtual void RequestPermission(PermissionRequestData request_data,
                                 BrowserPermissionCallback callback);

  // Returns whether the permission has been granted, denied etc.
  // |render_frame_host| may be nullptr if the call is coming from a context
  // other than a specific frame.
  content::PermissionResult GetPermissionStatus(
      content::RenderFrameHost* render_frame_host,
      const GURL& requesting_origin,
      const GURL& embedding_origin) const;

  // Returns whether the permission is usable by requesting/embedding origins.
  bool IsPermissionAvailableToOrigins(const GURL& requesting_origin,
                                      const GURL& embedding_origin) const;

  // Update |result| with any modifications based on the device state. For
  // example, if |result| is ALLOW but Chrome does not have the relevant
  // permission at the device level, but will prompt the user, return ASK.
  // This function updates the cached device permission status which can result
  // in the permission status changing and observers being notified.
  virtual content::PermissionResult UpdatePermissionStatusWithDeviceStatus(
      content::PermissionResult result,
      const GURL& requesting_origin,
      const GURL& embedding_origin) const;

  // Resets the permission to its default value.
  virtual void ResetPermission(const GURL& requesting_origin,
                               const GURL& embedding_origin);

  // Whether the kill switch has been enabled for this permission.
  // public for permissions that do not use RequestPermission, like
  // camera and microphone, and for testing.
  bool IsPermissionKillSwitchOn() const;

  void AddObserver(permissions::Observer* permission_observer);
  void RemoveObserver(permissions::Observer* permission_observer);

  ContentSettingsType content_settings_type() const {
    return content_settings_type_;
  }

 protected:
  virtual ContentSetting GetPermissionStatusInternal(
      content::RenderFrameHost* render_frame_host,
      const GURL& requesting_origin,
      const GURL& embedding_origin) const;

  // Called if generic checks (existing content setting, embargo, etc.) fail to
  // resolve a permission request. The default implementation prompts the user.
  virtual void DecidePermission(PermissionRequestData request_data,
                                BrowserPermissionCallback callback);

  // Updates stored content setting if persist is set, updates tab indicators
  // and runs the callback to finish the request.
  virtual void NotifyPermissionSet(const PermissionRequestID& id,
                                   const GURL& requesting_origin,
                                   const GURL& embedding_origin,
                                   BrowserPermissionCallback callback,
                                   bool persist,
                                   ContentSetting content_setting,
                                   bool is_one_time,
                                   bool is_final_decision);

  // Implementors can override this method to update the icons on the
  // url bar with the result of the new permission.
  virtual void UpdateTabContext(const PermissionRequestID& id,
                                const GURL& requesting_origin,
                                bool allowed) {}

  // Returns the browser context associated with this permission context.
  content::BrowserContext* browser_context() const;

  // Store the decided permission as a content setting.
  // virtual since the permission might be stored with different restrictions
  // (for example for desktop notifications).
  virtual void UpdateContentSetting(const GURL& requesting_origin,
                                    const GURL& embedding_origin,
                                    ContentSetting content_setting,
                                    bool is_one_time);

  // Whether the permission should be restricted to secure origins.
  virtual bool IsRestrictedToSecureOrigins() const;

  // Called by PermissionDecided when the user has made a permission decision.
  // Subclasses may override this method to perform context-specific logic
  // before the content setting is changed and the permission callback is run.
  virtual void UserMadePermissionDecision(const PermissionRequestID& id,
                                          const GURL& requesting_origin,
                                          const GURL& embedding_origin,
                                          ContentSetting content_setting);

  // content_settings::Observer:
  void OnContentSettingChanged(
      const ContentSettingsPattern& primary_pattern,
      const ContentSettingsPattern& secondary_pattern,
      ContentSettingsTypeSet content_type_set) override;

  // Implementors can override this method to use a different PermissionRequest
  // implementation.
  virtual std::unique_ptr<PermissionRequest> CreatePermissionRequest(
      content::WebContents* web_contents,
      PermissionRequestData request_data,
      PermissionRequest::PermissionDecidedCallback permission_decided_callback,
      base::OnceClosure delete_callback) const;

  base::ObserverList<permissions::Observer> permission_observers_;

  // Set by subclasses to inform the base class that they will handle adding
  // and removing themselves as observers to the HostContentSettingsMap.
  bool content_setting_observer_registered_by_subclass_ = false;

 private:
  friend class PermissionContextBaseTests;

  bool PermissionAllowedByPermissionsPolicy(
      content::RenderFrameHost* rfh) const;

  // Called when a request is no longer used so it can be cleaned up.
  void CleanUpRequest(const PermissionRequestID& id);

  // This is the callback for PermissionRequest and is called once the user
  // allows/blocks/dismisses a permission prompt.
  void PermissionDecided(const PermissionRequestID& id,
                         const GURL& requesting_origin,
                         const GURL& embedding_origin,
                         ContentSetting content_setting,
                         bool is_one_time,
                         bool is_final_decision);

  void NotifyObservers(const ContentSettingsPattern& primary_pattern,
                       const ContentSettingsPattern& secondary_pattern,
                       ContentSettingsTypeSet content_type_set) const;

  raw_ptr<content::BrowserContext> browser_context_;
  const ContentSettingsType content_settings_type_;
  const blink::mojom::PermissionsPolicyFeature permissions_policy_feature_;
  std::unordered_map<
      std::string,
      std::pair<std::unique_ptr<PermissionRequest>, BrowserPermissionCallback>>
      pending_requests_;

  mutable absl::optional<bool> last_has_device_permission_result_ =
      absl::nullopt;

  // Must be the last member, to ensure that it will be
  // destroyed first, which will invalidate weak pointers
  base::WeakPtrFactory<PermissionContextBase> weak_factory_{this};
};

}  // namespace permissions

#endif  // COMPONENTS_PERMISSIONS_PERMISSION_CONTEXT_BASE_H_