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

Unified Diff: chrome/browser/permissions/permission_context_base.cc

Issue 2555913002: Implement origin specific Permissions Blacklisting. (Closed)
Patch Set: Fixing indentation. 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/permissions/permission_context_base.cc
diff --git a/chrome/browser/permissions/permission_context_base.cc b/chrome/browser/permissions/permission_context_base.cc
index 5c99fbd3668796176b5a1b073fa2f16d013f9c3b..c056812497d3a652ce17b5559958bdfa1429912c 100644
--- a/chrome/browser/permissions/permission_context_base.cc
+++ b/chrome/browser/permissions/permission_context_base.cc
@@ -5,13 +5,19 @@
#include "chrome/browser/permissions/permission_context_base.h"
#include <stddef.h>
+
+#include <set>
+#include <string>
#include <utility>
#include "base/callback.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/weak_ptr.h"
#include "base/strings/stringprintf.h"
+#include "base/timer/timer.h"
#include "build/build_config.h"
+#include "chrome/browser/browser_process.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/permissions/permission_decision_auto_blocker.h"
#include "chrome/browser/permissions/permission_request.h"
@@ -21,14 +27,18 @@
#include "chrome/browser/permissions/permission_uma_util.h"
#include "chrome/browser/permissions/permission_util.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/safe_browsing/safe_browsing_service.h"
+#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/browser/website_settings_registry.h"
#include "components/prefs/pref_service.h"
+#include "components/safe_browsing_db/database_manager.h"
#include "components/variations/variations_associated_data.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/origin_util.h"
#include "url/gurl.h"
@@ -42,6 +52,94 @@ const char PermissionContextBase::kPermissionsKillSwitchFieldStudy[] =
// static
const char PermissionContextBase::kPermissionsKillSwitchBlockedValue[] =
"blocked";
+// Maximum time in milliseconds to wait for safe browsing service to check a
+// url for blacklisting. After this amount of time, the check will be aborted
+// and the url will be treated as not blacklisted.
+const int kCheckUrlTimeoutMs = 1000;
+
+// The client used when checking whether a permission has been blacklisted by
+// Safe Browsing. The check is done asynchronously as no state can be stored in
+// PermissionContextBase while it is in flight (since additional permission
+// requests may be made). Hence, the client is heap allocated and is responsible
+// for deleting itself when it is finished. Associated with a particular
+// WebContents, so it can still delete itself when the WebContents is destroyed.
+// A weak pointer factory is used to generate 'this' pointers for callbacks.
+class PermissionsBlacklistSBClientImpl
+ : public safe_browsing::SafeBrowsingDatabaseManager::Client,
+ public content::WebContentsObserver {
+ public:
+ static void CheckSafeBrowsingBlacklist(
+ content::PermissionType permission_type,
+ const GURL& request_origin,
+ scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager,
+ content::WebContents* web_contents,
+ base::Callback<void(bool)> callback) {
+ new PermissionsBlacklistSBClientImpl(permission_type, request_origin,
+ db_manager, web_contents, callback);
+ }
+
+ private:
+ PermissionsBlacklistSBClientImpl(
+ content::PermissionType permission_type,
+ const GURL& request_origin,
+ scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager,
+ content::WebContents* web_contents,
+ base::Callback<void(bool)> callback)
+ : content::WebContentsObserver(web_contents),
+ permission_type_(permission_type),
+ callback_(callback),
+ weak_ptr_factory_(this) {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&PermissionsBlacklistSBClientImpl::StartCheck,
+ weak_ptr_factory_.GetWeakPtr(), db_manager, request_origin));
+ }
+
+ ~PermissionsBlacklistSBClientImpl() override {}
+
+ void StartCheck(
+ scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager,
+ const GURL& request_origin) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ // Start the timer to interrupt into the client callback method with an
+ // empty response if Safe Browsing times out.
+ safe_browsing::ThreatMetadata empty_metadata;
+ timer_.Start(
+ FROM_HERE, base::TimeDelta::FromMilliseconds(kCheckUrlTimeoutMs),
+ base::Bind(
+ &PermissionsBlacklistSBClientImpl::OnCheckApiBlacklistUrlResult,
+ weak_ptr_factory_.GetWeakPtr(), request_origin, empty_metadata));
+ db_manager->CheckApiBlacklistUrl(request_origin, this);
+ }
+
+ // SafeBrowsingDatabaseManager::Client implementation.
+ void OnCheckApiBlacklistUrlResult(
+ const GURL& url,
+ const safe_browsing::ThreatMetadata& metadata) override {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ weak_ptr_factory_.InvalidateWeakPtrs();
+ bool permission_blocked =
+ metadata.api_permissions.find(PermissionUtil::GetPermissionString(
+ permission_type_)) != metadata.api_permissions.end();
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+ base::Bind(callback_, permission_blocked));
+ // The result has been received, so the object can now delete itself.
+ delete this;
+ }
+
+ // WebContentsObserver implementation. WebContents should outlive the
+ // permission request, however if it doesn't, this will ensure the object
+ // is still freed properly.
+ void WebContentsDestroyed() override { delete this; }
+
+ content::PermissionType permission_type_;
+ base::Callback<void(bool)> callback_;
+ // Timer to abort the Safe Browsing check if it takes too long.
+ base::OneShotTimer timer_;
+ // Note: Factory remains last member so it is destroyed and any weak
+ // pointers invalidated before other members are destroyed.
+ base::WeakPtrFactory<PermissionsBlacklistSBClientImpl> weak_ptr_factory_;
dominickn 2016/12/15 03:52:45 Nit: DISALLOW_COPY_AND_ASSIGN here.
meredithl 2016/12/15 04:15:34 Done.
+};
PermissionContextBase::PermissionContextBase(
Profile* profile,
@@ -101,12 +199,57 @@ void PermissionContextBase::RequestPermission(
return;
}
+ scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> database_manager =
+ GetSafeBrowsingDatabaseManager();
+ if (base::FeatureList::IsEnabled(features::kPermissionsBlacklist) &&
+ database_manager) {
+ // The client will contact Safe Browsing, and invoke the callback with the
+ // result. This object will be freed once Safe Browsing has returned the
+ // results or timed out.
+ PermissionsBlacklistSBClientImpl::CheckSafeBrowsingBlacklist(
+ permission_type_, requesting_origin, database_manager, web_contents,
+ base::Bind(&PermissionContextBase::CheckPermissionsBlacklistResult,
+ base::Unretained(this), web_contents, id, requesting_origin,
+ embedding_origin, user_gesture, callback));
+ } else {
+ // TODO(meredithl) : add UMA metrics here.
+ CheckPermissionsBlacklistResult(web_contents, id, requesting_origin,
+ embedding_origin, user_gesture, callback,
+ false);
+ }
+}
+
+void PermissionContextBase::CheckPermissionsBlacklistResult(
+ content::WebContents* web_contents,
+ const PermissionRequestID& id,
+ const GURL& requesting_origin,
+ const GURL& embedding_origin,
+ bool user_gesture,
+ const BrowserPermissionCallback& callback,
+ bool permission_blocked) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ if (permission_blocked) {
+ // TODO(meredithl) : add UMA metrics here.
+ web_contents->GetMainFrame()->AddMessageToConsole(
+ content::CONSOLE_MESSAGE_LEVEL_LOG,
+ base::StringPrintf(
+ "%s permission has been auto-blocked.",
+ PermissionUtil::GetPermissionString(permission_type_).c_str()));
+ // Permission has been blacklisted, block the request.
+ // TODO(meredithl) : consider setting the content setting and persisting
+ // the decision to block.
+ callback.Run(CONTENT_SETTING_BLOCK);
+ return;
+ }
+
+ // Site is not blacklisted by Safe Browsing for the requested permission.
ContentSetting content_setting =
GetPermissionStatus(requesting_origin, embedding_origin);
if (content_setting == CONTENT_SETTING_ALLOW) {
HostContentSettingsMapFactory::GetForProfile(profile_)->UpdateLastUsage(
requesting_origin, embedding_origin, content_settings_type_);
}
+
if (content_setting == CONTENT_SETTING_ALLOW ||
content_setting == CONTENT_SETTING_BLOCK) {
NotifyPermissionSet(id, requesting_origin, embedding_origin, callback,
@@ -124,7 +267,6 @@ void PermissionContextBase::RequestPermission(
ContentSetting PermissionContextBase::GetPermissionStatus(
const GURL& requesting_origin,
const GURL& embedding_origin) const {
-
// If the permission has been disabled through Finch, block all requests.
if (IsPermissionKillSwitchOn())
return CONTENT_SETTING_BLOCK;
@@ -139,9 +281,8 @@ ContentSetting PermissionContextBase::GetPermissionStatus(
content_settings_type_, std::string());
}
-void PermissionContextBase::ResetPermission(
- const GURL& requesting_origin,
- const GURL& embedding_origin) {
+void PermissionContextBase::ResetPermission(const GURL& requesting_origin,
+ const GURL& embedding_origin) {
HostContentSettingsMapFactory::GetForProfile(profile_)
->SetContentSettingDefaultScope(requesting_origin, embedding_origin,
content_settings_type_, std::string(),
@@ -181,7 +322,8 @@ void PermissionContextBase::DecidePermission(
if (PermissionRequestManager::IsEnabled()) {
PermissionRequestManager* permission_request_manager =
PermissionRequestManager::FromWebContents(web_contents);
- // TODO(felt): sometimes |permission_request_manager| is null. This check is
+ // TODO(felt): sometimes |permission_request_manager| is null. This check
+ // is
dominickn 2016/12/15 03:52:45 Nit: fix formatting here.
meredithl 2016/12/15 04:15:34 Done.
// meant to prevent crashes. See crbug.com/457091.
if (!permission_request_manager)
return;
@@ -318,3 +460,10 @@ bool PermissionContextBase::IsPermissionKillSwitchOn() const {
return param == kPermissionsKillSwitchBlockedValue;
}
+
+scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager>
+PermissionContextBase::GetSafeBrowsingDatabaseManager() {
+ safe_browsing::SafeBrowsingService* sb_service =
+ g_browser_process->safe_browsing_service();
+ return sb_service ? sb_service->database_manager() : nullptr;
+}
« 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