2012-06-14 Jon Honeycutt <jhoneycutt@apple.com>
[WebKit-https.git] / Source / WebCore / testing / Internals.cpp
1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "Internals.h"
28
29 #include "CachedResourceLoader.h"
30 #include "ClientRect.h"
31 #include "ClientRectList.h"
32 #include "ComposedShadowTreeWalker.h"
33 #include "DOMNodeHighlighter.h"
34 #include "Document.h"
35 #include "DocumentMarker.h"
36 #include "DocumentMarkerController.h"
37 #include "Element.h"
38 #include "ElementShadow.h"
39 #include "ExceptionCode.h"
40 #include "Frame.h"
41 #include "FrameView.h"
42 #include "HTMLContentElement.h"
43 #include "HTMLInputElement.h"
44 #include "HTMLNames.h"
45 #include "HTMLTextAreaElement.h"
46 #include "InspectorConsoleAgent.h"
47 #include "InspectorController.h"
48 #include "InspectorCounters.h"
49 #include "InspectorInstrumentation.h"
50 #include "InstrumentingAgents.h"
51 #include "InternalSettings.h"
52 #include "IntRect.h"
53 #include "Language.h"
54 #include "NodeRenderingContext.h"
55 #include "Page.h"
56 #include "Range.h"
57 #include "RenderObject.h"
58 #include "RenderTreeAsText.h"
59 #include "Settings.h"
60 #include "ShadowRoot.h"
61 #include "SpellChecker.h"
62 #include "TextIterator.h"
63 #include "TextRun.h"
64 #include "TreeScope.h"
65
66 #if ENABLE(INPUT_TYPE_COLOR)
67 #include "ColorChooser.h"
68 #endif
69
70 #if ENABLE(BATTERY_STATUS)
71 #include "BatteryController.h"
72 #endif
73
74 #if ENABLE(NETWORK_INFO)
75 #include "NetworkInfo.h"
76 #include "NetworkInfoController.h"
77 #endif
78
79 #if ENABLE(TOUCH_ADJUSTMENT)
80 #include "EventHandler.h"
81 #include "WebKitPoint.h"
82 #endif
83
84 #if PLATFORM(CHROMIUM)
85 #include "FilterOperation.h"
86 #include "FilterOperations.h"
87 #include "GraphicsLayer.h"
88 #include "GraphicsLayerChromium.h"
89 #include "RenderLayerBacking.h"
90 #endif
91
92 namespace WebCore {
93
94 using namespace HTMLNames;
95
96 static bool markerTypesFrom(const String& markerType, DocumentMarker::MarkerTypes& result)
97 {
98     if (markerType.isEmpty() || equalIgnoringCase(markerType, "all"))
99         result = DocumentMarker::AllMarkers();
100     else if (equalIgnoringCase(markerType, "Spelling"))
101         result =  DocumentMarker::Spelling;
102     else if (equalIgnoringCase(markerType, "Grammar"))
103         result =  DocumentMarker::Grammar;
104     else if (equalIgnoringCase(markerType, "TextMatch"))
105         result =  DocumentMarker::TextMatch;
106     else if (equalIgnoringCase(markerType, "Replacement"))
107         result =  DocumentMarker::Replacement;
108     else if (equalIgnoringCase(markerType, "CorrectionIndicator"))
109         result =  DocumentMarker::CorrectionIndicator;
110     else if (equalIgnoringCase(markerType, "RejectedCorrection"))
111         result =  DocumentMarker::RejectedCorrection;
112     else if (equalIgnoringCase(markerType, "Autocorrected"))
113         result =  DocumentMarker::Autocorrected;
114     else if (equalIgnoringCase(markerType, "SpellCheckingExemption"))
115         result =  DocumentMarker::SpellCheckingExemption;
116     else if (equalIgnoringCase(markerType, "DeletedAutocorrection"))
117         result =  DocumentMarker::DeletedAutocorrection;
118     else if (equalIgnoringCase(markerType, "DictationAlternatives"))
119         result =  DocumentMarker::DictationAlternatives;
120     else
121         return false;
122
123     return true;
124 }
125
126 static SpellChecker* spellchecker(Document* document)
127 {
128     if (!document || !document->frame() || !document->frame()->editor())
129         return 0;
130
131     return document->frame()->editor()->spellChecker();
132 }
133
134 const char* Internals::internalsId = "internals";
135
136 PassRefPtr<Internals> Internals::create(Document* document)
137 {
138     return adoptRef(new Internals(document));
139 }
140
141 Internals::~Internals()
142 {
143 }
144
145 Internals::Internals(Document* document)
146     : FrameDestructionObserver(0)
147 {
148     reset(document);
149 }
150
151 String Internals::address(Node* node)
152 {
153     char buf[32];
154     sprintf(buf, "%p", node);
155
156     return String(buf);
157 }
158
159 bool Internals::isPreloaded(Document* document, const String& url)
160 {
161     if (!document)
162         return false;
163
164     return document->cachedResourceLoader()->isPreloaded(url);
165 }
166
167 PassRefPtr<Element> Internals::createContentElement(Document* document, ExceptionCode& ec)
168 {
169     if (!document) {
170         ec = INVALID_ACCESS_ERR;
171         return 0;
172     }
173
174     return HTMLContentElement::create(document);
175 }
176
177 Element* Internals::getElementByIdInShadowRoot(Node* shadowRoot, const String& id, ExceptionCode& ec)
178 {
179     if (!shadowRoot || !shadowRoot->isShadowRoot()) {
180         ec = INVALID_ACCESS_ERR;
181         return 0;
182     }
183     return toShadowRoot(shadowRoot)->getElementById(id);
184 }
185
186 bool Internals::isValidContentSelect(Element* insertionPoint, ExceptionCode& ec)
187 {
188     if (!insertionPoint || !isInsertionPoint(insertionPoint)) {
189         ec = INVALID_ACCESS_ERR;
190         return false;
191     }
192
193     return toInsertionPoint(insertionPoint)->isSelectValid();
194 }
195
196 Node* Internals::treeScopeRootNode(Node* node, ExceptionCode& ec)
197 {
198     if (!node) {
199         ec = INVALID_ACCESS_ERR;
200         return 0;
201     }
202
203     return node->treeScope()->rootNode();
204 }
205
206 bool Internals::attached(Node* node, ExceptionCode& ec)
207 {
208     if (!node) {
209         ec = INVALID_ACCESS_ERR;
210         return false;
211     }
212
213     return node->attached();
214 }
215
216 Node* Internals::nextSiblingByWalker(Node* node, ExceptionCode& ec)
217 {
218     if (!node) {
219         ec = INVALID_ACCESS_ERR;
220         return 0;
221     }
222     ComposedShadowTreeWalker walker(node);
223     walker.nextSibling();
224     return walker.get();
225 }
226
227 Node* Internals::firstChildByWalker(Node* node, ExceptionCode& ec)
228 {
229     if (!node) {
230         ec = INVALID_ACCESS_ERR;
231         return 0;
232     }
233     ComposedShadowTreeWalker walker(node);
234     walker.firstChild();
235     return walker.get();
236 }
237
238 Node* Internals::lastChildByWalker(Node* node, ExceptionCode& ec)
239 {
240     if (!node) {
241         ec = INVALID_ACCESS_ERR;
242         return 0;
243     }
244     ComposedShadowTreeWalker walker(node);
245     walker.lastChild();
246     return walker.get();
247 }
248
249 Node* Internals::nextNodeByWalker(Node* node, ExceptionCode& ec)
250 {
251     if (!node) {
252         ec = INVALID_ACCESS_ERR;
253         return 0;
254     }
255     ComposedShadowTreeWalker walker(node);
256     walker.next();
257     return walker.get();
258 }
259
260 Node* Internals::previousNodeByWalker(Node* node, ExceptionCode& ec)
261 {
262     if (!node) {
263         ec = INVALID_ACCESS_ERR;
264         return 0;
265     }
266     ComposedShadowTreeWalker walker(node);
267     walker.previous();
268     return walker.get();
269 }
270
271 String Internals::elementRenderTreeAsText(Element* element, ExceptionCode& ec)
272 {
273     if (!element) {
274         ec = INVALID_ACCESS_ERR;
275         return String();
276     }
277
278     String representation = externalRepresentation(element);
279     if (representation.isEmpty()) {
280         ec = INVALID_ACCESS_ERR;
281         return String();
282     }
283
284     return representation;
285 }
286
287 size_t Internals::numberOfScopedHTMLStyleChildren(const Node* scope, ExceptionCode& ec) const
288 {
289     if (scope && (scope->isElementNode() || scope->isShadowRoot()))
290 #if ENABLE(STYLE_SCOPED)
291         return scope->numberOfScopedHTMLStyleChildren();
292 #else
293         return 0;
294 #endif
295
296     ec = INVALID_ACCESS_ERR;
297     return 0;
298 }
299
300 Internals::ShadowRootIfShadowDOMEnabledOrNode* Internals::ensureShadowRoot(Element* host, ExceptionCode& ec)
301 {
302     if (!host) {
303         ec = INVALID_ACCESS_ERR;
304         return 0;
305     }
306
307     if (ElementShadow* shadow = host->shadow())
308         return shadow->youngestShadowRoot();
309
310     return ShadowRoot::create(host, ec).get();
311 }
312
313 Internals::ShadowRootIfShadowDOMEnabledOrNode* Internals::shadowRoot(Element* host, ExceptionCode& ec)
314 {
315     // FIXME: Internals::shadowRoot() in tests should be converted to youngestShadowRoot() or oldestShadowRoot().
316     // https://bugs.webkit.org/show_bug.cgi?id=78465
317     return youngestShadowRoot(host, ec);
318 }
319
320 Internals::ShadowRootIfShadowDOMEnabledOrNode* Internals::youngestShadowRoot(Element* host, ExceptionCode& ec)
321 {
322     if (!host) {
323         ec = INVALID_ACCESS_ERR;
324         return 0;
325     }
326
327     if (ElementShadow* shadow = host->shadow())
328         return shadow->youngestShadowRoot();
329     return 0;
330 }
331
332 Internals::ShadowRootIfShadowDOMEnabledOrNode* Internals::oldestShadowRoot(Element* host, ExceptionCode& ec)
333 {
334     if (!host) {
335         ec = INVALID_ACCESS_ERR;
336         return 0;
337     }
338
339     if (ElementShadow* shadow = host->shadow())
340         return shadow->oldestShadowRoot();
341     return 0;
342 }
343
344 Internals::ShadowRootIfShadowDOMEnabledOrNode* Internals::youngerShadowRoot(Node* shadow, ExceptionCode& ec)
345 {
346     if (!shadow || !shadow->isShadowRoot()) {
347         ec = INVALID_ACCESS_ERR;
348         return 0;
349     }
350
351     return toShadowRoot(shadow)->youngerShadowRoot();
352 }
353
354 Internals::ShadowRootIfShadowDOMEnabledOrNode* Internals::olderShadowRoot(Node* shadow, ExceptionCode& ec)
355 {
356     if (!shadow || !shadow->isShadowRoot()) {
357         ec = INVALID_ACCESS_ERR;
358         return 0;
359     }
360
361     return toShadowRoot(shadow)->olderShadowRoot();
362 }
363
364 Element* Internals::includerFor(Node* node, ExceptionCode& ec)
365 {
366     if (!node) {
367         ec = INVALID_ACCESS_ERR;
368         return 0;
369     }
370
371     return NodeRenderingContext(node).insertionPoint();
372 }
373
374 String Internals::shadowPseudoId(Element* element, ExceptionCode& ec)
375 {
376     if (!element) {
377         ec = INVALID_ACCESS_ERR;
378         return String();
379     }
380
381     return element->shadowPseudoId().string();
382 }
383
384 void Internals::setShadowPseudoId(Element* element, const String& id, ExceptionCode& ec)
385 {
386     if (!element) {
387         ec = INVALID_ACCESS_ERR;
388         return;
389     }
390
391     return element->setShadowPseudoId(id, ec);
392 }
393
394 String Internals::visiblePlaceholder(Element* element)
395 {
396     HTMLTextFormControlElement* textControl = toTextFormControl(element);
397     if (textControl && textControl->placeholderShouldBeVisible())
398         return textControl->placeholderElement()->textContent();
399     return String();
400 }
401
402 #if ENABLE(INPUT_TYPE_COLOR)
403 void Internals::selectColorInColorChooser(Element* element, const String& colorValue)
404 {
405     if (!element->hasTagName(inputTag))
406         return;
407     HTMLInputElement* inputElement = element->toInputElement();
408     if (!inputElement)
409         return;
410     inputElement->selectColorInColorChooser(Color(colorValue));
411 }
412 #endif
413
414 PassRefPtr<ClientRect> Internals::absoluteCaretBounds(Document* document, ExceptionCode& ec)
415 {
416     if (!document || !document->frame() || !document->frame()->selection()) {
417         ec = INVALID_ACCESS_ERR;
418         return ClientRect::create();
419     }
420
421     return ClientRect::create(document->frame()->selection()->absoluteCaretBounds());
422 }
423
424 PassRefPtr<ClientRect> Internals::boundingBox(Element* element, ExceptionCode& ec)
425 {
426     if (!element) {
427         ec = INVALID_ACCESS_ERR;
428         return ClientRect::create();
429     }
430
431     element->document()->updateLayoutIgnorePendingStylesheets();
432     RenderObject* renderer = element->renderer();
433     if (!renderer)
434         return ClientRect::create();
435     return ClientRect::create(renderer->absoluteBoundingBoxRectIgnoringTransforms());
436 }
437
438 PassRefPtr<ClientRectList> Internals::inspectorHighlightRects(Document* document, ExceptionCode& ec)
439 {
440 #if ENABLE(INSPECTOR)
441     if (!document || !document->page() || !document->page()->inspectorController()) {
442         ec = INVALID_ACCESS_ERR;
443         return ClientRectList::create();
444     }
445
446     Highlight highlight;
447     document->page()->inspectorController()->getHighlight(&highlight);
448     return ClientRectList::create(highlight.quads);
449 #else
450     UNUSED_PARAM(document);
451     UNUSED_PARAM(ec);
452     return ClientRectList::create();
453 #endif
454 }
455
456 #if PLATFORM(CHROMIUM)
457 void Internals::setBackgroundBlurOnNode(Node* node, int blurLength, ExceptionCode& ec)
458 {
459     if (!node) {
460         ec = INVALID_ACCESS_ERR;
461         return;
462     }
463
464     RenderObject* renderObject = node->renderer();
465     if (!renderObject) {
466         ec = INVALID_NODE_TYPE_ERR;
467         return;
468     }
469
470     RenderLayer* renderLayer = renderObject->enclosingLayer();
471     if (!renderLayer || !renderLayer->isComposited()) {
472         ec = INVALID_STATE_ERR;
473         return;
474     }
475
476     GraphicsLayer* graphicsLayer = renderLayer->backing()->graphicsLayer();
477     if (!graphicsLayer) {
478         ec = INVALID_NODE_TYPE_ERR;
479         return;
480     }
481
482     FilterOperations filters;
483     filters.operations().append(BlurFilterOperation::create(Length(blurLength, Fixed), FilterOperation::BLUR));
484     static_cast<GraphicsLayerChromium*>(graphicsLayer)->setBackgroundFilters(filters);
485 }
486 #else
487 void Internals::setBackgroundBlurOnNode(Node*, int, ExceptionCode&)
488 {
489 }
490 #endif
491
492 unsigned Internals::markerCountForNode(Node* node, const String& markerType, ExceptionCode& ec)
493 {
494     if (!node) {
495         ec = INVALID_ACCESS_ERR;
496         return 0;
497     }
498
499     DocumentMarker::MarkerTypes markerTypes = 0;
500     if (!markerTypesFrom(markerType, markerTypes)) {
501         ec = SYNTAX_ERR;
502         return 0;
503     }
504
505     return node->document()->markers()->markersFor(node, markerTypes).size();
506 }
507
508 DocumentMarker* Internals::markerAt(Node* node, const String& markerType, unsigned index, ExceptionCode& ec)
509 {
510     if (!node) {
511         ec = INVALID_ACCESS_ERR;
512         return 0;
513     }
514
515     DocumentMarker::MarkerTypes markerTypes = 0;
516     if (!markerTypesFrom(markerType, markerTypes)) {
517         ec = SYNTAX_ERR;
518         return 0;
519     }
520
521     Vector<DocumentMarker*> markers = node->document()->markers()->markersFor(node, markerTypes);
522     if (markers.size() <= index)
523         return 0;
524     return markers[index];
525 }
526
527 PassRefPtr<Range> Internals::markerRangeForNode(Node* node, const String& markerType, unsigned index, ExceptionCode& ec)
528 {
529     DocumentMarker* marker = markerAt(node, markerType, index, ec);
530     if (!marker)
531         return 0;
532     return Range::create(node->document(), node, marker->startOffset(), node, marker->endOffset());
533 }
534
535 String Internals::markerDescriptionForNode(Node* node, const String& markerType, unsigned index, ExceptionCode& ec)
536 {
537     DocumentMarker* marker = markerAt(node, markerType, index, ec);
538     if (!marker)
539         return String();
540     return marker->description();
541 }
542
543 void Internals::setScrollViewPosition(Document* document, long x, long y, ExceptionCode& ec)
544 {
545     if (!document || !document->view()) {
546         ec = INVALID_ACCESS_ERR;
547         return;
548     }
549
550     FrameView* frameView = document->view();
551     bool constrainsScrollingToContentEdgeOldValue = frameView->constrainsScrollingToContentEdge();
552     bool scrollbarsSuppressedOldValue = frameView->scrollbarsSuppressed();
553
554     frameView->setConstrainsScrollingToContentEdge(false);
555     frameView->setScrollbarsSuppressed(false);
556     frameView->setScrollOffsetFromInternals(IntPoint(x, y));
557     frameView->setScrollbarsSuppressed(scrollbarsSuppressedOldValue);
558     frameView->setConstrainsScrollingToContentEdge(constrainsScrollingToContentEdgeOldValue);
559 }
560
561 void Internals::setPagination(Document* document, const String& mode, int gap, ExceptionCode& ec)
562 {
563     if (!document || !document->page()) {
564         ec = INVALID_ACCESS_ERR;
565         return;
566     }
567
568     Page::Pagination pagination;
569     if (mode == "Unpaginated")
570         pagination.mode = Page::Pagination::Unpaginated;
571     else if (mode == "HorizontallyPaginated")
572         pagination.mode = Page::Pagination::HorizontallyPaginated;
573     else if (mode == "VerticallyPaginated")
574         pagination.mode = Page::Pagination::VerticallyPaginated;
575     else {
576         ec = SYNTAX_ERR;
577         return;
578     }
579
580     pagination.gap = gap;
581
582     document->page()->setPagination(pagination);
583 }
584
585 void Internals::reset(Document* document)
586 {
587     if (!document || !document->settings())
588         return;
589
590     observeFrame(document->frame());
591
592     if (m_settings)
593         m_settings->restoreTo(document->page()->settings());
594     m_settings = InternalSettings::create(document->frame());
595     if (Page* page = document->page()) {
596         page->setPagination(Page::Pagination());
597
598         if (document->frame() == page->mainFrame())
599             setUserPreferredLanguages(Vector<String>());
600
601         page->setPageScaleFactor(1, IntPoint(0, 0));
602     }
603
604     resetDefaultsToConsistentValues();
605 }
606
607 void Internals::resetDefaultsToConsistentValues()
608 {
609     TextRun::setAllowsRoundingHacks(false);
610 }
611
612 bool Internals::wasLastChangeUserEdit(Element* textField, ExceptionCode& ec)
613 {
614     if (!textField) {
615         ec = INVALID_ACCESS_ERR;
616         return false;
617     }
618
619     if (HTMLInputElement* inputElement = textField->toInputElement())
620         return inputElement->lastChangeWasUserEdit();
621
622     // FIXME: We should be using hasTagName instead but Windows port doesn't link QualifiedNames properly.
623     if (textField->tagName() == "TEXTAREA")
624         return static_cast<HTMLTextAreaElement*>(textField)->lastChangeWasUserEdit();
625
626     ec = INVALID_NODE_TYPE_ERR;
627     return false;
628 }
629
630 String Internals::suggestedValue(Element* element, ExceptionCode& ec)
631 {
632     if (!element) {
633         ec = INVALID_ACCESS_ERR;
634         return String();
635     }
636
637     HTMLInputElement* inputElement = element->toInputElement();
638     if (!inputElement) {
639         ec = INVALID_NODE_TYPE_ERR;
640         return String();
641     }
642
643     return inputElement->suggestedValue();
644 }
645
646 void Internals::setSuggestedValue(Element* element, const String& value, ExceptionCode& ec)
647 {
648     if (!element) {
649         ec = INVALID_ACCESS_ERR;
650         return;
651     }
652
653     HTMLInputElement* inputElement = element->toInputElement();
654     if (!inputElement) {
655         ec = INVALID_NODE_TYPE_ERR;
656         return;
657     }
658
659     inputElement->setSuggestedValue(value);
660 }
661
662 void Internals::setEditingValue(Element* element, const String& value, ExceptionCode& ec)
663 {
664     if (!element) {
665         ec = INVALID_ACCESS_ERR;
666         return;
667     }
668
669     HTMLInputElement* inputElement = element->toInputElement();
670     if (!inputElement) {
671         ec = INVALID_NODE_TYPE_ERR;
672         return;
673     }
674
675     inputElement->setEditingValue(value);
676 }
677
678 void Internals::scrollElementToRect(Element* element, long x, long y, long w, long h, ExceptionCode& ec)
679 {
680     if (!element || !element->document() || !element->document()->view()) {
681         ec = INVALID_ACCESS_ERR;
682         return;
683     }
684     FrameView* frameView = element->document()->view();
685     frameView->scrollElementToRect(element, IntRect(x, y, w, h));
686 }
687
688 void Internals::paintControlTints(Document* document, ExceptionCode& ec)
689 {
690     if (!document || !document->view()) {
691         ec = INVALID_ACCESS_ERR;
692         return;
693     }
694
695     FrameView* frameView = document->view();
696     frameView->paintControlTints();
697 }
698
699 PassRefPtr<Range> Internals::rangeFromLocationAndLength(Element* scope, int rangeLocation, int rangeLength, ExceptionCode& ec)
700 {
701     if (!scope) {
702         ec = INVALID_ACCESS_ERR;
703         return 0;
704     }
705
706     return TextIterator::rangeFromLocationAndLength(scope, rangeLocation, rangeLength);
707 }
708
709 unsigned Internals::locationFromRange(Element* scope, const Range* range, ExceptionCode& ec)
710 {
711     if (!scope || !range) {
712         ec = INVALID_ACCESS_ERR;
713         return 0;
714     }
715
716     size_t location = 0;
717     size_t unusedLength = 0;
718     TextIterator::getLocationAndLengthFromRange(scope, range, location, unusedLength);
719     return location;
720 }
721
722 unsigned Internals::lengthFromRange(Element* scope, const Range* range, ExceptionCode& ec)
723 {
724     if (!scope || !range) {
725         ec = INVALID_ACCESS_ERR;
726         return 0;
727     }
728
729     size_t unusedLocation = 0;
730     size_t length = 0;
731     TextIterator::getLocationAndLengthFromRange(scope, range, unusedLocation, length);
732     return length;
733 }
734
735 String Internals::rangeAsText(const Range* range, ExceptionCode& ec)
736 {
737     if (!range) {
738         ec = INVALID_ACCESS_ERR;
739         return String();
740     }
741
742     return range->text();
743 }
744
745 void Internals::setDelegatesScrolling(bool enabled, Document* document, ExceptionCode& ec)
746 {
747     // Delegate scrolling is valid only on mainframe's view.
748     if (!document || !document->view() || !document->page() || document->page()->mainFrame() != document->frame()) {
749         ec = INVALID_ACCESS_ERR;
750         return;
751     }
752
753     document->view()->setDelegatesScrolling(enabled);
754 }
755
756 #if ENABLE(TOUCH_ADJUSTMENT)
757 PassRefPtr<WebKitPoint> Internals::touchPositionAdjustedToBestClickableNode(long x, long y, long width, long height, Document* document, ExceptionCode& ec)
758 {
759     if (!document || !document->frame()) {
760         ec = INVALID_ACCESS_ERR;
761         return 0;
762     }
763
764     IntSize radius(width / 2, height / 2);
765     IntPoint point(x + radius.width(), y + radius.height());
766
767     Node* targetNode;
768     IntPoint adjustedPoint;
769
770     bool foundNode = document->frame()->eventHandler()->bestClickableNodeForTouchPoint(point, radius, adjustedPoint, targetNode);
771     if (foundNode)
772         return WebKitPoint::create(adjustedPoint.x(), adjustedPoint.y());
773
774     return 0;
775 }
776
777 Node* Internals::touchNodeAdjustedToBestClickableNode(long x, long y, long width, long height, Document* document, ExceptionCode& ec)
778 {
779     if (!document || !document->frame()) {
780         ec = INVALID_ACCESS_ERR;
781         return 0;
782     }
783
784     IntSize radius(width / 2, height / 2);
785     IntPoint point(x + radius.width(), y + radius.height());
786
787     Node* targetNode;
788     IntPoint adjustedPoint;
789     document->frame()->eventHandler()->bestClickableNodeForTouchPoint(point, radius, adjustedPoint, targetNode);
790     return targetNode;
791 }
792
793 PassRefPtr<ClientRect> Internals::bestZoomableAreaForTouchPoint(long x, long y, long width, long height, Document* document, ExceptionCode& ec)
794 {
795     if (!document || !document->frame()) {
796         ec = INVALID_ACCESS_ERR;
797         return 0;
798     }
799
800     IntSize radius(width / 2, height / 2);
801     IntPoint point(x + radius.width(), y + radius.height());
802
803     Node* targetNode;
804     IntRect zoomableArea;
805     bool foundNode = document->frame()->eventHandler()->bestZoomableAreaForTouchPoint(point, radius, zoomableArea, targetNode);
806     if (foundNode)
807         return ClientRect::create(zoomableArea);
808
809     return 0;
810 }
811 #endif
812
813
814 int Internals::lastSpellCheckRequestSequence(Document* document, ExceptionCode& ec)
815 {
816     SpellChecker* checker = spellchecker(document);
817
818     if (!checker) {
819         ec = INVALID_ACCESS_ERR;
820         return -1;
821     }
822
823     return checker->lastRequestSequence();
824 }
825
826 int Internals::lastSpellCheckProcessedSequence(Document* document, ExceptionCode& ec)
827 {
828     SpellChecker* checker = spellchecker(document);
829
830     if (!checker) {
831         ec = INVALID_ACCESS_ERR;
832         return -1;
833     }
834
835     return checker->lastProcessedSequence();
836 }
837
838 Vector<String> Internals::userPreferredLanguages() const
839 {
840     return WebCore::userPreferredLanguages();
841 }
842
843 void Internals::setUserPreferredLanguages(const Vector<String>& languages)
844 {
845     WebCore::overrideUserPreferredLanguages(languages);
846 }
847
848 void Internals::setShouldDisplayTrackKind(Document* document, const String& kind, bool enabled, ExceptionCode& ec)
849 {
850     if (!document || !document->frame() || !document->frame()->settings()) {
851         ec = INVALID_ACCESS_ERR;
852         return;
853     }
854     
855 #if ENABLE(VIDEO_TRACK)
856     Settings* settings = document->frame()->settings();
857     
858     if (equalIgnoringCase(kind, "Subtitles"))
859         settings->setShouldDisplaySubtitles(enabled);
860     else if (equalIgnoringCase(kind, "Captions"))
861         settings->setShouldDisplayCaptions(enabled);
862     else if (equalIgnoringCase(kind, "TextDescriptions"))
863         settings->setShouldDisplayTextDescriptions(enabled);
864     else
865         ec = SYNTAX_ERR;
866 #else
867     UNUSED_PARAM(kind);
868     UNUSED_PARAM(enabled);
869 #endif
870 }
871
872 bool Internals::shouldDisplayTrackKind(Document* document, const String& kind, ExceptionCode& ec)
873 {
874     if (!document || !document->frame() || !document->frame()->settings()) {
875         ec = INVALID_ACCESS_ERR;
876         return false;
877     }
878     
879 #if ENABLE(VIDEO_TRACK)
880     Settings* settings = document->frame()->settings();
881     
882     if (equalIgnoringCase(kind, "Subtitles"))
883         return settings->shouldDisplaySubtitles();
884     if (equalIgnoringCase(kind, "Captions"))
885         return settings->shouldDisplayCaptions();
886     if (equalIgnoringCase(kind, "TextDescriptions"))
887         return settings->shouldDisplayTextDescriptions();
888
889     ec = SYNTAX_ERR;
890     return false;
891 #else
892     UNUSED_PARAM(kind);
893     return false;
894 #endif
895 }
896
897 unsigned Internals::wheelEventHandlerCount(Document* document, ExceptionCode& ec)
898 {
899     if (!document) {
900         ec = INVALID_ACCESS_ERR;
901         return 0;
902     }
903
904     return document->wheelEventHandlerCount();
905 }
906
907 unsigned Internals::touchEventHandlerCount(Document* document, ExceptionCode& ec)
908 {
909     if (!document) {
910         ec = INVALID_ACCESS_ERR;
911         return 0;
912     }
913
914     return document->touchEventHandlerCount();
915 }
916
917 PassRefPtr<NodeList> Internals::nodesFromRect(Document* document, int x, int y, unsigned topPadding, unsigned rightPadding,
918     unsigned bottomPadding, unsigned leftPadding, bool ignoreClipping, bool allowShadowContent, ExceptionCode& ec) const
919 {
920     if (!document || !document->frame() || !document->frame()->view()) {
921         ec = INVALID_ACCESS_ERR;
922         return 0;
923     }
924
925     return document->nodesFromRect(x, y, topPadding, rightPadding, bottomPadding, leftPadding, ignoreClipping, allowShadowContent);
926 }
927
928 void Internals::emitInspectorDidBeginFrame()
929 {
930     InspectorInstrumentation::didBeginFrame(frame()->page());
931 }
932
933 void Internals::emitInspectorDidCancelFrame()
934 {
935     InspectorInstrumentation::didCancelFrame(frame()->page());
936 }
937
938 void Internals::setBatteryStatus(Document* document, const String& eventType, bool charging, double chargingTime, double dischargingTime, double level, ExceptionCode& ec)
939 {
940     if (!document || !document->page()) {
941         ec = INVALID_ACCESS_ERR;
942         return;
943     }
944
945 #if ENABLE(BATTERY_STATUS)
946     BatteryController::from(document->page())->didChangeBatteryStatus(eventType, BatteryStatus::create(charging, chargingTime, dischargingTime, level));
947 #else
948     UNUSED_PARAM(eventType);
949     UNUSED_PARAM(charging);
950     UNUSED_PARAM(chargingTime);
951     UNUSED_PARAM(dischargingTime);
952     UNUSED_PARAM(level);
953 #endif
954 }
955
956 void Internals::setNetworkInformation(Document* document, const String& eventType, long bandwidth, bool metered, ExceptionCode& ec)
957 {
958     if (!document || !document->page()) {
959         ec = INVALID_ACCESS_ERR;
960         return;
961     }
962
963 #if ENABLE(NETWORK_INFO)
964     NetworkInfoController::from(document->page())->didChangeNetworkInformation(eventType, NetworkInfo::create(bandwidth, metered));
965 #else
966     UNUSED_PARAM(eventType);
967     UNUSED_PARAM(bandwidth);
968     UNUSED_PARAM(metered);
969 #endif
970 }
971
972 bool Internals::hasSpellingMarker(Document* document, int from, int length, ExceptionCode&)
973 {
974     if (!document || !document->frame())
975         return 0;
976
977     return document->frame()->editor()->selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
978 }
979
980 #if ENABLE(INSPECTOR)
981 unsigned Internals::numberOfLiveNodes() const
982 {
983     return InspectorCounters::counterValue(InspectorCounters::NodeCounter);
984 }
985
986 unsigned Internals::numberOfLiveDocuments() const
987 {
988     return InspectorCounters::counterValue(InspectorCounters::DocumentCounter);
989 }
990
991 Vector<String> Internals::consoleMessageArgumentCounts(Document* document) const
992 {
993     InstrumentingAgents* instrumentingAgents = instrumentationForPage(document->page());
994     if (!instrumentingAgents)
995         return Vector<String>();
996     InspectorConsoleAgent* consoleAgent = instrumentingAgents->inspectorConsoleAgent();
997     if (!consoleAgent)
998         return Vector<String>();
999     Vector<unsigned> counts = consoleAgent->consoleMessageArgumentCounts();
1000     Vector<String> result(counts.size());
1001     for (size_t i = 0; i < counts.size(); i++)
1002         result[i] = String::number(counts[i]);
1003     return result;
1004 }
1005 #endif // ENABLE(INSPECTOR)
1006
1007 bool Internals::hasGrammarMarker(Document* document, int from, int length, ExceptionCode&)
1008 {
1009     if (!document || !document->frame())
1010         return 0;
1011
1012     return document->frame()->editor()->selectionStartHasMarkerFor(DocumentMarker::Grammar, from, length);
1013 }
1014
1015 unsigned Internals::numberOfScrollableAreas(Document* document, ExceptionCode&)
1016 {
1017     unsigned count = 0;
1018     Frame* frame = document->frame();
1019     if (frame->view()->scrollableAreas())
1020         count += frame->view()->scrollableAreas()->size();
1021
1022     for (Frame* child = frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
1023         if (child->view() && child->view()->scrollableAreas())
1024             count += child->view()->scrollableAreas()->size();
1025     }
1026
1027     return count;
1028 }
1029     
1030 bool Internals::isPageBoxVisible(Document* document, int pageNumber, ExceptionCode& ec)
1031 {
1032     if (!document) {
1033         ec = INVALID_ACCESS_ERR;
1034         return false;
1035     }
1036
1037     return document->isPageBoxVisible(pageNumber);
1038 }
1039
1040 void Internals::suspendAnimations(Document* document, ExceptionCode& ec) const
1041 {
1042     if (!document || !document->frame()) {
1043         ec = INVALID_ACCESS_ERR;
1044         return;
1045     }
1046
1047     AnimationController* controller = document->frame()->animation();
1048     if (!controller)
1049         return;
1050
1051     controller->suspendAnimations();
1052 }
1053
1054 void Internals::resumeAnimations(Document* document, ExceptionCode& ec) const
1055 {
1056     if (!document || !document->frame()) {
1057         ec = INVALID_ACCESS_ERR;
1058         return;
1059     }
1060
1061     AnimationController* controller = document->frame()->animation();
1062     if (!controller)
1063         return;
1064
1065     controller->resumeAnimations();
1066 }
1067
1068 void Internals::allowRoundingHacks() const
1069 {
1070     TextRun::setAllowsRoundingHacks(true);
1071 }
1072
1073 String Internals::counterValue(Element* element)
1074 {
1075     if (!element)
1076         return String();
1077
1078     return counterValueForElement(element);
1079 }
1080
1081 #if ENABLE(FULLSCREEN_API)
1082 void Internals::webkitWillEnterFullScreenForElement(Document* document, Element* element)
1083 {
1084     if (!document)
1085         return;
1086     document->webkitWillEnterFullScreenForElement(element);
1087 }
1088
1089 void Internals::webkitDidEnterFullScreenForElement(Document* document, Element* element)
1090 {
1091     if (!document)
1092         return;
1093     document->webkitDidEnterFullScreenForElement(element);
1094 }
1095
1096 void Internals::webkitWillExitFullScreenForElement(Document* document, Element* element)
1097 {
1098     if (!document)
1099         return;
1100     document->webkitWillExitFullScreenForElement(element);
1101 }
1102
1103 void Internals::webkitDidExitFullScreenForElement(Document* document, Element* element)
1104 {
1105     if (!document)
1106         return;
1107     document->webkitDidExitFullScreenForElement(element);
1108 }
1109 #endif
1110 }