summaryrefslogtreecommitdiff
path: root/chromium/components/autofill/core/browser/password_requirements_spec_fetcher_impl.h
blob: 3d22b0e8af9740406f6c8eed8bc1f810e70c71c8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// Copyright 2018 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_AUTOFILL_CORE_BROWSER_PASSWORD_REQUIREMENTS_SPEC_FETCHER_IMPL_H_
#define COMPONENTS_AUTOFILL_CORE_BROWSER_PASSWORD_REQUIREMENTS_SPEC_FETCHER_IMPL_H_

#include <list>
#include <map>
#include <memory>
#include <string>
#include <utility>

#include "base/callback.h"
#include "base/macros.h"
#include "base/timer/timer.h"
#include "components/autofill/core/browser/password_requirements_spec_fetcher.h"
#include "url/gurl.h"

namespace network {
class SharedURLLoaderFactory;
class SimpleURLLoader;
}  // namespace network

namespace autofill {

class PasswordRequirementsSpec;

// A concrete implementation for PasswordRequirementsSpecFetcher that talks
// to the network.
class PasswordRequirementsSpecFetcherImpl
    : public PasswordRequirementsSpecFetcher {
 public:
  // This enum is used in histograms. Do not change or reuse values.
  enum class ResultCode {
    // Fetched spec file, parsed it, but found no entry for the origin.
    kFoundNoSpec = 0,
    // Fetched spec file, parsed it and found an entry.
    kFoundSpec = 1,
    // The origin is an IP address, not HTTP/HTTPS, or not a valid URL.
    kErrorInvalidOrigin = 2,
    // Server responded with an empty document or an error code.
    kErrorFailedToFetch = 3,
    // Server timed out.
    kErrorTimeout = 4,
    // Server responded with a document but it could not be parsed.
    kErrorFailedToParse = 5,
    // No URL loader configured for the PasswordRequirementsSpecFetcher.
    kErrorNoUrlLoader = 6,
    kMaxValue = kErrorNoUrlLoader,
  };

  // See the member variables for explanations of these parameters.
  PasswordRequirementsSpecFetcherImpl(
      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
      int version,
      size_t prefix_length,
      int timeout);
  ~PasswordRequirementsSpecFetcherImpl() override;

  // Implementation for PasswordRequirementsSpecFetcher:
  void Fetch(GURL origin, FetchCallback callback) override;

 private:
  // This structure bundles all data that are associated to a network request
  // for a file with a specific hash prefix.
  struct LookupInFlight {
    LookupInFlight();
    ~LookupInFlight();

    // Callbacks to be called if the network request resolves or is aborted.
    // The GURL represents the origin due to which a spec was fetched.
    // Used a std::list instead of std::vector to grow this cheaply.
    std::list<std::pair<GURL, FetchCallback>> callbacks;

    // Timer to kill pending downloads after |timeout_|.
    base::OneShotTimer download_timer;

    std::unique_ptr<network::SimpleURLLoader> url_loader;

    // Time when the network request is started.
    base::TimeTicks start_of_request;

   private:
    DISALLOW_COPY_AND_ASSIGN(LookupInFlight);
  };

  // These are the two ways how a network request can end. The functions remove
  // the entry corresponding to |hash_prefix| out of |lookups_in_flight_| as
  // their first order of business.
  void OnFetchComplete(const std::string& hash_prefix,
                       std::unique_ptr<std::string> response_body);
  void OnFetchTimeout(const std::string& hash_prefix);

  // Calls all |callbacks| in order. Note that these callbacks are OnceCallback
  // instances. Therefore, entries are reset after this function returns.
  void TriggerCallbackToAll(
      std::list<std::pair<GURL, FetchCallback>>* callbacks,
      ResultCode result,
      const PasswordRequirementsSpec& spec);

  // Calls the |callback| with the specific data and records some metrics.
  void TriggerCallback(FetchCallback callback,
                       ResultCode result,
                       const PasswordRequirementsSpec& spec);

  std::unique_ptr<LookupInFlight> RemoveLookupInFlight(
      const std::string& hash_prefix);

  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;

  // A version counter for requirements specs. If data changes on the server,
  // a new version number is pushed out to prevent that clients continue
  // using old cached data. This allows setting the HTTP caching expiration to
  // infinity.
  int version_;

  // The fetcher determines the URL of the spec file by first hashing the eTLD+1
  // of |origin| and then taking the first |prefix_length_| bits of the hash
  // value as part of the file name. (See the code for details.)
  // |prefix_length_| should always be <= 32 as filenames are limited to the
  // first 4 bytes of the hash prefix.
  size_t prefix_length_;

  // Timeout in milliseconds after which any ongoing fetch operation is
  // canceled.
  int timeout_;

  // Data about network requests in flight.
  // The key is the name of the file being fetched without the common URL prefix
  // (e.g. "0000"). The value contains callbacks that should process the result
  // and a timer to cancel the lookup after some time.
  // The invariant of |lookups_in_flight_| is that entries exist from the
  // time of starting the network request until receiving the response or a
  // timeout.
  std::map<std::string, std::unique_ptr<LookupInFlight>> lookups_in_flight_;

  DISALLOW_COPY_AND_ASSIGN(PasswordRequirementsSpecFetcherImpl);
};

}  // namespace autofill

#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_PASSWORD_REQUIREMENTS_SPEC_FETCHER_IMPL_H_