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
content / renderer / mhtml_handle_writer.h [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_RENDERER_MHTML_HANDLE_WRITER_H_
#define CONTENT_RENDERER_MHTML_HANDLE_WRITER_H_
#include <memory>
#include <vector>
#include "base/files/file.h"
#include "base/functional/callback.h"
#include "base/time/time.h"
#include "content/common/download/mhtml_file_writer.mojom-forward.h"
#include "mojo/public/cpp/system/data_pipe.h"
namespace base {
class TaskRunner;
}
namespace blink {
class WebThreadSafeData;
}
namespace mojo {
class SimpleWatcher;
}
namespace content {
// TODO(crbug.com/40606905): This class needs unit tests.
// Handle wrapper for MHTML serialization to abstract the handle which data
// is written to. This is instantiated on the heap and is responsible for
// destroying itself after completing its write operation.
// Should only live in blocking sequenced threads.
class MHTMLHandleWriter {
public:
using MHTMLWriteCompleteCallback =
base::OnceCallback<void(mojom::MhtmlSaveStatus)>;
MHTMLHandleWriter(scoped_refptr<base::TaskRunner> main_thread_task_runner,
MHTMLWriteCompleteCallback callback);
MHTMLHandleWriter(const MHTMLHandleWriter&) = delete;
MHTMLHandleWriter& operator=(const MHTMLHandleWriter&) = delete;
virtual ~MHTMLHandleWriter();
void WriteContents(std::vector<blink::WebThreadSafeData> mhtml_contents);
// Finalizes the writing operation, recording the UMA, closing the handle,
// and deleting itself.
void Finish(mojom::MhtmlSaveStatus save_status);
protected:
virtual void WriteContentsImpl(
std::vector<blink::WebThreadSafeData> mhtml_contents) = 0;
virtual void Close() = 0;
private:
scoped_refptr<base::TaskRunner> main_thread_task_runner_;
MHTMLWriteCompleteCallback callback_;
bool is_writing_ = false;
};
// Wraps a base::File target to write MHTML contents to.
// This implementation immediately finishes after writing all MHTML contents
// to the file handle.
class MHTMLFileHandleWriter : public MHTMLHandleWriter {
public:
MHTMLFileHandleWriter(scoped_refptr<base::TaskRunner> main_thread_task_runner,
MHTMLWriteCompleteCallback callback,
base::File file);
MHTMLFileHandleWriter(const MHTMLFileHandleWriter&) = delete;
MHTMLFileHandleWriter& operator=(const MHTMLFileHandleWriter&) = delete;
~MHTMLFileHandleWriter() override;
protected:
// Writes the serialized and encoded MHTML data from WebThreadSafeData
// instances directly to the file handle passed from the Browser.
void WriteContentsImpl(
std::vector<blink::WebThreadSafeData> mhtml_contents) override;
void Close() override;
private:
base::File file_;
};
// Wraps a mojo::ScopedDataPipeProducerHandle target to write MHTML contents to.
// This implementation does not immediately finish and destroy itself due to
// the limited size of the data pipe buffer. We must ensure all data is
// written to the handle before finishing the write operation.
class MHTMLProducerHandleWriter : public MHTMLHandleWriter {
public:
MHTMLProducerHandleWriter(
scoped_refptr<base::TaskRunner> main_thread_task_runner,
MHTMLWriteCompleteCallback callback,
mojo::ScopedDataPipeProducerHandle producer);
MHTMLProducerHandleWriter(const MHTMLProducerHandleWriter&) = delete;
MHTMLProducerHandleWriter& operator=(const MHTMLProducerHandleWriter&) =
delete;
~MHTMLProducerHandleWriter() override;
protected:
// Creates a new SequencedTaskRunner to dispatch |watcher_| invocations on.
void WriteContentsImpl(
std::vector<blink::WebThreadSafeData> mhtml_contents) override;
void Close() override;
private:
void BeginWatchingHandle();
// Writes the serialized and encoded MHTML data from WebThreadSafeData
// instances to producer while possible.
void TryWritingContents(MojoResult result,
const mojo::HandleSignalsState& state);
mojo::ScopedDataPipeProducerHandle producer_;
std::vector<blink::WebThreadSafeData> mhtml_contents_;
std::unique_ptr<mojo::SimpleWatcher> watcher_;
size_t current_block_;
size_t write_position_;
};
} // namespace content
#endif // CONTENT_RENDERER_MHTML_HANDLE_WRITER_H_