OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/base/dragdrop/os_exchange_data_provider_win.h" | 5 #include "ui/base/dragdrop/os_exchange_data_provider_win.h" |
6 | 6 |
7 #include <algorithm> | |
8 #include <vector> | |
9 | |
7 #include "base/file_path.h" | 10 #include "base/file_path.h" |
8 #include "base/i18n/file_util_icu.h" | 11 #include "base/i18n/file_util_icu.h" |
9 #include "base/logging.h" | 12 #include "base/logging.h" |
10 #include "base/memory/scoped_handle.h" | 13 #include "base/memory/scoped_handle.h" |
11 #include "base/pickle.h" | 14 #include "base/pickle.h" |
12 #include "base/stl_util.h" | 15 #include "base/stl_util.h" |
13 #include "base/utf_string_conversions.h" | 16 #include "base/utf_string_conversions.h" |
14 #include "base/win/scoped_hglobal.h" | 17 #include "base/win/scoped_hglobal.h" |
15 #include "googleurl/src/gurl.h" | 18 #include "googleurl/src/gurl.h" |
16 #include "grit/ui_strings.h" | 19 #include "grit/ui_strings.h" |
(...skipping 100 matching lines...) Loading... | |
117 } | 120 } |
118 | 121 |
119 FormatEtcEnumerator::~FormatEtcEnumerator() { | 122 FormatEtcEnumerator::~FormatEtcEnumerator() { |
120 STLDeleteContainerPointers(contents_.begin(), contents_.end()); | 123 STLDeleteContainerPointers(contents_.begin(), contents_.end()); |
121 } | 124 } |
122 | 125 |
123 STDMETHODIMP FormatEtcEnumerator::Next( | 126 STDMETHODIMP FormatEtcEnumerator::Next( |
124 ULONG count, FORMATETC* elements_array, ULONG* elements_fetched) { | 127 ULONG count, FORMATETC* elements_array, ULONG* elements_fetched) { |
125 // MSDN says |elements_fetched| is allowed to be NULL if count is 1. | 128 // MSDN says |elements_fetched| is allowed to be NULL if count is 1. |
126 if (!elements_fetched) | 129 if (!elements_fetched) |
127 DCHECK(count == 1); | 130 DCHECK_EQ(count, 1ul); |
128 | 131 |
129 // This method copies count elements into |elements_array|. | 132 // This method copies count elements into |elements_array|. |
130 ULONG index = 0; | 133 ULONG index = 0; |
131 while (cursor_ < contents_.size() && index < count) { | 134 while (cursor_ < contents_.size() && index < count) { |
132 CloneFormatEtc(contents_[cursor_], &elements_array[index]); | 135 CloneFormatEtc(contents_[cursor_], &elements_array[index]); |
133 ++cursor_; | 136 ++cursor_; |
134 ++index; | 137 ++index; |
135 } | 138 } |
136 // The out param is for how many we actually copied. | 139 // The out param is for how many we actually copied. |
137 if (elements_fetched) | 140 if (elements_fetched) |
(...skipping 258 matching lines...) Loading... | |
396 bool OSExchangeDataProviderWin::GetPickledData(CLIPFORMAT format, | 399 bool OSExchangeDataProviderWin::GetPickledData(CLIPFORMAT format, |
397 Pickle* data) const { | 400 Pickle* data) const { |
398 DCHECK(data); | 401 DCHECK(data); |
399 FORMATETC format_etc = | 402 FORMATETC format_etc = |
400 { format, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; | 403 { format, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; |
401 bool success = false; | 404 bool success = false; |
402 STGMEDIUM medium; | 405 STGMEDIUM medium; |
403 if (SUCCEEDED(source_object_->GetData(&format_etc, &medium))) { | 406 if (SUCCEEDED(source_object_->GetData(&format_etc, &medium))) { |
404 if (medium.tymed & TYMED_HGLOBAL) { | 407 if (medium.tymed & TYMED_HGLOBAL) { |
405 base::win::ScopedHGlobal<char> c_data(medium.hGlobal); | 408 base::win::ScopedHGlobal<char> c_data(medium.hGlobal); |
406 DCHECK(c_data.Size() > 0); | 409 DCHECK_GT(c_data.Size(), static_cast<size_t>(0)); |
sky
2011/09/08 17:25:46
0u
yosin_UTC9
2011/09/09 04:25:41
Done.
| |
407 // Need to subtract 1 as SetPickledData adds an extra byte to the end. | 410 // Need to subtract 1 as SetPickledData adds an extra byte to the end. |
408 *data = Pickle(c_data.get(), static_cast<int>(c_data.Size() - 1)); | 411 *data = Pickle(c_data.get(), static_cast<int>(c_data.Size() - 1)); |
409 success = true; | 412 success = true; |
410 } | 413 } |
411 ReleaseStgMedium(&medium); | 414 ReleaseStgMedium(&medium); |
412 } | 415 } |
413 return success; | 416 return success; |
414 } | 417 } |
415 | 418 |
416 bool OSExchangeDataProviderWin::GetFileContents( | 419 bool OSExchangeDataProviderWin::GetFileContents( |
(...skipping 465 matching lines...) Loading... | |
882 static const size_t max_length = MAX_PATH - arraysize(extension); | 885 static const size_t max_length = MAX_PATH - arraysize(extension); |
883 if (validated->size() > max_length) | 886 if (validated->size() > max_length) |
884 validated->erase(max_length); | 887 validated->erase(max_length); |
885 *validated += extension; | 888 *validated += extension; |
886 } | 889 } |
887 | 890 |
888 static STGMEDIUM* GetStorageForFileName(const FilePath& path) { | 891 static STGMEDIUM* GetStorageForFileName(const FilePath& path) { |
889 const size_t kDropSize = sizeof(DROPFILES); | 892 const size_t kDropSize = sizeof(DROPFILES); |
890 const size_t kTotalBytes = | 893 const size_t kTotalBytes = |
891 kDropSize + (path.value().length() + 2) * sizeof(wchar_t); | 894 kDropSize + (path.value().length() + 2) * sizeof(wchar_t); |
892 HANDLE hdata = GlobalAlloc(GMEM_MOVEABLE, kTotalBytes); | 895 HANDLE hdata = GlobalAlloc(GMEM_MOVEABLE, kTotalBytes); |
sky
2011/09/08 17:25:46
Shouldn't we check the return value?
yosin_UTC9
2011/09/09 04:25:41
Yes, we should check. Although, I would like to do
| |
893 | 896 |
894 base::win::ScopedHGlobal<DROPFILES> locked_mem(hdata); | 897 base::win::ScopedHGlobal<DROPFILES> locked_mem(hdata); |
895 DROPFILES* drop_files = locked_mem.get(); | 898 DROPFILES* drop_files = locked_mem.get(); |
896 drop_files->pFiles = sizeof(DROPFILES); | 899 drop_files->pFiles = sizeof(DROPFILES); |
897 drop_files->fWide = TRUE; | 900 drop_files->fWide = TRUE; |
898 wchar_t* data = reinterpret_cast<wchar_t*>( | 901 wchar_t* data = reinterpret_cast<wchar_t*>( |
899 reinterpret_cast<BYTE*>(drop_files) + kDropSize); | 902 reinterpret_cast<BYTE*>(drop_files) + kDropSize); |
900 const size_t copy_size = (path.value().length() + 1) * sizeof(wchar_t); | 903 const size_t copy_size = (path.value().length() + 1) * sizeof(wchar_t); |
901 memcpy(data, path.value().c_str(), copy_size); | 904 memcpy(data, path.value().c_str(), copy_size); |
902 data[path.value().length() + 1] = L'\0'; // Double NULL | 905 data[path.value().length() + 1] = L'\0'; // Double NULL |
903 | 906 |
904 STGMEDIUM* storage = new STGMEDIUM; | 907 STGMEDIUM* storage = new STGMEDIUM; |
905 storage->tymed = TYMED_HGLOBAL; | 908 storage->tymed = TYMED_HGLOBAL; |
906 storage->hGlobal = drop_files; | 909 storage->hGlobal = hdata; |
907 storage->pUnkForRelease = NULL; | 910 storage->pUnkForRelease = NULL; |
908 return storage; | 911 return storage; |
909 } | 912 } |
910 | 913 |
911 static STGMEDIUM* GetStorageForFileDescriptor( | 914 static STGMEDIUM* GetStorageForFileDescriptor( |
912 const FilePath& path) { | 915 const FilePath& path) { |
913 string16 valid_file_name = path.value(); | 916 string16 file_name = path.value(); |
914 DCHECK(!valid_file_name.empty() && valid_file_name.size() + 1 <= MAX_PATH); | 917 DCHECK(!file_name.empty()); |
915 HANDLE handle = GlobalAlloc(GPTR, sizeof(FILEGROUPDESCRIPTOR)); | 918 HANDLE hdata = GlobalAlloc(GPTR, sizeof(FILEGROUPDESCRIPTOR)); |
sky
2011/09/08 17:25:46
Same thing about checking return value here.
yosin_UTC9
2011/09/09 04:25:41
I'll do another CR.
| |
916 FILEGROUPDESCRIPTOR* descriptor = | 919 base::win::ScopedHGlobal<FILEGROUPDESCRIPTOR> locked_mem(hdata); |
917 reinterpret_cast<FILEGROUPDESCRIPTOR*>(GlobalLock(handle)); | |
918 | 920 |
921 FILEGROUPDESCRIPTOR* descriptor = locked_mem.get(); | |
919 descriptor->cItems = 1; | 922 descriptor->cItems = 1; |
920 wcscpy_s(descriptor->fgd[0].cFileName, | |
921 valid_file_name.size() + 1, | |
922 valid_file_name.c_str()); | |
923 descriptor->fgd[0].dwFlags = FD_LINKUI; | 923 descriptor->fgd[0].dwFlags = FD_LINKUI; |
924 | 924 int file_name_len = file_name.size(); |
925 GlobalUnlock(handle); | 925 if (file_name_len + 1 < MAX_PATH) { |
926 wcscpy_s(descriptor->fgd[0].cFileName, | |
927 MAX_PATH, | |
928 file_name.c_str()); | |
929 } else { | |
930 string16 extension = path.Extension(); | |
sky
2011/09/08 17:25:46
Shouldn't we make sure we maintain the path compon
yosin_UTC9
2011/09/09 04:25:41
Callers should take care of it. Actually, this fun
| |
931 int extension_len = extension.size(); | |
932 int max_name_len = MAX_PATH - extension_len - 1; | |
933 if (max_name_len >= 1) { | |
934 // We take at least one character from name. | |
935 int orig_name_len = file_name_len - extension_len; | |
936 int name_len = std::min(orig_name_len, max_name_len); | |
937 memcpy(descriptor->fgd[0].cFileName, | |
938 file_name.c_str(), | |
939 sizeof(wchar_t) * name_len); | |
940 wcscpy_s(descriptor->fgd[0].cFileName + name_len, | |
941 MAX_PATH - extension_len, | |
942 extension.c_str()); | |
943 } else { | |
944 // We take MAX_PATH-1 characters from file_name. | |
945 wcsncpy_s(descriptor->fgd[0].cFileName, | |
946 MAX_PATH, | |
947 file_name.c_str(), | |
948 MAX_PATH - 1); | |
949 } | |
950 } | |
926 | 951 |
927 STGMEDIUM* storage = new STGMEDIUM; | 952 STGMEDIUM* storage = new STGMEDIUM; |
928 storage->hGlobal = handle; | 953 storage->hGlobal = hdata; |
929 storage->tymed = TYMED_HGLOBAL; | 954 storage->tymed = TYMED_HGLOBAL; |
930 storage->pUnkForRelease = NULL; | 955 storage->pUnkForRelease = NULL; |
931 return storage; | 956 return storage; |
932 } | 957 } |
933 | 958 |
934 | |
935 /////////////////////////////////////////////////////////////////////////////// | 959 /////////////////////////////////////////////////////////////////////////////// |
936 // OSExchangeData, public: | 960 // OSExchangeData, public: |
937 | 961 |
938 // static | 962 // static |
939 OSExchangeData::Provider* OSExchangeData::CreateProvider() { | 963 OSExchangeData::Provider* OSExchangeData::CreateProvider() { |
940 return new OSExchangeDataProviderWin(); | 964 return new OSExchangeDataProviderWin(); |
941 } | 965 } |
942 | 966 |
943 // static | 967 // static |
944 OSExchangeData::CustomFormat OSExchangeData::RegisterCustomFormat( | 968 OSExchangeData::CustomFormat OSExchangeData::RegisterCustomFormat( |
945 const std::string& type) { | 969 const std::string& type) { |
946 return RegisterClipboardFormat(ASCIIToUTF16(type).c_str()); | 970 return RegisterClipboardFormat(ASCIIToUTF16(type).c_str()); |
947 } | 971 } |
948 | 972 |
949 } // namespace ui | 973 } // namespace ui |
OLD | NEW |