Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / permissions / permission_manager.cc
blob7ef2d83786bde92216bda897453ea1f5473b5d0c
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::NUM:
62 // This will hit the NOTREACHED below.
63 break;
66 NOTREACHED() << "Unknown content setting for permission "
67 << static_cast<int>(permission);
68 return CONTENT_SETTINGS_TYPE_DEFAULT;
71 // Helper method that wraps a callback a void(PermissionStatus)
72 // callback into a void(ContentSetting) callback.
73 void PermissionStatusCallbackWrapper(
74 const base::Callback<void(PermissionStatus)>& callback,
75 ContentSetting content_setting) {
76 callback.Run(ContentSettingToPermissionStatus(content_setting));
79 } // anonymous namespace
81 struct PermissionManager::Subscription {
82 PermissionType permission;
83 GURL requesting_origin;
84 GURL embedding_origin;
85 base::Callback<void(PermissionStatus)> callback;
86 ContentSetting current_value;
89 PermissionManager::PermissionManager(Profile* profile)
90 : profile_(profile) {
93 PermissionManager::~PermissionManager() {
94 if (!subscriptions_.IsEmpty())
95 profile_->GetHostContentSettingsMap()->RemoveObserver(this);
98 void PermissionManager::RequestPermission(
99 PermissionType permission,
100 content::RenderFrameHost* render_frame_host,
101 int request_id,
102 const GURL& requesting_origin,
103 bool user_gesture,
104 const base::Callback<void(PermissionStatus)>& callback) {
105 PermissionContextBase* context = PermissionContext::Get(profile_, permission);
106 if (!context) {
107 callback.Run(content::PERMISSION_STATUS_DENIED);
108 return;
111 int render_process_id = render_frame_host->GetProcess()->GetID();
112 int render_frame_id = render_frame_host->GetRoutingID();
113 const PermissionRequestID request(render_process_id,
114 render_frame_id,
115 request_id,
116 requesting_origin);
118 context->RequestPermission(
119 content::WebContents::FromRenderFrameHost(render_frame_host),
120 request, requesting_origin, user_gesture,
121 base::Bind(&PermissionStatusCallbackWrapper,
122 callback));
125 void PermissionManager::CancelPermissionRequest(
126 PermissionType permission,
127 content::RenderFrameHost* render_frame_host,
128 int request_id,
129 const GURL& requesting_origin) {
130 PermissionContextBase* context = PermissionContext::Get(profile_, permission);
131 if (!context)
132 return;
134 int render_process_id = render_frame_host->GetProcess()->GetID();
135 int render_frame_id = render_frame_host->GetRoutingID();
136 const PermissionRequestID request(render_process_id,
137 render_frame_id,
138 request_id,
139 requesting_origin);
141 context->CancelPermissionRequest(
142 content::WebContents::FromRenderFrameHost(render_frame_host), request);
145 void PermissionManager::ResetPermission(PermissionType permission,
146 const GURL& requesting_origin,
147 const GURL& embedding_origin) {
148 PermissionContextBase* context = PermissionContext::Get(profile_, permission);
149 if (!context)
150 return;
152 context->ResetPermission(requesting_origin.GetOrigin(),
153 embedding_origin.GetOrigin());
156 PermissionStatus PermissionManager::GetPermissionStatus(
157 PermissionType permission,
158 const GURL& requesting_origin,
159 const GURL& embedding_origin) {
160 PermissionContextBase* context = PermissionContext::Get(profile_, permission);
161 if (!context)
162 return content::PERMISSION_STATUS_DENIED;
164 return ContentSettingToPermissionStatus(
165 context->GetPermissionStatus(requesting_origin.GetOrigin(),
166 embedding_origin.GetOrigin()));
169 void PermissionManager::RegisterPermissionUsage(PermissionType permission,
170 const GURL& requesting_origin,
171 const GURL& embedding_origin) {
172 profile_->GetHostContentSettingsMap()->UpdateLastUsage(
173 requesting_origin,
174 embedding_origin,
175 PermissionTypeToContentSetting(permission));
178 int PermissionManager::SubscribePermissionStatusChange(
179 PermissionType permission,
180 const GURL& requesting_origin,
181 const GURL& embedding_origin,
182 const base::Callback<void(PermissionStatus)>& callback) {
183 if (subscriptions_.IsEmpty())
184 profile_->GetHostContentSettingsMap()->AddObserver(this);
186 Subscription* subscription = new Subscription();
187 subscription->permission = permission;
188 subscription->requesting_origin = requesting_origin;
189 subscription->embedding_origin = embedding_origin;
190 subscription->callback = callback;
191 subscription->current_value = PermissionContext::Get(profile_, permission)
192 ->GetPermissionStatus(subscription->requesting_origin,
193 subscription->embedding_origin);
195 return subscriptions_.Add(subscription);
198 void PermissionManager::UnsubscribePermissionStatusChange(int subscription_id) {
199 // Whether |subscription_id| is known will be checked by the Remove() call.
200 subscriptions_.Remove(subscription_id);
202 if (subscriptions_.IsEmpty())
203 profile_->GetHostContentSettingsMap()->RemoveObserver(this);
206 void PermissionManager::OnContentSettingChanged(
207 const ContentSettingsPattern& primary_pattern,
208 const ContentSettingsPattern& secondary_pattern,
209 ContentSettingsType content_type,
210 std::string resource_identifier) {
211 std::list<base::Closure> callbacks;
213 for (SubscriptionsMap::iterator iter(&subscriptions_);
214 !iter.IsAtEnd(); iter.Advance()) {
215 Subscription* subscription = iter.GetCurrentValue();
216 if (PermissionTypeToContentSetting(subscription->permission) !=
217 content_type) {
218 continue;
221 if (primary_pattern.IsValid() &&
222 !primary_pattern.Matches(subscription->requesting_origin))
223 continue;
224 if (secondary_pattern.IsValid() &&
225 !secondary_pattern.Matches(subscription->embedding_origin))
226 continue;
228 ContentSetting new_value =
229 PermissionContext::Get(profile_, subscription->permission)
230 ->GetPermissionStatus(subscription->requesting_origin,
231 subscription->embedding_origin);
232 if (subscription->current_value == new_value)
233 continue;
235 subscription->current_value = new_value;
237 // Add the callback to |callbacks| which will be run after the loop to
238 // prevent re-entrance issues.
239 callbacks.push_back(
240 base::Bind(subscription->callback,
241 ContentSettingToPermissionStatus(new_value)));
244 for (const auto& callback : callbacks)
245 callback.Run();