summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.cc
blob: a4887da5b3e108d50c492badb0cc36388e743a85 (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
// Copyright 2019 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.

#include "third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.h"

namespace blink {

StaticDataNavigationBodyLoader::StaticDataNavigationBodyLoader() {}

StaticDataNavigationBodyLoader::~StaticDataNavigationBodyLoader() = default;

void StaticDataNavigationBodyLoader::Write(const char* data, size_t size) {
  DCHECK(!received_all_data_);
  if (!data_)
    data_ = SharedBuffer::Create(data, size);
  else
    data_->Append(data, size);
  Continue();
}

void StaticDataNavigationBodyLoader::Write(const SharedBuffer& data) {
  DCHECK(!received_all_data_);
  if (!data_)
    data_ = SharedBuffer::Create();
  data_->Append(data);
  Continue();
}

void StaticDataNavigationBodyLoader::Finish() {
  DCHECK(!received_all_data_);
  received_all_data_ = true;
  Continue();
}

void StaticDataNavigationBodyLoader::SetDefersLoading(
    WebURLLoader::DeferType defers) {
  defers_loading_ = defers;
  Continue();
}

void StaticDataNavigationBodyLoader::StartLoadingBody(
    WebNavigationBodyLoader::Client* client,
    bool use_isolated_code_cache) {
  DCHECK(!is_in_continue_);
  client_ = client;
  Continue();
}

void StaticDataNavigationBodyLoader::Continue() {
  if (defers_loading_ != WebURLLoader::DeferType::kNotDeferred || !client_ ||
      is_in_continue_)
    return;

  // We don't want reentrancy in this method -
  // protect with a boolean. Cannot use AutoReset
  // because |this| can be deleted before reset.
  is_in_continue_ = true;
  base::WeakPtr<StaticDataNavigationBodyLoader> weak_self =
      weak_factory_.GetWeakPtr();

  if (!sent_all_data_) {
    while (data_ && data_->size()) {
      total_encoded_data_length_ += data_->size();

      // Cleanup |data_| before dispatching, so that
      // we can reentrantly append some data again.
      scoped_refptr<SharedBuffer> data = std::move(data_);

      for (const auto& span : *data) {
        client_->BodyDataReceived(span);
        // |this| can be destroyed from BodyDataReceived.
        if (!weak_self)
          return;
      }

      if (defers_loading_ != WebURLLoader::DeferType::kNotDeferred) {
        is_in_continue_ = false;
        return;
      }
    }
    if (received_all_data_)
      sent_all_data_ = true;
  }

  if (sent_all_data_) {
    // Clear |client_| to avoid any extra notifications from reentrancy.
    WebNavigationBodyLoader::Client* client = client_;
    client_ = nullptr;
    client->BodyLoadingFinished(
        base::TimeTicks::Now(), total_encoded_data_length_,
        total_encoded_data_length_, total_encoded_data_length_, false,
        absl::nullopt);
    // |this| can be destroyed from BodyLoadingFinished.
    if (!weak_self)
      return;
  }

  is_in_continue_ = false;
}

}  // namespace blink