Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(270)

Side by Side Diff: chrome/browser/permissions/permission_context_base.cc

Issue 2701343002: Implement permission embargo suppression metrics. (Closed)
Patch Set: Clean up Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698