1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef SERVICES_NETWORK_LEGACY_TLS_CONFIG_DISTRIBUTOR_H_
6 #define SERVICES_NETWORK_LEGACY_TLS_CONFIG_DISTRIBUTOR_H_
7
8 #include <stdint.h>
9
10 #include <algorithm>
11 #include <memory>
12 #include <string>
13
14 #include "base/component_export.h"
15 #include "base/containers/span.h"
16 #include "base/macros.h"
17 #include "base/memory/ref_counted.h"
18 #include "base/memory/weak_ptr.h"
19 #include "base/observer_list.h"
20 #include "base/observer_list_types.h"
21 #include "services/network/public/proto/tls_deprecation_config.pb.h"
22
23 namespace network {
24
25 // A LegacyTLSExperimentConfig is a wrapper for a
26 // chrome_browser_ssl::LegacyTLSExperimentConfig proto, which allows lookups of
27 // whether legacy TLS warnings should be suppressed for a URL.
COMPONENT_EXPORT(NETWORK_SERVICE)28 class COMPONENT_EXPORT(NETWORK_SERVICE) LegacyTLSExperimentConfig
29 : public base::RefCountedThreadSafe<LegacyTLSExperimentConfig> {
30 public:
31 LegacyTLSExperimentConfig();
32 LegacyTLSExperimentConfig(const LegacyTLSExperimentConfig&) = delete;
33 LegacyTLSExperimentConfig& operator=(const LegacyTLSExperimentConfig&) =
34 delete;
35
36 // Parses a binary proto in |data| into a LegacyTLSExperiment config. Returns
37 // nullptr if parsing fails.
38 static scoped_refptr<LegacyTLSExperimentConfig> Parse(
39 const std::string& data);
40
41 // Looks up whether |hostname| is in the experiment config.
42 bool ShouldSuppressLegacyTLSWarning(const std::string& hostname) const;
43
44 private:
45 ~LegacyTLSExperimentConfig();
46
47 friend class base::RefCountedThreadSafe<LegacyTLSExperimentConfig>;
48
49 chrome_browser_ssl::LegacyTLSExperimentConfig proto_;
50 };
51
52 // LegacyTLSConfigDistributor is a helper class to handle fan-out distribution
53 // of new legacy TLS configs. As new encoded configs are received (via
54 // OnNewLegacyTLSConfig), they will be parsed and, if successful, dispatched to
55 // LegacyTLSConfigDistributor::Observers' OnNewLegacyTLSConfig().
COMPONENT_EXPORT(NETWORK_SERVICE)56 class COMPONENT_EXPORT(NETWORK_SERVICE) LegacyTLSConfigDistributor {
57 public:
58 class Observer : public base::CheckedObserver {
59 public:
60 Observer(const Observer&) = delete;
61 Observer& operator=(const Observer&) = delete;
62
63 // Called whenever a new Legacy TLS config has been received.
64 virtual void OnNewLegacyTLSConfig(
65 scoped_refptr<LegacyTLSExperimentConfig> config) = 0;
66
67 protected:
68 Observer() = default;
69 ~Observer() override = default;
70 };
71
72 LegacyTLSConfigDistributor();
73 ~LegacyTLSConfigDistributor();
74 LegacyTLSConfigDistributor(const LegacyTLSConfigDistributor&) = delete;
75 LegacyTLSConfigDistributor& operator=(const LegacyTLSConfigDistributor&) =
76 delete;
77
78 // Adds an observer to be notified when new LegacyTLSConfigs are available.
79 // Note: Newly-added observers are not notified on the current |config()|,
80 // only newly configured LegacyTLSConfigs after the AddObserver call.
81 void AddObserver(Observer* observer);
82 // Removes a previously registered observer.
83 void RemoveObserver(Observer* observer);
84
85 // Returns the currently configured LegacyTLSConfig, or nullptr if one has not
86 // yet been configured.
87 scoped_refptr<LegacyTLSExperimentConfig> config() const { return config_; }
88
89 // Notifies the distributor that a new encoded LegacyTLSConfig, |config|, has
90 // been received. If the LegacyTLSConfig successfully decodes and is newer
91 // than the current LegacyTLSConfig, all observers will be notified.
92 // |callback| will be notified once all observers have been notified.
93 // |callback| is guaranteed to run (e.g., even if this object is deleted prior
94 // to it being run).
95 void OnNewLegacyTLSConfig(base::span<const uint8_t> config,
96 base::OnceClosure callback);
97
98 private:
99 void OnLegacyTLSConfigParsed(scoped_refptr<LegacyTLSExperimentConfig> config);
100
101 base::ObserverList<Observer,
102 /*check_empty=*/true,
103 /*allow_reentrancy=*/false>
104 observers_;
105 scoped_refptr<LegacyTLSExperimentConfig> config_ = nullptr;
106
107 base::WeakPtrFactory<LegacyTLSConfigDistributor> weak_factory_{this};
108 };
109
110 } // namespace network
111
112 #endif // SERVICES_NETWORK_LEGACY_TLS_CONFIG_DISTRIBUTOR_H_