OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/permissions/permission_context_base.h" | 5 #include "chrome/browser/permissions/permission_context_base.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <string> | 9 #include <string> |
10 #include <utility> | 10 #include <utility> |
11 | 11 |
12 #include "base/callback.h" | 12 #include "base/callback.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
15 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
16 #include "base/time/time.h" | 16 #include "base/time/time.h" |
17 #include "build/build_config.h" | 17 #include "build/build_config.h" |
18 #include "chrome/browser/browser_process.h" | 18 #include "chrome/browser/browser_process.h" |
19 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" | 19 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
20 #include "chrome/browser/permissions/permission_decision_auto_blocker.h" | 20 #include "chrome/browser/permissions/permission_decision_auto_blocker.h" |
21 #include "chrome/browser/permissions/permission_request.h" | 21 #include "chrome/browser/permissions/permission_request.h" |
22 #include "chrome/browser/permissions/permission_request_id.h" | 22 #include "chrome/browser/permissions/permission_request_id.h" |
23 #include "chrome/browser/permissions/permission_request_impl.h" | 23 #include "chrome/browser/permissions/permission_request_impl.h" |
24 #include "chrome/browser/permissions/permission_request_manager.h" | 24 #include "chrome/browser/permissions/permission_request_manager.h" |
25 #include "chrome/browser/permissions/permission_uma_util.h" | 25 #include "chrome/browser/permissions/permission_uma_util.h" |
26 #include "chrome/browser/permissions/permission_util.h" | |
27 #include "chrome/browser/profiles/profile.h" | 26 #include "chrome/browser/profiles/profile.h" |
28 #include "chrome/browser/safe_browsing/safe_browsing_service.h" | 27 #include "chrome/browser/safe_browsing/safe_browsing_service.h" |
29 #include "chrome/common/chrome_features.h" | 28 #include "chrome/common/chrome_features.h" |
30 #include "chrome/common/pref_names.h" | 29 #include "chrome/common/pref_names.h" |
31 #include "components/content_settings/core/browser/host_content_settings_map.h" | 30 #include "components/content_settings/core/browser/host_content_settings_map.h" |
32 #include "components/prefs/pref_service.h" | 31 #include "components/prefs/pref_service.h" |
33 #include "components/safe_browsing_db/database_manager.h" | 32 #include "components/safe_browsing_db/database_manager.h" |
34 #include "components/variations/variations_associated_data.h" | 33 #include "components/variations/variations_associated_data.h" |
35 #include "content/public/browser/browser_thread.h" | 34 #include "content/public/browser/browser_thread.h" |
36 #include "content/public/browser/render_frame_host.h" | 35 #include "content/public/browser/render_frame_host.h" |
37 #include "content/public/browser/web_contents.h" | 36 #include "content/public/browser/web_contents.h" |
38 #include "content/public/common/origin_util.h" | 37 #include "content/public/common/origin_util.h" |
39 #include "url/gurl.h" | 38 #include "url/gurl.h" |
40 | 39 |
41 #if defined(OS_ANDROID) | 40 #if defined(OS_ANDROID) |
42 #include "chrome/browser/permissions/permission_queue_controller.h" | 41 #include "chrome/browser/permissions/permission_queue_controller.h" |
43 #endif | 42 #endif |
44 | 43 |
45 // static | 44 // static |
46 const char PermissionContextBase::kPermissionsKillSwitchFieldStudy[] = | 45 const char PermissionContextBase::kPermissionsKillSwitchFieldStudy[] = |
47 "PermissionsKillSwitch"; | 46 "PermissionsKillSwitch"; |
48 // static | 47 // static |
49 const char PermissionContextBase::kPermissionsKillSwitchBlockedValue[] = | 48 const char PermissionContextBase::kPermissionsKillSwitchBlockedValue[] = |
50 "blocked"; | 49 "blocked"; |
51 | 50 |
52 PermissionResult::PermissionResult(ContentSetting cs, | |
53 PermissionStatusSource pss) | |
54 : content_setting(cs), source(pss) {} | |
55 | |
56 PermissionResult::~PermissionResult() {} | |
57 | |
58 PermissionContextBase::PermissionContextBase( | 51 PermissionContextBase::PermissionContextBase( |
59 Profile* profile, | 52 Profile* profile, |
60 const ContentSettingsType content_settings_type) | 53 const ContentSettingsType content_settings_type) |
61 : profile_(profile), | 54 : profile_(profile), |
62 content_settings_type_(content_settings_type), | 55 content_settings_type_(content_settings_type), |
63 weak_factory_(this) { | 56 weak_factory_(this) { |
64 #if defined(OS_ANDROID) | 57 #if defined(OS_ANDROID) |
65 permission_queue_controller_.reset( | 58 permission_queue_controller_.reset( |
66 new PermissionQueueController(profile_, content_settings_type_)); | 59 new PermissionQueueController(profile_, content_settings_type_)); |
67 #endif | 60 #endif |
68 PermissionDecisionAutoBlocker::UpdateFromVariations(); | 61 PermissionDecisionAutoBlocker::UpdateFromVariations(); |
69 } | 62 } |
70 | 63 |
71 PermissionContextBase::~PermissionContextBase() { | 64 PermissionContextBase::~PermissionContextBase() { |
72 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 65 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
73 } | 66 } |
74 | 67 |
75 void PermissionContextBase::RequestPermission( | 68 void PermissionContextBase::RequestPermission( |
76 content::WebContents* web_contents, | 69 content::WebContents* web_contents, |
77 const PermissionRequestID& id, | 70 const PermissionRequestID& id, |
78 const GURL& requesting_frame, | 71 const GURL& requesting_frame, |
79 bool user_gesture, | 72 bool user_gesture, |
80 const BrowserPermissionCallback& callback) { | 73 const BrowserPermissionCallback& callback) { |
81 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 74 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
82 | 75 |
83 // First check if this permission has been disabled. | |
84 if (IsPermissionKillSwitchOn()) { | |
85 // Log to the developer console. | |
86 web_contents->GetMainFrame()->AddMessageToConsole( | |
87 content::CONSOLE_MESSAGE_LEVEL_INFO, | |
88 base::StringPrintf( | |
89 "%s permission has been blocked.", | |
90 PermissionUtil::GetPermissionString(content_settings_type_) | |
91 .c_str())); | |
92 // The kill switch is enabled for this permission; Block all requests. | |
93 callback.Run(CONTENT_SETTING_BLOCK); | |
94 return; | |
95 } | |
96 | |
97 GURL requesting_origin = requesting_frame.GetOrigin(); | 76 GURL requesting_origin = requesting_frame.GetOrigin(); |
98 GURL embedding_origin = web_contents->GetLastCommittedURL().GetOrigin(); | 77 GURL embedding_origin = web_contents->GetLastCommittedURL().GetOrigin(); |
99 | 78 |
100 if (!requesting_origin.is_valid() || !embedding_origin.is_valid()) { | 79 if (!requesting_origin.is_valid() || !embedding_origin.is_valid()) { |
101 std::string type_name = | 80 std::string type_name = |
102 PermissionUtil::GetPermissionString(content_settings_type_); | 81 PermissionUtil::GetPermissionString(content_settings_type_); |
103 | 82 |
104 DVLOG(1) << "Attempt to use " << type_name | 83 DVLOG(1) << "Attempt to use " << type_name |
105 << " from an invalid URL: " << requesting_origin << "," | 84 << " from an invalid URL: " << requesting_origin << "," |
106 << embedding_origin << " (" << type_name | 85 << embedding_origin << " (" << type_name |
107 << " is not supported in popups)"; | 86 << " is not supported in popups)"; |
108 NotifyPermissionSet(id, requesting_origin, embedding_origin, callback, | 87 NotifyPermissionSet(id, requesting_origin, embedding_origin, callback, |
109 false /* persist */, CONTENT_SETTING_BLOCK); | 88 false /* persist */, CONTENT_SETTING_BLOCK); |
110 return; | 89 return; |
111 } | 90 } |
112 | 91 |
113 // Synchronously check the content setting to see if the user has already made | 92 // Synchronously check the content setting to see if the user has already made |
114 // a decision, or if the origin is under embargo. If so, respect that | 93 // a decision, or if the origin is under embargo. If so, respect that |
115 // decision. | 94 // decision. |
116 PermissionResult result = | 95 PermissionResult result = |
117 GetPermissionStatus(requesting_origin, embedding_origin); | 96 GetPermissionStatus(requesting_origin, embedding_origin); |
118 | 97 |
119 if (result.content_setting == CONTENT_SETTING_ALLOW || | 98 if (result.content_setting == CONTENT_SETTING_ALLOW || |
120 result.content_setting == CONTENT_SETTING_BLOCK) { | 99 result.content_setting == CONTENT_SETTING_BLOCK) { |
100 if (result.source == PermissionStatusSource::KILL_SWITCH) { | |
101 // Block the request and log to the developer console. | |
102 web_contents->GetMainFrame()->AddMessageToConsole( | |
103 content::CONSOLE_MESSAGE_LEVEL_INFO, | |
104 base::StringPrintf( | |
105 "%s permission has been blocked.", | |
106 PermissionUtil::GetPermissionString(content_settings_type_) | |
107 .c_str())); | |
108 callback.Run(CONTENT_SETTING_BLOCK); | |
109 return; | |
110 } | |
111 | |
112 // If we are under embargo, record the embargo reason for which we have | |
113 // suppressed the prompt. Explicitly switch to ensure that any new | |
114 // PermissionStatusSource values are dealt with appropriately. | |
115 switch (result.source) { | |
116 case PermissionStatusSource::MULTIPLE_DISMISSALS: | |
117 PermissionUmaUtil::RecordEmbargoPromptSuppression( | |
118 PermissionEmbargoStatus::REPEATED_DISMISSALS); | |
119 break; | |
120 case PermissionStatusSource::SAFE_BROWSING_BLACKLIST: | |
121 PermissionUmaUtil::RecordEmbargoPromptSuppression( | |
122 PermissionEmbargoStatus::PERMISSIONS_BLACKLISTING); | |
123 break; | |
124 case PermissionStatusSource::UNSPECIFIED: | |
125 case PermissionStatusSource::KILL_SWITCH: | |
126 case PermissionStatusSource::NUM: | |
127 break; | |
128 } | |
raymes
2017/02/22 23:13:50
nit: Could we make the conversion a helper functio
dominickn
2017/02/22 23:38:54
This can only be done by proxying the call to Reco
raymes
2017/02/23 01:28:58
I agree - it's not ideal. We could alternatively h
| |
121 NotifyPermissionSet(id, requesting_origin, embedding_origin, callback, | 129 NotifyPermissionSet(id, requesting_origin, embedding_origin, callback, |
122 false /* persist */, result.content_setting); | 130 false /* persist */, result.content_setting); |
123 return; | 131 return; |
124 } | 132 } |
125 | 133 |
126 // Asynchronously check whether the origin should be blocked from making this | 134 // Asynchronously check whether the origin should be blocked from making this |
127 // permission request. It may be on the Safe Browsing API blacklist, or it may | 135 // permission request, e.g. it may be on the Safe Browsing API blacklist. |
128 // have been dismissed too many times in a row. If the origin is allowed to | |
129 // request, that request will be made to ContinueRequestPermission(). | |
130 PermissionDecisionAutoBlocker::GetForProfile(profile_)->UpdateEmbargoedStatus( | 136 PermissionDecisionAutoBlocker::GetForProfile(profile_)->UpdateEmbargoedStatus( |
131 content_settings_type_, requesting_origin, web_contents, | 137 content_settings_type_, requesting_origin, web_contents, |
132 base::Bind(&PermissionContextBase::ContinueRequestPermission, | 138 base::Bind(&PermissionContextBase::ContinueRequestPermission, |
133 weak_factory_.GetWeakPtr(), web_contents, id, | 139 weak_factory_.GetWeakPtr(), web_contents, id, |
134 requesting_origin, embedding_origin, user_gesture, callback)); | 140 requesting_origin, embedding_origin, user_gesture, callback)); |
135 } | 141 } |
136 | 142 |
137 void PermissionContextBase::ContinueRequestPermission( | 143 void PermissionContextBase::ContinueRequestPermission( |
138 content::WebContents* web_contents, | 144 content::WebContents* web_contents, |
139 const PermissionRequestID& id, | 145 const PermissionRequestID& id, |
140 const GURL& requesting_origin, | 146 const GURL& requesting_origin, |
141 const GURL& embedding_origin, | 147 const GURL& embedding_origin, |
142 bool user_gesture, | 148 bool user_gesture, |
143 const BrowserPermissionCallback& callback, | 149 const BrowserPermissionCallback& callback, |
144 bool permission_blocked) { | 150 bool permission_blocked) { |
145 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 151 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
146 if (permission_blocked) { | 152 if (permission_blocked) { |
147 web_contents->GetMainFrame()->AddMessageToConsole( | 153 web_contents->GetMainFrame()->AddMessageToConsole( |
148 content::CONSOLE_MESSAGE_LEVEL_INFO, | 154 content::CONSOLE_MESSAGE_LEVEL_INFO, |
149 base::StringPrintf( | 155 base::StringPrintf( |
150 "%s permission has been auto-blocked.", | 156 "%s permission has been auto-blocked.", |
151 PermissionUtil::GetPermissionString(content_settings_type_) | 157 PermissionUtil::GetPermissionString(content_settings_type_) |
152 .c_str())); | 158 .c_str())); |
153 // Permission has been automatically blocked. | 159 // Permission has been automatically blocked. Record that the prompt was |
154 PermissionUmaUtil::RecordPermissionEmbargoStatus( | 160 // suppressed and that we hit the blacklist. |
161 PermissionUmaUtil::RecordEmbargoPromptSuppression( | |
162 PermissionEmbargoStatus::PERMISSIONS_BLACKLISTING); | |
163 PermissionUmaUtil::RecordEmbargoStatus( | |
155 PermissionEmbargoStatus::PERMISSIONS_BLACKLISTING); | 164 PermissionEmbargoStatus::PERMISSIONS_BLACKLISTING); |
156 callback.Run(CONTENT_SETTING_BLOCK); | 165 callback.Run(CONTENT_SETTING_BLOCK); |
157 return; | 166 return; |
158 } | 167 } |
159 | 168 |
169 // We are going to show a prompt now. | |
160 PermissionUmaUtil::PermissionRequested( | 170 PermissionUmaUtil::PermissionRequested( |
161 content_settings_type_, requesting_origin, embedding_origin, profile_); | 171 content_settings_type_, requesting_origin, embedding_origin, profile_); |
172 PermissionUmaUtil::RecordEmbargoPromptSuppression( | |
173 PermissionEmbargoStatus::NOT_EMBARGOED); | |
162 | 174 |
163 DecidePermission(web_contents, id, requesting_origin, embedding_origin, | 175 DecidePermission(web_contents, id, requesting_origin, embedding_origin, |
164 user_gesture, callback); | 176 user_gesture, callback); |
165 } | 177 } |
166 | 178 |
167 PermissionResult PermissionContextBase::GetPermissionStatus( | 179 PermissionResult PermissionContextBase::GetPermissionStatus( |
168 const GURL& requesting_origin, | 180 const GURL& requesting_origin, |
169 const GURL& embedding_origin) const { | 181 const GURL& embedding_origin) const { |
170 // TODO(raymes): Ensure we return appropriate decision reasons in the | |
171 // PermissionResult. We should add these as each is needed. | |
172 | |
173 // If the permission has been disabled through Finch, block all requests. | 182 // If the permission has been disabled through Finch, block all requests. |
174 if (IsPermissionKillSwitchOn()) { | 183 if (IsPermissionKillSwitchOn()) { |
175 return PermissionResult(CONTENT_SETTING_BLOCK, | 184 return PermissionResult(CONTENT_SETTING_BLOCK, |
176 PermissionStatusSource::UNSPECIFIED); | 185 PermissionStatusSource::KILL_SWITCH); |
177 } | 186 } |
178 | 187 |
179 if (IsRestrictedToSecureOrigins() && | 188 if (IsRestrictedToSecureOrigins() && |
180 !content::IsOriginSecure(requesting_origin)) { | 189 !content::IsOriginSecure(requesting_origin)) { |
181 return PermissionResult(CONTENT_SETTING_BLOCK, | 190 return PermissionResult(CONTENT_SETTING_BLOCK, |
182 PermissionStatusSource::UNSPECIFIED); | 191 PermissionStatusSource::UNSPECIFIED); |
183 } | 192 } |
184 | 193 |
185 ContentSetting content_setting = | 194 ContentSetting content_setting = |
186 GetPermissionStatusInternal(requesting_origin, embedding_origin); | 195 GetPermissionStatusInternal(requesting_origin, embedding_origin); |
187 if (content_setting == CONTENT_SETTING_ASK && | 196 if (content_setting == CONTENT_SETTING_ASK) { |
188 PermissionDecisionAutoBlocker::GetForProfile(profile_)->IsUnderEmbargo( | 197 return PermissionDecisionAutoBlocker::GetForProfile(profile_) |
189 content_settings_type_, requesting_origin)) { | 198 ->GetEmbargoResult(content_settings_type_, requesting_origin); |
raymes
2017/02/22 23:13:50
Could we DCHECK that the content setting of the re
dominickn
2017/02/22 23:38:54
Done.
| |
190 return PermissionResult(CONTENT_SETTING_BLOCK, | |
191 PermissionStatusSource::UNSPECIFIED); | |
192 } | 199 } |
193 | 200 |
194 return PermissionResult(content_setting, PermissionStatusSource::UNSPECIFIED); | 201 return PermissionResult(content_setting, PermissionStatusSource::UNSPECIFIED); |
195 } | 202 } |
196 | 203 |
197 void PermissionContextBase::ResetPermission( | 204 void PermissionContextBase::ResetPermission(const GURL& requesting_origin, |
198 const GURL& requesting_origin, | 205 const GURL& embedding_origin) { |
199 const GURL& embedding_origin) { | |
200 HostContentSettingsMapFactory::GetForProfile(profile_) | 206 HostContentSettingsMapFactory::GetForProfile(profile_) |
201 ->SetContentSettingDefaultScope(requesting_origin, embedding_origin, | 207 ->SetContentSettingDefaultScope(requesting_origin, embedding_origin, |
202 content_settings_storage_type(), | 208 content_settings_storage_type(), |
203 std::string(), CONTENT_SETTING_DEFAULT); | 209 std::string(), CONTENT_SETTING_DEFAULT); |
204 } | 210 } |
205 | 211 |
206 void PermissionContextBase::CancelPermissionRequest( | 212 void PermissionContextBase::CancelPermissionRequest( |
207 content::WebContents* web_contents, | 213 content::WebContents* web_contents, |
208 const PermissionRequestID& id) { | 214 const PermissionRequestID& id) { |
209 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 215 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
317 } else { | 323 } else { |
318 PermissionUmaUtil::PermissionDismissed( | 324 PermissionUmaUtil::PermissionDismissed( |
319 content_settings_type_, gesture_type, requesting_origin, profile_); | 325 content_settings_type_, gesture_type, requesting_origin, profile_); |
320 | 326 |
321 if (PermissionDecisionAutoBlocker::GetForProfile(profile_) | 327 if (PermissionDecisionAutoBlocker::GetForProfile(profile_) |
322 ->RecordDismissAndEmbargo(requesting_origin, | 328 ->RecordDismissAndEmbargo(requesting_origin, |
323 content_settings_type_)) { | 329 content_settings_type_)) { |
324 embargo_status = PermissionEmbargoStatus::REPEATED_DISMISSALS; | 330 embargo_status = PermissionEmbargoStatus::REPEATED_DISMISSALS; |
325 } | 331 } |
326 } | 332 } |
327 PermissionUmaUtil::RecordPermissionEmbargoStatus(embargo_status); | 333 PermissionUmaUtil::RecordEmbargoStatus(embargo_status); |
328 } | 334 } |
329 | 335 |
330 NotifyPermissionSet(id, requesting_origin, embedding_origin, callback, | 336 NotifyPermissionSet(id, requesting_origin, embedding_origin, callback, |
331 persist, content_setting); | 337 persist, content_setting); |
332 } | 338 } |
333 | 339 |
334 #if defined(OS_ANDROID) | 340 #if defined(OS_ANDROID) |
335 PermissionQueueController* PermissionContextBase::GetQueueController() { | 341 PermissionQueueController* PermissionContextBase::GetQueueController() { |
336 return permission_queue_controller_.get(); | 342 return permission_queue_controller_.get(); |
337 } | 343 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
383 content_settings_storage_type(), | 389 content_settings_storage_type(), |
384 std::string(), content_setting); | 390 std::string(), content_setting); |
385 } | 391 } |
386 | 392 |
387 ContentSettingsType PermissionContextBase::content_settings_storage_type() | 393 ContentSettingsType PermissionContextBase::content_settings_storage_type() |
388 const { | 394 const { |
389 if (content_settings_type_ == CONTENT_SETTINGS_TYPE_PUSH_MESSAGING) | 395 if (content_settings_type_ == CONTENT_SETTINGS_TYPE_PUSH_MESSAGING) |
390 return CONTENT_SETTINGS_TYPE_NOTIFICATIONS; | 396 return CONTENT_SETTINGS_TYPE_NOTIFICATIONS; |
391 return content_settings_type_; | 397 return content_settings_type_; |
392 } | 398 } |
OLD | NEW |