summaryrefslogtreecommitdiff
path: root/chromium/components/safe_browsing/ios
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/components/safe_browsing/ios')
-rw-r--r--chromium/components/safe_browsing/ios/browser/BUILD.gn18
-rw-r--r--chromium/components/safe_browsing/ios/browser/safe_browsing_url_allow_list.h131
-rw-r--r--chromium/components/safe_browsing/ios/browser/safe_browsing_url_allow_list.mm159
3 files changed, 308 insertions, 0 deletions
diff --git a/chromium/components/safe_browsing/ios/browser/BUILD.gn b/chromium/components/safe_browsing/ios/browser/BUILD.gn
new file mode 100644
index 00000000000..87ca89f183a
--- /dev/null
+++ b/chromium/components/safe_browsing/ios/browser/BUILD.gn
@@ -0,0 +1,18 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("allow_list") {
+ sources = [
+ "safe_browsing_url_allow_list.h",
+ "safe_browsing_url_allow_list.mm",
+ ]
+
+ deps = [
+ "//components/safe_browsing/core/db:v4_protocol_manager_util",
+ "//ios/web/public",
+ "//url",
+ ]
+
+ configs += [ "//build/config/compiler:enable_arc" ]
+}
diff --git a/chromium/components/safe_browsing/ios/browser/safe_browsing_url_allow_list.h b/chromium/components/safe_browsing/ios/browser/safe_browsing_url_allow_list.h
new file mode 100644
index 00000000000..3253e3bdea6
--- /dev/null
+++ b/chromium/components/safe_browsing/ios/browser/safe_browsing_url_allow_list.h
@@ -0,0 +1,131 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SAFE_BROWSING_IOS_BROWSER_SAFE_BROWSING_URL_ALLOW_LIST_H_
+#define COMPONENTS_SAFE_BROWSING_IOS_BROWSER_SAFE_BROWSING_URL_ALLOW_LIST_H_
+
+#include <map>
+#include <set>
+
+#include "base/observer_list.h"
+#include "base/observer_list_types.h"
+#include "components/safe_browsing/core/db/v4_protocol_manager_util.h"
+#import "ios/web/public/web_state_user_data.h"
+#include "url/gurl.h"
+
+// SafeBrowsingUrlAllowList tracks the whitelist decisions for URLs for a given
+// threat type, as well as decisions that are pending. Decisions are stored for
+// URLs with empty paths, meaning that whitelisted threats are allowed for the
+// entire domain.
+class SafeBrowsingUrlAllowList
+ : public web::WebStateUserData<SafeBrowsingUrlAllowList> {
+ public:
+ // Enum describing the policy for navigations with a particular threat type to
+ // a URL.
+ enum class Policy : short { kDisallowed, kPending, kAllowed };
+
+ // Observer class for the allow list.
+ class Observer : public base::CheckedObserver {
+ public:
+ // Called when the policy for navigations to |url| with |threat_type| is
+ // updated to |policy|.
+ virtual void ThreatPolicyUpdated(SafeBrowsingUrlAllowList* allow_list,
+ const GURL& url,
+ safe_browsing::SBThreatType threat_type,
+ Policy policy) {}
+
+ // Called when the policies for navigations to |url| with the threats in
+ // |threat_types| are updated to |policy|.
+ virtual void ThreatPolicyBatchUpdated(
+ SafeBrowsingUrlAllowList* allow_list,
+ const GURL& url,
+ const std::set<safe_browsing::SBThreatType>& threat_type,
+ Policy policy) {}
+
+ // Called when |allow_list| is about to be destroyed.
+ virtual void SafeBrowsingAllowListDestroyed(
+ SafeBrowsingUrlAllowList* allow_list) {}
+ };
+
+ ~SafeBrowsingUrlAllowList() override;
+
+ // Adds and removes observers.
+ void AddObserver(Observer* observer);
+ void RemoveObserver(Observer* observer);
+
+ // Returns whether unsafe navigations to |url| are allowed. If |threat_types|
+ // is non-null, it is populated with the allowed threat types.
+ bool AreUnsafeNavigationsAllowed(
+ const GURL& url,
+ std::set<safe_browsing::SBThreatType>* threat_types = nullptr) const;
+
+ // Allows future unsafe navigations to |url| that encounter threats with
+ // |threat_type|.
+ void AllowUnsafeNavigations(const GURL& url,
+ safe_browsing::SBThreatType threat_type);
+
+ // Prohibits all previously allowed navigations for |url|.
+ void DisallowUnsafeNavigations(const GURL& url);
+
+ // Returns whether there are pending unsafe navigation decisions for |url|.
+ // If |threat_types| is non-null, it is populated with the pending threat
+ // types.
+ bool IsUnsafeNavigationDecisionPending(
+ const GURL& url,
+ std::set<safe_browsing::SBThreatType>* threat_types = nullptr) const;
+
+ // Records that a navigation to |url| has encountered |threat_type|, but the
+ // user has not yet chosen whether to allow the navigation.
+ void AddPendingUnsafeNavigationDecision(
+ const GURL& url,
+ safe_browsing::SBThreatType threat_type);
+
+ // Removes all pending decisions for |url|.
+ void RemovePendingUnsafeNavigationDecisions(const GURL& url);
+
+ private:
+ explicit SafeBrowsingUrlAllowList(web::WebState* web_state);
+ friend class web::WebStateUserData<SafeBrowsingUrlAllowList>;
+ WEB_STATE_USER_DATA_KEY_DECL();
+
+ // Struct storing the threat types that have been allowed and those for
+ // which the user has not made a decision yet.
+ struct UnsafeNavigationDecisions {
+ UnsafeNavigationDecisions();
+ ~UnsafeNavigationDecisions();
+ std::set<safe_browsing::SBThreatType> allowed_threats;
+ std::set<safe_browsing::SBThreatType> pending_threats;
+ };
+
+ // Returns a reference to the UnsafeNavigationDecisions for |url|. The path
+ // is stripped from the URLs before accessing |decisions_| to allow unafe
+ // navigation decisions to be shared across all URLs for a given domain.
+ UnsafeNavigationDecisions& GetUnsafeNavigationDecisions(const GURL& url);
+ const UnsafeNavigationDecisions& GetUnsafeNavigationDecisions(
+ const GURL& url) const;
+
+ // Setter for the policy for navigations to |url| with |threat_type|.
+ void SetThreatPolicy(const GURL& url,
+ safe_browsing::SBThreatType threat_type,
+ Policy policy);
+
+ // Returns whether the list contains any |policy| decisions for |url|.
+ // Populates |threat_types| with found threats if provided.
+ bool ContainsThreats(
+ const GURL& url,
+ Policy policy,
+ std::set<safe_browsing::SBThreatType>* threat_types) const;
+
+ // Disallows all threats that for |url| that are currently allowed under
+ // |policy|.
+ void RevertPolicy(const GURL& url, Policy policy);
+
+ // The WebState whose allowed navigations are recorded by this list.
+ web::WebState* web_state_ = nullptr;
+ // Map storing the whitelist decisions for each URL.
+ std::map<GURL, UnsafeNavigationDecisions> decisions_;
+ base::ObserverList<Observer, /*check_empty=*/true> observers_;
+};
+
+#endif // COMPONENTS_SAFE_BROWSING_IOS_BROWSER_SAFE_BROWSING_URL_ALLOW_LIST_H_
diff --git a/chromium/components/safe_browsing/ios/browser/safe_browsing_url_allow_list.mm b/chromium/components/safe_browsing/ios/browser/safe_browsing_url_allow_list.mm
new file mode 100644
index 00000000000..763f01145e0
--- /dev/null
+++ b/chromium/components/safe_browsing/ios/browser/safe_browsing_url_allow_list.mm
@@ -0,0 +1,159 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "components/safe_browsing/ios/browser/safe_browsing_url_allow_list.h"
+
+#import "ios/web/public/web_state.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+using safe_browsing::SBThreatType;
+
+WEB_STATE_USER_DATA_KEY_IMPL(SafeBrowsingUrlAllowList)
+
+SafeBrowsingUrlAllowList::SafeBrowsingUrlAllowList(web::WebState* web_state)
+ : web_state_(web_state) {}
+
+SafeBrowsingUrlAllowList::~SafeBrowsingUrlAllowList() {
+ for (auto& observer : observers_) {
+ observer.SafeBrowsingAllowListDestroyed(this);
+ }
+}
+
+void SafeBrowsingUrlAllowList::AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+}
+
+void SafeBrowsingUrlAllowList::RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+bool SafeBrowsingUrlAllowList::AreUnsafeNavigationsAllowed(
+ const GURL& url,
+ std::set<SBThreatType>* threat_types) const {
+ return ContainsThreats(url, Policy::kAllowed, threat_types);
+}
+
+void SafeBrowsingUrlAllowList::AllowUnsafeNavigations(
+ const GURL& url,
+ SBThreatType threat_type) {
+ SetThreatPolicy(url, threat_type, Policy::kAllowed);
+}
+
+void SafeBrowsingUrlAllowList::DisallowUnsafeNavigations(const GURL& url) {
+ RevertPolicy(url, Policy::kAllowed);
+}
+
+bool SafeBrowsingUrlAllowList::IsUnsafeNavigationDecisionPending(
+ const GURL& url,
+ std::set<SBThreatType>* threat_types) const {
+ return ContainsThreats(url, Policy::kPending, threat_types);
+}
+
+void SafeBrowsingUrlAllowList::AddPendingUnsafeNavigationDecision(
+ const GURL& url,
+ SBThreatType threat_type) {
+ SetThreatPolicy(url, threat_type, Policy::kPending);
+}
+
+void SafeBrowsingUrlAllowList::RemovePendingUnsafeNavigationDecisions(
+ const GURL& url) {
+ RevertPolicy(url, Policy::kPending);
+}
+
+#pragma mark - Private
+
+SafeBrowsingUrlAllowList::UnsafeNavigationDecisions&
+SafeBrowsingUrlAllowList::GetUnsafeNavigationDecisions(const GURL& url) {
+ return decisions_[url.GetWithEmptyPath()];
+}
+
+const SafeBrowsingUrlAllowList::UnsafeNavigationDecisions&
+SafeBrowsingUrlAllowList::GetUnsafeNavigationDecisions(const GURL& url) const {
+ static UnsafeNavigationDecisions kEmptyDecisions;
+ const auto& it = decisions_.find(url.GetWithEmptyPath());
+ if (it == decisions_.end())
+ return kEmptyDecisions;
+ return it->second;
+}
+
+void SafeBrowsingUrlAllowList::SetThreatPolicy(
+ const GURL& url,
+ safe_browsing::SBThreatType threat_type,
+ Policy policy) {
+ auto& decisions = GetUnsafeNavigationDecisions(url);
+ if (policy == Policy::kDisallowed) {
+ decisions.allowed_threats.erase(threat_type);
+ decisions.pending_threats.erase(threat_type);
+ }
+ if (policy == Policy::kPending) {
+ decisions.allowed_threats.erase(threat_type);
+ decisions.pending_threats.insert(threat_type);
+ }
+ if (policy == Policy::kAllowed) {
+ decisions.allowed_threats.insert(threat_type);
+ decisions.pending_threats.erase(threat_type);
+ }
+ for (auto& observer : observers_) {
+ observer.ThreatPolicyUpdated(this, url, threat_type, policy);
+ }
+ web_state_->DidChangeVisibleSecurityState();
+}
+
+bool SafeBrowsingUrlAllowList::ContainsThreats(
+ const GURL& url,
+ Policy policy,
+ std::set<SBThreatType>* threat_types) const {
+ const std::set<SBThreatType>* threats_with_policy = nullptr;
+ switch (policy) {
+ case Policy::kAllowed:
+ threats_with_policy = &GetUnsafeNavigationDecisions(url).allowed_threats;
+ break;
+ case Policy::kPending:
+ threats_with_policy = &GetUnsafeNavigationDecisions(url).pending_threats;
+ break;
+ case Policy::kDisallowed:
+ break;
+ }
+ if (threats_with_policy && !threats_with_policy->empty()) {
+ if (threat_types)
+ *threat_types = *threats_with_policy;
+ return true;
+ }
+ return false;
+}
+
+void SafeBrowsingUrlAllowList::RevertPolicy(const GURL& url, Policy policy) {
+ std::set<SBThreatType>* decisions_to_revert = nullptr;
+ switch (policy) {
+ case Policy::kAllowed:
+ decisions_to_revert = &GetUnsafeNavigationDecisions(url).allowed_threats;
+ break;
+ case Policy::kPending:
+ decisions_to_revert = &GetUnsafeNavigationDecisions(url).pending_threats;
+ break;
+ case Policy::kDisallowed:
+ break;
+ }
+ if (!decisions_to_revert)
+ return;
+
+ std::set<SBThreatType> disallowed_threats;
+ disallowed_threats.swap(*decisions_to_revert);
+ for (auto& observer : observers_) {
+ observer.ThreatPolicyBatchUpdated(this, url, disallowed_threats,
+ Policy::kDisallowed);
+ }
+ web_state_->DidChangeVisibleSecurityState();
+}
+
+#pragma mark - SafeBrowsingUrlAllowList::UnsafeNavigationDecisions
+
+SafeBrowsingUrlAllowList::UnsafeNavigationDecisions::
+ UnsafeNavigationDecisions() = default;
+
+SafeBrowsingUrlAllowList::UnsafeNavigationDecisions::
+ ~UnsafeNavigationDecisions() = default;