Revert "Reland c91b178b07b0d - Delete dead signin code (SigninGlobalError)"
[chromium-blink-merge.git] / chrome / browser / permissions / permission_manager.cc
blobe39955ab7c364015d180c9bb05e67b771d752814
1 // Copyright 2015 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.
5 #include "chrome/browser/permissions/permission_manager.h"
7 #include "base/callback.h"
8 #include "chrome/browser/permissions/permission_context.h"
9 #include "chrome/browser/permissions/permission_context_base.h"
10 #include "chrome/browser/permissions/permission_request_id.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "components/content_settings/core/browser/host_content_settings_map.h"
13 #include "content/public/browser/permission_type.h"
14 #include "content/public/browser/render_frame_host.h"
15 #include "content/public/browser/render_process_host.h"
16 #include "content/public/browser/web_contents.h"
18 using content::PermissionStatus;
19 using content::PermissionType;
21 namespace {
23 // Helper method to convert ContentSetting to PermissionStatus.
24 PermissionStatus ContentSettingToPermissionStatus(ContentSetting setting) {
25 switch (setting) {
26 case CONTENT_SETTING_ALLOW:
27 case CONTENT_SETTING_SESSION_ONLY:
28 return content::PERMISSION_STATUS_GRANTED;
29 case CONTENT_SETTING_BLOCK:
30 return content::PERMISSION_STATUS_DENIED;
31 case CONTENT_SETTING_ASK:
32 return content::PERMISSION_STATUS_ASK;
33 case CONTENT_SETTING_DETECT_IMPORTANT_CONTENT:
34 case CONTENT_SETTING_DEFAULT:
35 case CONTENT_SETTING_NUM_SETTINGS:
36 break;
39 NOTREACHED();
40 return content::PERMISSION_STATUS_DENIED;
43 // Helper method to convert PermissionType to ContentSettingType.
44 ContentSettingsType PermissionTypeToContentSetting(PermissionType permission) {
45 switch (permission) {
46 case PermissionType::MIDI_SYSEX:
47 return CONTENT_SETTINGS_TYPE_MIDI_SYSEX;
48 case PermissionType::PUSH_MESSAGING:
49 return CONTENT_SETTINGS_TYPE_PUSH_MESSAGING;
50 case PermissionType::NOTIFICATIONS:
51 return CONTENT_SETTINGS_TYPE_NOTIFICATIONS;
52 case PermissionType::GEOLOCATION:
53 return CONTENT_SETTINGS_TYPE_GEOLOCATION;
54 case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
55 #if defined(OS_ANDROID) || defined(OS_CHROMEOS)
56 return CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER;
57 #else
58 NOTIMPLEMENTED();
59 break;
60 #endif
61 case PermissionType::DURABLE_STORAGE:
62 return CONTENT_SETTINGS_TYPE_DURABLE_STORAGE;
63 case PermissionType::MIDI:
64 // This will hit the NOTREACHED below.
65 break;
66 case PermissionType::NUM:
67 // This will hit the NOTREACHED below.
68 break;
71 NOTREACHED() << "Unknown content setting for permission "
72 << static_cast<int>(permission);
73 return CONTENT_SETTINGS_TYPE_DEFAULT;
76 // Helper method that wraps a callback a void(PermissionStatus)
77 // callback into a void(ContentSetting) callback.
78 void PermissionStatusCallbackWrapper(
79 const base::Callback<void(PermissionStatus)>& callback,
80 ContentSetting content_setting) {
81 callback.Run(ContentSettingToPermissionStatus(content_setting));
84 // Returns whether the permission has a constant PermissionStatus value (i.e.
85 // always approved or always denied)
86 // The PermissionTypes for which true is returned should be exactly those which
87 // return nullptr in PermissionContext::Get since they don't have a context.
88 bool IsConstantPermission(PermissionType type) {
89 switch (type) {
90 case PermissionType::MIDI:
91 return true;
92 default:
93 return false;
97 // Function used for handling permission types which do not change their
98 // value i.e. they are always approved or always denied etc.
99 // CONTENT_SETTING_DEFAULT is returned if the permission needs further handling.
100 // This function should only be called when IsConstantPermission has returned
101 // true for the PermissionType.
102 ContentSetting GetContentSettingForConstantPermission(PermissionType type) {
103 DCHECK(IsConstantPermission(type));
104 switch (type) {
105 case PermissionType::MIDI:
106 return CONTENT_SETTING_ALLOW;
107 default:
108 return CONTENT_SETTING_DEFAULT;
112 PermissionStatus GetPermissionStatusForConstantPermission(PermissionType type) {
113 return ContentSettingToPermissionStatus(
114 GetContentSettingForConstantPermission(type));
117 } // anonymous namespace
119 struct PermissionManager::Subscription {
120 PermissionType permission;
121 GURL requesting_origin;
122 GURL embedding_origin;
123 base::Callback<void(PermissionStatus)> callback;
124 ContentSetting current_value;
127 PermissionManager::PermissionManager(Profile* profile)
128 : profile_(profile) {
131 PermissionManager::~PermissionManager() {
132 if (!subscriptions_.IsEmpty())
133 profile_->GetHostContentSettingsMap()->RemoveObserver(this);
136 void PermissionManager::RequestPermission(
137 PermissionType permission,
138 content::RenderFrameHost* render_frame_host,
139 int request_id,
140 const GURL& requesting_origin,
141 bool user_gesture,
142 const base::Callback<void(PermissionStatus)>& callback) {
143 if (IsConstantPermission(permission)) {
144 callback.Run(GetPermissionStatusForConstantPermission(permission));
145 return;
148 PermissionContextBase* context = PermissionContext::Get(profile_, permission);
149 if (!context) {
150 callback.Run(content::PERMISSION_STATUS_DENIED);
151 return;
154 int render_process_id = render_frame_host->GetProcess()->GetID();
155 int render_frame_id = render_frame_host->GetRoutingID();
156 const PermissionRequestID request(render_process_id,
157 render_frame_id,
158 request_id,
159 requesting_origin);
161 context->RequestPermission(
162 content::WebContents::FromRenderFrameHost(render_frame_host),
163 request, requesting_origin, user_gesture,
164 base::Bind(&PermissionStatusCallbackWrapper,
165 callback));
168 void PermissionManager::CancelPermissionRequest(
169 PermissionType permission,
170 content::RenderFrameHost* render_frame_host,
171 int request_id,
172 const GURL& requesting_origin) {
173 PermissionContextBase* context = PermissionContext::Get(profile_, permission);
174 if (!context)
175 return;
177 int render_process_id = render_frame_host->GetProcess()->GetID();
178 int render_frame_id = render_frame_host->GetRoutingID();
179 const PermissionRequestID request(render_process_id,
180 render_frame_id,
181 request_id,
182 requesting_origin);
184 context->CancelPermissionRequest(
185 content::WebContents::FromRenderFrameHost(render_frame_host), request);
188 void PermissionManager::ResetPermission(PermissionType permission,
189 const GURL& requesting_origin,
190 const GURL& embedding_origin) {
191 PermissionContextBase* context = PermissionContext::Get(profile_, permission);
192 if (!context)
193 return;
195 context->ResetPermission(requesting_origin.GetOrigin(),
196 embedding_origin.GetOrigin());
199 PermissionStatus PermissionManager::GetPermissionStatus(
200 PermissionType permission,
201 const GURL& requesting_origin,
202 const GURL& embedding_origin) {
203 if (IsConstantPermission(permission))
204 return GetPermissionStatusForConstantPermission(permission);
206 PermissionContextBase* context = PermissionContext::Get(profile_, permission);
207 if (!context)
208 return content::PERMISSION_STATUS_DENIED;
210 return ContentSettingToPermissionStatus(
211 context->GetPermissionStatus(requesting_origin.GetOrigin(),
212 embedding_origin.GetOrigin()));
215 void PermissionManager::RegisterPermissionUsage(PermissionType permission,
216 const GURL& requesting_origin,
217 const GURL& embedding_origin) {
218 // This is required because constant permissions don't have a
219 // ContentSettingsType.
220 if (IsConstantPermission(permission))
221 return;
223 profile_->GetHostContentSettingsMap()->UpdateLastUsage(
224 requesting_origin,
225 embedding_origin,
226 PermissionTypeToContentSetting(permission));
229 int PermissionManager::SubscribePermissionStatusChange(
230 PermissionType permission,
231 const GURL& requesting_origin,
232 const GURL& embedding_origin,
233 const base::Callback<void(PermissionStatus)>& callback) {
234 if (subscriptions_.IsEmpty())
235 profile_->GetHostContentSettingsMap()->AddObserver(this);
237 Subscription* subscription = new Subscription();
238 subscription->permission = permission;
239 subscription->requesting_origin = requesting_origin;
240 subscription->embedding_origin = embedding_origin;
241 subscription->callback = callback;
243 if (IsConstantPermission(permission)) {
244 subscription->current_value = GetContentSettingForConstantPermission(
245 permission);
246 } else {
247 subscription->current_value = PermissionContext::Get(profile_, permission)
248 ->GetPermissionStatus(subscription->requesting_origin,
249 subscription->embedding_origin);
252 return subscriptions_.Add(subscription);
255 void PermissionManager::UnsubscribePermissionStatusChange(int subscription_id) {
256 // Whether |subscription_id| is known will be checked by the Remove() call.
257 subscriptions_.Remove(subscription_id);
259 if (subscriptions_.IsEmpty())
260 profile_->GetHostContentSettingsMap()->RemoveObserver(this);
263 void PermissionManager::OnContentSettingChanged(
264 const ContentSettingsPattern& primary_pattern,
265 const ContentSettingsPattern& secondary_pattern,
266 ContentSettingsType content_type,
267 std::string resource_identifier) {
268 std::list<base::Closure> callbacks;
270 for (SubscriptionsMap::iterator iter(&subscriptions_);
271 !iter.IsAtEnd(); iter.Advance()) {
272 Subscription* subscription = iter.GetCurrentValue();
273 if (PermissionTypeToContentSetting(subscription->permission) !=
274 content_type) {
275 continue;
278 if (primary_pattern.IsValid() &&
279 !primary_pattern.Matches(subscription->requesting_origin))
280 continue;
281 if (secondary_pattern.IsValid() &&
282 !secondary_pattern.Matches(subscription->embedding_origin))
283 continue;
285 ContentSetting new_value =
286 PermissionContext::Get(profile_, subscription->permission)
287 ->GetPermissionStatus(subscription->requesting_origin,
288 subscription->embedding_origin);
289 if (subscription->current_value == new_value)
290 continue;
292 subscription->current_value = new_value;
294 // Add the callback to |callbacks| which will be run after the loop to
295 // prevent re-entrance issues.
296 callbacks.push_back(
297 base::Bind(subscription->callback,
298 ContentSettingToPermissionStatus(new_value)));
301 for (const auto& callback : callbacks)
302 callback.Run();