OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "app/clipboard/clipboard_util_win.h" | 5 #include "app/clipboard/clipboard_util_win.h" |
6 | 6 |
7 #include <shellapi.h> | 7 #include <shellapi.h> |
8 #include <shlwapi.h> | 8 #include <shlwapi.h> |
9 #include <wininet.h> | 9 #include <wininet.h> |
10 | 10 |
(...skipping 17 matching lines...) Expand all Loading... |
28 if (!hdrop) | 28 if (!hdrop) |
29 return false; | 29 return false; |
30 | 30 |
31 bool success = false; | 31 bool success = false; |
32 wchar_t filename[MAX_PATH]; | 32 wchar_t filename[MAX_PATH]; |
33 if (DragQueryFileW(hdrop, 0, filename, arraysize(filename))) { | 33 if (DragQueryFileW(hdrop, 0, filename, arraysize(filename))) { |
34 wchar_t url_buffer[INTERNET_MAX_URL_LENGTH]; | 34 wchar_t url_buffer[INTERNET_MAX_URL_LENGTH]; |
35 if (0 == _wcsicmp(PathFindExtensionW(filename), L".url") && | 35 if (0 == _wcsicmp(PathFindExtensionW(filename), L".url") && |
36 GetPrivateProfileStringW(L"InternetShortcut", L"url", 0, url_buffer, | 36 GetPrivateProfileStringW(L"InternetShortcut", L"url", 0, url_buffer, |
37 arraysize(url_buffer), filename)) { | 37 arraysize(url_buffer), filename)) { |
38 *url = url_buffer; | 38 url->assign(url_buffer); |
39 PathRemoveExtension(filename); | 39 PathRemoveExtension(filename); |
40 title->assign(PathFindFileName(filename)); | 40 title->assign(PathFindFileName(filename)); |
41 success = true; | 41 success = true; |
42 } | 42 } |
43 } | 43 } |
44 | 44 |
45 DragFinish(hdrop); | 45 DragFinish(hdrop); |
46 GlobalUnlock(medium.hGlobal); | 46 GlobalUnlock(medium.hGlobal); |
47 // We don't need to call ReleaseStgMedium here because as far as I can tell, | 47 // We don't need to call ReleaseStgMedium here because as far as I can tell, |
48 // DragFinish frees the hGlobal for us. | 48 // DragFinish frees the hGlobal for us. |
49 return success; | 49 return success; |
50 } | 50 } |
51 | 51 |
52 bool SplitUrlAndTitle(const std::wstring& str, std::wstring* url, | 52 void SplitUrlAndTitle(const std::wstring& str, |
53 std::wstring* title) { | 53 std::wstring* url, |
| 54 std::wstring* title) { |
54 DCHECK(url && title); | 55 DCHECK(url && title); |
55 size_t newline_pos = str.find('\n'); | 56 size_t newline_pos = str.find('\n'); |
56 bool success = false; | 57 if (newline_pos != std::wstring::npos) { |
57 if (newline_pos != std::string::npos) { | 58 url->assign(str, 0, newline_pos); |
58 *url = str.substr(0, newline_pos); | 59 title->assign(str, newline_pos + 1, std::wstring::npos); |
59 title->assign(str.substr(newline_pos + 1)); | |
60 success = true; | |
61 } else { | 60 } else { |
62 *url = str; | 61 url->assign(str); |
63 title->assign(str); | 62 title->assign(str); |
64 success = true; | |
65 } | 63 } |
66 return success; | |
67 } | 64 } |
68 | 65 |
69 } // namespace | 66 } // namespace |
70 | 67 |
71 | 68 |
72 FORMATETC* ClipboardUtil::GetUrlFormat() { | 69 FORMATETC* ClipboardUtil::GetUrlFormat() { |
73 static UINT cf = RegisterClipboardFormat(CFSTR_INETURLA); | 70 static UINT cf = RegisterClipboardFormat(CFSTR_INETURLA); |
74 static FORMATETC format = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; | 71 static FORMATETC format = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; |
75 return &format; | 72 return &format; |
76 } | 73 } |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 | 181 |
185 | 182 |
186 bool ClipboardUtil::GetUrl(IDataObject* data_object, | 183 bool ClipboardUtil::GetUrl(IDataObject* data_object, |
187 std::wstring* url, std::wstring* title) { | 184 std::wstring* url, std::wstring* title) { |
188 DCHECK(data_object && url && title); | 185 DCHECK(data_object && url && title); |
189 if (!HasUrl(data_object)) | 186 if (!HasUrl(data_object)) |
190 return false; | 187 return false; |
191 | 188 |
192 // Try to extract a URL from |data_object| in a variety of formats. | 189 // Try to extract a URL from |data_object| in a variety of formats. |
193 STGMEDIUM store; | 190 STGMEDIUM store; |
194 if (GetUrlFromHDrop(data_object, url, title)) { | 191 if (GetUrlFromHDrop(data_object, url, title)) |
195 return true; | 192 return true; |
196 } | |
197 | 193 |
198 if (SUCCEEDED(data_object->GetData(GetMozUrlFormat(), &store)) || | 194 if (SUCCEEDED(data_object->GetData(GetMozUrlFormat(), &store)) || |
199 SUCCEEDED(data_object->GetData(GetUrlWFormat(), &store))) { | 195 SUCCEEDED(data_object->GetData(GetUrlWFormat(), &store))) { |
200 // Mozilla URL format or unicode URL | 196 // Mozilla URL format or unicode URL |
201 ScopedHGlobal<wchar_t> data(store.hGlobal); | 197 ScopedHGlobal<wchar_t> data(store.hGlobal); |
202 bool success = SplitUrlAndTitle(data.get(), url, title); | 198 SplitUrlAndTitle(data.get(), url, title); |
203 ReleaseStgMedium(&store); | 199 ReleaseStgMedium(&store); |
204 if (success) | 200 return true; |
205 return true; | |
206 } | 201 } |
207 | 202 |
208 if (SUCCEEDED(data_object->GetData(GetUrlFormat(), &store))) { | 203 if (SUCCEEDED(data_object->GetData(GetUrlFormat(), &store))) { |
209 // URL using ascii | 204 // URL using ascii |
210 ScopedHGlobal<char> data(store.hGlobal); | 205 ScopedHGlobal<char> data(store.hGlobal); |
211 bool success = SplitUrlAndTitle(UTF8ToWide(data.get()), url, title); | 206 SplitUrlAndTitle(UTF8ToWide(data.get()), url, title); |
212 ReleaseStgMedium(&store); | 207 ReleaseStgMedium(&store); |
213 if (success) | 208 return true; |
214 return true; | |
215 } | 209 } |
216 | 210 |
217 if (SUCCEEDED(data_object->GetData(GetFilenameWFormat(), &store))) { | 211 if (SUCCEEDED(data_object->GetData(GetFilenameWFormat(), &store))) { |
218 // filename using unicode | 212 // filename using unicode |
219 ScopedHGlobal<wchar_t> data(store.hGlobal); | 213 ScopedHGlobal<wchar_t> data(store.hGlobal); |
220 bool success = false; | 214 bool success = false; |
221 if (data.get() && data.get()[0] && (PathFileExists(data.get()) || | 215 if (data.get() && data.get()[0] && |
222 PathIsUNC(data.get()))) { | 216 (PathFileExists(data.get()) || PathIsUNC(data.get()))) { |
223 wchar_t file_url[INTERNET_MAX_URL_LENGTH]; | 217 wchar_t file_url[INTERNET_MAX_URL_LENGTH]; |
224 DWORD file_url_len = sizeof(file_url) / sizeof(file_url[0]); | 218 DWORD file_url_len = arraysize(file_url); |
225 if (SUCCEEDED(::UrlCreateFromPathW(data.get(), file_url, &file_url_len, | 219 if (SUCCEEDED(::UrlCreateFromPathW(data.get(), file_url, &file_url_len, |
226 0))) { | 220 0))) { |
227 *url = file_url; | 221 url->assign(file_url); |
228 title->assign(file_url); | 222 title->assign(file_url); |
229 success = true; | 223 success = true; |
230 } | 224 } |
231 } | 225 } |
232 ReleaseStgMedium(&store); | 226 ReleaseStgMedium(&store); |
233 if (success) | 227 if (success) |
234 return true; | 228 return true; |
235 } | 229 } |
236 | 230 |
237 if (SUCCEEDED(data_object->GetData(GetFilenameFormat(), &store))) { | 231 if (SUCCEEDED(data_object->GetData(GetFilenameFormat(), &store))) { |
238 // filename using ascii | 232 // filename using ascii |
239 ScopedHGlobal<char> data(store.hGlobal); | 233 ScopedHGlobal<char> data(store.hGlobal); |
240 bool success = false; | 234 bool success = false; |
241 if (data.get() && data.get()[0] && (PathFileExistsA(data.get()) || | 235 if (data.get() && data.get()[0] && (PathFileExistsA(data.get()) || |
242 PathIsUNCA(data.get()))) { | 236 PathIsUNCA(data.get()))) { |
243 char file_url[INTERNET_MAX_URL_LENGTH]; | 237 char file_url[INTERNET_MAX_URL_LENGTH]; |
244 DWORD file_url_len = sizeof(file_url) / sizeof(file_url[0]); | 238 DWORD file_url_len = arraysize(file_url); |
245 if (SUCCEEDED(::UrlCreateFromPathA(data.get(), | 239 if (SUCCEEDED(::UrlCreateFromPathA(data.get(), file_url, &file_url_len, |
246 file_url, | |
247 &file_url_len, | |
248 0))) { | 240 0))) { |
249 *url = UTF8ToWide(file_url); | 241 url->assign(UTF8ToWide(file_url)); |
250 title->assign(*url); | 242 title->assign(*url); |
251 success = true; | 243 success = true; |
252 } | 244 } |
253 } | 245 } |
254 ReleaseStgMedium(&store); | 246 ReleaseStgMedium(&store); |
255 if (success) | 247 if (success) |
256 return true; | 248 return true; |
257 } | 249 } |
258 | 250 |
259 return false; | 251 return false; |
(...skipping 29 matching lines...) Expand all Loading... |
289 return true; | 281 return true; |
290 } | 282 } |
291 | 283 |
292 bool ClipboardUtil::GetPlainText(IDataObject* data_object, | 284 bool ClipboardUtil::GetPlainText(IDataObject* data_object, |
293 std::wstring* plain_text) { | 285 std::wstring* plain_text) { |
294 DCHECK(data_object && plain_text); | 286 DCHECK(data_object && plain_text); |
295 if (!HasPlainText(data_object)) | 287 if (!HasPlainText(data_object)) |
296 return false; | 288 return false; |
297 | 289 |
298 STGMEDIUM store; | 290 STGMEDIUM store; |
299 bool success = false; | |
300 if (SUCCEEDED(data_object->GetData(GetPlainTextWFormat(), &store))) { | 291 if (SUCCEEDED(data_object->GetData(GetPlainTextWFormat(), &store))) { |
301 // Unicode text | 292 // Unicode text |
302 ScopedHGlobal<wchar_t> data(store.hGlobal); | 293 ScopedHGlobal<wchar_t> data(store.hGlobal); |
303 plain_text->assign(data.get()); | 294 plain_text->assign(data.get()); |
304 ReleaseStgMedium(&store); | 295 ReleaseStgMedium(&store); |
305 success = true; | 296 return true; |
306 } else if (SUCCEEDED(data_object->GetData(GetPlainTextFormat(), &store))) { | 297 } |
| 298 |
| 299 if (SUCCEEDED(data_object->GetData(GetPlainTextFormat(), &store))) { |
307 // ascii text | 300 // ascii text |
308 ScopedHGlobal<char> data(store.hGlobal); | 301 ScopedHGlobal<char> data(store.hGlobal); |
309 plain_text->assign(UTF8ToWide(data.get())); | 302 plain_text->assign(UTF8ToWide(data.get())); |
310 ReleaseStgMedium(&store); | 303 ReleaseStgMedium(&store); |
311 success = true; | 304 return true; |
312 } else { | |
313 // If a file is dropped on the window, it does not provide either of the | |
314 // plain text formats, so here we try to forcibly get a url. | |
315 std::wstring title; | |
316 success = GetUrl(data_object, plain_text, &title); | |
317 } | 305 } |
318 | 306 |
319 return success; | 307 // If a file is dropped on the window, it does not provide either of the |
| 308 // plain text formats, so here we try to forcibly get a url. |
| 309 std::wstring title; |
| 310 return GetUrl(data_object, plain_text, &title); |
320 } | 311 } |
321 | 312 |
322 bool ClipboardUtil::GetHtml(IDataObject* data_object, | 313 bool ClipboardUtil::GetHtml(IDataObject* data_object, |
323 std::wstring* html, std::string* base_url) { | 314 std::wstring* html, std::string* base_url) { |
324 DCHECK(data_object && html && base_url); | 315 DCHECK(data_object && html && base_url); |
325 | 316 |
326 if (SUCCEEDED(data_object->QueryGetData(GetHtmlFormat()))) { | 317 STGMEDIUM store; |
327 STGMEDIUM store; | 318 if (SUCCEEDED(data_object->QueryGetData(GetHtmlFormat())) && |
328 if (SUCCEEDED(data_object->GetData(GetHtmlFormat(), &store))) { | 319 SUCCEEDED(data_object->GetData(GetHtmlFormat(), &store))) { |
329 // MS CF html | 320 // MS CF html |
330 ScopedHGlobal<char> data(store.hGlobal); | 321 ScopedHGlobal<char> data(store.hGlobal); |
331 | 322 |
332 std::string html_utf8; | 323 std::string html_utf8; |
333 CFHtmlToHtml(std::string(data.get(), data.Size()), &html_utf8, base_url); | 324 CFHtmlToHtml(std::string(data.get(), data.Size()), &html_utf8, base_url); |
334 html->assign(UTF8ToWide(html_utf8)); | 325 html->assign(UTF8ToWide(html_utf8)); |
335 | 326 |
336 ReleaseStgMedium(&store); | 327 ReleaseStgMedium(&store); |
337 return true; | 328 return true; |
338 } | |
339 } | 329 } |
340 | 330 |
341 if (FAILED(data_object->QueryGetData(GetTextHtmlFormat()))) | 331 if (FAILED(data_object->QueryGetData(GetTextHtmlFormat()))) |
342 return false; | 332 return false; |
343 | 333 |
344 STGMEDIUM store; | |
345 if (FAILED(data_object->GetData(GetTextHtmlFormat(), &store))) | 334 if (FAILED(data_object->GetData(GetTextHtmlFormat(), &store))) |
346 return false; | 335 return false; |
347 | 336 |
348 // text/html | 337 // text/html |
349 ScopedHGlobal<wchar_t> data(store.hGlobal); | 338 ScopedHGlobal<wchar_t> data(store.hGlobal); |
350 html->assign(data.get()); | 339 html->assign(data.get()); |
351 ReleaseStgMedium(&store); | 340 ReleaseStgMedium(&store); |
352 return true; | 341 return true; |
353 } | 342 } |
354 | 343 |
355 bool ClipboardUtil::GetFileContents(IDataObject* data_object, | 344 bool ClipboardUtil::GetFileContents(IDataObject* data_object, |
356 std::wstring* filename, std::string* file_contents) { | 345 std::wstring* filename, std::string* file_contents) { |
357 DCHECK(data_object && filename && file_contents); | 346 DCHECK(data_object && filename && file_contents); |
358 bool has_data = | 347 if (!SUCCEEDED(data_object->QueryGetData(GetFileContentFormatZero())) && |
359 SUCCEEDED(data_object->QueryGetData(GetFileContentFormatZero())) || | 348 !SUCCEEDED(data_object->QueryGetData(GetFileDescriptorFormat()))) |
360 SUCCEEDED(data_object->QueryGetData(GetFileDescriptorFormat())); | |
361 | |
362 if (!has_data) | |
363 return false; | 349 return false; |
364 | 350 |
365 STGMEDIUM content; | 351 STGMEDIUM content; |
366 // The call to GetData can be very slow depending on what is in | 352 // The call to GetData can be very slow depending on what is in |
367 // |data_object|. | 353 // |data_object|. |
368 if (SUCCEEDED(data_object->GetData(GetFileContentFormatZero(), &content))) { | 354 if (SUCCEEDED(data_object->GetData(GetFileContentFormatZero(), &content))) { |
369 if (TYMED_HGLOBAL == content.tymed) { | 355 if (TYMED_HGLOBAL == content.tymed) { |
370 ScopedHGlobal<char> data(content.hGlobal); | 356 ScopedHGlobal<char> data(content.hGlobal); |
371 file_contents->assign(data.get(), data.Size()); | 357 file_contents->assign(data.get(), data.Size()); |
372 } | 358 } |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
493 size_t fragment_start = cf_html.find('>', tag_start) + 1; | 479 size_t fragment_start = cf_html.find('>', tag_start) + 1; |
494 size_t tag_end = cf_html.rfind("EndFragment", std::string::npos); | 480 size_t tag_end = cf_html.rfind("EndFragment", std::string::npos); |
495 size_t fragment_end = cf_html.rfind('<', tag_end); | 481 size_t fragment_end = cf_html.rfind('<', tag_end); |
496 if (fragment_start != std::string::npos && | 482 if (fragment_start != std::string::npos && |
497 fragment_end != std::string::npos) { | 483 fragment_end != std::string::npos) { |
498 *html = cf_html.substr(fragment_start, fragment_end - fragment_start); | 484 *html = cf_html.substr(fragment_start, fragment_end - fragment_start); |
499 TrimWhitespace(*html, TRIM_ALL, html); | 485 TrimWhitespace(*html, TRIM_ALL, html); |
500 } | 486 } |
501 } | 487 } |
502 } | 488 } |
OLD | NEW |