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

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

Issue 2555913002: Implement origin specific Permissions Blacklisting. (Closed)
Patch Set: Comments 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 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 ffb0e8fb38fdb17272cc9541756ab27ca4150263..8911b967bc0f3e388c2b945333ccdd47fd7280b6 100644
--- a/chrome/browser/permissions/permission_context_base.cc
+++ b/chrome/browser/permissions/permission_context_base.cc
@@ -5,13 +5,18 @@
#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/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 +26,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 +51,133 @@ 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.
+// TODO(meredithl): Revisit this once UMA metrics have data about request time.
+const int kCheckUrlTimeoutMs = 2000;
+
+// 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 (since additional permission requests may be made).
+// This class must be created and destroyed on the UI thread.
+class PermissionsBlacklistingClient
+ : public safe_browsing::SafeBrowsingDatabaseManager::Client,
+ public base::RefCountedThreadSafe<PermissionsBlacklistingClient>,
+ public content::WebContentsObserver {
+ public:
+ static void CheckSafeBrowsingBlacklist(
+ scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager,
+ content::PermissionType permission_type,
+ const GURL& request_origin,
+ content::WebContents* web_contents,
+ int timeout,
+ base::Callback<void(bool)> callback) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ new PermissionsBlacklistingClient(db_manager, permission_type,
+ request_origin, web_contents, timeout,
+ callback);
+ }
+
+ private:
+ friend class base::RefCountedThreadSafe<PermissionsBlacklistingClient>;
+
+ PermissionsBlacklistingClient(
+ scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager,
+ content::PermissionType permission_type,
+ const GURL& request_origin,
+ content::WebContents* web_contents,
+ int timeout,
+ base::Callback<void(bool)> callback)
+ : content::WebContentsObserver(web_contents),
+ db_manager_(db_manager),
+ permission_type_(permission_type),
+ callback_(callback),
+ timeout_(timeout),
+ is_active_(true) {
+ // Balanced by a call to Release() in OnCheckApiBlacklistUrlResult().
+ AddRef();
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&PermissionsBlacklistingClient::StartCheck, this,
+ request_origin));
+ }
+
+ ~PermissionsBlacklistingClient() override {}
+
+ void StartCheck(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_ = base::MakeUnique<base::OneShotTimer>();
+ timer_->Start(
+ FROM_HERE, base::TimeDelta::FromMilliseconds(timeout_),
+ base::Bind(&PermissionsBlacklistingClient::OnCheckApiBlacklistUrlResult,
+ this, 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);
+
+ if (timer_->IsRunning())
+ timer_->Stop();
+ else
+ db_manager_->CancelApiCheck(this);
+ timer_.reset(nullptr);
+
+ // TODO(meredithl): Convert the strings returned from Safe Browsing to the
+ // ones used by PermissionUtil for comparison.
+ 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(
+ &PermissionsBlacklistingClient::EvaluateBlacklistResultOnUiThread,
+ this, permission_blocked));
+ }
+
+ void EvaluateBlacklistResultOnUiThread(bool permission_blocked) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ if (is_active_)
+ callback_.Run(permission_blocked);
+ Release();
+ }
+
+ // WebContentsObserver implementation. Sets the flag so that when the database
+ // manager returns with a result, it won't attempt to run the callback with a
+ // deleted WebContents.
+ void WebContentsDestroyed() override {
+ is_active_ = false;
+ Observe(nullptr);
+ }
+
+ scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager_;
+ content::PermissionType permission_type_;
+
+ // PermissionContextBase callback to run on the UI thread.
+ base::Callback<void(bool)> callback_;
+
+ // Timer to abort the Safe Browsing check if it takes too long. Created and
+ // used on the IO Thread.
+ std::unique_ptr<base::OneShotTimer> timer_;
+ int timeout_;
+
+ // True if |callback_| should be invoked, if web_contents() is destroyed, this
+ // is set to false.
+ bool is_active_;
+
+ DISALLOW_COPY_AND_ASSIGN(PermissionsBlacklistingClient);
+};
PermissionContextBase::PermissionContextBase(
Profile* profile,
@@ -50,6 +186,7 @@ PermissionContextBase::PermissionContextBase(
: profile_(profile),
permission_type_(permission_type),
content_settings_type_(content_settings_type),
+ safe_browsing_timeout_(kCheckUrlTimeoutMs),
weak_factory_(this) {
#if defined(OS_ANDROID)
permission_queue_controller_.reset(new PermissionQueueController(
@@ -101,12 +238,60 @@ void PermissionContextBase::RequestPermission(
return;
}
+ if (base::FeatureList::IsEnabled(features::kPermissionsBlacklist)) {
+ if (!db_manager_) {
+ safe_browsing::SafeBrowsingService* sb_service =
+ g_browser_process->safe_browsing_service();
+ if (sb_service)
+ db_manager_ = sb_service->database_manager();
+ }
+
+ // The client contacts Safe Browsing, and runs the callback with the result.
+ PermissionsBlacklistingClient::CheckSafeBrowsingBlacklist(
+ db_manager_, permission_type_, requesting_origin, web_contents,
+ safe_browsing_timeout_,
+ base::Bind(&PermissionContextBase::ContinueRequestPermission,
+ weak_factory_.GetWeakPtr(), web_contents, id,
+ requesting_origin, embedding_origin, user_gesture,
+ callback));
+ } else {
+ // TODO(meredithl): Add UMA metrics here.
+ ContinueRequestPermission(web_contents, id, requesting_origin,
+ embedding_origin, user_gesture, callback,
+ false /* permission blocked */);
+ }
+}
+
+void PermissionContextBase::ContinueRequestPermission(
+ 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,
@@ -325,3 +510,10 @@ void PermissionContextBase::UpdateContentSetting(
content_settings_type_, std::string(),
content_setting);
}
+
+void PermissionContextBase::SetSafeBrowsingDatabaseManagerAndTimeoutForTest(
+ scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager,
+ int timeout) {
+ db_manager_ = db_manager;
+ safe_browsing_timeout_ = timeout;
+}
« 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