5d8e400506fbc45b47b18623e034331f66e9f361
[WebKit-https.git] / WebKit / gtk / WebCoreSupport / DumpRenderTreeSupportGtk.cpp
1 /*
2  *  Copyright (C) Research In Motion Limited 2010. All rights reserved.
3  *  Copyright (C) 2010 Joone Hur <joone@kldp.org>
4  *  Copyright (C) 2009 Google Inc. All rights reserved.
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20
21 #include "config.h"
22 #include "DumpRenderTreeSupportGtk.h"
23
24 #include "APICast.h"
25 #include "AXObjectCache.h"
26 #include "AccessibilityObjectWrapperAtk.h"
27 #include "AnimationController.h"
28 #include "DOMWrapperWorld.h"
29 #include "Document.h"
30 #include "FocusController.h"
31 #include "FrameLoaderClientGtk.h"
32 #include "FrameTree.h"
33 #include "FrameView.h"
34 #include "GCController.h"
35 #include "GraphicsContext.h"
36 #include "JSDOMWindow.h"
37 #include "JSDocument.h"
38 #include "JSElement.h"
39 #include "JSLock.h"
40 #include "JSNodeList.h"
41 #include "JSValue.h"
42 #include "NodeList.h"
43 #include "PageGroup.h"
44 #include "PlatformString.h"
45 #include "PrintContext.h"
46 #include "RenderListItem.h"
47 #include "RenderTreeAsText.h"
48 #include "RenderView.h"
49 #include "SecurityOrigin.h"
50 #include "WorkerThread.h"
51 #include "webkitwebframe.h"
52 #include "webkitwebframeprivate.h"
53 #include "webkitwebview.h"
54 #include "webkitwebviewprivate.h"
55 #include <JavaScriptCore/APICast.h>
56
57 #if ENABLE(SVG)
58 #include "SVGSMILElement.h"
59 #endif
60
61 using namespace JSC;
62 using namespace WebCore;
63 using namespace WebKit;
64
65 bool DumpRenderTreeSupportGtk::s_drtRun = false;
66 bool DumpRenderTreeSupportGtk::s_linksIncludedInTabChain = true;
67
68 DumpRenderTreeSupportGtk::DumpRenderTreeSupportGtk()
69 {
70 }
71
72 DumpRenderTreeSupportGtk::~DumpRenderTreeSupportGtk()
73 {
74 }
75
76 void DumpRenderTreeSupportGtk::setDumpRenderTreeModeEnabled(bool enabled)
77 {
78     s_drtRun = enabled;
79 }
80
81 bool DumpRenderTreeSupportGtk::dumpRenderTreeModeEnabled()
82 {
83     return s_drtRun;
84 }
85 void DumpRenderTreeSupportGtk::setLinksIncludedInFocusChain(bool enabled)
86 {
87     s_linksIncludedInTabChain = enabled;
88 }
89
90 bool DumpRenderTreeSupportGtk::linksIncludedInFocusChain()
91 {
92     return s_linksIncludedInTabChain;
93 }
94
95 JSValueRef DumpRenderTreeSupportGtk::nodesFromRect(JSContextRef context, JSValueRef value, int x, int y, unsigned top, unsigned right, unsigned bottom, unsigned left, bool ignoreClipping)
96 {
97     JSLock lock(SilenceAssertionsOnly);
98     ExecState* exec = toJS(context);
99     if (!value)
100         return JSValueMakeUndefined(context);
101     JSValue jsValue = toJS(exec, value);
102     if (!jsValue.inherits(&JSDocument::s_info))
103        return JSValueMakeUndefined(context);
104
105     JSDocument* jsDocument = static_cast<JSDocument*>(asObject(jsValue));
106     Document* document = jsDocument->impl();
107     RefPtr<NodeList> nodes = document->nodesFromRect(x, y, top, right, bottom, left, ignoreClipping);
108     return toRef(exec, toJS(exec, jsDocument->globalObject(), nodes.get()));
109 }
110
111 /**
112  * getFrameChildren:
113  * @frame: a #WebKitWebFrame
114  *
115  * Return value: child frames of @frame
116  */
117 GSList* DumpRenderTreeSupportGtk::getFrameChildren(WebKitWebFrame* frame)
118 {
119     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), 0);
120
121     Frame* coreFrame = core(frame);
122     if (!coreFrame)
123         return 0;
124
125     GSList* children = 0;
126     for (Frame* child = coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
127         FrameLoader* loader = child->loader();
128         WebKit::FrameLoaderClient* client = static_cast<WebKit::FrameLoaderClient*>(loader->client());
129         if (client)
130           children = g_slist_append(children, client->webFrame());
131     }
132
133     return children;
134 }
135
136 /**
137  * getInnerText:
138  * @frame: a #WebKitWebFrame
139  *
140  * Return value: inner text of @frame
141  */
142 CString DumpRenderTreeSupportGtk::getInnerText(WebKitWebFrame* frame)
143 {
144     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), CString(""));
145
146     Frame* coreFrame = core(frame);
147     if (!coreFrame)
148         return CString("");
149
150     FrameView* view = coreFrame->view();
151
152     if (view && view->layoutPending())
153         view->layout();
154
155     Element* documentElement = coreFrame->document()->documentElement();
156     return documentElement->innerText().utf8();
157 }
158
159 /**
160  * dumpRenderTree:
161  * @frame: a #WebKitWebFrame
162  *
163  * Return value: Non-recursive render tree dump of @frame
164  */
165 CString DumpRenderTreeSupportGtk::dumpRenderTree(WebKitWebFrame* frame)
166 {
167     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), CString(""));
168
169     Frame* coreFrame = core(frame);
170     if (!coreFrame)
171         return CString("");
172
173     FrameView* view = coreFrame->view();
174
175     if (view && view->layoutPending())
176         view->layout();
177
178     return externalRepresentation(coreFrame).utf8();
179 }
180
181 /**
182  * counterValueForElementById:
183  * @frame: a #WebKitWebFrame
184  * @id: an element ID string
185  *
186  * Return value: The counter value of element @id in @frame
187  */
188 CString DumpRenderTreeSupportGtk::counterValueForElementById(WebKitWebFrame* frame, const char* id)
189 {
190     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), CString());
191
192     Frame* coreFrame = core(frame);
193     if (!coreFrame)
194         return CString();
195
196     Element* coreElement = coreFrame->document()->getElementById(AtomicString(id));
197     if (!coreElement)
198         return CString();
199
200     return counterValueForElement(coreElement).utf8();
201 }
202
203 /**
204  * numberForElementById
205  * @frame: a #WebKitWebFrame
206  * @id: an element ID string
207  * @pageWidth: width of a page
208  * @pageHeight: height of a page
209  *
210  * Return value: The number of page where the specified element will be put
211  */
212 int DumpRenderTreeSupportGtk::pageNumberForElementById(WebKitWebFrame* frame, const char* id, float pageWidth, float pageHeight)
213 {
214     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), 0);
215
216     Frame* coreFrame = core(frame);
217     if (!coreFrame)
218         return -1;
219
220     Element* coreElement = coreFrame->document()->getElementById(AtomicString(id));
221     if (!coreElement)
222         return -1;
223     return PrintContext::pageNumberForElement(coreElement, FloatSize(pageWidth, pageHeight));
224 }
225
226 /**
227  * numberOfPagesForFrame
228  * @frame: a #WebKitWebFrame
229  * @pageWidth: width of a page
230  * @pageHeight: height of a page
231  *
232  * Return value: The number of pages to be printed.
233  */
234 int DumpRenderTreeSupportGtk::numberOfPagesForFrame(WebKitWebFrame* frame, float pageWidth, float pageHeight)
235 {
236     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), 0);
237
238     Frame* coreFrame = core(frame);
239     if (!coreFrame)
240         return -1;
241
242     return PrintContext::numberOfPages(coreFrame, FloatSize(pageWidth, pageHeight));
243 }
244
245 /**
246  * pageProperty
247  * @frame: a #WebKitWebFrame
248  * @propertyName: name of a property
249  * @pageNumber: number of a page 
250  *
251  * Return value: The value of the given property name.
252  */
253 CString DumpRenderTreeSupportGtk::pageProperty(WebKitWebFrame* frame, const char* propertyName, int pageNumber)
254 {
255     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), CString());
256
257     Frame* coreFrame = core(frame);
258     if (!coreFrame)
259         return CString();
260
261     return PrintContext::pageProperty(coreFrame, propertyName, pageNumber).utf8();
262 }
263
264 /**
265  * isPageBoxVisible
266  * @frame: a #WebKitWebFrame
267  * @pageNumber: number of a page 
268  *
269  * Return value: TRUE if a page box is visible. 
270  */
271 bool DumpRenderTreeSupportGtk::isPageBoxVisible(WebKitWebFrame* frame, int pageNumber)
272 {
273     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), false);
274
275     Frame* coreFrame = core(frame);
276     if (!coreFrame)
277         return false;
278
279     return coreFrame->document()->isPageBoxVisible(pageNumber); 
280 }
281
282 /**
283  * pageSizeAndMarginsInPixels
284  * @frame: a #WebKitWebFrame
285  * @pageNumber: number of a page 
286  * @width: width of a page
287  * @height: height of a page
288  * @marginTop: top margin of a page
289  * @marginRight: right margin of a page
290  * @marginBottom: bottom margin of a page
291  * @marginLeft: left margin of a page
292  *
293  * Return value: The value of page size and margin.
294  */
295 CString DumpRenderTreeSupportGtk::pageSizeAndMarginsInPixels(WebKitWebFrame* frame, int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft)
296 {
297     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), CString());
298
299     Frame* coreFrame = core(frame);
300     if (!coreFrame)
301         return CString();
302
303     return PrintContext::pageSizeAndMarginsInPixels(coreFrame, pageNumber, width, height, marginTop, marginRight, marginBottom, marginLeft).utf8();
304 }
305
306 /**
307  * addUserStyleSheet
308  * @frame: a #WebKitWebFrame
309  * @sourceCode: code of a user stylesheet
310  *
311  */
312 void DumpRenderTreeSupportGtk::addUserStyleSheet(WebKitWebFrame* frame, const char* sourceCode, bool allFrames)
313 {
314     g_return_if_fail(WEBKIT_IS_WEB_FRAME(frame));
315
316     Frame* coreFrame = core(frame);
317     if (!coreFrame)
318         return;
319
320     WebKitWebView* webView = getViewFromFrame(frame);
321     Page* page = core(webView);
322     page->group().addUserStyleSheetToWorld(mainThreadNormalWorld(), sourceCode, KURL(), 0, 0, allFrames ? InjectInAllFrames : InjectInTopFrameOnly); 
323 }
324
325 /**
326  * getPendingUnloadEventCount:
327  * @frame: a #WebKitWebFrame
328  *
329  * Return value: number of pending unload events
330  */
331 guint DumpRenderTreeSupportGtk::getPendingUnloadEventCount(WebKitWebFrame* frame)
332 {
333     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), 0);
334
335     return core(frame)->domWindow()->pendingUnloadEventListeners();
336 }
337
338 bool DumpRenderTreeSupportGtk::pauseAnimation(WebKitWebFrame* frame, const char* name, double time, const char* element)
339 {
340     ASSERT(core(frame));
341     Element* coreElement = core(frame)->document()->getElementById(AtomicString(element));
342     if (!coreElement || !coreElement->renderer())
343         return false;
344     return core(frame)->animation()->pauseAnimationAtTime(coreElement->renderer(), AtomicString(name), time);
345 }
346
347 bool DumpRenderTreeSupportGtk::pauseTransition(WebKitWebFrame* frame, const char* name, double time, const char* element)
348 {
349     ASSERT(core(frame));
350     Element* coreElement = core(frame)->document()->getElementById(AtomicString(element));
351     if (!coreElement || !coreElement->renderer())
352         return false;
353     return core(frame)->animation()->pauseTransitionAtTime(coreElement->renderer(), AtomicString(name), time);
354 }
355
356 bool DumpRenderTreeSupportGtk::pauseSVGAnimation(WebKitWebFrame* frame, const char* animationId, double time, const char* elementId)
357 {
358     ASSERT(core(frame));
359 #if ENABLE(SVG)
360     Document* document = core(frame)->document();
361     if (!document || !document->svgExtensions())
362         return false;
363     Element* coreElement = document->getElementById(AtomicString(animationId));
364     if (!coreElement || !SVGSMILElement::isSMILElement(coreElement))
365         return false;
366     return document->accessSVGExtensions()->sampleAnimationAtTime(elementId, static_cast<SVGSMILElement*>(coreElement), time);
367 #else
368     return false;
369 #endif
370 }
371
372 CString DumpRenderTreeSupportGtk::markerTextForListItem(WebKitWebFrame* frame, JSContextRef context, JSValueRef nodeObject)
373 {
374     JSC::ExecState* exec = toJS(context);
375     Element* element = toElement(toJS(exec, nodeObject));
376     if (!element)
377         return CString();
378
379     return WebCore::markerTextForListItem(element).utf8();
380 }
381
382 unsigned int DumpRenderTreeSupportGtk::numberOfActiveAnimations(WebKitWebFrame* frame)
383 {
384     Frame* coreFrame = core(frame);
385     if (!coreFrame)
386         return 0;
387
388     return coreFrame->animation()->numberOfActiveAnimations();
389 }
390
391 void DumpRenderTreeSupportGtk::suspendAnimations(WebKitWebFrame* frame)
392 {
393     Frame* coreFrame = core(frame);
394     if (!coreFrame)
395         return;
396
397     return coreFrame->animation()->suspendAnimations();
398 }
399
400 void DumpRenderTreeSupportGtk::resumeAnimations(WebKitWebFrame* frame)
401 {
402     Frame* coreFrame = core(frame);
403     if (!coreFrame)
404         return;
405
406     return coreFrame->animation()->resumeAnimations();
407 }
408
409 void DumpRenderTreeSupportGtk::clearMainFrameName(WebKitWebFrame* frame)
410 {
411     g_return_if_fail(WEBKIT_IS_WEB_FRAME(frame));
412
413     core(frame)->tree()->clearName();
414 }
415
416 AtkObject* DumpRenderTreeSupportGtk::getFocusedAccessibleElement(WebKitWebFrame* frame)
417 {
418     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), 0);
419
420 #if HAVE(ACCESSIBILITY)
421     if (!AXObjectCache::accessibilityEnabled())
422         AXObjectCache::enableAccessibility();
423
424     WebKitWebFramePrivate* priv = frame->priv;
425     if (!priv->coreFrame || !priv->coreFrame->document())
426         return 0;
427
428     RenderView* root = toRenderView(priv->coreFrame->document()->renderer());
429     if (!root)
430         return 0;
431
432     AtkObject* wrapper =  priv->coreFrame->document()->axObjectCache()->getOrCreate(root)->wrapper();
433     if (!wrapper)
434         return 0;
435
436     return webkit_accessible_get_focused_element(WEBKIT_ACCESSIBLE(wrapper));
437 #else
438     return 0;
439 #endif
440 }
441
442 void DumpRenderTreeSupportGtk::executeCoreCommandByName(WebKitWebView* webView, const gchar* name, const gchar* value)
443 {
444     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
445     g_return_if_fail(name);
446     g_return_if_fail(value);
447
448     core(webView)->focusController()->focusedOrMainFrame()->editor()->command(name).execute(value);
449 }
450
451 bool DumpRenderTreeSupportGtk::isCommandEnabled(WebKitWebView* webView, const gchar* name)
452 {
453     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
454     g_return_val_if_fail(name, FALSE);
455
456     return core(webView)->focusController()->focusedOrMainFrame()->editor()->command(name).isEnabled();
457 }
458
459 void DumpRenderTreeSupportGtk::whiteListAccessFromOrigin(const gchar* sourceOrigin, const gchar* destinationProtocol, const gchar* destinationHost, bool allowDestinationSubdomains)
460 {
461     SecurityOrigin::addOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains);
462 }
463
464 void DumpRenderTreeSupportGtk::resetOriginAccessWhiteLists()
465 {
466     SecurityOrigin::resetOriginAccessWhitelists();
467 }
468
469 void DumpRenderTreeSupportGtk::gcCollectJavascriptObjects()
470 {
471     gcController().garbageCollectNow();
472 }
473
474 void DumpRenderTreeSupportGtk::gcCollectJavascriptObjectsOnAlternateThread(bool waitUntilDone)
475 {
476     gcController().garbageCollectOnAlternateThreadForDebugging(waitUntilDone);
477 }
478
479 unsigned long DumpRenderTreeSupportGtk::gcCountJavascriptObjects()
480 {
481     JSC::JSLock lock(JSC::SilenceAssertionsOnly);
482     return JSDOMWindow::commonJSGlobalData()->heap.objectCount();
483 }
484
485 void DumpRenderTreeSupportGtk::layoutFrame(WebKitWebFrame* frame)
486 {
487     Frame* coreFrame = core(frame);
488     if (!coreFrame)
489         return;
490
491     FrameView* view = coreFrame->view();
492     if (!view)
493         return;
494
495     view->layout();
496 }
497
498 // For testing fast/viewport.
499 void DumpRenderTreeSupportGtk::dumpConfigurationForViewport(WebKitWebView* webView, gint availableWidth, gint availableHeight)
500 {
501     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
502
503     ViewportArguments arguments = webView->priv->corePage->mainFrame()->document()->viewportArguments();
504     // desktopWidth = 980, deviceWidth = 320, deviceHeight = 480, deviceDPI = 160
505     ViewportAttributes attrs = computeViewportAttributes(arguments, 980, 320, 480, 160, IntSize(availableWidth, availableHeight));
506
507     fprintf(stdout, "viewport size %dx%d scale %f with limits [%f, %f]\n", attrs.layoutSize.width(), attrs.layoutSize.height(), attrs.initialScale, attrs.minimumScale, attrs.maximumScale);
508 }
509
510 unsigned int DumpRenderTreeSupportGtk::workerThreadCount()
511 {
512 #if ENABLE(WORKERS)
513     return WebCore::WorkerThread::workerThreadCount();
514 #else
515     return 0;
516 #endif
517 }
518
519 bool DumpRenderTreeSupportGtk::webkitWebFrameSelectionHasSpellingMarker(WebKitWebFrame *frame, gint from, gint length)
520 {
521     g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), FALSE);
522
523     return core(frame)->editor()->selectionStartHasSpellingMarkerFor(from, length);
524 }