File: mojo_blob_reader.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; 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,806; 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 (140 lines) | stat: -rw-r--r-- 5,629 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
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef STORAGE_BROWSER_BLOB_MOJO_BLOB_READER_H_
#define STORAGE_BROWSER_BLOB_MOJO_BLOB_READER_H_

#include <memory>
#include <optional>

#include "base/component_export.h"
#include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "mojo/public/cpp/system/simple_watcher.h"
#include "net/base/net_errors.h"
#include "net/http/http_byte_range.h"
#include "storage/browser/blob/blob_reader.h"

namespace network {
class NetToMojoPendingBuffer;
}

namespace storage {
class BlobDataHandle;

// Reads a blob into a data pipe. Owns itself, and owns its delegate. Self
// destructs when reading is complete.
class COMPONENT_EXPORT(STORAGE_BROWSER) MojoBlobReader {
 public:
  // Methods on this delegate are called in the order they are defined here.
  // With the exception of DidRead, each method is called at most once.
  // OnComplete is always called, and is always the last method to be called,
  // every other method could be skipped in case of errors, or if the method is
  // otherwise not applicable.
  class Delegate {
   public:
    enum RequestSideData { REQUEST_SIDE_DATA, DONT_REQUEST_SIDE_DATA };

    virtual ~Delegate() = default;

    // Called when the blob being read has been fully constructed and its size
    // is known. |total_size| is the total size of the blob, while
    // |content_size| is the size of the subset of this blob that matches the
    // range passed to Create.
    // Return |REQUEST_SIDE_DATA| if the blob's side data should be returned,
    // otherwise MojoBlobReader will skip reading side data and immediately
    // start reading the actual blob contents. Side data is used for example by
    // service worker code to store compiled javascript alongside the script
    // source in the cache.
    virtual RequestSideData DidCalculateSize(uint64_t total_size,
                                             uint64_t content_size) = 0;

    // Called if DidCalculateSize returned |REQUEST_SIDE_DATA|, with the side
    // data associated with the blob being read, if any.
    virtual void DidReadSideData(std::optional<mojo_base::BigBuffer> data) {}

    // Called whenever some amount of data is read from the blob and about to be
    // written to the data pipe.
    virtual void DidRead(int num_bytes) {}

    // Called when reading the blob has finished. If an error occurs this could
    // be the only method that gets called, but either way this method is always
    // the last to be called, shortly before the delegate is deleted.
    // |total_written_bytes| indicated the total number of bytes that were read
    // from the blob, and written to the data pipe. When successful this should
    // always be equal to the |content_size| that was passed to
    // DidCalculateSize.
    virtual void OnComplete(net::Error result,
                            uint64_t total_written_bytes) = 0;
  };

  static void Create(const BlobDataHandle* handle,
                     const net::HttpByteRange& range,
                     std::unique_ptr<Delegate> delegate,
                     mojo::ScopedDataPipeProducerHandle response_body_stream);

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

 private:
  MojoBlobReader(const BlobDataHandle* handle,
                 const net::HttpByteRange& range,
                 std::unique_ptr<Delegate> delegate,
                 mojo::ScopedDataPipeProducerHandle response_body_stream);
  ~MojoBlobReader();

  void Start();

  void NotifyCompletedAndDeleteIfNeeded(int result);

  void DidCalculateSize(int result);
  void DidReadSideData(BlobReader::Status status);
  void StartReading();
  void ReadMore();
  void DidRead(bool completed_synchronously, int num_bytes);
  void OnResponseBodyStreamClosed(MojoResult result,
                                  const mojo::HandleSignalsState& state);
  void OnResponseBodyStreamReady(MojoResult result,
                                 const mojo::HandleSignalsState& state);

  const std::unique_ptr<Delegate> delegate_;

  // The range of the blob that should be read. Could be unbounded if the entire
  // blob is being read.
  net::HttpByteRange byte_range_;

  // Underlying BlobReader data is being read from.
  std::unique_ptr<BlobReader> blob_reader_;

  // Mojo data pipe where the data that is being read is written to. Will be
  // null during write operations, at which time |pending_write_| owns the data
  // pipe instead.
  mojo::ScopedDataPipeProducerHandle response_body_stream_;

  // During a write operation this owns the data pipe handle and gives access to
  // the pipe's internal buffer where data should be written.
  scoped_refptr<network::NetToMojoPendingBuffer> pending_write_;

  // Watchers to keep track of the state of the data pipe. One watches for the
  // pipe being writable, while the other watches for the pipe unexpectedly
  // closing.
  mojo::SimpleWatcher writable_handle_watcher_;
  mojo::SimpleWatcher peer_closed_handle_watcher_;

  // Total number of bytes written to the data pipe so far.
  int64_t total_written_bytes_ = 0;

  // Set to true when the delegate's OnComplete has been called. Used to make
  // sure OnComplete isn't called more than once.
  bool notified_completed_ = false;

  SEQUENCE_CHECKER(sequence_checker_);

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

}  // namespace storage

#endif  // STORAGE_BROWSER_BLOB_MOJO_BLOB_READER_H_