1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "webkit/glue/webkit_glue.h"
10 #elif defined(OS_POSIX) && !defined(OS_MACOSX)
11 #include <sys/utsname.h>
20 #include "base/logging.h"
21 #include "base/memory/scoped_ptr.h"
22 #include "base/path_service.h"
23 #include "base/process_util.h"
24 #include "base/string_piece.h"
25 #include "base/string_util.h"
26 #include "base/stringprintf.h"
27 #include "base/strings/string_tokenizer.h"
28 #include "base/sys_info.h"
29 #include "base/utf_string_conversions.h"
30 #include "net/base/escape.h"
31 #include "net/url_request/url_request.h"
32 #include "skia/ext/platform_canvas.h"
33 #if defined(OS_MACOSX)
34 #include "skia/ext/skia_utils_mac.h"
36 #include "third_party/WebKit/Source/Platform/chromium/public/WebData.h"
37 #include "third_party/WebKit/Source/Platform/chromium/public/WebFileInfo.h"
38 #include "third_party/WebKit/Source/Platform/chromium/public/WebImage.h"
39 #include "third_party/WebKit/Source/Platform/chromium/public/WebRect.h"
40 #include "third_party/WebKit/Source/Platform/chromium/public/WebSize.h"
41 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
42 #include "third_party/WebKit/Source/Platform/chromium/public/WebVector.h"
43 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsAgent.h"
44 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
45 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
46 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
47 #include "third_party/WebKit/Source/WebKit/chromium/public/WebGlyphCache.h"
48 #include "third_party/WebKit/Source/WebKit/chromium/public/WebHistoryItem.h"
49 #include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
50 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPrintParams.h"
51 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
53 #include "third_party/WebKit/Source/WebKit/chromium/public/win/WebInputEventFactory.h"
55 #include "third_party/skia/include/core/SkBitmap.h"
56 #include "v8/include/v8.h"
57 #include "webkit/glue/glue_serialize.h"
59 using WebKit::WebCanvas
;
60 using WebKit::WebData
;
61 using WebKit::WebDevToolsAgent
;
62 using WebKit::WebElement
;
63 using WebKit::WebFrame
;
64 using WebKit::WebGlyphCache
;
65 using WebKit::WebHistoryItem
;
66 using WebKit::WebImage
;
67 using WebKit::WebPrintParams
;
68 using WebKit::WebRect
;
69 using WebKit::WebSize
;
70 using WebKit::WebString
;
71 using WebKit::WebVector
;
72 using WebKit::WebView
;
74 static const char kLayoutTestsPattern
[] = "/LayoutTests/";
75 static const std::string::size_type kLayoutTestsPatternSize
=
76 arraysize(kLayoutTestsPattern
) - 1;
77 static const char kFileUrlPattern
[] = "file:/";
78 static const char kDataUrlPattern
[] = "data:";
79 static const std::string::size_type kDataUrlPatternSize
=
80 arraysize(kDataUrlPattern
) - 1;
81 static const char kFileTestPrefix
[] = "(file test):";
83 //------------------------------------------------------------------------------
86 namespace webkit_glue
{
88 // Global variable used by the plugin quirk "die after unload".
89 bool g_forcefully_terminate_plugin_process
= false;
91 void SetJavaScriptFlags(const std::string
& str
) {
92 v8::V8::SetFlagsFromString(str
.data(), static_cast<int>(str
.size()));
95 void EnableWebCoreLogChannels(const std::string
& channels
) {
98 base::StringTokenizer
t(channels
, ", ");
100 WebKit::enableLogChannel(t
.token().c_str());
104 base::string16
DumpDocumentText(WebFrame
* web_frame
) {
105 // We use the document element's text instead of the body text here because
106 // not all documents have a body, such as XML documents.
107 WebElement document_element
= web_frame
->document().documentElement();
108 if (document_element
.isNull())
109 return base::string16();
111 return document_element
.innerText();
114 base::string16
DumpFramesAsText(WebFrame
* web_frame
, bool recursive
) {
115 base::string16 result
;
117 // Add header for all but the main frame. Skip empty frames.
118 if (web_frame
->parent() &&
119 !web_frame
->document().documentElement().isNull()) {
120 result
.append(ASCIIToUTF16("\n--------\nFrame: '"));
121 result
.append(web_frame
->uniqueName());
122 result
.append(ASCIIToUTF16("'\n--------\n"));
125 result
.append(DumpDocumentText(web_frame
));
126 result
.append(ASCIIToUTF16("\n"));
129 WebFrame
* child
= web_frame
->firstChild();
130 for (; child
; child
= child
->nextSibling())
131 result
.append(DumpFramesAsText(child
, recursive
));
137 base::string16
DumpRenderer(WebFrame
* web_frame
) {
138 return web_frame
->renderTreeAsText();
141 int NumberOfPages(WebFrame
* web_frame
,
142 float page_width_in_pixels
,
143 float page_height_in_pixels
) {
144 WebSize
size(static_cast<int>(page_width_in_pixels
),
145 static_cast<int>(page_height_in_pixels
));
147 WebPrintParams print_params
;
148 print_params
.paperSize
= size
;
149 print_params
.printContentArea
= WebRect(0, 0, size
.width
, size
.height
);
150 print_params
.printableArea
= WebRect(0, 0, size
.width
, size
.height
);
152 int number_of_pages
= web_frame
->printBegin(print_params
);
153 web_frame
->printEnd();
154 return number_of_pages
;
157 base::string16
DumpFrameScrollPosition(WebFrame
* web_frame
, bool recursive
) {
158 gfx::Size offset
= web_frame
->scrollOffset();
159 std::string result_utf8
;
161 if (offset
.width() > 0 || offset
.height() > 0) {
162 if (web_frame
->parent()) {
163 base::StringAppendF(&result_utf8
, "frame '%s' ",
164 UTF16ToUTF8(web_frame
->uniqueName()).c_str());
166 base::StringAppendF(&result_utf8
, "scrolled to %d,%d\n",
167 offset
.width(), offset
.height());
170 base::string16 result
= UTF8ToUTF16(result_utf8
);
173 WebFrame
* child
= web_frame
->firstChild();
174 for (; child
; child
= child
->nextSibling())
175 result
.append(DumpFrameScrollPosition(child
, recursive
));
181 // Returns True if item1 < item2.
182 static bool HistoryItemCompareLess(const WebHistoryItem
& item1
,
183 const WebHistoryItem
& item2
) {
184 base::string16 target1
= item1
.target();
185 base::string16 target2
= item2
.target();
186 std::transform(target1
.begin(), target1
.end(), target1
.begin(), tolower
);
187 std::transform(target2
.begin(), target2
.end(), target2
.begin(), tolower
);
188 return target1
< target2
;
191 // Writes out a HistoryItem into a UTF-8 string in a readable format.
192 static std::string
DumpHistoryItem(const WebHistoryItem
& item
,
193 int indent
, bool is_current
) {
197 result
.append("curr->");
198 result
.append(indent
- 6, ' '); // 6 == "curr->".length()
200 result
.append(indent
, ' ');
203 std::string url
= item
.urlString().utf8();
205 if (url
.find(kFileUrlPattern
) == 0 &&
206 ((pos
= url
.find(kLayoutTestsPattern
)) != std::string::npos
)) {
207 // adjust file URLs to match upstream results.
208 url
.replace(0, pos
+ kLayoutTestsPatternSize
, kFileTestPrefix
);
209 } else if (url
.find(kDataUrlPattern
) == 0) {
210 // URL-escape data URLs to match results upstream.
211 std::string path
= net::EscapePath(url
.substr(kDataUrlPatternSize
));
212 url
.replace(kDataUrlPatternSize
, url
.length(), path
);
216 if (!item
.target().isEmpty())
217 result
.append(" (in frame \"" + UTF16ToUTF8(item
.target()) + "\")");
218 if (item
.isTargetItem())
219 result
.append(" **nav target**");
222 const WebVector
<WebHistoryItem
>& children
= item
.children();
223 if (!children
.isEmpty()) {
224 // Must sort to eliminate arbitrary result ordering which defeats
225 // reproducible testing.
226 // TODO(darin): WebVector should probably just be a std::vector!!
227 std::vector
<WebHistoryItem
> sorted_children
;
228 for (size_t i
= 0; i
< children
.size(); ++i
)
229 sorted_children
.push_back(children
[i
]);
230 std::sort(sorted_children
.begin(), sorted_children
.end(),
231 HistoryItemCompareLess
);
232 for (size_t i
= 0; i
< sorted_children
.size(); i
++)
233 result
+= DumpHistoryItem(sorted_children
[i
], indent
+4, false);
239 base::string16
DumpHistoryState(const std::string
& history_state
, int indent
,
242 DumpHistoryItem(HistoryItemFromString(history_state
), indent
,
247 // The log macro was having problems due to collisions with WTF, so we just
248 // code here what that would have inlined.
249 void DumpLeakedObject(const char* file
, int line
, const char* object
,
251 std::string msg
= base::StringPrintf("%s LEAKED %d TIMES", object
, count
);
252 logging::LogMessage(file
, line
).stream() << msg
;
256 void CheckForLeaks() {
258 int count
= WebFrame::instanceCount();
260 DumpLeakedObject(__FILE__
, __LINE__
, "WebFrame", count
);
264 bool DecodeImage(const std::string
& image_data
, SkBitmap
* image
) {
265 WebData
web_data(image_data
.data(), image_data
.length());
266 WebImage
web_image(WebImage::fromData(web_data
, WebSize()));
267 if (web_image
.isNull())
270 *image
= web_image
.getSkBitmap();
274 void PlatformFileInfoToWebFileInfo(
275 const base::PlatformFileInfo
& file_info
,
276 WebKit::WebFileInfo
* web_file_info
) {
277 DCHECK(web_file_info
);
278 // WebKit now expects NaN as uninitialized/null Date.
279 if (file_info
.last_modified
.is_null())
280 web_file_info
->modificationTime
= std::numeric_limits
<double>::quiet_NaN();
282 web_file_info
->modificationTime
= file_info
.last_modified
.ToDoubleT();
283 web_file_info
->length
= file_info
.size
;
284 if (file_info
.is_directory
)
285 web_file_info
->type
= WebKit::WebFileInfo::TypeDirectory
;
287 web_file_info
->type
= WebKit::WebFileInfo::TypeFile
;
290 void SetForcefullyTerminatePluginProcess(bool value
) {
291 g_forcefully_terminate_plugin_process
= value
;
294 bool ShouldForcefullyTerminatePluginProcess() {
295 return g_forcefully_terminate_plugin_process
;
298 WebCanvas
* ToWebCanvas(skia::PlatformCanvas
* canvas
) {
302 int GetGlyphPageCount() {
303 return WebGlyphCache::pageCount();
306 std::string
GetInspectorProtocolVersion() {
307 return WebDevToolsAgent::inspectorProtocolVersion().utf8();
310 bool IsInspectorProtocolVersionSupported(const std::string
& version
) {
311 return WebDevToolsAgent::supportsInspectorProtocolVersion(
312 WebString::fromUTF8(version
));
315 void ConfigureURLRequestForReferrerPolicy(
316 net::URLRequest
* request
, WebKit::WebReferrerPolicy referrer_policy
) {
317 net::URLRequest::ReferrerPolicy net_referrer_policy
=
318 net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE
;
319 switch (referrer_policy
) {
320 case WebKit::WebReferrerPolicyDefault
:
321 net_referrer_policy
=
322 net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE
;
325 case WebKit::WebReferrerPolicyAlways
:
326 case WebKit::WebReferrerPolicyNever
:
327 case WebKit::WebReferrerPolicyOrigin
:
328 net_referrer_policy
= net::URLRequest::NEVER_CLEAR_REFERRER
;
331 request
->set_referrer_policy(net_referrer_policy
);
334 COMPILE_ASSERT(std::numeric_limits
<double>::has_quiet_NaN
, has_quiet_NaN
);
336 #if defined(OS_LINUX) || defined(OS_ANDROID)
337 size_t MemoryUsageKB() {
338 struct mallinfo minfo
= mallinfo();
340 #if defined(USE_TCMALLOC)
343 (minfo
.hblkhd
+ minfo
.arena
)
347 v8::HeapStatistics stat
;
348 // TODO(svenpanne) The call below doesn't take web workers into account, this
349 // has to be done manually by iterating over all Isolates involved.
350 v8::Isolate::GetCurrent()->GetHeapStatistics(&stat
);
351 return mem_usage
+ (static_cast<uint64_t>(stat
.total_heap_size()) >> 10);
353 #elif defined(OS_MACOSX)
354 size_t MemoryUsageKB() {
355 scoped_ptr
<base::ProcessMetrics
> process_metrics(
356 // The default port provider is sufficient to get data for the current
358 base::ProcessMetrics::CreateProcessMetrics(
359 base::GetCurrentProcessHandle(), NULL
));
360 return process_metrics
->GetWorkingSetSize() >> 10;
363 size_t MemoryUsageKB() {
364 scoped_ptr
<base::ProcessMetrics
> process_metrics(
365 base::ProcessMetrics::CreateProcessMetrics(
366 base::GetCurrentProcessHandle()));
367 return process_metrics
->GetPagefileUsage() >> 10;
371 double ZoomFactorToZoomLevel(double factor
) {
372 return WebView::zoomFactorToZoomLevel(factor
);
375 } // namespace webkit_glue