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

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

Issue 2701343002: Implement permission embargo suppression metrics. (Closed)
Patch Set: Rebase 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.
114 PermissionUmaUtil::RecordEmbargoPromptSuppressionFromSource(result.source);
121 NotifyPermissionSet(id, requesting_origin, embedding_origin, callback, 115 NotifyPermissionSet(id, requesting_origin, embedding_origin, callback,
122 false /* persist */, result.content_setting); 116 false /* persist */, result.content_setting);
123 return; 117 return;
124 } 118 }
125 119
126 // Asynchronously check whether the origin should be blocked from making this 120 // 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 121 // 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( 122 PermissionDecisionAutoBlocker::GetForProfile(profile_)->UpdateEmbargoedStatus(
131 content_settings_type_, requesting_origin, web_contents, 123 content_settings_type_, requesting_origin, web_contents,
132 base::Bind(&PermissionContextBase::ContinueRequestPermission, 124 base::Bind(&PermissionContextBase::ContinueRequestPermission,
133 weak_factory_.GetWeakPtr(), web_contents, id, 125 weak_factory_.GetWeakPtr(), web_contents, id,
134 requesting_origin, embedding_origin, user_gesture, callback)); 126 requesting_origin, embedding_origin, user_gesture, callback));
135 } 127 }
136 128
137 void PermissionContextBase::ContinueRequestPermission( 129 void PermissionContextBase::ContinueRequestPermission(
138 content::WebContents* web_contents, 130 content::WebContents* web_contents,
139 const PermissionRequestID& id, 131 const PermissionRequestID& id,
140 const GURL& requesting_origin, 132 const GURL& requesting_origin,
141 const GURL& embedding_origin, 133 const GURL& embedding_origin,
142 bool user_gesture, 134 bool user_gesture,
143 const BrowserPermissionCallback& callback, 135 const BrowserPermissionCallback& callback,
144 bool permission_blocked) { 136 bool permission_blocked) {
145 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 137 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
146 if (permission_blocked) { 138 if (permission_blocked) {
147 web_contents->GetMainFrame()->AddMessageToConsole( 139 web_contents->GetMainFrame()->AddMessageToConsole(
148 content::CONSOLE_MESSAGE_LEVEL_INFO, 140 content::CONSOLE_MESSAGE_LEVEL_INFO,
149 base::StringPrintf( 141 base::StringPrintf(
150 "%s permission has been auto-blocked.", 142 "%s permission has been auto-blocked.",
151 PermissionUtil::GetPermissionString(content_settings_type_) 143 PermissionUtil::GetPermissionString(content_settings_type_)
152 .c_str())); 144 .c_str()));
153 // Permission has been automatically blocked. 145 // Permission has been automatically blocked. Record that the prompt was
154 PermissionUmaUtil::RecordPermissionEmbargoStatus( 146 // suppressed and that we hit the blacklist.
147 PermissionUmaUtil::RecordEmbargoPromptSuppression(
148 PermissionEmbargoStatus::PERMISSIONS_BLACKLISTING);
149 PermissionUmaUtil::RecordEmbargoStatus(
155 PermissionEmbargoStatus::PERMISSIONS_BLACKLISTING); 150 PermissionEmbargoStatus::PERMISSIONS_BLACKLISTING);
156 callback.Run(CONTENT_SETTING_BLOCK); 151 callback.Run(CONTENT_SETTING_BLOCK);
157 return; 152 return;
158 } 153 }
159 154
155 // We are going to show a prompt now.
160 PermissionUmaUtil::PermissionRequested( 156 PermissionUmaUtil::PermissionRequested(
161 content_settings_type_, requesting_origin, embedding_origin, profile_); 157 content_settings_type_, requesting_origin, embedding_origin, profile_);
158 PermissionUmaUtil::RecordEmbargoPromptSuppression(
159 PermissionEmbargoStatus::NOT_EMBARGOED);
162 160
163 DecidePermission(web_contents, id, requesting_origin, embedding_origin, 161 DecidePermission(web_contents, id, requesting_origin, embedding_origin,
164 user_gesture, callback); 162 user_gesture, callback);
165 } 163 }
166 164
167 PermissionResult PermissionContextBase::GetPermissionStatus( 165 PermissionResult PermissionContextBase::GetPermissionStatus(
168 const GURL& requesting_origin, 166 const GURL& requesting_origin,
169 const GURL& embedding_origin) const { 167 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. 168 // If the permission has been disabled through Finch, block all requests.
174 if (IsPermissionKillSwitchOn()) { 169 if (IsPermissionKillSwitchOn()) {
175 return PermissionResult(CONTENT_SETTING_BLOCK, 170 return PermissionResult(CONTENT_SETTING_BLOCK,
176 PermissionStatusSource::UNSPECIFIED); 171 PermissionStatusSource::KILL_SWITCH);
177 } 172 }
178 173
179 if (IsRestrictedToSecureOrigins() && 174 if (IsRestrictedToSecureOrigins() &&
180 !content::IsOriginSecure(requesting_origin)) { 175 !content::IsOriginSecure(requesting_origin)) {
181 return PermissionResult(CONTENT_SETTING_BLOCK, 176 return PermissionResult(CONTENT_SETTING_BLOCK,
182 PermissionStatusSource::UNSPECIFIED); 177 PermissionStatusSource::UNSPECIFIED);
183 } 178 }
184 179
185 ContentSetting content_setting = 180 ContentSetting content_setting =
186 GetPermissionStatusInternal(requesting_origin, embedding_origin); 181 GetPermissionStatusInternal(requesting_origin, embedding_origin);
187 if (content_setting == CONTENT_SETTING_ASK && 182 if (content_setting == CONTENT_SETTING_ASK) {
188 PermissionDecisionAutoBlocker::GetForProfile(profile_)->IsUnderEmbargo( 183 PermissionResult result =
189 content_settings_type_, requesting_origin)) { 184 PermissionDecisionAutoBlocker::GetForProfile(profile_)
190 return PermissionResult(CONTENT_SETTING_BLOCK, 185 ->GetEmbargoResult(content_settings_type_, requesting_origin);
191 PermissionStatusSource::UNSPECIFIED); 186 DCHECK(result.content_setting == CONTENT_SETTING_ASK ||
187 result.content_setting == CONTENT_SETTING_BLOCK);
188 return result;
192 } 189 }
193 190
194 return PermissionResult(content_setting, PermissionStatusSource::UNSPECIFIED); 191 return PermissionResult(content_setting, PermissionStatusSource::UNSPECIFIED);
195 } 192 }
196 193
197 void PermissionContextBase::ResetPermission( 194 void PermissionContextBase::ResetPermission(const GURL& requesting_origin,
198 const GURL& requesting_origin, 195 const GURL& embedding_origin) {
199 const GURL& embedding_origin) {
200 HostContentSettingsMapFactory::GetForProfile(profile_) 196 HostContentSettingsMapFactory::GetForProfile(profile_)
201 ->SetContentSettingDefaultScope(requesting_origin, embedding_origin, 197 ->SetContentSettingDefaultScope(requesting_origin, embedding_origin,
202 content_settings_storage_type(), 198 content_settings_storage_type(),
203 std::string(), CONTENT_SETTING_DEFAULT); 199 std::string(), CONTENT_SETTING_DEFAULT);
204 } 200 }
205 201
206 void PermissionContextBase::CancelPermissionRequest( 202 void PermissionContextBase::CancelPermissionRequest(
207 content::WebContents* web_contents, 203 content::WebContents* web_contents,
208 const PermissionRequestID& id) { 204 const PermissionRequestID& id) {
209 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 205 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 } else { 313 } else {
318 PermissionUmaUtil::PermissionDismissed( 314 PermissionUmaUtil::PermissionDismissed(
319 content_settings_type_, gesture_type, requesting_origin, profile_); 315 content_settings_type_, gesture_type, requesting_origin, profile_);
320 316
321 if (PermissionDecisionAutoBlocker::GetForProfile(profile_) 317 if (PermissionDecisionAutoBlocker::GetForProfile(profile_)
322 ->RecordDismissAndEmbargo(requesting_origin, 318 ->RecordDismissAndEmbargo(requesting_origin,
323 content_settings_type_)) { 319 content_settings_type_)) {
324 embargo_status = PermissionEmbargoStatus::REPEATED_DISMISSALS; 320 embargo_status = PermissionEmbargoStatus::REPEATED_DISMISSALS;
325 } 321 }
326 } 322 }
327 PermissionUmaUtil::RecordPermissionEmbargoStatus(embargo_status); 323 PermissionUmaUtil::RecordEmbargoStatus(embargo_status);
328 } 324 }
329 325
330 NotifyPermissionSet(id, requesting_origin, embedding_origin, callback, 326 NotifyPermissionSet(id, requesting_origin, embedding_origin, callback,
331 persist, content_setting); 327 persist, content_setting);
332 } 328 }
333 329
334 #if defined(OS_ANDROID) 330 #if defined(OS_ANDROID)
335 PermissionQueueController* PermissionContextBase::GetQueueController() { 331 PermissionQueueController* PermissionContextBase::GetQueueController() {
336 return permission_queue_controller_.get(); 332 return permission_queue_controller_.get();
337 } 333 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 content_settings_storage_type(), 379 content_settings_storage_type(),
384 std::string(), content_setting); 380 std::string(), content_setting);
385 } 381 }
386 382
387 ContentSettingsType PermissionContextBase::content_settings_storage_type() 383 ContentSettingsType PermissionContextBase::content_settings_storage_type()
388 const { 384 const {
389 if (content_settings_type_ == CONTENT_SETTINGS_TYPE_PUSH_MESSAGING) 385 if (content_settings_type_ == CONTENT_SETTINGS_TYPE_PUSH_MESSAGING)
390 return CONTENT_SETTINGS_TYPE_NOTIFICATIONS; 386 return CONTENT_SETTINGS_TYPE_NOTIFICATIONS;
391 return content_settings_type_; 387 return content_settings_type_;
392 } 388 }
OLDNEW
« no previous file with comments | « chrome/browser/permissions/permission_context_base.h ('k') | chrome/browser/permissions/permission_context_base_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698