15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_handle.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_hglobal.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/base/clipboard/clipboard.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/dragdrop/os_exchange_data.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/dragdrop/os_exchange_data_provider_win.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test getting using the IDataObject COM API
19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST(OSExchangeDataWinTest, StringDataAccessViaCOM) {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSExchangeData data;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring input = L"O hai googlz.";
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.SetString(input);
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedComPtr<IDataObject> com_data(
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSExchangeDataProviderWin::GetIDataObject(data));
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FORMATETC format_etc =
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { CF_UNICODETEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(S_OK, com_data->QueryGetData(&format_etc));
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STGMEDIUM medium;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(S_OK, com_data->GetData(&format_etc, &medium));
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring output =
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::win::ScopedHGlobal<wchar_t>(medium.hGlobal).get();
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(input, output);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseStgMedium(&medium);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test setting using the IDataObject COM API
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST(OSExchangeDataWinTest, StringDataWritingViaCOM) {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSExchangeData data;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring input = L"http://www.google.com/";
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedComPtr<IDataObject> com_data(
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSExchangeDataProviderWin::GetIDataObject(data));
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Store data in the object using the COM SetData API.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CLIPFORMAT cfstr_ineturl = RegisterClipboardFormat(CFSTR_INETURL);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FORMATETC format_etc =
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { cfstr_ineturl, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STGMEDIUM medium;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  medium.tymed = TYMED_HGLOBAL;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HGLOBAL glob = GlobalAlloc(GPTR, sizeof(wchar_t) * (input.size() + 1));
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t stringsz = input.size();
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SIZE_T sz = GlobalSize(glob);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedHGlobal<wchar_t> global_lock(glob);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wchar_t* buffer_handle = global_lock.get();
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wcscpy_s(buffer_handle, input.size() + 1, input.c_str());
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  medium.hGlobal = glob;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  medium.pUnkForRelease = NULL;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(S_OK, com_data->SetData(&format_etc, &medium, TRUE));
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct a new object with the old object so that we can use our access
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // APIs.
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OSExchangeData data2(data.provider().Clone());
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(data2.HasURL());
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url_from_data;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring title;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(data2.GetURLAndTitle(&url_from_data, &title));
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL reference_url(input);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(reference_url.spec(), url_from_data.spec());
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verifies SetData invoked twice with the same data clobbers existing data.
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST(OSExchangeDataWinTest, RemoveData) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSExchangeData data;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring input = L"http://www.google.com/";
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring input2 = L"http://www.google2.com/";
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedComPtr<IDataObject> com_data(
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSExchangeDataProviderWin::GetIDataObject(data));
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Store data in the object using the COM SetData API.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CLIPFORMAT cfstr_ineturl = RegisterClipboardFormat(CFSTR_INETURL);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FORMATETC format_etc =
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { cfstr_ineturl, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STGMEDIUM medium;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  medium.tymed = TYMED_HGLOBAL;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HGLOBAL glob = GlobalAlloc(GPTR, sizeof(wchar_t) * (input.size() + 1));
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t stringsz = input.size();
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SIZE_T sz = GlobalSize(glob);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::win::ScopedHGlobal<wchar_t> global_lock(glob);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wchar_t* buffer_handle = global_lock.get();
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wcscpy_s(buffer_handle, input.size() + 1, input.c_str());
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    medium.hGlobal = glob;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    medium.pUnkForRelease = NULL;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(S_OK, com_data->SetData(&format_etc, &medium, TRUE));
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This should clobber the existing data.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HGLOBAL glob = GlobalAlloc(GPTR, sizeof(wchar_t) * (input2.size() + 1));
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t stringsz = input2.size();
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SIZE_T sz = GlobalSize(glob);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::win::ScopedHGlobal<wchar_t> global_lock(glob);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wchar_t* buffer_handle = global_lock.get();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wcscpy_s(buffer_handle, input2.size() + 1, input2.c_str());
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    medium.hGlobal = glob;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    medium.pUnkForRelease = NULL;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(S_OK, com_data->SetData(&format_etc, &medium, TRUE));
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1u, static_cast<DataObjectImpl*>(com_data.get())->size());
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct a new object with the old object so that we can use our access
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // APIs.
115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OSExchangeData data2(data.provider().Clone());
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(data2.HasURL());
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url_from_data;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring title;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(data2.GetURLAndTitle(&url_from_data, &title));
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(GURL(input2).spec(), url_from_data.spec());
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST(OSExchangeDataWinTest, URLDataAccessViaCOM) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSExchangeData data;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url("http://www.google.com/");
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.SetURL(url, L"");
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedComPtr<IDataObject> com_data(
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSExchangeDataProviderWin::GetIDataObject(data));
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CLIPFORMAT cfstr_ineturl = RegisterClipboardFormat(CFSTR_INETURL);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FORMATETC format_etc =
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { cfstr_ineturl, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(S_OK, com_data->QueryGetData(&format_etc));
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STGMEDIUM medium;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(S_OK, com_data->GetData(&format_etc, &medium));
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring output =
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::win::ScopedHGlobal<wchar_t>(medium.hGlobal).get();
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(url.spec(), WideToUTF8(output));
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseStgMedium(&medium);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST(OSExchangeDataWinTest, MultipleFormatsViaCOM) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSExchangeData data;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_spec = "http://www.google.com/";
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url(url_spec);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring text = L"O hai googlz.";
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.SetURL(url, L"Google");
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.SetString(text);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedComPtr<IDataObject> com_data(
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSExchangeDataProviderWin::GetIDataObject(data));
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CLIPFORMAT cfstr_ineturl = RegisterClipboardFormat(CFSTR_INETURL);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FORMATETC url_format_etc =
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { cfstr_ineturl, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(S_OK, com_data->QueryGetData(&url_format_etc));
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FORMATETC text_format_etc =
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { CF_UNICODETEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(S_OK, com_data->QueryGetData(&text_format_etc));
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STGMEDIUM medium;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(S_OK, com_data->GetData(&url_format_etc, &medium));
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring output_url =
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::win::ScopedHGlobal<wchar_t>(medium.hGlobal).get();
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(url.spec(), WideToUTF8(output_url));
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseStgMedium(&medium);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The text is supposed to be the raw text of the URL, _NOT_ the value of
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |text|! This is because the URL is added first and thus takes precedence!
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(S_OK, com_data->GetData(&text_format_etc, &medium));
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring output_text =
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::win::ScopedHGlobal<wchar_t>(medium.hGlobal).get();
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(url_spec, WideToUTF8(output_text));
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseStgMedium(&medium);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST(OSExchangeDataWinTest, EnumerationViaCOM) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSExchangeData data;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.SetURL(GURL("http://www.google.com/"), L"");
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.SetString(L"O hai googlz.");
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CLIPFORMAT cfstr_file_group_descriptor =
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CLIPFORMAT text_x_moz_url = RegisterClipboardFormat(L"text/x-moz-url");
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedComPtr<IDataObject> com_data(
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSExchangeDataProviderWin::GetIDataObject(data));
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedComPtr<IEnumFORMATETC> enumerator;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(S_OK, com_data.get()->EnumFormatEtc(DATADIR_GET,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                enumerator.Receive()));
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test that we can get one item.
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Explictly don't reset the first time, to verify the creation state is
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // OK.
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ULONG retrieved = 0;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FORMATETC elements_array[1];
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(S_OK, enumerator->Next(1,
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<FORMATETC*>(&elements_array), &retrieved));
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(1, retrieved);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(text_x_moz_url, elements_array[0].cfFormat);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test that we can get one item with a NULL retrieved value.
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(S_OK, enumerator->Reset());
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FORMATETC elements_array[1];
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(S_OK, enumerator->Next(1,
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<FORMATETC*>(&elements_array), NULL));
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(text_x_moz_url, elements_array[0].cfFormat);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test that we can get two items.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(S_OK, enumerator->Reset());
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ULONG retrieved = 0;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FORMATETC elements_array[2];
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(S_OK, enumerator->Next(2,
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<FORMATETC*>(&elements_array), &retrieved));
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(2, retrieved);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(text_x_moz_url, elements_array[0].cfFormat);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(cfstr_file_group_descriptor, elements_array[1].cfFormat);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test that we can skip the first item.
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(S_OK, enumerator->Reset());
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(S_OK, enumerator->Skip(1));
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ULONG retrieved = 0;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FORMATETC elements_array[1];
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(S_OK, enumerator->Next(1,
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<FORMATETC*>(&elements_array), &retrieved));
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(1, retrieved);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(cfstr_file_group_descriptor, elements_array[0].cfFormat);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test that we can skip the first item, and create a clone that matches in
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this state, and modify the original without affecting the clone.
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(S_OK, enumerator->Reset());
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(S_OK, enumerator->Skip(1));
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::win::ScopedComPtr<IEnumFORMATETC> cloned_enumerator;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(S_OK, enumerator.get()->Clone(cloned_enumerator.Receive()));
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(S_OK, enumerator.get()->Reset());
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ULONG retrieved = 0;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FORMATETC elements_array[1];
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(S_OK, cloned_enumerator->Next(1,
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reinterpret_cast<FORMATETC*>(&elements_array), &retrieved));
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(1, retrieved);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(cfstr_file_group_descriptor, elements_array[0].cfFormat);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ULONG retrieved = 0;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FORMATETC elements_array[1];
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(S_OK, enumerator->Next(1,
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reinterpret_cast<FORMATETC*>(&elements_array), &retrieved));
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(1, retrieved);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(text_x_moz_url, elements_array[0].cfFormat);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST(OSExchangeDataWinTest, TestURLExchangeFormatsViaCOM) {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSExchangeData data;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_spec = "http://www.google.com/";
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url(url_spec);
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::wstring url_title = L"www.google.com";
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.SetURL(url, url_title);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // File contents access via COM
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedComPtr<IDataObject> com_data(
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSExchangeDataProviderWin::GetIDataObject(data));
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CLIPFORMAT cfstr_file_contents =
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RegisterClipboardFormat(CFSTR_FILECONTENTS);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FORMATETC format_etc =
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { cfstr_file_contents, NULL, DVASPECT_CONTENT, 0, TYMED_HGLOBAL };
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(S_OK, com_data->QueryGetData(&format_etc));
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STGMEDIUM medium;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(S_OK, com_data->GetData(&format_etc, &medium));
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::win::ScopedHGlobal<char> glob(medium.hGlobal);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string output(glob.get(), glob.Size());
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string file_contents = "[InternetShortcut]\r\nURL=";
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_contents += url_spec;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_contents += "\r\n";
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(file_contents, output);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReleaseStgMedium(&medium);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST(OSExchangeDataWinTest, FileContents) {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSExchangeData data;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string file_contents("data\0with\0nulls", 15);
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.SetFileContents(base::FilePath(L"filename.txt"), file_contents);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OSExchangeData copy(data.provider().Clone());
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath filename;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string read_contents;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(copy.GetFileContents(&filename, &read_contents));
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(L"filename.txt", filename.value());
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(file_contents, read_contents);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST(OSExchangeDataWinTest, CFHtml) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSExchangeData data;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url("http://www.google.com/");
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring html(
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      L"<HTML>\n<BODY>\n"
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      L"<b>bold.</b> <i><b>This is bold italic.</b></i>\n"
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      L"</BODY>\n</HTML>");
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.SetHtml(html, url);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check the CF_HTML too.
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string expected_cf_html(
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Version:0.9\r\nStartHTML:0000000139\r\nEndHTML:0000000288\r\n"
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "StartFragment:0000000175\r\nEndFragment:0000000252\r\n"
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "SourceURL:http://www.google.com/\r\n<html>\r\n<body>\r\n"
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "<!--StartFragment-->");
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected_cf_html += WideToUTF8(html);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected_cf_html.append("<!--EndFragment-->\r\n</body>\r\n</html>");
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  FORMATETC format = Clipboard::GetHtmlFormatType().ToFormatEtc();
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STGMEDIUM medium;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDataObject* data_object = OSExchangeDataProviderWin::GetIDataObject(data);
33090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(S_OK, data_object->GetData(&format, &medium));
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedHGlobal<char> glob(medium.hGlobal);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string output(glob.get(), glob.Size());
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(expected_cf_html, output);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseStgMedium(&medium);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST(OSExchangeDataWinTest, SetURLWithMaxPath) {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSExchangeData data;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring long_title(L'a', MAX_PATH + 1);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.SetURL(GURL("http://google.com"), long_title);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST(OSExchangeDataWinTest, ProvideURLForPlainTextURL) {
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSExchangeData data;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.SetString(L"http://google.com");
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OSExchangeData data2(data.provider().Clone());
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(data2.HasURL());
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL read_url;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring title;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(data2.GetURLAndTitle(&read_url, &title));
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(GURL("http://google.com"), read_url);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ui
356