File: url_loader_post_interceptor.h

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (185 lines) | stat: -rw-r--r-- 6,468 bytes parent folder | download | duplicates (8)
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_UPDATE_CLIENT_NET_URL_LOADER_POST_INTERCEPTOR_H_
#define COMPONENTS_UPDATE_CLIENT_NET_URL_LOADER_POST_INTERCEPTOR_H_

#include <memory>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

#include "base/containers/queue.h"
#include "base/files/file_path.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_status_code.h"
#include "url/gurl.h"

namespace network {
class TestURLLoaderFactory;
}

namespace net {
namespace test_server {
class EmbeddedTestServer;
class HttpResponse;
struct HttpRequest;
}  // namespace test_server
}  // namespace net

namespace update_client {

// Intercepts requests to a file path, counts them, and captures the body of
// the requests. Optionally, for each request, it can return a canned response
// from a given file. The class maintains a queue of expectations, and returns
// one and only one response for each request that matches the expectation.
// Then, the expectation is removed from the queue.
class URLLoaderPostInterceptor {
 public:
  using InterceptedRequest =
      std::tuple<std::string, net::HttpRequestHeaders, GURL>;

  // Called when the load associated with the url request is intercepted
  // by this object:.
  using UrlJobRequestReadyCallback = base::OnceCallback<void()>;

  // Allows a generic string maching interface when setting up expectations.
  class RequestMatcher {
   public:
    virtual bool Match(const std::string& actual) const = 0;
    virtual ~RequestMatcher() = default;
  };

  explicit URLLoaderPostInterceptor(
      network::TestURLLoaderFactory* url_loader_factory);
  URLLoaderPostInterceptor(std::vector<GURL> supported_urls,
                           network::TestURLLoaderFactory* url_loader_factory);
  URLLoaderPostInterceptor(std::vector<GURL> supported_urls,
                           net::test_server::EmbeddedTestServer*);

  URLLoaderPostInterceptor(const URLLoaderPostInterceptor&) = delete;
  URLLoaderPostInterceptor& operator=(const URLLoaderPostInterceptor&) = delete;

  ~URLLoaderPostInterceptor();

  // Sets an expection for the body of the POST request and optionally,
  // provides a canned response identified by a |file_path| to be returned when
  // the expectation is met. If no |file_path| is provided, then an empty
  // response body is served. If |response_code| is provided, then an empty
  // response body with that response code is returned.
  // Returns |true| if the expectation was set.
  bool ExpectRequest(std::unique_ptr<RequestMatcher> request_matcher);

  bool ExpectRequest(std::unique_ptr<RequestMatcher> request_matcher,
                     net::HttpStatusCode response_code);

  bool ExpectRequest(std::unique_ptr<RequestMatcher> request_matcher,
                     const base::FilePath& filepath);

  // Returns how many requests have been intercepted and matched by
  // an expectation. One expectation can only be matched by one request.
  int GetHitCount() const;

  // Returns how many requests in total have been captured by the interceptor.
  int GetCount() const;

  // Returns all requests that have been intercepted, matched or not.
  std::vector<InterceptedRequest> GetRequests() const;

  // Return the body of the n-th request, zero-based.
  std::string GetRequestBody(size_t n) const;

  // Returns the joined bodies of all requests for debugging purposes.
  std::string GetRequestsAsString() const;

  // Resets the state of the interceptor so that new expectations can be set.
  void Reset();

  // Prevents the intercepted request from starting, as a way to simulate
  // the effects of a very slow network. Call this function before the actual
  // network request occurs.
  void Pause();

  // Allows a previously paused request to continue.
  void Resume();

  // Sets a callback to be invoked when the request job associated with
  // an intercepted request is created. This allows the test execution to
  // synchronize with network tasks running on the IO thread and avoid polling
  // using idle run loops. A paused request can be resumed after this callback
  // has been invoked.
  void url_job_request_ready_callback(
      UrlJobRequestReadyCallback url_job_request_ready_callback);

  int GetHitCountForURL(const GURL& url);

 private:
  void InitializeWithInterceptor();
  void InitializeWithRequestHandler();

  std::unique_ptr<net::test_server::HttpResponse> RequestHandler(
      const net::test_server::HttpRequest& request);

  struct ExpectationResponse {
    ExpectationResponse(net::HttpStatusCode code, const std::string& body)
        : response_code(code), response_body(body) {}
    const net::HttpStatusCode response_code;
    const std::string response_body;
  };
  using Expectation =
      std::pair<std::unique_ptr<RequestMatcher>, ExpectationResponse>;

  using PendingExpectation = std::pair<GURL, ExpectationResponse>;

  // Contains the count of the request matching expectations.
  int hit_count_ = 0;

  // Contains the request body and the extra headers of the intercepted
  // requests.
  std::vector<InterceptedRequest> requests_;

  // Contains the expectations which this interceptor tries to match.
  base::queue<Expectation> expectations_;

  base::queue<PendingExpectation> pending_expectations_;

  raw_ptr<network::TestURLLoaderFactory> url_loader_factory_ = nullptr;
  raw_ptr<net::test_server::EmbeddedTestServer> embedded_test_server_ = nullptr;

  bool is_paused_ = false;

  std::vector<GURL> filtered_urls_;

  UrlJobRequestReadyCallback url_job_request_ready_callback_;
};

class PartialMatch : public URLLoaderPostInterceptor::RequestMatcher {
 public:
  explicit PartialMatch(const std::string& expected) : expected_(expected) {}

  PartialMatch(const PartialMatch&) = delete;
  PartialMatch& operator=(const PartialMatch&) = delete;

  bool Match(const std::string& actual) const override;

 private:
  const std::string expected_;
};

class AnyMatch : public URLLoaderPostInterceptor::RequestMatcher {
 public:
  AnyMatch() = default;

  AnyMatch(const AnyMatch&) = delete;
  AnyMatch& operator=(const AnyMatch&) = delete;

  bool Match(const std::string& actual) const override;
};

}  // namespace update_client

#endif  // COMPONENTS_UPDATE_CLIENT_NET_URL_LOADER_POST_INTERCEPTOR_H_