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
|
// 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(https://crbug.com/915966): 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_
|