OLD | NEW |
1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2008 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 "config.h" | 5 #include "config.h" |
6 | 6 |
7 #include "webkit/glue/clipboard_conversion.h" | 7 #include "webkit/glue/clipboard_conversion.h" |
8 | 8 |
9 #include "build/build_config.h" | 9 #include "build/build_config.h" |
10 | 10 |
11 #include "ChromiumDataObject.h" | 11 #include "ChromiumDataObject.h" |
12 #include "ClipboardUtilitiesChromium.h" | 12 #include "ClipboardUtilitiesChromium.h" |
13 #include "KURL.h" | 13 #include "KURL.h" |
14 #include "SharedBuffer.h" | 14 #include "SharedBuffer.h" |
15 #include <wtf/Vector.h> | 15 #include <wtf/Vector.h> |
16 | 16 |
17 #include "webkit/glue/glue_util.h" | 17 #include "webkit/glue/glue_util.h" |
18 | 18 |
19 namespace { | |
20 | |
21 // TODO(tc): CF_HTML logic should move into the browser process since it only | |
22 // makes sense on Windows. | |
23 #if defined(OS_WIN) | |
24 void append(WTF::Vector<char>& vector, const WebCore::CString& string) { | |
25 vector.append(string.data(), string.length()); | |
26 } | |
27 // Documentation for the CF_HTML format is available at | |
28 // http://msdn.microsoft.com/workshop/networking/clipboard/htmlclipboard.asp | |
29 void markupToCF_HTML(const WebCore::String& markup, | |
30 const WebCore::String& src_url, | |
31 WTF::Vector<char>& result) { | |
32 if (markup.isEmpty()) | |
33 return; | |
34 | |
35 #define MAX_DIGITS 10 | |
36 #define MAKE_NUMBER_FORMAT_1(digits) MAKE_NUMBER_FORMAT_2(digits) | |
37 #define MAKE_NUMBER_FORMAT_2(digits) "%0" #digits "u" | |
38 #define NUMBER_FORMAT MAKE_NUMBER_FORMAT_1(MAX_DIGITS) | |
39 | |
40 static const char* header = "Version:0.9\n" | |
41 "StartHTML:" NUMBER_FORMAT "\n" | |
42 "EndHTML:" NUMBER_FORMAT "\n" | |
43 "StartFragment:" NUMBER_FORMAT "\n" | |
44 "EndFragment:" NUMBER_FORMAT "\n"; | |
45 static const char* source_url_prefix = "SourceURL:"; | |
46 | |
47 static const char* start_markup = "<HTML>\n<BODY>\n<!--StartFragment-->\n"; | |
48 static const char* end_markup = "\n<!--EndFragment-->\n</BODY>\n</HTML>"; | |
49 | |
50 WebCore::CString source_url_utf8 = (src_url == WebCore::blankURL()) ? | |
51 "" : src_url.utf8(); | |
52 WebCore::CString markup_utf8 = markup.utf8(); | |
53 | |
54 // calculate offsets | |
55 size_t start_html_offset = strlen(header) - strlen(NUMBER_FORMAT) * 4 + | |
56 MAX_DIGITS * 4; | |
57 if (source_url_utf8.length()) { | |
58 start_html_offset += strlen(source_url_prefix) + | |
59 source_url_utf8.length() + 1; | |
60 } | |
61 size_t start_fragment_offset = start_html_offset + strlen(start_markup); | |
62 size_t end_fragment_offset = start_fragment_offset + markup_utf8.length(); | |
63 size_t end_html_offset = end_fragment_offset + strlen(end_markup); | |
64 | |
65 append(result, WebCore::String::format(header, start_html_offset, | |
66 end_html_offset, start_fragment_offset, end_fragment_offset).utf8()); | |
67 if (source_url_utf8.length()) { | |
68 append(result, source_url_prefix); | |
69 append(result, source_url_utf8); | |
70 result.append('\n'); | |
71 } | |
72 append(result, start_markup); | |
73 append(result, markup_utf8); | |
74 append(result, end_markup); | |
75 | |
76 #undef MAX_DIGITS | |
77 #undef MAKE_NUMBER_FORMAT_1 | |
78 #undef MAKE_NUMBER_FORMAT_2 | |
79 #undef NUMBER_FORMAT | |
80 } | |
81 #endif | |
82 | |
83 std::wstring HTMLToCFHTML(const WebCore::String& html, | |
84 const WebCore::KURL& url) { | |
85 #if defined(OS_WIN) | |
86 Vector<char> cf_html_data; | |
87 markupToCF_HTML(html, url, cf_html_data); | |
88 WebCore::String cf_html_str(cf_html_data.data(), cf_html_data.size()); | |
89 return webkit_glue::StringToStdWString(cf_html_str); | |
90 #else | |
91 return std::wstring(); | |
92 #endif | |
93 } | |
94 | |
95 WebCore::String CFHTMLToHTML(const std::wstring& cf_html_wstr) { | |
96 #if defined(OS_WIN) | |
97 WebCore::String cf_html = webkit_glue::StdWStringToString(cf_html_wstr); | |
98 // Obtain baseURL if present. | |
99 WebCore::String src_url_str("sourceURL:"); | |
100 WebCore::String src_url; | |
101 unsigned int line_start = cf_html.find(src_url_str, 0, false); | |
102 if (line_start != -1) { | |
103 unsigned int src_end = cf_html.find("\n", line_start, false); | |
104 unsigned int src_start = line_start + src_url_str.length(); | |
105 WebCore::String raw_src_url = cf_html.substring(src_start, src_end - src_sta
rt); | |
106 replaceNBSPWithSpace(raw_src_url); | |
107 src_url = raw_src_url.stripWhiteSpace(); | |
108 } | |
109 | |
110 // find the markup between "<!--StartFragment -->" and "<!--EndFragment | |
111 // -->", accounting for browser quirks | |
112 unsigned markup_start = cf_html.find("<html", 0, false); | |
113 unsigned tag_start = cf_html.find("startfragment", markup_start, false); | |
114 unsigned fragment_start = cf_html.find('>', tag_start) + 1; | |
115 unsigned tag_end = cf_html.find("endfragment", fragment_start, false); | |
116 unsigned fragment_end = cf_html.reverseFind('<', tag_end); | |
117 WebCore::String markup = cf_html.substring(fragment_start, | |
118 fragment_end - fragment_start).stripWhiteSpace(); | |
119 return markup; | |
120 #else | |
121 return WebCore::String(); | |
122 #endif | |
123 } | |
124 | |
125 } // namespace | |
126 | |
127 namespace webkit_glue { | 19 namespace webkit_glue { |
128 | 20 |
129 WebDropData ChromiumDataObjectToWebDropData( | 21 WebDropData ChromiumDataObjectToWebDropData( |
130 WebCore::ChromiumDataObject* data_object) { | 22 WebCore::ChromiumDataObject* data_object) { |
131 WebDropData drop_data; | 23 WebDropData drop_data; |
132 drop_data.url = KURLToGURL(data_object->url); | 24 drop_data.url = KURLToGURL(data_object->url); |
133 drop_data.url_title = StringToStdWString(data_object->url_title); | 25 drop_data.url_title = StringToStdWString(data_object->url_title); |
134 | 26 |
135 for (size_t i = 0; i < data_object->filenames.size(); ++i) { | 27 for (size_t i = 0; i < data_object->filenames.size(); ++i) { |
136 drop_data.filenames.push_back(StringToStdWString( | 28 drop_data.filenames.push_back(StringToStdWString( |
137 data_object->filenames[i])); | 29 data_object->filenames[i])); |
138 } | 30 } |
139 | 31 |
140 drop_data.plain_text = StringToStdWString(data_object->plain_text); | 32 drop_data.plain_text = StringToStdWString(data_object->plain_text); |
141 | 33 |
142 drop_data.cf_html = HTMLToCFHTML(data_object->text_html, data_object->url); | |
143 | |
144 drop_data.text_html = StringToStdWString(data_object->text_html); | 34 drop_data.text_html = StringToStdWString(data_object->text_html); |
| 35 drop_data.html_base_url = KURLToGURL(data_object->html_base_url); |
145 | 36 |
146 drop_data.file_description_filename = StringToStdWString( | 37 drop_data.file_description_filename = StringToStdWString( |
147 data_object->file_content_filename); | 38 data_object->file_content_filename); |
148 if (data_object->file_content) { | 39 if (data_object->file_content) { |
149 drop_data.file_contents.assign(data_object->file_content->data(), | 40 drop_data.file_contents.assign(data_object->file_content->data(), |
150 data_object->file_content->size()); | 41 data_object->file_content->size()); |
151 } | 42 } |
152 | 43 |
153 return drop_data; | 44 return drop_data; |
154 } | 45 } |
155 | 46 |
156 PassRefPtr<WebCore::ChromiumDataObject> WebDropDataToChromiumDataObject( | 47 PassRefPtr<WebCore::ChromiumDataObject> WebDropDataToChromiumDataObject( |
157 const WebDropData& drop_data) { | 48 const WebDropData& drop_data) { |
158 RefPtr<WebCore::ChromiumDataObject> data_object = | 49 RefPtr<WebCore::ChromiumDataObject> data_object = |
159 WebCore::ChromiumDataObject::create(); | 50 WebCore::ChromiumDataObject::create(); |
160 data_object->url = GURLToKURL(drop_data.url); | 51 data_object->url = GURLToKURL(drop_data.url); |
161 data_object->url_title = StdWStringToString(drop_data.url_title); | 52 data_object->url_title = StdWStringToString(drop_data.url_title); |
162 | 53 |
163 for (size_t i = 0; i < drop_data.filenames.size(); ++i) { | 54 for (size_t i = 0; i < drop_data.filenames.size(); ++i) { |
164 data_object->filenames.append(StdWStringToString(drop_data.filenames[i])); | 55 data_object->filenames.append(StdWStringToString(drop_data.filenames[i])); |
165 } | 56 } |
166 | 57 |
167 data_object->plain_text = StdWStringToString(drop_data.plain_text); | 58 data_object->plain_text = StdWStringToString(drop_data.plain_text); |
168 | 59 |
169 data_object->text_html = StdWStringToString(drop_data.text_html); | 60 data_object->text_html = StdWStringToString(drop_data.text_html); |
170 if (data_object->text_html.isEmpty()) { | 61 data_object->html_base_url = GURLToKURL(drop_data.html_base_url); |
171 // Use CF_HTML only if there's no text/html data. | |
172 data_object->text_html = CFHTMLToHTML(drop_data.cf_html); | |
173 } | |
174 | 62 |
175 data_object->file_content_filename = StdWStringToString( | 63 data_object->file_content_filename = StdWStringToString( |
176 drop_data.file_description_filename); | 64 drop_data.file_description_filename); |
177 if (!drop_data.file_contents.empty()) { | 65 if (!drop_data.file_contents.empty()) { |
178 data_object->file_content = | 66 data_object->file_content = |
179 WebCore::SharedBuffer::create(drop_data.file_contents.data(), | 67 WebCore::SharedBuffer::create(drop_data.file_contents.data(), |
180 drop_data.file_contents.size()); | 68 drop_data.file_contents.size()); |
181 } | 69 } |
182 | 70 |
183 return data_object; | 71 return data_object; |
184 } | 72 } |
185 | 73 |
186 } // namespace webkit_glue | 74 } // namespace webkit_glue |
OLD | NEW |