Re-land: C++ readability review
[chromium-blink-merge.git] / chrome / browser / permissions / permission_manager.cc
blob217ec7f603762542392ae007cd7a9cadbc3e8b03
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/content_settings/permission_context_base.h"
9 #include "chrome/browser/permissions/permission_context.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "components/content_settings/core/browser/host_content_settings_map.h"
12 #include "components/content_settings/core/common/permission_request_id.h"
13 #include "content/public/browser/permission_type.h"
14 #include "content/public/browser/render_process_host.h"
15 #include "content/public/browser/render_view_host.h"
16 #include "content/public/browser/web_contents.h"
18 namespace {
20 // Helper method to convert ContentSetting to content::PermissionStatus.
21 content::PermissionStatus
22 ContentSettingToPermissionStatus(ContentSetting setting) {
23 switch (setting) {
24 case CONTENT_SETTING_ALLOW:
25 case CONTENT_SETTING_SESSION_ONLY:
26 return content::PERMISSION_STATUS_GRANTED;
27 case CONTENT_SETTING_BLOCK:
28 return content::PERMISSION_STATUS_DENIED;
29 case CONTENT_SETTING_ASK:
30 return content::PERMISSION_STATUS_ASK;
31 case CONTENT_SETTING_DETECT_IMPORTANT_CONTENT:
32 case CONTENT_SETTING_DEFAULT:
33 case CONTENT_SETTING_NUM_SETTINGS:
34 break;
37 NOTREACHED();
38 return content::PERMISSION_STATUS_DENIED;
41 // Helper method to convert content::PermissionType to ContentSettingType.
42 ContentSettingsType PermissionTypeToContentSetting(
43 content::PermissionType permission) {
44 switch (permission) {
45 case content::PermissionType::MIDI_SYSEX:
46 return CONTENT_SETTINGS_TYPE_MIDI_SYSEX;
47 case content::PermissionType::PUSH_MESSAGING:
48 return CONTENT_SETTINGS_TYPE_PUSH_MESSAGING;
49 case content::PermissionType::NOTIFICATIONS:
50 return CONTENT_SETTINGS_TYPE_NOTIFICATIONS;
51 case content::PermissionType::GEOLOCATION:
52 return CONTENT_SETTINGS_TYPE_GEOLOCATION;
53 case content::PermissionType::PROTECTED_MEDIA_IDENTIFIER:
54 #if defined(OS_ANDROID) || defined(OS_CHROMEOS)
55 return CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER;
56 #else
57 NOTIMPLEMENTED();
58 break;
59 #endif
60 case content::PermissionType::NUM:
61 // This will hit the NOTREACHED below.
62 break;
65 NOTREACHED() << "Unknown content setting for permission "
66 << static_cast<int>(permission);
67 return CONTENT_SETTINGS_TYPE_DEFAULT;
70 // Helper method that wraps a callback a void(content::PermissionStatus)
71 // callback into a void(ContentSetting) callback.
72 void PermissionStatusCallbackWrapper(
73 const base::Callback<void(content::PermissionStatus)>& callback,
74 ContentSetting content_setting) {
75 callback.Run(ContentSettingToPermissionStatus(content_setting));
78 } // anonymous namespace
80 struct PermissionManager::Subscription {
81 content::PermissionType permission;
82 GURL requesting_origin;
83 GURL embedding_origin;
84 base::Callback<void(content::PermissionStatus)> callback;
85 ContentSetting current_value;
88 PermissionManager::PermissionManager(Profile* profile)
89 : profile_(profile) {
92 PermissionManager::~PermissionManager() {
93 if (!subscriptions_.IsEmpty())
94 profile_->GetHostContentSettingsMap()->RemoveObserver(this);
97 void PermissionManager::RequestPermission(
98 content::PermissionType permission,
99 content::WebContents* web_contents,
100 int request_id,
101 const GURL& requesting_origin,
102 bool user_gesture,
103 const base::Callback<void(content::PermissionStatus)>& callback) {
104 PermissionContextBase* context = PermissionContext::Get(profile_, permission);
105 if (!context) {
106 callback.Run(content::PERMISSION_STATUS_DENIED);
107 return;
110 int render_process_id = web_contents->GetRenderProcessHost()->GetID();
111 int render_view_id = web_contents->GetRenderViewHost()->GetRoutingID();
112 const PermissionRequestID request(render_process_id,
113 render_view_id,
114 request_id,
115 requesting_origin);
117 context->RequestPermission(web_contents, request, requesting_origin,
118 user_gesture,
119 base::Bind(&PermissionStatusCallbackWrapper,
120 callback));
123 void PermissionManager::CancelPermissionRequest(
124 content::PermissionType permission,
125 content::WebContents* web_contents,
126 int request_id,
127 const GURL& requesting_origin) {
128 PermissionContextBase* context = PermissionContext::Get(profile_, permission);
129 if (!context)
130 return;
132 int render_process_id = web_contents->GetRenderProcessHost()->GetID();
133 int render_view_id = web_contents->GetRenderViewHost()->GetRoutingID();
134 const PermissionRequestID request(render_process_id,
135 render_view_id,
136 request_id,
137 requesting_origin);
139 context->CancelPermissionRequest(web_contents, request);
142 void PermissionManager::ResetPermission(
143 content::PermissionType permission,
144 const GURL& requesting_origin,
145 const GURL& embedding_origin) {
146 PermissionContextBase* context = PermissionContext::Get(profile_, permission);
147 if (!context)
148 return;
150 context->ResetPermission(requesting_origin.GetOrigin(),
151 embedding_origin.GetOrigin());
154 content::PermissionStatus PermissionManager::GetPermissionStatus(
155 content::PermissionType permission,
156 const GURL& requesting_origin,
157 const GURL& embedding_origin) {
158 PermissionContextBase* context = PermissionContext::Get(profile_, permission);
159 if (!context)
160 return content::PERMISSION_STATUS_DENIED;
162 return ContentSettingToPermissionStatus(
163 context->GetPermissionStatus(requesting_origin.GetOrigin(),
164 embedding_origin.GetOrigin()));
167 void PermissionManager::RegisterPermissionUsage(
168 content::PermissionType permission,
169 const GURL& requesting_origin,
170 const GURL& embedding_origin) {
171 profile_->GetHostContentSettingsMap()->UpdateLastUsage(
172 requesting_origin,
173 embedding_origin,
174 PermissionTypeToContentSetting(permission));
177 int PermissionManager::SubscribePermissionStatusChange(
178 content::PermissionType permission,
179 const GURL& requesting_origin,
180 const GURL& embedding_origin,
181 const base::Callback<void(content::PermissionStatus)>& callback) {
182 if (subscriptions_.IsEmpty())
183 profile_->GetHostContentSettingsMap()->AddObserver(this);
185 Subscription* subscription = new Subscription();
186 subscription->permission = permission;
187 subscription->requesting_origin = requesting_origin;
188 subscription->embedding_origin = embedding_origin;
189 subscription->callback = callback;
190 subscription->current_value = PermissionContext::Get(profile_, permission)
191 ->GetPermissionStatus(subscription->requesting_origin,
192 subscription->embedding_origin);
194 return subscriptions_.Add(subscription);
197 void PermissionManager::UnsubscribePermissionStatusChange(int subscription_id) {
198 // Whether |subscription_id| is known will be checked by the Remove() call.
199 subscriptions_.Remove(subscription_id);
201 if (subscriptions_.IsEmpty())
202 profile_->GetHostContentSettingsMap()->RemoveObserver(this);
205 void PermissionManager::OnContentSettingChanged(
206 const ContentSettingsPattern& primary_pattern,
207 const ContentSettingsPattern& secondary_pattern,
208 ContentSettingsType content_type,
209 std::string resource_identifier) {
210 std::list<base::Closure> callbacks;
212 for (SubscriptionsMap::iterator iter(&subscriptions_);
213 !iter.IsAtEnd(); iter.Advance()) {
214 Subscription* subscription = iter.GetCurrentValue();
215 if (PermissionTypeToContentSetting(subscription->permission) !=
216 content_type) {
217 continue;
220 if (primary_pattern.IsValid() &&
221 !primary_pattern.Matches(subscription->requesting_origin))
222 continue;
223 if (secondary_pattern.IsValid() &&
224 !secondary_pattern.Matches(subscription->embedding_origin))
225 continue;
227 ContentSetting new_value =
228 PermissionContext::Get(profile_, subscription->permission)
229 ->GetPermissionStatus(subscription->requesting_origin,
230 subscription->embedding_origin);
231 if (subscription->current_value == new_value)
232 continue;
234 subscription->current_value = new_value;
236 // Add the callback to |callbacks| which will be run after the loop to
237 // prevent re-entrance issues.
238 callbacks.push_back(
239 base::Bind(subscription->callback,
240 ContentSettingToPermissionStatus(new_value)));
243 for (const auto& callback : callbacks)
244 callback.Run();