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

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

Issue 2555913002: Implement origin specific Permissions Blacklisting. (Closed)
Patch Set: Fix spelling error. Created 3 years, 11 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
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"
13 #include "base/strings/stringprintf.h" 16 #include "base/strings/stringprintf.h"
17 #include "base/timer/timer.h"
14 #include "build/build_config.h" 18 #include "build/build_config.h"
19 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" 20 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
16 #include "chrome/browser/permissions/permission_decision_auto_blocker.h" 21 #include "chrome/browser/permissions/permission_decision_auto_blocker.h"
17 #include "chrome/browser/permissions/permission_request.h" 22 #include "chrome/browser/permissions/permission_request.h"
18 #include "chrome/browser/permissions/permission_request_id.h" 23 #include "chrome/browser/permissions/permission_request_id.h"
19 #include "chrome/browser/permissions/permission_request_impl.h" 24 #include "chrome/browser/permissions/permission_request_impl.h"
20 #include "chrome/browser/permissions/permission_request_manager.h" 25 #include "chrome/browser/permissions/permission_request_manager.h"
21 #include "chrome/browser/permissions/permission_uma_util.h" 26 #include "chrome/browser/permissions/permission_uma_util.h"
22 #include "chrome/browser/permissions/permission_util.h" 27 #include "chrome/browser/permissions/permission_util.h"
23 #include "chrome/browser/profiles/profile.h" 28 #include "chrome/browser/profiles/profile.h"
29 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
30 #include "chrome/common/chrome_features.h"
24 #include "chrome/common/pref_names.h" 31 #include "chrome/common/pref_names.h"
25 #include "components/content_settings/core/browser/host_content_settings_map.h" 32 #include "components/content_settings/core/browser/host_content_settings_map.h"
26 #include "components/content_settings/core/browser/website_settings_registry.h" 33 #include "components/content_settings/core/browser/website_settings_registry.h"
27 #include "components/prefs/pref_service.h" 34 #include "components/prefs/pref_service.h"
35 #include "components/safe_browsing_db/database_manager.h"
28 #include "components/variations/variations_associated_data.h" 36 #include "components/variations/variations_associated_data.h"
29 #include "content/public/browser/browser_thread.h" 37 #include "content/public/browser/browser_thread.h"
30 #include "content/public/browser/render_frame_host.h" 38 #include "content/public/browser/render_frame_host.h"
31 #include "content/public/browser/web_contents.h" 39 #include "content/public/browser/web_contents.h"
40 #include "content/public/browser/web_contents_observer.h"
32 #include "content/public/common/origin_util.h" 41 #include "content/public/common/origin_util.h"
33 #include "url/gurl.h" 42 #include "url/gurl.h"
34 43
35 #if defined(OS_ANDROID) 44 #if defined(OS_ANDROID)
36 #include "chrome/browser/permissions/permission_queue_controller.h" 45 #include "chrome/browser/permissions/permission_queue_controller.h"
37 #endif 46 #endif
38 47
39 // static 48 // static
40 const char PermissionContextBase::kPermissionsKillSwitchFieldStudy[] = 49 const char PermissionContextBase::kPermissionsKillSwitchFieldStudy[] =
41 "PermissionsKillSwitch"; 50 "PermissionsKillSwitch";
42 // static 51 // static
43 const char PermissionContextBase::kPermissionsKillSwitchBlockedValue[] = 52 const char PermissionContextBase::kPermissionsKillSwitchBlockedValue[] =
44 "blocked"; 53 "blocked";
54 // Maximum time in milliseconds to wait for safe browsing service to check a
55 // url for blacklisting. After this amount of time, the check will be aborted
56 // and the url will be treated as not blacklisted.
57 // TODO(meredithl): Revisit this once UMA metrics have data about request time.
58 const int kCheckUrlTimeoutMs = 2000;
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 (since additional permission requests may be made).
63 // This class must be created and destroyed on the UI thread.
64 class PermissionsBlacklistingClient
65 : public safe_browsing::SafeBrowsingDatabaseManager::Client,
66 public base::RefCountedThreadSafe<PermissionsBlacklistingClient>,
67 public content::WebContentsObserver {
68 public:
69 static void CheckSafeBrowsingBlacklist(
70 scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager,
71 content::PermissionType permission_type,
72 const GURL& request_origin,
73 content::WebContents* web_contents,
74 int timeout,
75 base::Callback<void(bool)> callback) {
76 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
77
78 new PermissionsBlacklistingClient(db_manager, permission_type,
79 request_origin, web_contents, timeout,
80 callback);
81 }
82
83 private:
84 friend class base::RefCountedThreadSafe<PermissionsBlacklistingClient>;
85
86 PermissionsBlacklistingClient(
87 scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager,
88 content::PermissionType permission_type,
89 const GURL& request_origin,
90 content::WebContents* web_contents,
91 int timeout,
92 base::Callback<void(bool)> callback)
93 : content::WebContentsObserver(web_contents),
94 db_manager_(db_manager),
95 permission_type_(permission_type),
96 callback_(callback),
97 timeout_(timeout),
98 is_active_(true) /* Web Contents is active upon construction */ {
raymes 2017/01/10 02:57:15 nit: don't use an inline comment here. I think it'
meredithl 2017/01/10 03:40:46 Done.
99 // Balanced by a call to Release() in OnCheckApiBlacklistUrlResult().
100 AddRef();
101 content::BrowserThread::PostTask(
102 content::BrowserThread::IO, FROM_HERE,
103 base::Bind(&PermissionsBlacklistingClient::StartCheck, this,
104 request_origin));
105 }
106
107 ~PermissionsBlacklistingClient() override {}
108
109 void StartCheck(const GURL& request_origin) {
110 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
111
112 // Start the timer to interrupt into the client callback method with an
113 // empty response if Safe Browsing times out.
114 safe_browsing::ThreatMetadata empty_metadata;
115 timer_ = base::MakeUnique<base::OneShotTimer>();
116 timer_->Start(
117 FROM_HERE, base::TimeDelta::FromMilliseconds(timeout_),
118 base::Bind(&PermissionsBlacklistingClient::OnCheckApiBlacklistUrlResult,
119 this, request_origin, empty_metadata));
120 db_manager_->CheckApiBlacklistUrl(request_origin, this);
121 }
122
123 // SafeBrowsingDatabaseManager::Client implementation.
124 void OnCheckApiBlacklistUrlResult(
125 const GURL& url,
126 const safe_browsing::ThreatMetadata& metadata) override {
127 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
128
129 if (timer_->IsRunning())
130 timer_->Stop();
131 else
132 db_manager_->CancelApiCheck(this);
133 timer_.reset(nullptr);
134
135 // TODO(meredithl): Convert the strings returned from Safe Browsing to the
136 // ones used by PermissionUtil for comparison.
137 bool permission_blocked =
138 metadata.api_permissions.find(PermissionUtil::GetPermissionString(
139 permission_type_)) != metadata.api_permissions.end();
140
141 content::BrowserThread::PostTask(
142 content::BrowserThread::UI, FROM_HERE,
143 base::Bind(
144 &PermissionsBlacklistingClient::EvaluateBlacklistResultOnUiThread,
145 this, permission_blocked));
146 }
147
148 void EvaluateBlacklistResultOnUiThread(bool permission_blocked) {
149 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
150
151 if (is_active_)
152 callback_.Run(permission_blocked);
153 Release();
154 }
155
156 // WebContentsObserver implementation. Sets the flag so that when the database
157 // manager returns with a result, it won't attempt to run the callback with a
158 // deleted WebContents.
159 void WebContentsDestroyed() override {
160 is_active_ = false;
161 Observe(nullptr);
162 }
163
164 scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager_;
165 content::PermissionType permission_type_;
166
167 // PermissionContextBase callback to run on the UI thread.
168 base::Callback<void(bool)> callback_;
169
170 // Timer to abort the Safe Browsing check if it takes too long. Created and
171 // used on the IO Thread.
172 std::unique_ptr<base::OneShotTimer> timer_;
173 int timeout_;
174
175 // True if |callback_| should be invoked, if web_contents() is destroyed, this
176 // is set to false.
177 bool is_active_;
178
179 DISALLOW_COPY_AND_ASSIGN(PermissionsBlacklistingClient);
180 };
45 181
46 PermissionContextBase::PermissionContextBase( 182 PermissionContextBase::PermissionContextBase(
47 Profile* profile, 183 Profile* profile,
48 const content::PermissionType permission_type, 184 const content::PermissionType permission_type,
49 const ContentSettingsType content_settings_type) 185 const ContentSettingsType content_settings_type)
50 : profile_(profile), 186 : profile_(profile),
51 permission_type_(permission_type), 187 permission_type_(permission_type),
52 content_settings_type_(content_settings_type), 188 content_settings_type_(content_settings_type),
189 safe_browsing_timeout_(kCheckUrlTimeoutMs),
53 weak_factory_(this) { 190 weak_factory_(this) {
54 #if defined(OS_ANDROID) 191 #if defined(OS_ANDROID)
55 permission_queue_controller_.reset(new PermissionQueueController( 192 permission_queue_controller_.reset(new PermissionQueueController(
56 profile_, permission_type_, content_settings_type_)); 193 profile_, permission_type_, content_settings_type_));
57 #endif 194 #endif
58 PermissionDecisionAutoBlocker::UpdateFromVariations(); 195 PermissionDecisionAutoBlocker::UpdateFromVariations();
59 } 196 }
60 197
61 PermissionContextBase::~PermissionContextBase() { 198 PermissionContextBase::~PermissionContextBase() {
62 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 199 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 231
95 DVLOG(1) << "Attempt to use " << type_name 232 DVLOG(1) << "Attempt to use " << type_name
96 << " from an invalid URL: " << requesting_origin << "," 233 << " from an invalid URL: " << requesting_origin << ","
97 << embedding_origin << " (" << type_name 234 << embedding_origin << " (" << type_name
98 << " is not supported in popups)"; 235 << " is not supported in popups)";
99 NotifyPermissionSet(id, requesting_origin, embedding_origin, callback, 236 NotifyPermissionSet(id, requesting_origin, embedding_origin, callback,
100 false /* persist */, CONTENT_SETTING_BLOCK); 237 false /* persist */, CONTENT_SETTING_BLOCK);
101 return; 238 return;
102 } 239 }
103 240
241 if (base::FeatureList::IsEnabled(features::kPermissionsBlacklist)) {
242 if (!db_manager_) {
243 safe_browsing::SafeBrowsingService* sb_service =
244 g_browser_process->safe_browsing_service();
245 if (sb_service)
246 db_manager_ = sb_service->database_manager();
247 }
248
249 // The client contacts Safe Browsing, and runs the callback with the result.
250 PermissionsBlacklistingClient::CheckSafeBrowsingBlacklist(
251 db_manager_, permission_type_, requesting_origin, web_contents,
252 safe_browsing_timeout_,
253 base::Bind(&PermissionContextBase::ContinueRequestPermission,
254 weak_factory_.GetWeakPtr(), web_contents, id,
255 requesting_origin, embedding_origin, user_gesture,
256 callback));
257 } else {
258 // TODO(meredithl): Add UMA metrics here.
259 ContinueRequestPermission(web_contents, id, requesting_origin,
260 embedding_origin, user_gesture, callback,
261 false /* permission blocked */);
262 }
263 }
264
265 void PermissionContextBase::ContinueRequestPermission(
266 content::WebContents* web_contents,
267 const PermissionRequestID& id,
268 const GURL& requesting_origin,
269 const GURL& embedding_origin,
270 bool user_gesture,
271 const BrowserPermissionCallback& callback,
272 bool permission_blocked) {
273 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
274 if (permission_blocked) {
275 // TODO(meredithl): Add UMA metrics here.
276 web_contents->GetMainFrame()->AddMessageToConsole(
277 content::CONSOLE_MESSAGE_LEVEL_LOG,
278 base::StringPrintf(
279 "%s permission has been auto-blocked.",
280 PermissionUtil::GetPermissionString(permission_type_).c_str()));
281 // Permission has been blacklisted, block the request.
282 // TODO(meredithl): Consider setting the content setting and persisting
283 // the decision to block.
284 callback.Run(CONTENT_SETTING_BLOCK);
285 return;
286 }
287 // Site is not blacklisted by Safe Browsing for the requested permission.
104 ContentSetting content_setting = 288 ContentSetting content_setting =
105 GetPermissionStatus(requesting_origin, embedding_origin); 289 GetPermissionStatus(requesting_origin, embedding_origin);
106 if (content_setting == CONTENT_SETTING_ALLOW) { 290 if (content_setting == CONTENT_SETTING_ALLOW) {
107 HostContentSettingsMapFactory::GetForProfile(profile_)->UpdateLastUsage( 291 HostContentSettingsMapFactory::GetForProfile(profile_)->UpdateLastUsage(
108 requesting_origin, embedding_origin, content_settings_type_); 292 requesting_origin, embedding_origin, content_settings_type_);
109 } 293 }
294
110 if (content_setting == CONTENT_SETTING_ALLOW || 295 if (content_setting == CONTENT_SETTING_ALLOW ||
111 content_setting == CONTENT_SETTING_BLOCK) { 296 content_setting == CONTENT_SETTING_BLOCK) {
112 NotifyPermissionSet(id, requesting_origin, embedding_origin, callback, 297 NotifyPermissionSet(id, requesting_origin, embedding_origin, callback,
113 false /* persist */, content_setting); 298 false /* persist */, content_setting);
114 return; 299 return;
115 } 300 }
116 301
117 PermissionUmaUtil::PermissionRequested(permission_type_, requesting_origin, 302 PermissionUmaUtil::PermissionRequested(permission_type_, requesting_origin,
118 embedding_origin, profile_); 303 embedding_origin, profile_);
119 304
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 DCHECK(content_setting == CONTENT_SETTING_ALLOW || 501 DCHECK(content_setting == CONTENT_SETTING_ALLOW ||
317 content_setting == CONTENT_SETTING_BLOCK); 502 content_setting == CONTENT_SETTING_BLOCK);
318 DCHECK(!requesting_origin.SchemeIsFile()); 503 DCHECK(!requesting_origin.SchemeIsFile());
319 DCHECK(!embedding_origin.SchemeIsFile()); 504 DCHECK(!embedding_origin.SchemeIsFile());
320 505
321 HostContentSettingsMapFactory::GetForProfile(profile_) 506 HostContentSettingsMapFactory::GetForProfile(profile_)
322 ->SetContentSettingDefaultScope(requesting_origin, embedding_origin, 507 ->SetContentSettingDefaultScope(requesting_origin, embedding_origin,
323 content_settings_type_, std::string(), 508 content_settings_type_, std::string(),
324 content_setting); 509 content_setting);
325 } 510 }
511
512 void PermissionContextBase::SetSafeBrowsingDatabaseManagerAndTimeoutForTest(
513 scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager,
514 int timeout) {
515 db_manager_ = db_manager;
516 safe_browsing_timeout_ = timeout;
517 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698