| 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 |