Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/views/mus/os_exchange_data_provider_mus.h" | 5 #include "ui/views/mus/os_exchange_data_provider_mus.h" |
| 6 | 6 |
| 7 #include "base/stl_util.h" | |
| 8 #include "base/strings/string_split.h" | |
| 9 #include "base/strings/utf_string_conversions.h" | |
| 10 #include "mojo/common/common_type_converters.h" | |
| 11 #include "net/base/filename_util.h" | |
| 12 #include "services/ui/public/interfaces/clipboard.mojom.h" | |
| 13 #include "ui/base/dragdrop/file_info.h" | |
| 14 #include "url/gurl.h" | |
| 15 | |
| 7 namespace views { | 16 namespace views { |
| 8 | 17 |
| 18 namespace { | |
| 19 | |
| 20 std::vector<uint8_t> FromString(const std::string& str) { | |
| 21 return std::vector<uint8_t>(str.begin(), str.end()); | |
| 22 } | |
| 23 | |
| 24 std::string ToString(const std::vector<uint8_t>& v) { | |
| 25 return std::string(v.begin(), v.end()); | |
| 26 } | |
| 27 | |
| 28 base::string16 ToString16(const std::vector<uint8_t>& v) { | |
| 29 return base::string16( | |
|
sky
2016/08/15 20:31:26
This seems rather risky. Wouldn't it be better to
Elliot Glaysher
2016/08/15 21:53:13
As mentioned in person, we do this in the linux po
| |
| 30 reinterpret_cast<const base::char16*>(v.data()), | |
| 31 v.size() / 2); | |
| 32 } | |
| 33 | |
| 34 std::vector<base::StringPiece> ParseURIList(const std::vector<uint8_t>& data) { | |
| 35 return base::SplitStringPiece( | |
| 36 base::StringPiece( | |
| 37 reinterpret_cast<const char*>(&data.front()), data.size()), | |
| 38 "\n", | |
| 39 base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); | |
| 40 } | |
| 41 | |
| 42 void AddString16ToVector(const base::string16& str, | |
| 43 std::vector<uint8_t>* bytes) { | |
| 44 const unsigned char* front = | |
| 45 reinterpret_cast<const uint8_t*>(str.data()); | |
| 46 bytes->insert(bytes->end(), front, front + (str.size() * 2)); | |
| 47 } | |
| 48 | |
| 49 } // namespace | |
| 50 | |
| 9 OSExchangeDataProviderMus::OSExchangeDataProviderMus() {} | 51 OSExchangeDataProviderMus::OSExchangeDataProviderMus() {} |
| 10 | 52 |
| 11 OSExchangeDataProviderMus::~OSExchangeDataProviderMus() {} | 53 OSExchangeDataProviderMus::~OSExchangeDataProviderMus() {} |
| 12 | 54 |
| 55 OSExchangeDataProviderMus::Data OSExchangeDataProviderMus::GetData() const { | |
| 56 return mime_data_; | |
| 57 } | |
| 58 | |
| 13 std::unique_ptr<ui::OSExchangeData::Provider> | 59 std::unique_ptr<ui::OSExchangeData::Provider> |
| 14 OSExchangeDataProviderMus::Clone() const { | 60 OSExchangeDataProviderMus::Clone() const { |
| 15 return std::unique_ptr<ui::OSExchangeData::Provider>(); | 61 std::unique_ptr<OSExchangeDataProviderMus> r = |
| 62 base::MakeUnique<OSExchangeDataProviderMus>(); | |
| 63 r->drag_image_ = drag_image_; | |
| 64 r->drag_image_offset_ = drag_image_offset_; | |
| 65 r->mime_data_ = mime_data_; | |
| 66 return base::WrapUnique<ui::OSExchangeData::Provider>(r.release()); | |
| 16 } | 67 } |
| 17 | 68 |
| 18 void OSExchangeDataProviderMus::MarkOriginatedFromRenderer() { | 69 void OSExchangeDataProviderMus::MarkOriginatedFromRenderer() { |
| 70 // Currently unimplemented because ChromeOS doesn't need this. | |
| 71 // | |
| 72 // TODO(erg): Implement this when we start porting mus to other platforms. | |
| 19 } | 73 } |
| 20 | 74 |
| 21 bool OSExchangeDataProviderMus::DidOriginateFromRenderer() const { | 75 bool OSExchangeDataProviderMus::DidOriginateFromRenderer() const { |
| 22 return false; | 76 return false; |
| 23 } | 77 } |
| 24 | 78 |
| 25 void OSExchangeDataProviderMus::SetString(const base::string16& data) { | 79 void OSExchangeDataProviderMus::SetString(const base::string16& data) { |
| 80 if (HasString()) | |
| 81 return; | |
| 82 | |
| 83 mime_data_[ui::mojom::kMimeTypeText] = FromString(base::UTF16ToUTF8(data)); | |
| 26 } | 84 } |
| 27 | 85 |
| 28 void OSExchangeDataProviderMus::SetURL(const GURL& url, | 86 void OSExchangeDataProviderMus::SetURL(const GURL& url, |
| 29 const base::string16& title) { | 87 const base::string16& title) { |
| 88 base::string16 spec = base::UTF8ToUTF16(url.spec()); | |
| 89 std::vector<unsigned char> data; | |
| 90 AddString16ToVector(spec, &data); | |
| 91 AddString16ToVector(base::ASCIIToUTF16("\n"), &data); | |
| 92 AddString16ToVector(title, &data); | |
| 93 mime_data_[ui::mojom::kMimeTypeMozillaURL] = std::move(data); | |
| 94 | |
| 95 if (!base::ContainsKey(mime_data_, ui::mojom::kMimeTypeText)) | |
| 96 mime_data_[ui::mojom::kMimeTypeText] = FromString(url.spec()); | |
| 30 } | 97 } |
| 31 | 98 |
| 32 void OSExchangeDataProviderMus::SetFilename(const base::FilePath& path) { | 99 void OSExchangeDataProviderMus::SetFilename(const base::FilePath& path) { |
| 100 std::vector<ui::FileInfo> data; | |
| 101 data.push_back(ui::FileInfo(path, base::FilePath())); | |
| 102 SetFilenames(data); | |
| 33 } | 103 } |
| 34 | 104 |
| 35 void OSExchangeDataProviderMus::SetFilenames( | 105 void OSExchangeDataProviderMus::SetFilenames( |
| 36 const std::vector<ui::FileInfo>& file_names) { | 106 const std::vector<ui::FileInfo>& file_names) { |
| 107 std::vector<std::string> paths; | |
| 108 for (std::vector<ui::FileInfo>::const_iterator it = file_names.begin(); | |
| 109 it != file_names.end(); | |
| 110 ++it) { | |
| 111 std::string url_spec = net::FilePathToFileURL(it->path).spec(); | |
| 112 if (!url_spec.empty()) | |
| 113 paths.push_back(url_spec); | |
| 114 } | |
| 115 | |
| 116 std::string joined_data = base::JoinString(paths, "\n"); | |
| 117 mime_data_[ui::mojom::kMimeTypeURIList] = FromString(joined_data); | |
| 37 } | 118 } |
| 38 | 119 |
| 39 void OSExchangeDataProviderMus::SetPickledData( | 120 void OSExchangeDataProviderMus::SetPickledData( |
| 40 const ui::Clipboard::FormatType& format, | 121 const ui::Clipboard::FormatType& format, |
| 41 const base::Pickle& data) { | 122 const base::Pickle& pickle) { |
| 123 const unsigned char* bytes = | |
| 124 reinterpret_cast<const unsigned char*>(pickle.data()); | |
| 125 | |
| 126 mime_data_[format.Serialize()] = mojo::Array<uint8_t>( | |
| 127 std::vector<uint8_t>(bytes, bytes + pickle.size())); | |
| 42 } | 128 } |
| 43 | 129 |
| 44 bool OSExchangeDataProviderMus::GetString(base::string16* data) const { | 130 bool OSExchangeDataProviderMus::GetString(base::string16* data) const { |
| 45 return false; | 131 auto it = mime_data_.find(ui::mojom::kMimeTypeText); |
| 132 if (it != mime_data_.end()) | |
| 133 *data = base::UTF8ToUTF16(ToString(it->second)); | |
| 134 return it != mime_data_.end(); | |
| 46 } | 135 } |
| 47 | 136 |
| 48 bool OSExchangeDataProviderMus::GetURLAndTitle( | 137 bool OSExchangeDataProviderMus::GetURLAndTitle( |
| 49 ui::OSExchangeData::FilenameToURLPolicy policy, | 138 ui::OSExchangeData::FilenameToURLPolicy policy, |
| 50 GURL* url, | 139 GURL* url, |
| 51 base::string16* title) const { | 140 base::string16* title) const { |
| 52 return false; | 141 auto it = mime_data_.find(ui::mojom::kMimeTypeMozillaURL); |
| 142 if (it == mime_data_.end()) { | |
| 143 title->clear(); | |
| 144 return GetPlainTextURL(url) || | |
| 145 (policy == ui::OSExchangeData::CONVERT_FILENAMES && GetFileURL(url)); | |
| 146 } | |
| 147 | |
| 148 base::string16 data = ToString16(it->second); | |
| 149 base::string16::size_type newline = data.find('\n'); | |
| 150 if (newline == std::string::npos) | |
| 151 return false; | |
| 152 | |
| 153 GURL unparsed_url(data.substr(0, newline)); | |
| 154 if (!unparsed_url.is_valid()) | |
| 155 return false; | |
| 156 | |
| 157 *url = unparsed_url; | |
| 158 *title = data.substr(newline + 1); | |
| 159 return true; | |
| 53 } | 160 } |
| 54 | 161 |
| 55 bool OSExchangeDataProviderMus::GetFilename(base::FilePath* path) const { | 162 bool OSExchangeDataProviderMus::GetFilename(base::FilePath* path) const { |
| 163 std::vector<ui::FileInfo> filenames; | |
| 164 if (GetFilenames(&filenames)) { | |
| 165 *path = filenames.front().path; | |
| 166 return true; | |
| 167 } | |
| 168 | |
| 56 return false; | 169 return false; |
| 57 } | 170 } |
| 58 | 171 |
| 59 bool OSExchangeDataProviderMus::GetFilenames( | 172 bool OSExchangeDataProviderMus::GetFilenames( |
| 60 std::vector<ui::FileInfo>* file_names) const { | 173 std::vector<ui::FileInfo>* file_names) const { |
| 61 return false; | 174 auto it = mime_data_.find(ui::mojom::kMimeTypeURIList); |
| 175 if (it == mime_data_.end()) | |
| 176 return false; | |
| 177 | |
| 178 file_names->clear(); | |
| 179 for (const base::StringPiece& piece : ParseURIList(it->second)) { | |
| 180 GURL url(piece); | |
| 181 base::FilePath file_path; | |
| 182 if (url.SchemeIsFile() && net::FileURLToFilePath(url, &file_path)) | |
| 183 file_names->push_back(ui::FileInfo(file_path, base::FilePath())); | |
| 184 } | |
| 185 | |
| 186 return true; | |
| 62 } | 187 } |
| 63 | 188 |
| 64 bool OSExchangeDataProviderMus::GetPickledData( | 189 bool OSExchangeDataProviderMus::GetPickledData( |
| 65 const ui::Clipboard::FormatType& format, | 190 const ui::Clipboard::FormatType& format, |
| 66 base::Pickle* data) const { | 191 base::Pickle* data) const { |
| 67 return false; | 192 auto it = mime_data_.find(format.Serialize()); |
| 193 if (it == mime_data_.end()) | |
| 194 return false; | |
| 195 | |
| 196 // Note that the pickle object on the right hand side of the assignment | |
| 197 // only refers to the bytes in |data|. The assignment copies the data. | |
| 198 *data = base::Pickle(reinterpret_cast<const char*>(it->second.data()), | |
| 199 static_cast<int>(it->second.size())); | |
| 200 return true; | |
| 68 } | 201 } |
| 69 | 202 |
| 70 bool OSExchangeDataProviderMus::HasString() const { | 203 bool OSExchangeDataProviderMus::HasString() const { |
| 71 return false; | 204 return base::ContainsKey(mime_data_, ui::mojom::kMimeTypeText); |
| 72 } | 205 } |
| 73 | 206 |
| 74 bool OSExchangeDataProviderMus::HasURL( | 207 bool OSExchangeDataProviderMus::HasURL( |
| 75 ui::OSExchangeData::FilenameToURLPolicy policy) const { | 208 ui::OSExchangeData::FilenameToURLPolicy policy) const { |
| 209 if (base::ContainsKey(mime_data_, ui::mojom::kMimeTypeMozillaURL)) | |
| 210 return true; | |
| 211 | |
| 212 auto it = mime_data_.find(ui::mojom::kMimeTypeURIList); | |
| 213 if (it == mime_data_.end()) | |
| 214 return false; | |
| 215 | |
| 216 for (const base::StringPiece& piece : ParseURIList(it->second)) { | |
| 217 if (!GURL(piece).SchemeIsFile() || | |
| 218 policy == ui::OSExchangeData::CONVERT_FILENAMES) { | |
| 219 return true; | |
| 220 } | |
| 221 } | |
| 222 | |
| 76 return false; | 223 return false; |
| 77 } | 224 } |
| 78 | 225 |
| 79 bool OSExchangeDataProviderMus::HasFile() const { | 226 bool OSExchangeDataProviderMus::HasFile() const { |
| 227 auto it = mime_data_.find(ui::mojom::kMimeTypeURIList); | |
| 228 if (it == mime_data_.end()) | |
| 229 return false; | |
| 230 | |
| 231 for (const base::StringPiece& piece : ParseURIList(it->second)) { | |
| 232 GURL url(piece); | |
| 233 base::FilePath file_path; | |
| 234 if (url.SchemeIsFile() && net::FileURLToFilePath(url, &file_path)) | |
| 235 return true; | |
| 236 } | |
| 237 | |
| 80 return false; | 238 return false; |
| 81 } | 239 } |
| 82 | 240 |
| 83 bool OSExchangeDataProviderMus::HasCustomFormat( | 241 bool OSExchangeDataProviderMus::HasCustomFormat( |
| 84 const ui::Clipboard::FormatType& format) const { | 242 const ui::Clipboard::FormatType& format) const { |
| 85 return false; | 243 return base::ContainsKey(mime_data_, format.Serialize()); |
| 86 } | 244 } |
| 87 | 245 |
| 88 // These methods were added in an ad-hoc way to different operating | 246 // These methods were added in an ad-hoc way to different operating |
| 89 // systems. We need to support them until they get cleaned up. | 247 // systems. We need to support them until they get cleaned up. |
| 90 #if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN) | 248 #if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN) |
| 91 void OSExchangeDataProviderMus::SetFileContents( | 249 void OSExchangeDataProviderMus::SetFileContents( |
| 92 const base::FilePath& filename, | 250 const base::FilePath& filename, |
| 93 const std::string& file_contents) { | 251 const std::string& file_contents) { |
| 94 | 252 |
| 95 } | 253 } |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 107 } | 265 } |
| 108 | 266 |
| 109 void OSExchangeDataProviderMus::SetDownloadFileInfo( | 267 void OSExchangeDataProviderMus::SetDownloadFileInfo( |
| 110 const ui::OSExchangeData::DownloadFileInfo& download) { | 268 const ui::OSExchangeData::DownloadFileInfo& download) { |
| 111 } | 269 } |
| 112 #endif | 270 #endif |
| 113 | 271 |
| 114 #if defined(USE_AURA) | 272 #if defined(USE_AURA) |
| 115 void OSExchangeDataProviderMus::SetHtml(const base::string16& html, | 273 void OSExchangeDataProviderMus::SetHtml(const base::string16& html, |
| 116 const GURL& base_url) { | 274 const GURL& base_url) { |
| 117 | 275 std::vector<unsigned char> bytes; |
| 276 // Manually jam a UTF16 BOM into bytes because otherwise, other programs will | |
| 277 // assume UTF-8. | |
| 278 bytes.push_back(0xFF); | |
| 279 bytes.push_back(0xFE); | |
| 280 AddString16ToVector(html, &bytes); | |
| 281 mime_data_[ui::mojom::kMimeTypeHTML] = bytes; | |
| 118 } | 282 } |
| 119 | 283 |
| 120 bool OSExchangeDataProviderMus::GetHtml(base::string16* html, | 284 bool OSExchangeDataProviderMus::GetHtml(base::string16* html, |
| 121 GURL* base_url) const { | 285 GURL* base_url) const { |
| 122 return false; | 286 auto it = mime_data_.find(ui::mojom::kMimeTypeHTML); |
| 287 if (it == mime_data_.end()) | |
| 288 return false; | |
| 289 | |
| 290 const unsigned char* data = it->second.data(); | |
| 291 size_t size = it->second.size(); | |
| 292 base::string16 markup; | |
| 293 | |
| 294 // If the data starts with 0xFEFF, i.e., Byte Order Mark, assume it is | |
| 295 // UTF-16, otherwise assume UTF-8. | |
| 296 if (size >= 2 && | |
| 297 reinterpret_cast<const uint16_t*>(data)[0] == 0xFEFF) { | |
| 298 markup.assign(reinterpret_cast<const base::char16*>(data) + 1, | |
| 299 (size / 2) - 1); | |
| 300 } else { | |
| 301 base::UTF8ToUTF16(reinterpret_cast<const char*>(data), size, &markup); | |
| 302 } | |
| 303 | |
| 304 // If there is a terminating NULL, drop it. | |
| 305 if (!markup.empty() && markup.at(markup.length() - 1) == '\0') | |
| 306 markup.resize(markup.length() - 1); | |
| 307 | |
| 308 *html = markup; | |
| 309 *base_url = GURL(); | |
| 310 return true; | |
| 123 } | 311 } |
| 124 | 312 |
| 125 bool OSExchangeDataProviderMus::HasHtml() const { | 313 bool OSExchangeDataProviderMus::HasHtml() const { |
| 126 return false; | 314 return base::ContainsKey(mime_data_, ui::mojom::kMimeTypeHTML); |
| 127 } | 315 } |
| 128 #endif | 316 #endif |
| 129 | 317 |
| 130 #if defined(USE_AURA) || defined(OS_MACOSX) | 318 #if defined(USE_AURA) || defined(OS_MACOSX) |
| 131 void OSExchangeDataProviderMus::SetDragImage( | 319 void OSExchangeDataProviderMus::SetDragImage( |
| 132 const gfx::ImageSkia& image, | 320 const gfx::ImageSkia& image, |
| 133 const gfx::Vector2d& cursor_offset) { | 321 const gfx::Vector2d& cursor_offset) { |
| 134 drag_image_ = image; | 322 drag_image_ = image; |
| 135 drag_image_offset_ = cursor_offset; | 323 drag_image_offset_ = cursor_offset; |
| 136 } | 324 } |
| 137 | 325 |
| 138 const gfx::ImageSkia& OSExchangeDataProviderMus::GetDragImage() const { | 326 const gfx::ImageSkia& OSExchangeDataProviderMus::GetDragImage() const { |
| 139 return drag_image_; | 327 return drag_image_; |
| 140 } | 328 } |
| 141 | 329 |
| 142 const gfx::Vector2d& OSExchangeDataProviderMus::GetDragImageOffset() const { | 330 const gfx::Vector2d& OSExchangeDataProviderMus::GetDragImageOffset() const { |
| 143 return drag_image_offset_; | 331 return drag_image_offset_; |
| 144 } | 332 } |
| 145 #endif | 333 #endif |
| 146 | 334 |
| 335 bool OSExchangeDataProviderMus::GetFileURL(GURL* url) const { | |
| 336 base::FilePath file_path; | |
| 337 if (!GetFilename(&file_path)) | |
| 338 return false; | |
| 339 | |
| 340 GURL test_url = net::FilePathToFileURL(file_path); | |
| 341 if (!test_url.is_valid()) | |
| 342 return false; | |
| 343 | |
| 344 if (url) | |
| 345 *url = test_url; | |
| 346 return true; | |
| 347 } | |
| 348 | |
| 349 bool OSExchangeDataProviderMus::GetPlainTextURL(GURL* url) const { | |
| 350 base::string16 str; | |
| 351 if (!GetString(&str)) | |
| 352 return false; | |
| 353 | |
| 354 GURL test_url(str); | |
| 355 if (!test_url.is_valid()) | |
| 356 return false; | |
| 357 | |
| 358 if (url) | |
| 359 *url = test_url; | |
| 360 return true; | |
| 361 } | |
| 362 | |
| 147 } // namespace views | 363 } // namespace views |
| OLD | NEW |