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. |
| 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 Loading... |
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 Loading... |
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 } |
OLD | NEW |