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

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

Issue 2555913002: Implement origin specific Permissions Blacklisting. (Closed)
Patch Set: Nits Created 4 years 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
9 #include <set>
10 #include <string>
8 #include <utility> 11 #include <utility>
9 12
10 #include "base/callback.h" 13 #include "base/callback.h"
11 #include "base/logging.h" 14 #include "base/logging.h"
12 #include "base/memory/ptr_util.h" 15 #include "base/memory/ptr_util.h"
16 #include "base/memory/weak_ptr.h"
raymes 2016/12/19 00:07:41 nit: this one is included in the header so not req
meredithl 2016/12/20 07:38:26 Done.
13 #include "base/strings/stringprintf.h" 17 #include "base/strings/stringprintf.h"
18 #include "base/timer/timer.h"
14 #include "build/build_config.h" 19 #include "build/build_config.h"
20 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" 21 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
16 #include "chrome/browser/permissions/permission_decision_auto_blocker.h" 22 #include "chrome/browser/permissions/permission_decision_auto_blocker.h"
17 #include "chrome/browser/permissions/permission_request.h" 23 #include "chrome/browser/permissions/permission_request.h"
18 #include "chrome/browser/permissions/permission_request_id.h" 24 #include "chrome/browser/permissions/permission_request_id.h"
19 #include "chrome/browser/permissions/permission_request_impl.h" 25 #include "chrome/browser/permissions/permission_request_impl.h"
20 #include "chrome/browser/permissions/permission_request_manager.h" 26 #include "chrome/browser/permissions/permission_request_manager.h"
21 #include "chrome/browser/permissions/permission_uma_util.h" 27 #include "chrome/browser/permissions/permission_uma_util.h"
22 #include "chrome/browser/permissions/permission_util.h" 28 #include "chrome/browser/permissions/permission_util.h"
23 #include "chrome/browser/profiles/profile.h" 29 #include "chrome/browser/profiles/profile.h"
30 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
31 #include "chrome/common/chrome_features.h"
24 #include "chrome/common/pref_names.h" 32 #include "chrome/common/pref_names.h"
25 #include "components/content_settings/core/browser/host_content_settings_map.h" 33 #include "components/content_settings/core/browser/host_content_settings_map.h"
26 #include "components/content_settings/core/browser/website_settings_registry.h" 34 #include "components/content_settings/core/browser/website_settings_registry.h"
27 #include "components/prefs/pref_service.h" 35 #include "components/prefs/pref_service.h"
36 #include "components/safe_browsing_db/database_manager.h"
28 #include "components/variations/variations_associated_data.h" 37 #include "components/variations/variations_associated_data.h"
29 #include "content/public/browser/browser_thread.h" 38 #include "content/public/browser/browser_thread.h"
30 #include "content/public/browser/render_frame_host.h" 39 #include "content/public/browser/render_frame_host.h"
31 #include "content/public/browser/web_contents.h" 40 #include "content/public/browser/web_contents.h"
41 #include "content/public/browser/web_contents_observer.h"
32 #include "content/public/common/origin_util.h" 42 #include "content/public/common/origin_util.h"
33 #include "url/gurl.h" 43 #include "url/gurl.h"
34 44
35 #if defined(OS_ANDROID) 45 #if defined(OS_ANDROID)
36 #include "chrome/browser/permissions/permission_queue_controller.h" 46 #include "chrome/browser/permissions/permission_queue_controller.h"
37 #endif 47 #endif
38 48
39 // static 49 // static
40 const char PermissionContextBase::kPermissionsKillSwitchFieldStudy[] = 50 const char PermissionContextBase::kPermissionsKillSwitchFieldStudy[] =
41 "PermissionsKillSwitch"; 51 "PermissionsKillSwitch";
42 // static 52 // static
43 const char PermissionContextBase::kPermissionsKillSwitchBlockedValue[] = 53 const char PermissionContextBase::kPermissionsKillSwitchBlockedValue[] =
44 "blocked"; 54 "blocked";
55 // Maximum time in milliseconds to wait for safe browsing service to check a
56 // url for blacklisting. After this amount of time, the check will be aborted
57 // and the url will be treated as not blacklisted.
58 const int kCheckUrlTimeoutMs = 1000;
Nathan Parker 2016/12/15 18:15:12 This might be a bit short. Make sure there's (eve
meredithl 2016/12/16 00:10:39 Acknowledged.
kcarattini 2016/12/19 06:37:45 Just wondering how you arrived at 1000ms? What abo
meredithl 2016/12/20 07:38:26 This was just a value that Dominick decided on, th
59
60 // The client used when checking whether a permission has been blacklisted by
61 // Safe Browsing. The check is done asynchronously as no state can be stored in
62 // PermissionContextBase while it is in flight (since additional permission
63 // requests may be made). Hence, the client is heap allocated and is responsible
64 // for deleting itself when it is finished. Associated with a particular
65 // WebContents, so it can still delete itself when the WebContents is destroyed.
66 // A weak pointer factory is used to generate 'this' pointers for callbacks.
67 class PermissionsBlacklistSBClientImpl
68 : public safe_browsing::SafeBrowsingDatabaseManager::Client,
69 public content::WebContentsObserver {
70 public:
71 static void CheckSafeBrowsingBlacklist(
72 content::PermissionType permission_type,
73 const GURL& request_origin,
74 scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager,
75 content::WebContents* web_contents,
76 base::Callback<void(bool)> callback) {
77 new PermissionsBlacklistSBClientImpl(permission_type, request_origin,
78 db_manager, web_contents, callback);
79 }
80
81 private:
82 PermissionsBlacklistSBClientImpl(
83 content::PermissionType permission_type,
84 const GURL& request_origin,
85 scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager,
86 content::WebContents* web_contents,
87 base::Callback<void(bool)> callback)
88 : content::WebContentsObserver(web_contents),
89 permission_type_(permission_type),
90 callback_(callback),
91 weak_ptr_factory_(this) {
92 content::BrowserThread::PostTask(
93 content::BrowserThread::IO, FROM_HERE,
94 base::Bind(&PermissionsBlacklistSBClientImpl::StartCheck,
95 weak_ptr_factory_.GetWeakPtr(), db_manager, request_origin));
96 }
97
98 ~PermissionsBlacklistSBClientImpl() override {}
99
100 void StartCheck(
101 scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager,
102 const GURL& request_origin) {
103 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
104 // Start the timer to interrupt into the client callback method with an
105 // empty response if Safe Browsing times out.
106 safe_browsing::ThreatMetadata empty_metadata;
107 timer_.Start(
108 FROM_HERE, base::TimeDelta::FromMilliseconds(kCheckUrlTimeoutMs),
109 base::Bind(
110 &PermissionsBlacklistSBClientImpl::OnCheckApiBlacklistUrlResult,
111 weak_ptr_factory_.GetWeakPtr(), request_origin, empty_metadata));
112 db_manager->CheckApiBlacklistUrl(request_origin, this);
113 }
114
115 // SafeBrowsingDatabaseManager::Client implementation.
116 void OnCheckApiBlacklistUrlResult(
117 const GURL& url,
118 const safe_browsing::ThreatMetadata& metadata) override {
119 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
120 weak_ptr_factory_.InvalidateWeakPtrs();
121 bool permission_blocked =
122 metadata.api_permissions.find(PermissionUtil::GetPermissionString(
123 permission_type_)) != metadata.api_permissions.end();
124 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
125 base::Bind(callback_, permission_blocked));
raymes 2016/12/19 00:07:41 I think there might be a few threading issues here
meredithl 2016/12/20 07:38:27 Done. Removed weak pointers and instead using Ref
raymes 2016/12/20 23:58:56 I don't think the last bit is too important. It wo
meredithl 2016/12/29 06:23:35 Ohh I see. So if WebContents goes away, call the C
126 // The result has been received, so the object can now delete itself.
127 delete this;
128 }
129
130 // WebContentsObserver implementation. WebContents should outlive the
131 // permission request, however if it doesn't, this will ensure the object
132 // is still freed properly.
raymes 2016/12/19 00:07:41 Hmm what does it mean that the WebContents should
meredithl 2016/12/20 07:38:27 Just a bad comment I think! Fixed.
133 void WebContentsDestroyed() override { delete this; }
134
135 content::PermissionType permission_type_;
136 base::Callback<void(bool)> callback_;
137 // Timer to abort the Safe Browsing check if it takes too long.
138 base::OneShotTimer timer_;
raymes 2016/12/19 00:07:41 It can be helpful to document which threads differ
meredithl 2016/12/20 07:38:26 Done.
139 // Note: Factory remains last member so it is destroyed and any weak
140 // pointers invalidated before other members are destroyed.
141 base::WeakPtrFactory<PermissionsBlacklistSBClientImpl> weak_ptr_factory_;
142
143 DISALLOW_COPY_AND_ASSIGN(PermissionsBlacklistSBClientImpl);
144 };
45 145
46 PermissionContextBase::PermissionContextBase( 146 PermissionContextBase::PermissionContextBase(
47 Profile* profile, 147 Profile* profile,
48 const content::PermissionType permission_type, 148 const content::PermissionType permission_type,
49 const ContentSettingsType content_settings_type) 149 const ContentSettingsType content_settings_type)
50 : profile_(profile), 150 : profile_(profile),
51 permission_type_(permission_type), 151 permission_type_(permission_type),
52 content_settings_type_(content_settings_type), 152 content_settings_type_(content_settings_type),
53 weak_factory_(this) { 153 weak_factory_(this) {
54 #if defined(OS_ANDROID) 154 #if defined(OS_ANDROID)
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 194
95 DVLOG(1) << "Attempt to use " << type_name 195 DVLOG(1) << "Attempt to use " << type_name
96 << " from an invalid URL: " << requesting_origin << "," 196 << " from an invalid URL: " << requesting_origin << ","
97 << embedding_origin << " (" << type_name 197 << embedding_origin << " (" << type_name
98 << " is not supported in popups)"; 198 << " is not supported in popups)";
99 NotifyPermissionSet(id, requesting_origin, embedding_origin, callback, 199 NotifyPermissionSet(id, requesting_origin, embedding_origin, callback,
100 false /* persist */, CONTENT_SETTING_BLOCK); 200 false /* persist */, CONTENT_SETTING_BLOCK);
101 return; 201 return;
102 } 202 }
103 203
204 scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> database_manager =
205 GetSafeBrowsingDatabaseManager();
206 if (base::FeatureList::IsEnabled(features::kPermissionsBlacklist) &&
207 database_manager) {
208 // The client will contact Safe Browsing, and invoke the callback with the
209 // result. This object will be freed once Safe Browsing has returned the
210 // results or timed out.
raymes 2016/12/19 00:07:41 We're not allocating the object here anymore so we
meredithl 2016/12/20 07:38:26 Yep. I've updated the comment.
211 PermissionsBlacklistSBClientImpl::CheckSafeBrowsingBlacklist(
212 permission_type_, requesting_origin, database_manager, web_contents,
213 base::Bind(&PermissionContextBase::CheckPermissionsBlacklistResult,
214 base::Unretained(this), web_contents, id, requesting_origin,
215 embedding_origin, user_gesture, callback));
216 } else {
217 // TODO(meredithl) : add UMA metrics here.
raymes 2016/12/19 00:07:41 nit: It might be better to remove this TODO (and t
meredithl 2016/12/20 07:38:26 Okay. Should I leave them in for now until a bug g
218 CheckPermissionsBlacklistResult(web_contents, id, requesting_origin,
219 embedding_origin, user_gesture, callback,
220 false);
raymes 2016/12/19 00:07:41 nit: We tend to document bool arguments so that it
meredithl 2016/12/20 07:38:26 Done.
221 }
222 }
223
224 void PermissionContextBase::CheckPermissionsBlacklistResult(
raymes 2016/12/19 00:07:41 very nitty: this does more than just check the per
meredithl 2016/12/20 07:38:27 Done.
225 content::WebContents* web_contents,
226 const PermissionRequestID& id,
227 const GURL& requesting_origin,
228 const GURL& embedding_origin,
229 bool user_gesture,
230 const BrowserPermissionCallback& callback,
231 bool permission_blocked) {
232 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
233 if (permission_blocked) {
234 // TODO(meredithl) : add UMA metrics here.
235 web_contents->GetMainFrame()->AddMessageToConsole(
236 content::CONSOLE_MESSAGE_LEVEL_LOG,
237 base::StringPrintf(
238 "%s permission has been auto-blocked.",
239 PermissionUtil::GetPermissionString(permission_type_).c_str()));
240 // Permission has been blacklisted, block the request.
241 // TODO(meredithl) : consider setting the content setting and persisting
242 // the decision to block.
243 callback.Run(CONTENT_SETTING_BLOCK);
raymes 2016/12/19 00:07:41 I think we might want to call NotifyPermissionSet
kcarattini 2016/12/19 06:37:45 Won't that result in a page action icon being show
meredithl 2016/12/20 07:38:27 For now I'll leave it out for consistency. Is ther
raymes 2016/12/20 23:58:56 I think this case is different to the kill switch
meredithl 2016/12/29 06:23:35 I think that makes sense. The kill switch is like
244 return;
245 }
246
247 // Site is not blacklisted by Safe Browsing for the requested permission.
104 ContentSetting content_setting = 248 ContentSetting content_setting =
105 GetPermissionStatus(requesting_origin, embedding_origin); 249 GetPermissionStatus(requesting_origin, embedding_origin);
106 if (content_setting == CONTENT_SETTING_ALLOW) { 250 if (content_setting == CONTENT_SETTING_ALLOW) {
107 HostContentSettingsMapFactory::GetForProfile(profile_)->UpdateLastUsage( 251 HostContentSettingsMapFactory::GetForProfile(profile_)->UpdateLastUsage(
108 requesting_origin, embedding_origin, content_settings_type_); 252 requesting_origin, embedding_origin, content_settings_type_);
109 } 253 }
254
110 if (content_setting == CONTENT_SETTING_ALLOW || 255 if (content_setting == CONTENT_SETTING_ALLOW ||
111 content_setting == CONTENT_SETTING_BLOCK) { 256 content_setting == CONTENT_SETTING_BLOCK) {
112 NotifyPermissionSet(id, requesting_origin, embedding_origin, callback, 257 NotifyPermissionSet(id, requesting_origin, embedding_origin, callback,
113 false /* persist */, content_setting); 258 false /* persist */, content_setting);
114 return; 259 return;
115 } 260 }
116 261
117 PermissionUmaUtil::PermissionRequested(permission_type_, requesting_origin, 262 PermissionUmaUtil::PermissionRequested(permission_type_, requesting_origin,
118 embedding_origin, profile_); 263 embedding_origin, profile_);
119 264
120 DecidePermission(web_contents, id, requesting_origin, embedding_origin, 265 DecidePermission(web_contents, id, requesting_origin, embedding_origin,
121 user_gesture, callback); 266 user_gesture, callback);
122 } 267 }
123 268
124 ContentSetting PermissionContextBase::GetPermissionStatus( 269 ContentSetting PermissionContextBase::GetPermissionStatus(
125 const GURL& requesting_origin, 270 const GURL& requesting_origin,
126 const GURL& embedding_origin) const { 271 const GURL& embedding_origin) const {
127
128 // If the permission has been disabled through Finch, block all requests. 272 // If the permission has been disabled through Finch, block all requests.
129 if (IsPermissionKillSwitchOn()) 273 if (IsPermissionKillSwitchOn())
130 return CONTENT_SETTING_BLOCK; 274 return CONTENT_SETTING_BLOCK;
131 275
132 if (IsRestrictedToSecureOrigins() && 276 if (IsRestrictedToSecureOrigins() &&
133 !content::IsOriginSecure(requesting_origin)) { 277 !content::IsOriginSecure(requesting_origin)) {
134 return CONTENT_SETTING_BLOCK; 278 return CONTENT_SETTING_BLOCK;
135 } 279 }
136 280
137 return HostContentSettingsMapFactory::GetForProfile(profile_) 281 return HostContentSettingsMapFactory::GetForProfile(profile_)
138 ->GetContentSetting(requesting_origin, embedding_origin, 282 ->GetContentSetting(requesting_origin, embedding_origin,
139 content_settings_type_, std::string()); 283 content_settings_type_, std::string());
140 } 284 }
141 285
142 void PermissionContextBase::ResetPermission( 286 void PermissionContextBase::ResetPermission(const GURL& requesting_origin,
143 const GURL& requesting_origin, 287 const GURL& embedding_origin) {
144 const GURL& embedding_origin) {
145 HostContentSettingsMapFactory::GetForProfile(profile_) 288 HostContentSettingsMapFactory::GetForProfile(profile_)
146 ->SetContentSettingDefaultScope(requesting_origin, embedding_origin, 289 ->SetContentSettingDefaultScope(requesting_origin, embedding_origin,
147 content_settings_type_, std::string(), 290 content_settings_type_, std::string(),
148 CONTENT_SETTING_DEFAULT); 291 CONTENT_SETTING_DEFAULT);
149 } 292 }
150 293
151 void PermissionContextBase::CancelPermissionRequest( 294 void PermissionContextBase::CancelPermissionRequest(
152 content::WebContents* web_contents, 295 content::WebContents* web_contents,
153 const PermissionRequestID& id) { 296 const PermissionRequestID& id) {
154 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 297 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
(...skipping 19 matching lines...) Expand all
174 const PermissionRequestID& id, 317 const PermissionRequestID& id,
175 const GURL& requesting_origin, 318 const GURL& requesting_origin,
176 const GURL& embedding_origin, 319 const GURL& embedding_origin,
177 bool user_gesture, 320 bool user_gesture,
178 const BrowserPermissionCallback& callback) { 321 const BrowserPermissionCallback& callback) {
179 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 322 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
180 323
181 if (PermissionRequestManager::IsEnabled()) { 324 if (PermissionRequestManager::IsEnabled()) {
182 PermissionRequestManager* permission_request_manager = 325 PermissionRequestManager* permission_request_manager =
183 PermissionRequestManager::FromWebContents(web_contents); 326 PermissionRequestManager::FromWebContents(web_contents);
184 // TODO(felt): sometimes |permission_request_manager| is null. This check is 327 // TODO(felt): sometimes |permission_request_manager| is null. This check
185 // meant to prevent crashes. See crbug.com/457091. 328 // is meant to prevent crashes. See crbug.com/457091.
186 if (!permission_request_manager) 329 if (!permission_request_manager)
187 return; 330 return;
188 331
189 std::unique_ptr<PermissionRequest> request_ptr = 332 std::unique_ptr<PermissionRequest> request_ptr =
190 base::MakeUnique<PermissionRequestImpl>( 333 base::MakeUnique<PermissionRequestImpl>(
191 requesting_origin, permission_type_, profile_, user_gesture, 334 requesting_origin, permission_type_, profile_, user_gesture,
192 base::Bind(&PermissionContextBase::PermissionDecided, 335 base::Bind(&PermissionContextBase::PermissionDecided,
193 weak_factory_.GetWeakPtr(), id, requesting_origin, 336 weak_factory_.GetWeakPtr(), id, requesting_origin,
194 embedding_origin, user_gesture, callback), 337 embedding_origin, user_gesture, callback),
195 base::Bind(&PermissionContextBase::CleanUpRequest, 338 base::Bind(&PermissionContextBase::CleanUpRequest,
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 content_setting); 454 content_setting);
312 } 455 }
313 456
314 bool PermissionContextBase::IsPermissionKillSwitchOn() const { 457 bool PermissionContextBase::IsPermissionKillSwitchOn() const {
315 const std::string param = variations::GetVariationParamValue( 458 const std::string param = variations::GetVariationParamValue(
316 kPermissionsKillSwitchFieldStudy, 459 kPermissionsKillSwitchFieldStudy,
317 PermissionUtil::GetPermissionString(permission_type_)); 460 PermissionUtil::GetPermissionString(permission_type_));
318 461
319 return param == kPermissionsKillSwitchBlockedValue; 462 return param == kPermissionsKillSwitchBlockedValue;
320 } 463 }
464
465 scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager>
466 PermissionContextBase::GetSafeBrowsingDatabaseManager() {
467 safe_browsing::SafeBrowsingService* sb_service =
468 g_browser_process->safe_browsing_service();
469 return sb_service ? sb_service->database_manager() : nullptr;
470 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698