1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "third_party/blink/renderer/modules/cache_storage/cache_storage_blob_client_list.h"
6 
7 namespace blink {
8 
9 // Class implementing the BlobReaderClient interface.  This is used to
10 // propagate the completion of an eager body blob read to the
11 // DataPipeBytesConsumer.
12 class CacheStorageBlobClientList::Client
13     : public GarbageCollected<CacheStorageBlobClientList::Client>,
14       public mojom::blink::BlobReaderClient {
15   // We must prevent any mojo messages from coming in after this object
16   // starts getting garbage collected.
17   USING_PRE_FINALIZER(CacheStorageBlobClientList::Client, Dispose);
18 
19  public:
Client(CacheStorageBlobClientList * owner,mojo::PendingReceiver<mojom::blink::BlobReaderClient> client_pending_receiver,DataPipeBytesConsumer::CompletionNotifier * completion_notifier)20   Client(CacheStorageBlobClientList* owner,
21          mojo::PendingReceiver<mojom::blink::BlobReaderClient>
22              client_pending_receiver,
23          DataPipeBytesConsumer::CompletionNotifier* completion_notifier)
24       : owner_(owner),
25         client_receiver_(this, std::move(client_pending_receiver)),
26         completion_notifier_(completion_notifier) {}
27 
OnCalculatedSize(uint64_t total_size,uint64_t expected_content_size)28   void OnCalculatedSize(uint64_t total_size,
29                         uint64_t expected_content_size) override {}
30 
OnComplete(int32_t status,uint64_t data_length)31   void OnComplete(int32_t status, uint64_t data_length) override {
32     client_receiver_.reset();
33 
34     // 0 is net::OK
35     if (status == 0)
36       completion_notifier_->SignalComplete();
37     else
38       completion_notifier_->SignalError(BytesConsumer::Error());
39 
40     if (owner_)
41       owner_->RevokeClient(this);
42   }
43 
Trace(Visitor * visitor)44   void Trace(Visitor* visitor) {
45     visitor->Trace(owner_);
46     visitor->Trace(completion_notifier_);
47   }
48 
49  private:
Dispose()50   void Dispose() {
51     // Use the existence of the client_receiver_ binding to see if this
52     // client has already completed.
53     if (!client_receiver_.is_bound())
54       return;
55 
56     client_receiver_.reset();
57     completion_notifier_->SignalError(BytesConsumer::Error("aborted"));
58 
59     // If we are already being garbage collected its not necessary to
60     // call RevokeClient() on the owner.
61   }
62 
63   WeakMember<CacheStorageBlobClientList> owner_;
64   mojo::Receiver<mojom::blink::BlobReaderClient> client_receiver_;
65   Member<DataPipeBytesConsumer::CompletionNotifier> completion_notifier_;
66 
67   DISALLOW_COPY_AND_ASSIGN(Client);
68 };
69 
AddClient(mojo::PendingReceiver<mojom::blink::BlobReaderClient> client_pending_receiver,DataPipeBytesConsumer::CompletionNotifier * completion_notifier)70 void CacheStorageBlobClientList::AddClient(
71     mojo::PendingReceiver<mojom::blink::BlobReaderClient>
72         client_pending_receiver,
73     DataPipeBytesConsumer::CompletionNotifier* completion_notifier) {
74   clients.emplace_back(MakeGarbageCollected<Client>(
75       this, std::move(client_pending_receiver), completion_notifier));
76 }
77 
Trace(Visitor * visitor)78 void CacheStorageBlobClientList::Trace(Visitor* visitor) {
79   visitor->Trace(clients);
80 }
81 
RevokeClient(Client * client)82 void CacheStorageBlobClientList::RevokeClient(Client* client) {
83   auto index = clients.Find(client);
84   clients.EraseAt(index);
85 }
86 
87 }  // namespace blink
88