summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/platform/loader/fetch/bytes_consumer.h
blob: c557ed1495d87bf12ab956a7ff870ada70180f5d (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
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
// Copyright 2016 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_BYTES_CONSUMER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_BYTES_CONSUMER_H_

#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"

namespace blink {

class ExecutionContext;

// BytesConsumer represents the "consumer" side of a data pipe. A user
// can read data from it.
//
// A BytesConsumer is bound to the thread on which it is created.
// BytesConsumer has four states: waiting, readable, closed and errored. Once
// the state becomes closed or errored, it will never change. |readable| means
// that the BytesConsumer is ready to read non-empty bytes synchronously.
class PLATFORM_EXPORT BytesConsumer : public GarbageCollected<BytesConsumer> {
 public:
  enum class Result {
    kOk,
    kShouldWait,
    kDone,
    kError,
  };
  // Readable and Waiting are indistinguishable from BytesConsumer users.
  enum class PublicState {
    kReadableOrWaiting,
    kClosed,
    kErrored,
  };
  enum class BlobSizePolicy {
    // The returned blob must have a valid size (i.e. != kuint64max).
    kDisallowBlobWithInvalidSize,
    // The returned blob can have an invalid size.
    kAllowBlobWithInvalidSize
  };
  class PLATFORM_EXPORT Error {
   public:
    Error() {}
    explicit Error(const String& message) : message_(message) {}
    const String& Message() const { return message_; }
    bool operator==(const Error& e) const { return e.message_ == message_; }

   private:
    String message_;
  };
  // Client gets notification from the associated ByteConsumer.
  class PLATFORM_EXPORT Client : public GarbageCollectedMixin {
   public:
    virtual ~Client() {}

    // This function is called when the state changes (e.g., readable =>
    // errored). This function can be called more than needed, i.e., it can
    // be called even when the state is not actually changed, but it is
    // guaranteed that this function cannot be called after the state
    // becomes closed or errored.
    //
    // This function is not called when the state change is trigerred by
    // public methods called by a user. For example, when a user reads
    // data by |read| and the state changes from waiting to readable, this
    // function will not be called.
    virtual void OnStateChange() = 0;

    // Each implementation should return a string that represents the
    // implementation for debug purpose.
    virtual String DebugName() const = 0;
  };

  virtual ~BytesConsumer() {}

  // Begins a two-phase read. On success, the function stores a buffer
  // that contains the read data of length |*available| into |*buffer|.
  // Returns Ok when readable.
  // Returns ShouldWait when it's waiting.
  // Returns Done when it's closed.
  // Returns Error when errored.
  // When not readable, the caller doesn't have to (and must not) call
  // EndRead, because the read session implicitly ends in that case.
  //
  // |*buffer| will become invalid when this object becomes unreachable,
  // even if EndRead is not called.
  //
  // |*buffer| will be set to null and |*available| will be set to 0 if not
  // readable.
  virtual Result BeginRead(const char** buffer,
                           size_t* available) WARN_UNUSED_RESULT = 0;

  // Ends a two-phase read.
  // This function can modify this BytesConsumer's state.
  // Returns Ok when the consumer stays readable or waiting.
  // Returns Done when it's closed.
  // Returns Error when it's errored.
  virtual Result EndRead(size_t read_size) WARN_UNUSED_RESULT = 0;

  // Drains the data as a BlobDataHandle.
  // When this function returns a non-null value, the returned blob handle
  // contains bytes that would be read through the BeginRead and
  // EndRead functions without calling this function. In such a case, this
  // object becomes closed.
  // When this function returns null value, this function does nothing.
  // When |policy| is DisallowBlobWithInvalidSize, this function doesn't
  // return a non-null blob handle with unspecified size.
  // The type of the returned blob handle may not be meaningful.
  virtual scoped_refptr<BlobDataHandle> DrainAsBlobDataHandle(
      BlobSizePolicy = BlobSizePolicy::kDisallowBlobWithInvalidSize) {
    return nullptr;
  }

  // Drains the data as an EncodedFormData.
  // When this function returns a non-null value, the returned form data
  // contains bytes that would be read through the BeginRead and
  // EndRead functions without calling this function. In such a case, this
  // object becomes closed.
  // When this function returns null value, this function does nothing.
  // This function returns a non-null form data when the handle is made
  // from an EncodedFormData-convertible value.
  virtual scoped_refptr<EncodedFormData> DrainAsFormData() { return nullptr; }

  // Drains the data as a ScopedDataPipeConsumerHandle.
  // When this function returns a valid handle, the returned pipe handle
  // contains bytes that would be read through the BeginRead and
  // EndRead functions without calling this function. The consumer may
  // become closed or remain in the open state depending on if it has
  // received an explicit completion signal.  If the consumer becomes
  // closed OnstateChange() will *not* be called.  Instead manually
  // call GetPublicState() to check if draining closed the consumer.
  //
  // When this function returns an invalid handle, this function does nothing.
  virtual mojo::ScopedDataPipeConsumerHandle DrainAsDataPipe() {
    return mojo::ScopedDataPipeConsumerHandle();
  }

  // Sets a client. This can be called only when no client is set. When
  // this object is already closed or errored, this function does nothing.
  virtual void SetClient(Client*) = 0;
  // Clears the set client.
  // A client will be implicitly cleared when this object gets closed or
  // errored (after the state change itself is notified).
  virtual void ClearClient() = 0;

  // Cancels this ByteConsumer. This function does nothing when |this| is
  // already closed or errored. Otherwise, this object becomes closed.
  // This function cannot be called in a two-phase read.
  virtual void Cancel() = 0;

  // Returns the current state.
  virtual PublicState GetPublicState() const = 0;

  // Returns the associated error of this object. This function can be called
  // only when errored.
  virtual Error GetError() const = 0;

  // Each implementation should return a string that represents the
  // implementation for debug purpose.
  virtual String DebugName() const = 0;

  // Creates two BytesConsumer both of which represent the data sequence that
  // would be read from |src| and store them to |*dest1| and |*dest2|.
  // |src| must not have a client when called.
  static void Tee(ExecutionContext*,
                  BytesConsumer* src,
                  BytesConsumer** dest1,
                  BytesConsumer** dest2);

  // Returns a BytesConsumer whose state is Closed.
  static BytesConsumer* CreateClosed();

  // Returns a BytesConsumer whose state is Errored.
  static BytesConsumer* CreateErrored(const Error&);

  virtual void Trace(blink::Visitor* visitor) {}

 protected:
  // This InternalState directly corresponds to the states in the class
  // comments. This enum is defined here for subclasses.
  enum class InternalState {
    kReadable,
    kWaiting,
    kClosed,
    kErrored,
  };

  static PublicState GetPublicStateFromInternalState(InternalState state) {
    switch (state) {
      case InternalState::kReadable:
      case InternalState::kWaiting:
        return PublicState::kReadableOrWaiting;
      case InternalState::kClosed:
        return PublicState::kClosed;
      case InternalState::kErrored:
        return PublicState::kErrored;
    }
    NOTREACHED();
    return PublicState::kReadableOrWaiting;
  }
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_BYTES_CONSUMER_H_