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_