Remove cf_html from webdropdata.h. This is windows
specific code so we should handle it before we get to webkit. CF_HTML needs the source URL to resolve relative URLs so I added that to the format and plumb it through from webcore. I also did some small refactoring so we only have one implementation of converting to/from CF_HTML and regular markup. We can tweak these converters (and add unit tests) in follow up changes. Review URL: http://codereview.chromium.org/11247 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@5662 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
base
chrome
browser
common
webkit
@ -168,14 +168,6 @@ class Clipboard {
|
||||
// Safely write to system clipboard. Free |handle| on failure.
|
||||
void WriteToClipboard(FormatType format, HANDLE handle);
|
||||
|
||||
static void MarkupToHTMLClipboardFormat(const std::string& markup,
|
||||
const std::string& src_url,
|
||||
std::string* html_fragment);
|
||||
|
||||
static void ParseHTMLClipboardFormat(const std::string& html_fragment,
|
||||
std::wstring* markup,
|
||||
std::string* src_url);
|
||||
|
||||
static void ParseBookmarkClipboardFormat(const std::wstring& bookmark,
|
||||
std::wstring* title,
|
||||
std::string* url);
|
||||
|
@ -306,26 +306,25 @@ bool ClipboardUtil::GetPlainText(IDataObject* data_object,
|
||||
return success;
|
||||
}
|
||||
|
||||
bool ClipboardUtil::GetCFHtml(IDataObject* data_object,
|
||||
std::wstring* cf_html) {
|
||||
DCHECK(data_object && cf_html);
|
||||
if (FAILED(data_object->QueryGetData(GetHtmlFormat())))
|
||||
return false;
|
||||
bool ClipboardUtil::GetHtml(IDataObject* data_object,
|
||||
std::wstring* html, std::string* base_url) {
|
||||
DCHECK(data_object && html && base_url);
|
||||
|
||||
STGMEDIUM store;
|
||||
if (FAILED(data_object->GetData(GetHtmlFormat(), &store)))
|
||||
return false;
|
||||
if (SUCCEEDED(data_object->QueryGetData(GetHtmlFormat()))) {
|
||||
STGMEDIUM store;
|
||||
if (SUCCEEDED(data_object->GetData(GetHtmlFormat(), &store))) {
|
||||
// MS CF html
|
||||
ScopedHGlobal<char> data(store.hGlobal);
|
||||
|
||||
// MS CF html
|
||||
ScopedHGlobal<char> data(store.hGlobal);
|
||||
cf_html->assign(UTF8ToWide(std::string(data.get(), data.Size())));
|
||||
ReleaseStgMedium(&store);
|
||||
return true;
|
||||
}
|
||||
std::string html_utf8;
|
||||
CFHtmlToHtml(std::string(data.get(), data.Size()), &html_utf8, base_url);
|
||||
html->assign(UTF8ToWide(html_utf8));
|
||||
|
||||
ReleaseStgMedium(&store);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool ClipboardUtil::GetTextHtml(IDataObject* data_object,
|
||||
std::wstring* text_html) {
|
||||
DCHECK(data_object && text_html);
|
||||
if (FAILED(data_object->QueryGetData(GetTextHtmlFormat())))
|
||||
return false;
|
||||
|
||||
@ -333,9 +332,9 @@ bool ClipboardUtil::GetTextHtml(IDataObject* data_object,
|
||||
if (FAILED(data_object->GetData(GetTextHtmlFormat(), &store)))
|
||||
return false;
|
||||
|
||||
// raw html
|
||||
// text/html
|
||||
ScopedHGlobal<wchar_t> data(store.hGlobal);
|
||||
text_html->assign(data.get());
|
||||
html->assign(data.get());
|
||||
ReleaseStgMedium(&store);
|
||||
return true;
|
||||
}
|
||||
@ -373,3 +372,113 @@ bool ClipboardUtil::GetFileContents(IDataObject* data_object,
|
||||
return true;
|
||||
}
|
||||
|
||||
// HtmlToCFHtml and CFHtmlToHtml are based on similar methods in
|
||||
// WebCore/platform/win/ClipboardUtilitiesWin.cpp.
|
||||
/*
|
||||
* Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// Helper method for converting from text/html to MS CF_HTML.
|
||||
// Documentation for the CF_HTML format is available at
|
||||
// http://msdn.microsoft.com/en-us/library/aa767917(VS.85).aspx
|
||||
std::string ClipboardUtil::HtmlToCFHtml(const std::string& html,
|
||||
const std::string& base_url) {
|
||||
if (html.empty())
|
||||
return std::string();
|
||||
|
||||
#define MAX_DIGITS 10
|
||||
#define MAKE_NUMBER_FORMAT_1(digits) MAKE_NUMBER_FORMAT_2(digits)
|
||||
#define MAKE_NUMBER_FORMAT_2(digits) "%0" #digits "u"
|
||||
#define NUMBER_FORMAT MAKE_NUMBER_FORMAT_1(MAX_DIGITS)
|
||||
|
||||
static const char* header = "Version:0.9\r\n"
|
||||
"StartHTML:" NUMBER_FORMAT "\r\n"
|
||||
"EndHTML:" NUMBER_FORMAT "\r\n"
|
||||
"StartFragment:" NUMBER_FORMAT "\r\n"
|
||||
"EndFragment:" NUMBER_FORMAT "\r\n";
|
||||
static const char* source_url_prefix = "SourceURL:";
|
||||
|
||||
static const char* start_markup =
|
||||
"<html>\r\n<body>\r\n<!--StartFragment-->\r\n";
|
||||
static const char* end_markup =
|
||||
"\r\n<!--EndFragment-->\r\n</body>\r\n</html>";
|
||||
|
||||
// Calculate offsets
|
||||
size_t start_html_offset = strlen(header) - strlen(NUMBER_FORMAT) * 4 +
|
||||
MAX_DIGITS * 4;
|
||||
if (!base_url.empty()) {
|
||||
start_html_offset += strlen(source_url_prefix) +
|
||||
base_url.length() + 1;
|
||||
}
|
||||
size_t start_fragment_offset = start_html_offset + strlen(start_markup);
|
||||
size_t end_fragment_offset = start_fragment_offset + html.length();
|
||||
size_t end_html_offset = end_fragment_offset + strlen(end_markup);
|
||||
|
||||
std::string result = StringPrintf(header, start_html_offset,
|
||||
end_html_offset, start_fragment_offset, end_fragment_offset);
|
||||
if (!base_url.empty()) {
|
||||
result.append(source_url_prefix);
|
||||
result.append(base_url);
|
||||
result.append("\r\n");
|
||||
}
|
||||
result.append(start_markup);
|
||||
result.append(html);
|
||||
result.append(end_markup);
|
||||
|
||||
#undef MAX_DIGITS
|
||||
#undef MAKE_NUMBER_FORMAT_1
|
||||
#undef MAKE_NUMBER_FORMAT_2
|
||||
#undef NUMBER_FORMAT
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Helper method for converting from MS CF_HTML to text/html.
|
||||
void ClipboardUtil::CFHtmlToHtml(const std::string& cf_html,
|
||||
std::string* html,
|
||||
std::string* base_url) {
|
||||
// Obtain base_url if present.
|
||||
static std::string src_url_str("SourceURL:");
|
||||
size_t line_start = cf_html.find(src_url_str);
|
||||
if (line_start != std::string::npos) {
|
||||
size_t src_end = cf_html.find("\n", line_start);
|
||||
size_t src_start = line_start + src_url_str.length();
|
||||
if (src_end != std::string::npos && src_start != std::string::npos) {
|
||||
*base_url = cf_html.substr(src_start, src_end - src_start);
|
||||
}
|
||||
}
|
||||
|
||||
// Find the markup between "<!--StartFragment -->" and "<!--EndFragment-->".
|
||||
std::string cf_html_lower = StringToLowerASCII(cf_html);
|
||||
size_t markup_start = cf_html_lower.find("<html", 0);
|
||||
size_t tag_start = cf_html.find("StartFragment", markup_start);
|
||||
size_t fragment_start = cf_html.find('>', tag_start) + 1;
|
||||
size_t tag_end = cf_html.find("EndFragment", fragment_start);
|
||||
size_t fragment_end = cf_html.rfind('<', tag_end);
|
||||
if (fragment_start != std::string::npos &&
|
||||
fragment_end != std::string::npos) {
|
||||
*html = cf_html.substr(fragment_start, fragment_end - fragment_start);
|
||||
TrimWhitespace(*html, TRIM_ALL, html);
|
||||
}
|
||||
}
|
||||
|
@ -43,10 +43,16 @@ class ClipboardUtil {
|
||||
static bool GetFilenames(IDataObject* data_object,
|
||||
std::vector<std::wstring>* filenames);
|
||||
static bool GetPlainText(IDataObject* data_object, std::wstring* plain_text);
|
||||
static bool GetCFHtml(IDataObject* data_object, std::wstring* cf_html);
|
||||
static bool GetTextHtml(IDataObject* data_object, std::wstring* text_html);
|
||||
static bool GetHtml(IDataObject* data_object, std::wstring* text_html,
|
||||
std::string* base_url);
|
||||
static bool GetFileContents(IDataObject* data_object,
|
||||
std::wstring* filename,
|
||||
std::string* file_contents);
|
||||
};
|
||||
|
||||
// A helper method for converting between MS CF_HTML format and plain
|
||||
// text/html.
|
||||
static std::string HtmlToCFHtml(const std::string& html,
|
||||
const std::string& base_url);
|
||||
static void CFHtmlToHtml(const std::string& cf_html, std::string* html,
|
||||
std::string* base_url);
|
||||
};
|
||||
|
@ -178,14 +178,13 @@ void Clipboard::WriteHTML(const char* markup_data,
|
||||
size_t markup_len,
|
||||
const char* url_data,
|
||||
size_t url_len) {
|
||||
std::string html_fragment,
|
||||
markup(markup_data, markup_len),
|
||||
url;
|
||||
std::string markup(markup_data, markup_len);
|
||||
std::string url;
|
||||
|
||||
if (url_len > 0)
|
||||
url.assign(url_data, url_len);
|
||||
|
||||
MarkupToHTMLClipboardFormat(markup, url, &html_fragment);
|
||||
std::string html_fragment = ClipboardUtil::HtmlToCFHtml(markup, url);
|
||||
HGLOBAL glob = CreateGlobalData(html_fragment);
|
||||
|
||||
WriteToClipboard(GetHtmlFormatType(), glob);
|
||||
@ -437,7 +436,9 @@ void Clipboard::ReadHTML(std::wstring* markup, std::string* src_url) const {
|
||||
std::string html_fragment(static_cast<const char*>(::GlobalLock(data)));
|
||||
::GlobalUnlock(data);
|
||||
|
||||
ParseHTMLClipboardFormat(html_fragment, markup, src_url);
|
||||
std::string markup_utf8;
|
||||
ClipboardUtil::CFHtmlToHtml(html_fragment, &markup_utf8, src_url);
|
||||
markup->assign(UTF8ToWide(markup_utf8));
|
||||
}
|
||||
|
||||
void Clipboard::ReadBookmark(std::wstring* title, std::string* url) const {
|
||||
@ -508,104 +509,6 @@ void Clipboard::ReadFiles(std::vector<std::wstring>* files) const {
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void Clipboard::MarkupToHTMLClipboardFormat(const std::string& markup,
|
||||
const std::string& src_url,
|
||||
std::string* html_fragment) {
|
||||
DCHECK(html_fragment);
|
||||
// Documentation for the CF_HTML format is available at
|
||||
// http://msdn.microsoft.com/workshop/networking/clipboard/htmlclipboard.asp
|
||||
|
||||
if (markup.empty()) {
|
||||
html_fragment->clear();
|
||||
return;
|
||||
}
|
||||
|
||||
html_fragment->assign("Version:0.9");
|
||||
|
||||
std::string start_html("\nStartHTML:");
|
||||
std::string end_html("\nEndHTML:");
|
||||
std::string start_fragment("\nStartFragment:");
|
||||
std::string end_fragment("\nEndFragment:");
|
||||
std::string source_url("\nSourceURL:");
|
||||
|
||||
bool has_source_url = !src_url.empty() &&
|
||||
!StartsWithASCII(src_url, "about:", false);
|
||||
if (has_source_url)
|
||||
source_url.append(src_url);
|
||||
|
||||
std::string start_markup("\n<HTML>\n<BODY>\n<!--StartFragment-->\n");
|
||||
std::string end_markup("\n<!--EndFragment-->\n</BODY>\n</HTML>");
|
||||
|
||||
// calculate offsets
|
||||
const size_t kMaxDigits = 10; // number of digits in UINT_MAX in base 10
|
||||
|
||||
size_t start_html_offset, start_fragment_offset;
|
||||
size_t end_fragment_offset, end_html_offset;
|
||||
|
||||
start_html_offset = html_fragment->length() +
|
||||
start_html.length() + end_html.length() +
|
||||
start_fragment.length() + end_fragment.length() +
|
||||
(has_source_url ? source_url.length() : 0) +
|
||||
(4*kMaxDigits);
|
||||
|
||||
start_fragment_offset = start_html_offset + start_markup.length();
|
||||
end_fragment_offset = start_fragment_offset + markup.length();
|
||||
end_html_offset = end_fragment_offset + end_markup.length();
|
||||
|
||||
// fill in needed data
|
||||
start_html.append(StringPrintf("%010u", start_html_offset));
|
||||
end_html.append(StringPrintf("%010u", end_html_offset));
|
||||
start_fragment.append(StringPrintf("%010u", start_fragment_offset));
|
||||
end_fragment.append(StringPrintf("%010u", end_fragment_offset));
|
||||
start_markup.append(markup);
|
||||
|
||||
// create full html_fragment string from the fragments
|
||||
html_fragment->append(start_html);
|
||||
html_fragment->append(end_html);
|
||||
html_fragment->append(start_fragment);
|
||||
html_fragment->append(end_fragment);
|
||||
if (has_source_url)
|
||||
html_fragment->append(source_url);
|
||||
html_fragment->append(start_markup);
|
||||
html_fragment->append(end_markup);
|
||||
}
|
||||
|
||||
// static
|
||||
void Clipboard::ParseHTMLClipboardFormat(const std::string& html_frag,
|
||||
std::wstring* markup,
|
||||
std::string* src_url) {
|
||||
if (src_url) {
|
||||
// Obtain SourceURL, if present
|
||||
std::string src_url_str("SourceURL:");
|
||||
size_t line_start = html_frag.find(src_url_str, 0);
|
||||
if (line_start != std::string::npos) {
|
||||
size_t src_start = line_start+src_url_str.length();
|
||||
size_t src_end = html_frag.find("\n", line_start);
|
||||
|
||||
if (src_end != std::string::npos)
|
||||
*src_url = html_frag.substr(src_start, src_end - src_start);
|
||||
}
|
||||
}
|
||||
|
||||
if (markup) {
|
||||
// Find the markup between "<!--StartFragment -->" and
|
||||
// "<!--EndFragment -->", accounting for browser quirks
|
||||
size_t markup_start = html_frag.find('<', 0);
|
||||
size_t tag_start = html_frag.find("StartFragment", markup_start);
|
||||
size_t frag_start = html_frag.find('>', tag_start) + 1;
|
||||
// Here we do something slightly differently than WebKit. Webkit does a
|
||||
// forward find for EndFragment, but that seems to be a bug if the html
|
||||
// fragment actually includes the string "EndFragment"
|
||||
size_t tag_end = html_frag.rfind("EndFragment", std::string::npos);
|
||||
size_t frag_end = html_frag.rfind('<', tag_end);
|
||||
|
||||
TrimWhitespace(UTF8ToWide(html_frag.substr(frag_start,
|
||||
frag_end - frag_start)),
|
||||
TRIM_ALL, markup);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void Clipboard::ParseBookmarkClipboardFormat(const std::wstring& bookmark,
|
||||
std::wstring* title,
|
||||
|
@ -38,7 +38,7 @@ void ScopedClipboardWriter::WriteHTML(const std::wstring& markup,
|
||||
Clipboard::ObjectMapParams params;
|
||||
params.push_back(
|
||||
Clipboard::ObjectMapParam(utf8_markup.begin(),
|
||||
utf8_markup.end()));
|
||||
utf8_markup.end()));
|
||||
if (!src_url.empty()) {
|
||||
params.push_back(Clipboard::ObjectMapParam(src_url.begin(),
|
||||
src_url.end()));
|
||||
|
@ -100,8 +100,8 @@ void WebContentsViewWin::StartDragging(const WebDropData& drop_data) {
|
||||
data->SetFileContents(drop_data.file_description_filename,
|
||||
drop_data.file_contents);
|
||||
}
|
||||
if (!drop_data.cf_html.empty())
|
||||
data->SetCFHtml(drop_data.cf_html);
|
||||
if (!drop_data.text_html.empty())
|
||||
data->SetHtml(drop_data.text_html, drop_data.html_base_url);
|
||||
if (drop_data.url.is_valid()) {
|
||||
if (drop_data.url.SchemeIs("javascript")) {
|
||||
// We don't want to allow javascript URLs to be dragged to the desktop,
|
||||
|
@ -335,11 +335,20 @@ void OSExchangeData::SetFileContents(const std::wstring& filename,
|
||||
ClipboardUtil::GetFileContentFormatZero()->cfFormat, storage));
|
||||
}
|
||||
|
||||
void OSExchangeData::SetCFHtml(const std::wstring& cf_html) {
|
||||
std::string utf8 = WideToUTF8(cf_html);
|
||||
STGMEDIUM* storage = GetStorageForBytes(utf8.c_str(), utf8.size());
|
||||
void OSExchangeData::SetHtml(const std::wstring& html, const GURL& base_url) {
|
||||
// Add both MS CF_HTML and text/html format. CF_HTML should be in utf-8.
|
||||
std::string utf8_html = WideToUTF8(html);
|
||||
std::string url = base_url.is_valid() ? base_url.spec() : std::string();
|
||||
|
||||
std::string cf_html = ClipboardUtil::HtmlToCFHtml(utf8_html, url);
|
||||
STGMEDIUM* storage = GetStorageForBytes(cf_html.c_str(), cf_html.size());
|
||||
contents_.push_back(new StoredDataInfo(
|
||||
ClipboardUtil::GetHtmlFormat()->cfFormat, storage));
|
||||
|
||||
STGMEDIUM* storage_plain = GetStorageForBytes(utf8_html.c_str(),
|
||||
utf8_html.size());
|
||||
contents_.push_back(new StoredDataInfo(
|
||||
ClipboardUtil::GetTextHtmlFormat()->cfFormat, storage_plain));
|
||||
}
|
||||
|
||||
bool OSExchangeData::GetString(std::wstring* data) const {
|
||||
@ -395,8 +404,12 @@ bool OSExchangeData::GetFileContents(std::wstring* filename,
|
||||
file_contents);
|
||||
}
|
||||
|
||||
bool OSExchangeData::GetCFHtml(std::wstring* cf_html) const {
|
||||
return ClipboardUtil::GetCFHtml(source_object_, cf_html);
|
||||
bool OSExchangeData::GetHtml(std::wstring* html, GURL* base_url) const {
|
||||
std::string url;
|
||||
bool success = ClipboardUtil::GetHtml(source_object_, html, &url);
|
||||
if (success)
|
||||
*base_url = GURL(url);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool OSExchangeData::HasString() const {
|
||||
|
@ -56,8 +56,9 @@ class OSExchangeData : public IDataObject {
|
||||
// Adds the bytes of a file (CFSTR_FILECONTENTS and CFSTR_FILEDESCRIPTOR).
|
||||
void SetFileContents(const std::wstring& filename,
|
||||
const std::string& file_contents);
|
||||
// Adds a snippet of Windows HTML (CF_HTML).
|
||||
void SetCFHtml(const std::wstring& cf_html);
|
||||
// Adds a snippet of HTML. |html| is just raw html but this sets both
|
||||
// text/html and CF_HTML.
|
||||
void SetHtml(const std::wstring& html, const GURL& base_url);
|
||||
|
||||
// These functions retrieve data of the specified type. If data exists, the
|
||||
// functions return and the result is in the out parameter. If the data does
|
||||
@ -70,7 +71,7 @@ class OSExchangeData : public IDataObject {
|
||||
bool GetPickledData(CLIPFORMAT format, Pickle* data) const;
|
||||
bool GetFileContents(std::wstring* filename,
|
||||
std::string* file_contents) const;
|
||||
bool GetCFHtml(std::wstring* cf_html) const;
|
||||
bool GetHtml(std::wstring* html, GURL* base_url) const;
|
||||
|
||||
// Test whether or not data of certain types is present, without actually
|
||||
// returning anything.
|
||||
@ -141,4 +142,3 @@ class OSExchangeData : public IDataObject {
|
||||
};
|
||||
|
||||
#endif // #ifndef CHROME_COMMON_OS_EXCHANGE_DATA_H__
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <atlbase.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
#include "base/clipboard_util.h"
|
||||
#include "base/pickle.h"
|
||||
#include "base/ref_counted.h"
|
||||
#include "base/scoped_handle.h"
|
||||
@ -313,16 +314,33 @@ TEST(OSExchangeDataTest, FileContents) {
|
||||
|
||||
TEST(OSExchangeDataTest, Html) {
|
||||
scoped_refptr<OSExchangeData> data(new OSExchangeData);
|
||||
std::wstring html(L"Version:0.9\nStartHTML:71\nEndHTML:160\n"
|
||||
L"StartFragment:130\nEndFragment:150\n<HTML>\n<BODY>\n"
|
||||
L"<!--StartFragment-->\n<b>bold.</b> <i><b>This is bold italic.</b></i>\n"
|
||||
L"<!--EndFragment-->\n</BODY>\n</HTML>");
|
||||
data->SetCFHtml(html);
|
||||
GURL url("http://www.google.com/");
|
||||
std::wstring html(
|
||||
L"<HTML>\n<BODY>\n"
|
||||
L"<b>bold.</b> <i><b>This is bold italic.</b></i>\n"
|
||||
L"</BODY>\n</HTML>");
|
||||
data->SetHtml(html, url);
|
||||
|
||||
scoped_refptr<OSExchangeData> copy(new OSExchangeData(data.get()));
|
||||
std::wstring read_html;
|
||||
EXPECT_TRUE(copy->GetCFHtml(&read_html));
|
||||
EXPECT_TRUE(copy->GetHtml(&read_html, &url));
|
||||
EXPECT_EQ(html, read_html);
|
||||
|
||||
// Check the CF_HTML too.
|
||||
std::string expected_cf_html(
|
||||
"Version:0.9\r\nStartHTML:0000000138\r\nEndHTML:0000000291\r\n"
|
||||
"StartFragment:0000000176\r\nEndFragment:0000000253\r\n"
|
||||
"SourceURL:http://www.google.com/\r\n<html>\r\n<body>\r\n"
|
||||
"<!--StartFragment-->\r\n");
|
||||
expected_cf_html += WideToUTF8(html);
|
||||
expected_cf_html.append("\r\n<!--EndFragment-->\r\n</body>\r\n</html>");
|
||||
|
||||
STGMEDIUM medium;
|
||||
EXPECT_EQ(S_OK, data->GetData(ClipboardUtil::GetHtmlFormat(), &medium));
|
||||
ScopedHGlobal<char> glob(medium.hGlobal);
|
||||
std::string output(glob.get(), glob.Size());
|
||||
EXPECT_EQ(expected_cf_html, output);
|
||||
ReleaseStgMedium(&medium);
|
||||
}
|
||||
|
||||
TEST(OSExchangeDataTest, SetURLWithMaxPath) {
|
||||
|
@ -1662,8 +1662,8 @@ struct ParamTraits<WebDropData> {
|
||||
WriteParam(m, p.url_title);
|
||||
WriteParam(m, p.filenames);
|
||||
WriteParam(m, p.plain_text);
|
||||
WriteParam(m, p.cf_html);
|
||||
WriteParam(m, p.text_html);
|
||||
WriteParam(m, p.html_base_url);
|
||||
WriteParam(m, p.file_description_filename);
|
||||
WriteParam(m, p.file_contents);
|
||||
}
|
||||
@ -1673,8 +1673,8 @@ struct ParamTraits<WebDropData> {
|
||||
ReadParam(m, iter, &p->url_title) &&
|
||||
ReadParam(m, iter, &p->filenames) &&
|
||||
ReadParam(m, iter, &p->plain_text) &&
|
||||
ReadParam(m, iter, &p->cf_html) &&
|
||||
ReadParam(m, iter, &p->text_html) &&
|
||||
ReadParam(m, iter, &p->html_base_url) &&
|
||||
ReadParam(m, iter, &p->file_description_filename) &&
|
||||
ReadParam(m, iter, &p->file_contents);
|
||||
}
|
||||
|
@ -16,114 +16,6 @@
|
||||
|
||||
#include "webkit/glue/glue_util.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// TODO(tc): CF_HTML logic should move into the browser process since it only
|
||||
// makes sense on Windows.
|
||||
#if defined(OS_WIN)
|
||||
void append(WTF::Vector<char>& vector, const WebCore::CString& string) {
|
||||
vector.append(string.data(), string.length());
|
||||
}
|
||||
// Documentation for the CF_HTML format is available at
|
||||
// http://msdn.microsoft.com/workshop/networking/clipboard/htmlclipboard.asp
|
||||
void markupToCF_HTML(const WebCore::String& markup,
|
||||
const WebCore::String& src_url,
|
||||
WTF::Vector<char>& result) {
|
||||
if (markup.isEmpty())
|
||||
return;
|
||||
|
||||
#define MAX_DIGITS 10
|
||||
#define MAKE_NUMBER_FORMAT_1(digits) MAKE_NUMBER_FORMAT_2(digits)
|
||||
#define MAKE_NUMBER_FORMAT_2(digits) "%0" #digits "u"
|
||||
#define NUMBER_FORMAT MAKE_NUMBER_FORMAT_1(MAX_DIGITS)
|
||||
|
||||
static const char* header = "Version:0.9\n"
|
||||
"StartHTML:" NUMBER_FORMAT "\n"
|
||||
"EndHTML:" NUMBER_FORMAT "\n"
|
||||
"StartFragment:" NUMBER_FORMAT "\n"
|
||||
"EndFragment:" NUMBER_FORMAT "\n";
|
||||
static const char* source_url_prefix = "SourceURL:";
|
||||
|
||||
static const char* start_markup = "<HTML>\n<BODY>\n<!--StartFragment-->\n";
|
||||
static const char* end_markup = "\n<!--EndFragment-->\n</BODY>\n</HTML>";
|
||||
|
||||
WebCore::CString source_url_utf8 = (src_url == WebCore::blankURL()) ?
|
||||
"" : src_url.utf8();
|
||||
WebCore::CString markup_utf8 = markup.utf8();
|
||||
|
||||
// calculate offsets
|
||||
size_t start_html_offset = strlen(header) - strlen(NUMBER_FORMAT) * 4 +
|
||||
MAX_DIGITS * 4;
|
||||
if (source_url_utf8.length()) {
|
||||
start_html_offset += strlen(source_url_prefix) +
|
||||
source_url_utf8.length() + 1;
|
||||
}
|
||||
size_t start_fragment_offset = start_html_offset + strlen(start_markup);
|
||||
size_t end_fragment_offset = start_fragment_offset + markup_utf8.length();
|
||||
size_t end_html_offset = end_fragment_offset + strlen(end_markup);
|
||||
|
||||
append(result, WebCore::String::format(header, start_html_offset,
|
||||
end_html_offset, start_fragment_offset, end_fragment_offset).utf8());
|
||||
if (source_url_utf8.length()) {
|
||||
append(result, source_url_prefix);
|
||||
append(result, source_url_utf8);
|
||||
result.append('\n');
|
||||
}
|
||||
append(result, start_markup);
|
||||
append(result, markup_utf8);
|
||||
append(result, end_markup);
|
||||
|
||||
#undef MAX_DIGITS
|
||||
#undef MAKE_NUMBER_FORMAT_1
|
||||
#undef MAKE_NUMBER_FORMAT_2
|
||||
#undef NUMBER_FORMAT
|
||||
}
|
||||
#endif
|
||||
|
||||
std::wstring HTMLToCFHTML(const WebCore::String& html,
|
||||
const WebCore::KURL& url) {
|
||||
#if defined(OS_WIN)
|
||||
Vector<char> cf_html_data;
|
||||
markupToCF_HTML(html, url, cf_html_data);
|
||||
WebCore::String cf_html_str(cf_html_data.data(), cf_html_data.size());
|
||||
return webkit_glue::StringToStdWString(cf_html_str);
|
||||
#else
|
||||
return std::wstring();
|
||||
#endif
|
||||
}
|
||||
|
||||
WebCore::String CFHTMLToHTML(const std::wstring& cf_html_wstr) {
|
||||
#if defined(OS_WIN)
|
||||
WebCore::String cf_html = webkit_glue::StdWStringToString(cf_html_wstr);
|
||||
// Obtain baseURL if present.
|
||||
WebCore::String src_url_str("sourceURL:");
|
||||
WebCore::String src_url;
|
||||
unsigned int line_start = cf_html.find(src_url_str, 0, false);
|
||||
if (line_start != -1) {
|
||||
unsigned int src_end = cf_html.find("\n", line_start, false);
|
||||
unsigned int src_start = line_start + src_url_str.length();
|
||||
WebCore::String raw_src_url = cf_html.substring(src_start, src_end - src_start);
|
||||
replaceNBSPWithSpace(raw_src_url);
|
||||
src_url = raw_src_url.stripWhiteSpace();
|
||||
}
|
||||
|
||||
// find the markup between "<!--StartFragment -->" and "<!--EndFragment
|
||||
// -->", accounting for browser quirks
|
||||
unsigned markup_start = cf_html.find("<html", 0, false);
|
||||
unsigned tag_start = cf_html.find("startfragment", markup_start, false);
|
||||
unsigned fragment_start = cf_html.find('>', tag_start) + 1;
|
||||
unsigned tag_end = cf_html.find("endfragment", fragment_start, false);
|
||||
unsigned fragment_end = cf_html.reverseFind('<', tag_end);
|
||||
WebCore::String markup = cf_html.substring(fragment_start,
|
||||
fragment_end - fragment_start).stripWhiteSpace();
|
||||
return markup;
|
||||
#else
|
||||
return WebCore::String();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace webkit_glue {
|
||||
|
||||
WebDropData ChromiumDataObjectToWebDropData(
|
||||
@ -139,9 +31,8 @@ WebDropData ChromiumDataObjectToWebDropData(
|
||||
|
||||
drop_data.plain_text = StringToStdWString(data_object->plain_text);
|
||||
|
||||
drop_data.cf_html = HTMLToCFHTML(data_object->text_html, data_object->url);
|
||||
|
||||
drop_data.text_html = StringToStdWString(data_object->text_html);
|
||||
drop_data.html_base_url = KURLToGURL(data_object->html_base_url);
|
||||
|
||||
drop_data.file_description_filename = StringToStdWString(
|
||||
data_object->file_content_filename);
|
||||
@ -167,10 +58,7 @@ PassRefPtr<WebCore::ChromiumDataObject> WebDropDataToChromiumDataObject(
|
||||
data_object->plain_text = StdWStringToString(drop_data.plain_text);
|
||||
|
||||
data_object->text_html = StdWStringToString(drop_data.text_html);
|
||||
if (data_object->text_html.isEmpty()) {
|
||||
// Use CF_HTML only if there's no text/html data.
|
||||
data_object->text_html = CFHTMLToHTML(drop_data.cf_html);
|
||||
}
|
||||
data_object->html_base_url = GURLToKURL(drop_data.html_base_url);
|
||||
|
||||
data_object->file_content_filename = StdWStringToString(
|
||||
drop_data.file_description_filename);
|
||||
|
@ -20,8 +20,11 @@ void WebDropData::PopulateWebDropData(IDataObject* data_object,
|
||||
}
|
||||
ClipboardUtil::GetFilenames(data_object, &drop_data->filenames);
|
||||
ClipboardUtil::GetPlainText(data_object, &drop_data->plain_text);
|
||||
ClipboardUtil::GetCFHtml(data_object, &drop_data->cf_html);
|
||||
ClipboardUtil::GetTextHtml(data_object, &drop_data->text_html);
|
||||
std::string base_url;
|
||||
ClipboardUtil::GetHtml(data_object, &drop_data->text_html, &base_url);
|
||||
if (!base_url.empty()) {
|
||||
drop_data->html_base_url = GURL(base_url);
|
||||
}
|
||||
ClipboardUtil::GetFileContents(data_object,
|
||||
&drop_data->file_description_filename, &drop_data->file_contents);
|
||||
}
|
||||
|
@ -26,14 +26,11 @@ struct WebDropData {
|
||||
// User is dragging plain text into the webview.
|
||||
std::wstring plain_text;
|
||||
|
||||
// User is dragging MS HTML into the webview (e.g., out of IE).
|
||||
// TODO(tc): We should remove this from webdropdata because not all platforms
|
||||
// have cf_html. On the browser side, we should do the necessary conversions
|
||||
// so we still support cf_html.
|
||||
std::wstring cf_html;
|
||||
|
||||
// User is dragging text/html into the webview (e.g., out of Firefox).
|
||||
// User is dragging text/html into the webview (e.g., out of Firefox).
|
||||
// |html_base_url| is the URL that the html fragment is taken from (used to
|
||||
// resolve relative links). It's ok for |html_base_url| to be empty.
|
||||
std::wstring text_html;
|
||||
GURL html_base_url;
|
||||
|
||||
// User is dragging data from the webview (e.g., an image).
|
||||
std::wstring file_description_filename;
|
||||
|
@ -39,6 +39,7 @@ void ChromiumDataObject::clear()
|
||||
filenames.clear();
|
||||
plain_text = "";
|
||||
text_html = "";
|
||||
html_base_url = KURL();
|
||||
file_content_filename = "";
|
||||
if (file_content)
|
||||
file_content->clear();
|
||||
|
@ -57,6 +57,7 @@ namespace WebCore {
|
||||
String plain_text;
|
||||
|
||||
String text_html;
|
||||
KURL html_base_url;
|
||||
|
||||
String file_content_filename;
|
||||
RefPtr<SharedBuffer> file_content;
|
||||
|
@ -331,6 +331,7 @@ void ClipboardChromium::writeURL(const KURL& url, const String& title, Frame*)
|
||||
|
||||
// The URL can also be used as an HTML fragment.
|
||||
m_dataObject->text_html = urlToMarkup(url, title);
|
||||
m_dataObject->html_base_url = url;
|
||||
}
|
||||
|
||||
void ClipboardChromium::writeRange(Range* selectedRange, Frame* frame)
|
||||
@ -341,6 +342,7 @@ void ClipboardChromium::writeRange(Range* selectedRange, Frame* frame)
|
||||
|
||||
m_dataObject->text_html = createMarkup(selectedRange, 0,
|
||||
AnnotateForInterchange);
|
||||
m_dataObject->html_base_url = frame->document()->url();
|
||||
|
||||
String str = frame->selectedText();
|
||||
#if PLATFORM(WIN_OS)
|
||||
|
@ -126,21 +126,21 @@ PassRefPtr<DocumentFragment> DragData::asFragment(Document* doc) const
|
||||
* * PICT
|
||||
*/
|
||||
|
||||
// TODO(tc): Disabled because containsFilenames is hardcoded to return
|
||||
// false. We need to implement fragmentFromFilenames when this is
|
||||
// re-enabled in Apple's win port.
|
||||
//if (containsFilenames())
|
||||
// if (PassRefPtr<DocumentFragment> fragment = fragmentFromFilenames(doc, m_platformDragData))
|
||||
// return fragment;
|
||||
if (containsFiles()) {
|
||||
// TODO(tc): Implement this. Should be pretty simple to make some HTML
|
||||
// and call createFragmentFromMarkup.
|
||||
//if (RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(doc,
|
||||
// ?, KURL()))
|
||||
// return fragment;
|
||||
}
|
||||
|
||||
if (!m_platformDragData->text_html.isEmpty()) {
|
||||
String url;
|
||||
RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(doc,
|
||||
m_platformDragData->text_html, url);
|
||||
return fragment;
|
||||
}
|
||||
if (!m_platformDragData->text_html.isEmpty()) {
|
||||
RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(doc,
|
||||
m_platformDragData->text_html, m_platformDragData->html_base_url);
|
||||
return fragment.release();
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Color DragData::asColor() const
|
||||
|
Reference in New Issue
Block a user