File: url_index.h

package info (click to toggle)
chromium 139.0.7258.138-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 6,120,676 kB
  • sloc: cpp: 35,100,869; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (352 lines) | stat: -rw-r--r-- 12,608 bytes parent folder | download | duplicates (7)
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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_URL_INDEX_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_URL_INDEX_H_

#include <stddef.h>
#include <stdint.h>

#include <map>
#include <string>
#include <utility>
#include <vector>

#include "base/memory/memory_pressure_listener.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "base/types/pass_key.h"
#include "third_party/blink/renderer/platform/allow_discouraged_type.h"
#include "third_party/blink/renderer/platform/media/multi_buffer.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/kurl_hash.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"

namespace base {
class SingleThreadTaskRunner;
}

namespace blink {

const int64_t kPositionNotSpecified = -1;

class ResourceFetchContext;
class UrlData;
class UrlIndexTest;

// A multibuffer for loading media resources which knows
// how to create MultiBufferDataProviders to load data
// into the cache.
class PLATFORM_EXPORT ResourceMultiBuffer : public MultiBuffer {
 public:
  ResourceMultiBuffer(UrlData* url_data_,
                      int block_shift,
                      scoped_refptr<base::SingleThreadTaskRunner> task_runner);
  ~ResourceMultiBuffer() override;

  // MultiBuffer implementation.
  std::unique_ptr<MultiBuffer::DataProvider> CreateWriter(
      const BlockId& pos,
      bool is_client_audio_element) override;
  bool RangeSupported() const override;
  void OnEmpty() override;

 protected:
  // Do not access from destructor, it is a pointer to the
  // object that contains us.
  raw_ptr<UrlData> url_data_;
  const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
};

class UrlIndex;

// All the data & metadata for a single resource.
// Data is cached using a MultiBuffer instance.
class PLATFORM_EXPORT UrlData : public RefCounted<UrlData> {
 public:
  // Keep in sync with WebMediaPlayer::CorsMode.
  enum CorsMode { CORS_UNSPECIFIED, CORS_ANONYMOUS, CORS_USE_CREDENTIALS };
  enum CacheMode { kNormal, kCacheDisabled };
  using KeyType = std::pair<KURL, CorsMode>;

  // `url_index` is a WeakPtr since while UrlData objects are created by the
  // UrlIndex they are not owned by the UrlIndex until after the network load
  // starts successfully. If the UrlIndex dies before that happens the UrlData
  // is left with a dangling pointer to the index.
  UrlData(base::PassKey<UrlIndex>,
          const KURL& url,
          CorsMode cors_mode,
          base::WeakPtr<UrlIndex> url_index,
          CacheMode cache_lookup_mode,
          scoped_refptr<base::SingleThreadTaskRunner> task_runner);
  UrlData(const UrlData&) = delete;
  UrlData& operator=(const UrlData&) = delete;

  // Accessors
  const KURL& url() const { return url_; }

  // Cross-origin access mode
  CorsMode cors_mode() const { return cors_mode_; }

  bool has_access_control() const { return has_access_control_; }

  bool passed_timing_allow_origin_check() const {
    return passed_timing_allow_origin_check_;
  }

  const std::string& mime_type() const { return mime_type_; }

  // Are HTTP range requests supported?
  bool range_supported() const { return range_supported_; }

  // True if we found a reason why this URL won't be stored in the
  // HTTP disk cache.
  bool cacheable() const { return cacheable_; }

  // True if this UrlData and any it might redirect to should bypass cache
  // lookups, regardless of disk cache or response status.
  CacheMode cache_lookup_mode() const { return cache_lookup_mode_; }

  // Last used time.
  base::Time last_used() const { return last_used_; }

  // Last modified time.
  base::Time last_modified() const { return last_modified_; }

  const std::string& etag() const { return etag_; }

  // Expiration time.
  base::Time valid_until() const { return valid_until_; }

  // The key used by UrlIndex to find this UrlData.
  KeyType key() const;

  // Length of data associated with url or |kPositionNotSpecified|
  int64_t length() const { return length_; }

  // Returns the number of blocks cached for this resource.
  size_t CachedSize();

  // Returns true if this resource is fully cached in memory.
  bool FullyCached();

  // Returns our url_index.
  base::WeakPtr<UrlIndex> url_index() const { return url_index_; }

  // This must be called after the response arrives.
  bool is_cors_cross_origin() const { return is_cors_cross_origin_; }

  // Notifies the url index that this is currently used.
  // The url <-> URLData mapping will be eventually be invalidated if
  // this is not called regularly.
  void Use();

  // Call this before we add some data to the multibuffer().
  // If the multibuffer is empty, the data origin is set from
  // |origin| and returns true. If not, it compares |origin|
  // to the previous origin and returns whether they match or not.
  bool ValidateDataOrigin(const KURL& origin);

  // Setters.
  void set_length(int64_t length);
  void set_cacheable(bool cacheable);
  void set_valid_until(base::Time valid_until);
  void set_range_supported();
  void set_last_modified(base::Time last_modified);
  void set_etag(const std::string& etag);
  void set_is_cors_cross_origin(bool is_cors_cross_origin);
  void set_has_access_control();
  void set_passed_timing_allow_origin_check(bool);
  void set_mime_type(std::string mime_type);

  // A redirect has occurred (or we've found a better UrlData for the same
  // resource).
  void RedirectTo(const scoped_refptr<UrlData>& to);

  // Fail, tell all clients that a failure has occurred.
  void Fail();

  // Callback for receiving notifications when a redirect occurs.
  using RedirectCB = base::OnceCallback<void(const scoped_refptr<UrlData>&)>;

  // Register a callback to be called when a redirect occurs.
  // Callbacks are cleared when a redirect occurs, so clients must call
  // OnRedirect again if they wish to continue receiving callbacks.
  void OnRedirect(RedirectCB cb);

  // Returns true it is valid to keep using this to access cached data.
  // A single media player instance may choose to ignore this for resources
  // that have already been opened.
  bool Valid();

  // Virtual so we can override it for testing.
  virtual ResourceMultiBuffer* multibuffer();

  void AddBytesRead(int64_t b) { bytes_read_from_cache_ += b; }
  int64_t BytesReadFromCache() const { return bytes_read_from_cache_; }

 protected:
  UrlData(const KURL& url,
          CorsMode cors_mode,
          base::WeakPtr<UrlIndex> url_index,
          CacheMode cache_lookup_mode,
          scoped_refptr<base::SingleThreadTaskRunner> task_runner);
  virtual ~UrlData();

 private:
  friend class ResourceMultiBuffer;
  friend class RefCounted<UrlData>;
  friend class UrlIndex;

  void OnEmpty();
  void MergeFrom(const scoped_refptr<UrlData>& other);

  // Url we represent, note that there may be multiple UrlData for
  // the same url.
  const KURL url_;

  // Origin of the data, should only be different from the
  // url_.DeprecatedGetOriginAsURL() when service workers are involved.
  KURL data_origin_;
  bool have_data_origin_;

  // Cross-origin access mode.
  const CorsMode cors_mode_;
  bool has_access_control_;

  // Timing-allow-origin
  bool passed_timing_allow_origin_check_;

  // Mime type category (stashed for UMA / metrics).
  std::string mime_type_;

  const base::WeakPtr<UrlIndex> url_index_;

  // Length of resource this url points to. (in bytes)
  int64_t length_;

  // Number of bytes read from this resource.
  int64_t bytes_read_from_cache_ = 0;

  // Does the server support ranges?
  bool range_supported_;

  // Set to false if we have reason to believe the chrome disk cache
  // will not cache this url.
  bool cacheable_;

  // While `cacheable_` determines whether this UrlData's underlying data should
  // be stored in the cache, `cache_lookup_mode_` determines whether this
  // UrlData should use existing underlying cached data.
  CacheMode cache_lookup_mode_;

  // https://html.spec.whatwg.org/#cors-cross-origin
  bool is_cors_cross_origin_ = false;

  // Last time some media time used this resource.
  // Note that we use base::Time rather than base::TimeTicks because
  // TimeTicks will stop advancing when a machine goes to sleep.
  // base::Time can go backwards, jump hours at a time and be generally
  // unpredictable, but it doesn't stop, which is preferable here.
  // (False negatives are better than false positivies.)
  base::Time last_used_;

  // Expiration time according to http headers.
  base::Time valid_until_;

  // Last modification time according to http headers.
  base::Time last_modified_;

  // Etag from HTTP reply.
  std::string etag_;

  ResourceMultiBuffer multibuffer_;
  std::vector<RedirectCB> redirect_callbacks_
      ALLOW_DISCOURAGED_TYPE("TODO(crbug.com/40760651)");

  THREAD_CHECKER(thread_checker_);
};

// The UrlIndex lets you look up UrlData instances by url.
class PLATFORM_EXPORT UrlIndex {
 public:
  UrlIndex(ResourceFetchContext* fetch_context,
           scoped_refptr<base::SingleThreadTaskRunner> task_runner);
  UrlIndex(ResourceFetchContext* fetch_context,
           int block_shift,
           scoped_refptr<base::SingleThreadTaskRunner> task_runner);
  virtual ~UrlIndex();

  // Look up an UrlData in the index and return it. If none is found,
  // create a new one. Note that newly created UrlData entries are NOT
  // added to the index, instead you must call TryInsert on them after
  // initializing relevant parameters, like whether it support
  // ranges and it's last modified time.
  // Because the returned UrlData has a raw reference to |this|, it must be
  // released before |this| is destroyed.
  scoped_refptr<UrlData> GetByUrl(const KURL& gurl,
                                  UrlData::CorsMode cors_mode,
                                  UrlData::CacheMode cache_mode);

  // Add the given UrlData to the index if possible. If a better UrlData
  // is already present in the index, return it instead. (If not, we just
  // return the given UrlData.) Please make sure to initialize all the data
  // that can be gathered from HTTP headers in |url_data| before calling this.
  // In particular, the following fields are important:
  //   o range_supported: Entries which do not support ranges cannot be
  //     shared and are not added to the index.
  //   o valid_until, last_used: Entries have to be valid to be inserted
  //     into the index, this means that they have to have been recently
  //     used or have an Expires: header that says when they stop being valid.
  //   o last_modified: Expired cache entries can be re-used if last_modified
  //     matches.
  // Because the returned UrlData has a raw reference to |this|, it must be
  // released before |this| is destroyed.
  // TODO(hubbe): Add etag support.
  scoped_refptr<UrlData> TryInsert(const scoped_refptr<UrlData>& url_data);

  ResourceFetchContext* fetch_context() const { return fetch_context_; }
  int block_shift() const { return block_shift_; }

  // Returns true kMaxParallelPreload or more urls are loading at the same time.
  bool HasReachedMaxParallelPreload() const;

  // Protected rather than private for testing.
 protected:
  friend class UrlData;
  friend class ResourceMultiBuffer;
  friend class UrlIndexTest;
  void RemoveUrlData(const scoped_refptr<UrlData>& url_data);

  // Virtual so we can override it in tests.
  virtual scoped_refptr<UrlData> NewUrlData(
      const KURL& url,
      UrlData::CorsMode cors_mode,
      UrlData::CacheMode cache_lookup_mode);

  void OnMemoryPressure(
      base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);

  raw_ptr<ResourceFetchContext> fetch_context_;
  using UrlDataMap = HashMap<UrlData::KeyType, scoped_refptr<UrlData>>;
  UrlDataMap indexed_data_;
  scoped_refptr<MultiBuffer::GlobalLRU> lru_;

  // log2 of block size in multibuffer cache. Defaults to kBlockSizeShift.
  // Currently only changed for testing purposes.
  const int block_shift_;

  base::MemoryPressureListener memory_pressure_listener_;
  const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;

  base::WeakPtrFactory<UrlIndex> weak_factory_{this};
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_URL_INDEX_H_