1 // Copyright 2014 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_context_base.h"
7 #include "base/logging.h"
8 #include "base/prefs/pref_service.h"
9 #include "chrome/browser/permissions/permission_bubble_request_impl.h"
10 #include "chrome/browser/permissions/permission_context_uma_util.h"
11 #include "chrome/browser/permissions/permission_queue_controller.h"
12 #include "chrome/browser/permissions/permission_request_id.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
15 #include "chrome/common/pref_names.h"
16 #include "components/content_settings/core/browser/host_content_settings_map.h"
17 #include "components/content_settings/core/browser/website_settings_registry.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/web_contents.h"
20 #include "content/public/common/origin_util.h"
22 PermissionContextBase::PermissionContextBase(
24 const ContentSettingsType permission_type
)
26 permission_type_(permission_type
),
28 permission_queue_controller_
.reset(
29 new PermissionQueueController(profile_
, permission_type_
));
32 PermissionContextBase::~PermissionContextBase() {
33 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
36 void PermissionContextBase::RequestPermission(
37 content::WebContents
* web_contents
,
38 const PermissionRequestID
& id
,
39 const GURL
& requesting_frame
,
41 const BrowserPermissionCallback
& callback
) {
42 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
44 DecidePermission(web_contents
,
46 requesting_frame
.GetOrigin(),
47 web_contents
->GetLastCommittedURL().GetOrigin(),
52 ContentSetting
PermissionContextBase::GetPermissionStatus(
53 const GURL
& requesting_origin
,
54 const GURL
& embedding_origin
) const {
55 if (IsRestrictedToSecureOrigins() &&
56 !content::IsOriginSecure(requesting_origin
)) {
57 return CONTENT_SETTING_BLOCK
;
60 return profile_
->GetHostContentSettingsMap()->GetContentSetting(
61 requesting_origin
, embedding_origin
, permission_type_
, std::string());
64 void PermissionContextBase::ResetPermission(
65 const GURL
& requesting_origin
,
66 const GURL
& embedding_origin
) {
67 profile_
->GetHostContentSettingsMap()->SetContentSetting(
68 ContentSettingsPattern::FromURLNoWildcard(requesting_origin
),
69 ContentSettingsPattern::FromURLNoWildcard(embedding_origin
),
70 permission_type_
, std::string(), CONTENT_SETTING_DEFAULT
);
73 void PermissionContextBase::CancelPermissionRequest(
74 content::WebContents
* web_contents
,
75 const PermissionRequestID
& id
) {
76 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
78 if (PermissionBubbleManager::Enabled()) {
79 PermissionBubbleRequest
* cancelling
=
80 pending_bubbles_
.get(id
.ToString());
81 if (cancelling
!= NULL
&& web_contents
!= NULL
&&
82 PermissionBubbleManager::FromWebContents(web_contents
) != NULL
) {
83 PermissionBubbleManager::FromWebContents(web_contents
)->
84 CancelRequest(cancelling
);
89 GetQueueController()->CancelInfoBarRequest(id
);
92 void PermissionContextBase::DecidePermission(
93 content::WebContents
* web_contents
,
94 const PermissionRequestID
& id
,
95 const GURL
& requesting_origin
,
96 const GURL
& embedding_origin
,
98 const BrowserPermissionCallback
& callback
) {
99 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
101 if (!requesting_origin
.is_valid() || !embedding_origin
.is_valid()) {
102 std::string type_name
=
103 content_settings::WebsiteSettingsRegistry::GetInstance()
104 ->Get(permission_type_
)
107 DVLOG(1) << "Attempt to use " << type_name
108 << " from an invalid URL: " << requesting_origin
<< ","
109 << embedding_origin
<< " (" << type_name
110 << " is not supported in popups)";
111 NotifyPermissionSet(id
, requesting_origin
, embedding_origin
, callback
,
112 false /* persist */, CONTENT_SETTING_BLOCK
);
116 if (IsRestrictedToSecureOrigins() &&
117 !content::IsOriginSecure(requesting_origin
)) {
118 NotifyPermissionSet(id
, requesting_origin
, embedding_origin
, callback
,
119 false /* persist */, CONTENT_SETTING_BLOCK
);
123 ContentSetting content_setting
=
124 profile_
->GetHostContentSettingsMap()
125 ->GetContentSettingAndMaybeUpdateLastUsage(
126 requesting_origin
, embedding_origin
, permission_type_
,
129 if (content_setting
== CONTENT_SETTING_ALLOW
||
130 content_setting
== CONTENT_SETTING_BLOCK
) {
131 NotifyPermissionSet(id
, requesting_origin
, embedding_origin
, callback
,
132 false /* persist */, content_setting
);
136 PermissionContextUmaUtil::PermissionRequested(
137 permission_type_
, requesting_origin
, embedding_origin
, profile_
);
139 if (PermissionBubbleManager::Enabled()) {
140 PermissionBubbleManager
* bubble_manager
=
141 PermissionBubbleManager::FromWebContents(web_contents
);
142 DCHECK(bubble_manager
);
143 scoped_ptr
<PermissionBubbleRequest
> request_ptr(
144 new PermissionBubbleRequestImpl(
145 requesting_origin
, user_gesture
, permission_type_
,
146 profile_
->GetPrefs()->GetString(prefs::kAcceptLanguages
),
147 base::Bind(&PermissionContextBase::PermissionDecided
,
148 weak_factory_
.GetWeakPtr(), id
, requesting_origin
,
149 embedding_origin
, callback
),
150 base::Bind(&PermissionContextBase::CleanUpBubble
,
151 weak_factory_
.GetWeakPtr(), id
)));
152 PermissionBubbleRequest
* request
= request_ptr
.get();
154 bool inserted
= pending_bubbles_
.add(
155 id
.ToString(), request_ptr
.Pass()).second
;
156 DCHECK(inserted
) << "Duplicate id " << id
.ToString();
157 bubble_manager
->AddRequest(request
);
161 // TODO(gbillock): Delete this and the infobar delegate when
162 // we're using only bubbles. crbug.com/337458
163 GetQueueController()->CreateInfoBarRequest(
164 id
, requesting_origin
, embedding_origin
,
165 base::Bind(&PermissionContextBase::PermissionDecided
,
166 weak_factory_
.GetWeakPtr(), id
, requesting_origin
,
167 embedding_origin
, callback
,
168 // the queue controller takes care of persisting the
173 void PermissionContextBase::PermissionDecided(
174 const PermissionRequestID
& id
,
175 const GURL
& requesting_origin
,
176 const GURL
& embedding_origin
,
177 const BrowserPermissionCallback
& callback
,
179 ContentSetting content_setting
) {
180 // Infobar persistance and its related UMA is tracked on the infobar
181 // controller directly.
182 if (PermissionBubbleManager::Enabled()) {
184 DCHECK(content_setting
== CONTENT_SETTING_ALLOW
||
185 content_setting
== CONTENT_SETTING_BLOCK
);
186 if (content_setting
== CONTENT_SETTING_ALLOW
)
187 PermissionContextUmaUtil::PermissionGranted(permission_type_
,
190 PermissionContextUmaUtil::PermissionDenied(permission_type_
,
193 DCHECK_EQ(content_setting
, CONTENT_SETTING_DEFAULT
);
194 PermissionContextUmaUtil::PermissionDismissed(permission_type_
,
199 NotifyPermissionSet(id
, requesting_origin
, embedding_origin
, callback
,
200 persist
, content_setting
);
203 PermissionQueueController
* PermissionContextBase::GetQueueController() {
204 return permission_queue_controller_
.get();
207 Profile
* PermissionContextBase::profile() const {
211 void PermissionContextBase::NotifyPermissionSet(
212 const PermissionRequestID
& id
,
213 const GURL
& requesting_origin
,
214 const GURL
& embedding_origin
,
215 const BrowserPermissionCallback
& callback
,
217 ContentSetting content_setting
) {
218 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
221 UpdateContentSetting(requesting_origin
, embedding_origin
, content_setting
);
223 UpdateTabContext(id
, requesting_origin
,
224 content_setting
== CONTENT_SETTING_ALLOW
);
226 if (content_setting
== CONTENT_SETTING_DEFAULT
) {
228 profile_
->GetHostContentSettingsMap()->GetDefaultContentSetting(
229 permission_type_
, nullptr);
232 DCHECK_NE(content_setting
, CONTENT_SETTING_DEFAULT
);
233 callback
.Run(content_setting
);
236 void PermissionContextBase::CleanUpBubble(const PermissionRequestID
& id
) {
237 size_t success
= pending_bubbles_
.erase(id
.ToString());
238 DCHECK(success
== 1) << "Missing request " << id
.ToString();
241 void PermissionContextBase::UpdateContentSetting(
242 const GURL
& requesting_origin
,
243 const GURL
& embedding_origin
,
244 ContentSetting content_setting
) {
245 DCHECK_EQ(requesting_origin
, requesting_origin
.GetOrigin());
246 DCHECK_EQ(embedding_origin
, embedding_origin
.GetOrigin());
247 DCHECK(content_setting
== CONTENT_SETTING_ALLOW
||
248 content_setting
== CONTENT_SETTING_BLOCK
);
250 profile_
->GetHostContentSettingsMap()->SetContentSetting(
251 ContentSettingsPattern::FromURLNoWildcard(requesting_origin
),
252 ContentSettingsPattern::FromURLNoWildcard(embedding_origin
),
253 permission_type_
, std::string(), content_setting
);