summaryrefslogtreecommitdiff
path: root/chromium/components/exo/data_source.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/components/exo/data_source.cc')
-rw-r--r--chromium/components/exo/data_source.cc115
1 files changed, 96 insertions, 19 deletions
diff --git a/chromium/components/exo/data_source.cc b/chromium/components/exo/data_source.cc
index f4390c6234f..e25c6df5fc3 100644
--- a/chromium/components/exo/data_source.cc
+++ b/chromium/components/exo/data_source.cc
@@ -10,6 +10,7 @@
#include "base/bind_helpers.h"
#include "base/files/file_util.h"
#include "base/i18n/character_encoding.h"
+#include "base/i18n/icu_string_conversions.h"
#include "base/posix/eintr_wrapper.h"
#include "base/strings/string_util.h"
#include "base/task/post_task.h"
@@ -18,6 +19,7 @@
#include "components/exo/mime_utils.h"
#include "net/base/mime_util.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
+#include "third_party/icu/source/common/unicode/ucnv.h"
namespace exo {
@@ -30,8 +32,12 @@ constexpr char kTextHTML[] = "text/html";
constexpr char kUtfPrefix[] = "UTF";
constexpr char kEncoding16[] = "16";
constexpr char kEncodingASCII[] = "ASCII";
-constexpr char kEncodingUTF8Legacy[] = "UTF8_STRING";
-constexpr char kEncodingUTF8Charset[] = "UTF-8";
+
+constexpr char kUTF16Unspecified[] = "UTF-16";
+constexpr char kUTF16LittleEndian[] = "UTF-16LE";
+constexpr char kUTF16BigEndian[] = "UTF-16BE";
+constexpr uint8_t kByteOrderMark[] = {0xFE, 0xFF};
+constexpr int kByteOrderMarkSize = sizeof(kByteOrderMark);
constexpr char kImageBitmap[] = "image/bmp";
constexpr char kImagePNG[] = "image/png";
@@ -92,6 +98,38 @@ int GetImageTypeRank(const std::string& mime_type) {
return 2;
}
+base::string16 CodepageToUTF16(const std::vector<uint8_t>& data,
+ const std::string& charset_input) {
+ base::string16 output;
+ base::StringPiece piece(reinterpret_cast<const char*>(data.data()),
+ data.size());
+ const char* charset = charset_input.c_str();
+
+ // Despite claims in the documentation to the contrary, the ICU UTF-16
+ // converter does not automatically detect and interpret the byte order
+ // mark. Therefore, we must do this ourselves.
+ if (!ucnv_compareNames(charset, kUTF16Unspecified) &&
+ data.size() >= kByteOrderMarkSize) {
+ if (static_cast<uint8_t>(piece.data()[0]) == kByteOrderMark[0] &&
+ static_cast<uint8_t>(piece.data()[1]) == kByteOrderMark[1]) {
+ // BOM is in big endian format. Consume the BOM so it doesn't get
+ // interpreted as a character.
+ piece.remove_prefix(2);
+ charset = kUTF16BigEndian;
+ } else if (static_cast<uint8_t>(piece.data()[0]) == kByteOrderMark[1] &&
+ static_cast<uint8_t>(piece.data()[1]) == kByteOrderMark[0]) {
+ // BOM is in little endian format. Consume the BOM so it doesn't get
+ // interpreted as a character.
+ piece.remove_prefix(2);
+ charset = kUTF16LittleEndian;
+ }
+ }
+
+ base::CodepageToUTF16(
+ piece, charset, base::OnStringConversionError::Type::SUBSTITUTE, &output);
+ return output;
+}
+
} // namespace
ScopedDataSource::ScopedDataSource(DataSource* data_source,
@@ -105,9 +143,7 @@ ScopedDataSource::~ScopedDataSource() {
}
DataSource::DataSource(DataSourceDelegate* delegate)
- : delegate_(delegate),
- cancelled_(false),
- read_data_weak_ptr_factory_(this) {}
+ : delegate_(delegate), finished_(false) {}
DataSource::~DataSource() {
delegate_->OnDataSourceDestroying(this);
@@ -129,15 +165,33 @@ void DataSource::Offer(const std::string& mime_type) {
}
void DataSource::SetActions(const base::flat_set<DndAction>& dnd_actions) {
- NOTIMPLEMENTED();
+ dnd_actions_ = dnd_actions;
+}
+
+void DataSource::Target(const base::Optional<std::string>& mime_type) {
+ delegate_->OnTarget(mime_type);
+}
+
+void DataSource::Action(DndAction action) {
+ delegate_->OnAction(action);
+}
+
+void DataSource::DndDropPerformed() {
+ delegate_->OnDndDropPerformed();
}
void DataSource::Cancelled() {
- cancelled_ = true;
+ finished_ = true;
read_data_weak_ptr_factory_.InvalidateWeakPtrs();
delegate_->OnCancelled();
}
+void DataSource::DndFinished() {
+ finished_ = true;
+ read_data_weak_ptr_factory_.InvalidateWeakPtrs();
+ delegate_->OnDndFinished();
+}
+
void DataSource::ReadDataForTesting(const std::string& mime_type,
ReadDataCallback callback) {
ReadData(mime_type, std::move(callback), base::DoNothing());
@@ -147,7 +201,7 @@ void DataSource::ReadData(const std::string& mime_type,
ReadDataCallback callback,
base::OnceClosure failure_callback) {
// This DataSource does not contain the requested MIME type.
- if (!mime_types_.count(mime_type) || cancelled_) {
+ if (mime_type.empty() || !mime_types_.count(mime_type) || finished_) {
std::move(failure_callback).Run();
return;
}
@@ -157,9 +211,9 @@ void DataSource::ReadData(const std::string& mime_type,
PCHECK(base::CreatePipe(&read_fd, &write_fd));
delegate_->OnSend(mime_type, std::move(write_fd));
- base::PostTaskWithTraitsAndReplyWithResult(
+ base::PostTaskAndReplyWithResult(
FROM_HERE,
- {base::MayBlock(), base::TaskPriority::USER_BLOCKING,
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::BindOnce(&ReadDataOnWorkerThread, std::move(read_fd)),
base::BindOnce(&DataSource::OnDataRead,
@@ -174,9 +228,9 @@ void DataSource::OnDataRead(ReadDataCallback callback,
}
void DataSource::GetDataForPreferredMimeTypes(
- ReadDataCallback text_reader,
+ ReadTextDataCallback text_reader,
ReadDataCallback rtf_reader,
- ReadDataCallback html_reader,
+ ReadTextDataCallback html_reader,
ReadDataCallback image_reader,
base::RepeatingClosure failure_callback) {
std::string text_mime, rtf_mime, html_mime, image_mime;
@@ -188,22 +242,27 @@ void DataSource::GetDataForPreferredMimeTypes(
for (auto mime_type : mime_types_) {
if (net::MatchesMimeType(std::string(kTextPlain), mime_type) ||
mime_type == kEncodingUTF8Legacy) {
+ if (text_reader.is_null())
+ continue;
+
std::string charset;
- // We special case UTF8_STRING to provide minimal handling of X11 apps.
- if (mime_type == kEncodingUTF8Legacy)
- charset = kEncodingUTF8Charset;
- else
- charset = GetCharset(mime_type);
+ charset = GetCharset(mime_type);
int new_rank = GetCharsetRank(charset);
if (new_rank < text_rank) {
text_mime = mime_type;
text_rank = new_rank;
}
} else if (net::MatchesMimeType(std::string(kTextRTF), mime_type)) {
+ if (rtf_reader.is_null())
+ continue;
+
// The RTF MIME type will never have a character set because it only uses
// 7-bit bytes and stores character set information internally.
rtf_mime = mime_type;
} else if (net::MatchesMimeType(std::string(kTextHTML), mime_type)) {
+ if (html_reader.is_null())
+ continue;
+
auto charset = GetCharset(mime_type);
int new_rank = GetCharsetRank(charset);
if (new_rank < html_rank) {
@@ -211,6 +270,9 @@ void DataSource::GetDataForPreferredMimeTypes(
html_rank = new_rank;
}
} else if (blink::IsSupportedImageMimeType(mime_type)) {
+ if (image_reader.is_null())
+ continue;
+
int new_rank = GetImageTypeRank(mime_type);
if (new_rank < image_rank) {
image_mime = mime_type;
@@ -219,10 +281,25 @@ void DataSource::GetDataForPreferredMimeTypes(
}
}
- ReadData(text_mime, std::move(text_reader), failure_callback);
+ ReadData(text_mime,
+ base::BindOnce(&DataSource::OnTextRead,
+ read_data_weak_ptr_factory_.GetWeakPtr(),
+ std::move(text_reader)),
+ failure_callback);
ReadData(rtf_mime, std::move(rtf_reader), failure_callback);
- ReadData(html_mime, std::move(html_reader), failure_callback);
+ ReadData(html_mime,
+ base::BindOnce(&DataSource::OnTextRead,
+ read_data_weak_ptr_factory_.GetWeakPtr(),
+ std::move(html_reader)),
+ failure_callback);
ReadData(image_mime, std::move(image_reader), failure_callback);
}
+void DataSource::OnTextRead(ReadTextDataCallback callback,
+ const std::string& mime_type,
+ const std::vector<uint8_t>& data) {
+ base::string16 output = CodepageToUTF16(data, GetCharset(mime_type));
+ std::move(callback).Run(mime_type, std::move(output));
+}
+
} // namespace exo