[refactor] More post-NSS WebCrypto cleanups (utility functions).
[chromium-blink-merge.git] / content / browser / devtools / devtools_io_context.cc
blobe3082ddb3cd7d5e2a95f6b2527e36bfa10a31ae7
1 // Copyright 2015 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.
5 #include "content/browser/devtools/devtools_io_context.h"
7 #include "base/files/file.h"
8 #include "base/files/file_util.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_util.h"
11 #include "base/third_party/icu/icu_utf.h"
12 #include "content/public/browser/browser_thread.h"
14 namespace content {
15 namespace devtools {
17 namespace {
18 unsigned s_last_stream_handle = 0;
21 using Stream = DevToolsIOContext::Stream;
23 Stream::Stream()
24 : base::RefCountedDeleteOnMessageLoop<Stream>(
25 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)),
26 handle_(base::IntToString(++s_last_stream_handle)),
27 had_errors_(false),
28 last_read_pos_(0) {}
30 Stream::~Stream() {
31 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
34 bool Stream::InitOnFileThreadIfNeeded() {
35 if (had_errors_)
36 return false;
37 if (file_.IsValid())
38 return true;
39 base::FilePath temp_path;
40 if (!base::CreateTemporaryFile(&temp_path)) {
41 LOG(ERROR) << "Failed to create temporary file";
42 had_errors_ = true;
43 return false;
45 const unsigned flags = base::File::FLAG_OPEN_TRUNCATED |
46 base::File::FLAG_WRITE | base::File::FLAG_READ |
47 base::File::FLAG_DELETE_ON_CLOSE;
48 file_.Initialize(temp_path, flags);
49 if (!file_.IsValid()) {
50 LOG(ERROR) << "Failed to open temporary file: " << temp_path.value()
51 << ", " << base::File::ErrorToString(file_.error_details());
52 had_errors_ = true;
53 DeleteFile(temp_path, false);
54 return false;
56 return true;
59 void Stream::Read(off_t position, size_t max_size, ReadCallback callback) {
60 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
61 base::Bind(&Stream::ReadOnFileThread, this, position, max_size,
62 callback));
65 void Stream::Append(const scoped_refptr<base::RefCountedString>& data) {
66 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
67 base::Bind(&Stream::AppendOnFileThread, this, data));
70 void Stream::ReadOnFileThread(off_t position, size_t max_size,
71 ReadCallback callback) {
72 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
73 Status status = StatusFailure;
74 scoped_refptr<base::RefCountedString> data;
76 if (file_.IsValid()) {
77 std::string buffer;
78 buffer.resize(max_size);
79 if (position < 0)
80 position = last_read_pos_;
81 int size_got = file_.ReadNoBestEffort(position, &*buffer.begin(), max_size);
82 if (size_got < 0) {
83 LOG(ERROR) << "Failed to read temporary file";
84 had_errors_ = true;
85 file_.Close();
86 } else {
87 // Provided client has requested sufficient large block, make their
88 // life easier by not truncating in the middle of a UTF-8 character.
89 if (size_got > 6 && !CBU8_IS_SINGLE(buffer[size_got - 1])) {
90 base::TruncateUTF8ToByteSize(buffer, size_got, &buffer);
91 size_got = buffer.size();
92 } else {
93 buffer.resize(size_got);
95 data = base::RefCountedString::TakeString(&buffer);
96 status = size_got ? StatusSuccess : StatusEOF;
97 last_read_pos_ = position + size_got;
100 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
101 base::Bind(callback, data, status));
104 void Stream::AppendOnFileThread(
105 const scoped_refptr<base::RefCountedString>& data) {
106 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
107 if (!InitOnFileThreadIfNeeded())
108 return;
109 const std::string& buffer = data->data();
110 int size_written = file_.WriteAtCurrentPos(&*buffer.begin(), buffer.size());
111 if (size_written != static_cast<int>(buffer.size())) {
112 LOG(ERROR) << "Failed to write temporary file";
113 had_errors_ = true;
114 file_.Close();
118 DevToolsIOContext::DevToolsIOContext() {}
120 DevToolsIOContext::~DevToolsIOContext() {}
122 scoped_refptr<Stream> DevToolsIOContext::CreateTempFileBackedStream() {
123 scoped_refptr<Stream> result = new Stream();
124 bool inserted =
125 streams_.insert(std::make_pair(result->handle(), result)).second;
126 DCHECK(inserted);
127 return result;
130 scoped_refptr<Stream>
131 DevToolsIOContext::GetByHandle(const std::string& handle) {
132 StreamsMap::const_iterator it = streams_.find(handle);
133 return it == streams_.end() ? scoped_refptr<Stream>() : it->second;
136 bool DevToolsIOContext::Close(const std::string& handle) {
137 return streams_.erase(handle) == 1;
140 void DevToolsIOContext::DiscardAllStreams() {
141 return streams_.clear();
144 } // namespace devtools
145 } // namespace content