71689f02a290c1b93f7541ef865b0b05d93926ba
[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
602     resetDefaultsToConsistentValues();
603 }
604
605 void Internals::resetDefaultsToConsistentValues()
606 {
607     TextRun::setAllowsRoundingHacks(false);
608 }
609
610 bool Internals::wasLastChangeUserEdit(Element* textField, ExceptionCode& ec)
611 {
612     if (!textField) {
613         ec = INVALID_ACCESS_ERR;
614         return false;
615     }
616
617     if (HTMLInputElement* inputElement = textField->toInputElement())
618         return inputElement->lastChangeWasUserEdit();
619
620     // FIXME: We should be using hasTagName instead but Windows port doesn't link QualifiedNames properly.
621     if (textField->tagName() == "TEXTAREA")
622         return static_cast<HTMLTextAreaElement*>(textField)->lastChangeWasUserEdit();
623
624     ec = INVALID_NODE_TYPE_ERR;
625     return false;
626 }
627
628 String Internals::suggestedValue(Element* element, ExceptionCode& ec)
629 {
630     if (!element) {
631         ec = INVALID_ACCESS_ERR;
632         return String();
633     }
634
635     HTMLInputElement* inputElement = element->toInputElement();
636     if (!inputElement) {
637         ec = INVALID_NODE_TYPE_ERR;
638         return String();
639     }
640
641     return inputElement->suggestedValue();
642 }
643
644 void Internals::setSuggestedValue(Element* element, const String& value, ExceptionCode& ec)
645 {
646     if (!element) {
647         ec = INVALID_ACCESS_ERR;
648         return;
649     }
650
651     HTMLInputElement* inputElement = element->toInputElement();
652     if (!inputElement) {
653         ec = INVALID_NODE_TYPE_ERR;
654         return;
655     }
656
657     inputElement->setSuggestedValue(value);
658 }
659
660 void Internals::setEditingValue(Element* element, const String& value, ExceptionCode& ec)
661 {
662     if (!element) {
663         ec = INVALID_ACCESS_ERR;
664         return;
665     }
666
667     HTMLInputElement* inputElement = element->toInputElement();
668     if (!inputElement) {
669         ec = INVALID_NODE_TYPE_ERR;
670         return;
671     }
672
673     inputElement->setEditingValue(value);
674 }
675
676 void Internals::scrollElementToRect(Element* element, long x, long y, long w, long h, ExceptionCode& ec)
677 {
678     if (!element || !element->document() || !element->document()->view()) {
679         ec = INVALID_ACCESS_ERR;
680         return;
681     }
682     FrameView* frameView = element->document()->view();
683     frameView->scrollElementToRect(element, IntRect(x, y, w, h));
684 }
685
686 void Internals::paintControlTints(Document* document, ExceptionCode& ec)
687 {
688     if (!document || !document->view()) {
689         ec = INVALID_ACCESS_ERR;
690         return;
691     }
692
693     FrameView* frameView = document->view();
694     frameView->paintControlTints();
695 }
696
697 PassRefPtr<Range> Internals::rangeFromLocationAndLength(Element* scope, int rangeLocation, int rangeLength, ExceptionCode& ec)
698 {
699     if (!scope) {
700         ec = INVALID_ACCESS_ERR;
701         return 0;
702     }
703
704     return TextIterator::rangeFromLocationAndLength(scope, rangeLocation, rangeLength);
705 }
706
707 unsigned Internals::locationFromRange(Element* scope, const Range* range, ExceptionCode& ec)
708 {
709     if (!scope || !range) {
710         ec = INVALID_ACCESS_ERR;
711         return 0;
712     }
713
714     size_t location = 0;
715     size_t unusedLength = 0;
716     TextIterator::getLocationAndLengthFromRange(scope, range, location, unusedLength);
717     return location;
718 }
719
720 unsigned Internals::lengthFromRange(Element* scope, const Range* range, ExceptionCode& ec)
721 {
722     if (!scope || !range) {
723         ec = INVALID_ACCESS_ERR;
724         return 0;
725     }
726
727     size_t unusedLocation = 0;
728     size_t length = 0;
729     TextIterator::getLocationAndLengthFromRange(scope, range, unusedLocation, length);
730     return length;
731 }
732
733 String Internals::rangeAsText(const Range* range, ExceptionCode& ec)
734 {
735     if (!range) {
736         ec = INVALID_ACCESS_ERR;
737         return String();
738     }
739
740     return range->text();
741 }
742
743 void Internals::setDelegatesScrolling(bool enabled, Document* document, ExceptionCode& ec)
744 {
745     // Delegate scrolling is valid only on mainframe's view.
746     if (!document || !document->view() || !document->page() || document->page()->mainFrame() != document->frame()) {
747         ec = INVALID_ACCESS_ERR;
748         return;
749     }
750
751     document->view()->setDelegatesScrolling(enabled);
752 }
753
754 #if ENABLE(TOUCH_ADJUSTMENT)
755 PassRefPtr<WebKitPoint> Internals::touchPositionAdjustedToBestClickableNode(long x, long y, long width, long height, Document* document, ExceptionCode& ec)
756 {
757     if (!document || !document->frame()) {
758         ec = INVALID_ACCESS_ERR;
759         return 0;
760     }
761
762     IntSize radius(width / 2, height / 2);
763     IntPoint point(x + radius.width(), y + radius.height());
764
765     Node* targetNode;
766     IntPoint adjustedPoint;
767
768     bool foundNode = document->frame()->eventHandler()->bestClickableNodeForTouchPoint(point, radius, adjustedPoint, targetNode);
769     if (foundNode)
770         return WebKitPoint::create(adjustedPoint.x(), adjustedPoint.y());
771
772     return 0;
773 }
774
775 Node* Internals::touchNodeAdjustedToBestClickableNode(long x, long y, long width, long height, Document* document, ExceptionCode& ec)
776 {
777     if (!document || !document->frame()) {
778         ec = INVALID_ACCESS_ERR;
779         return 0;
780     }
781
782     IntSize radius(width / 2, height / 2);
783     IntPoint point(x + radius.width(), y + radius.height());
784
785     Node* targetNode;
786     IntPoint adjustedPoint;
787     document->frame()->eventHandler()->bestClickableNodeForTouchPoint(point, radius, adjustedPoint, targetNode);
788     return targetNode;
789 }
790
791 PassRefPtr<ClientRect> Internals::bestZoomableAreaForTouchPoint(long x, long y, long width, long height, Document* document, ExceptionCode& ec)
792 {
793     if (!document || !document->frame()) {
794         ec = INVALID_ACCESS_ERR;
795         return 0;
796     }
797
798     IntSize radius(width / 2, height / 2);
799     IntPoint point(x + radius.width(), y + radius.height());
800
801     Node* targetNode;
802     IntRect zoomableArea;
803     bool foundNode = document->frame()->eventHandler()->bestZoomableAreaForTouchPoint(point, radius, zoomableArea, targetNode);
804     if (foundNode)
805         return ClientRect::create(zoomableArea);
806
807     return 0;
808 }
809 #endif
810
811
812 int Internals::lastSpellCheckRequestSequence(Document* document, ExceptionCode& ec)
813 {
814     SpellChecker* checker = spellchecker(document);
815
816     if (!checker) {
817         ec = INVALID_ACCESS_ERR;
818         return -1;
819     }
820
821     return checker->lastRequestSequence();
822 }
823
824 int Internals::lastSpellCheckProcessedSequence(Document* document, ExceptionCode& ec)
825 {
826     SpellChecker* checker = spellchecker(document);
827
828     if (!checker) {
829         ec = INVALID_ACCESS_ERR;
830         return -1;
831     }
832
833     return checker->lastProcessedSequence();
834 }
835
836 Vector<String> Internals::userPreferredLanguages() const
837 {
838     return WebCore::userPreferredLanguages();
839 }
840
841 void Internals::setUserPreferredLanguages(const Vector<String>& languages)
842 {
843     WebCore::overrideUserPreferredLanguages(languages);
844 }
845
846 void Internals::setShouldDisplayTrackKind(Document* document, const String& kind, bool enabled, ExceptionCode& ec)
847 {
848     if (!document || !document->frame() || !document->frame()->settings()) {
849         ec = INVALID_ACCESS_ERR;
850         return;
851     }
852     
853 #if ENABLE(VIDEO_TRACK)
854     Settings* settings = document->frame()->settings();
855     
856     if (equalIgnoringCase(kind, "Subtitles"))
857         settings->setShouldDisplaySubtitles(enabled);
858     else if (equalIgnoringCase(kind, "Captions"))
859         settings->setShouldDisplayCaptions(enabled);
860     else if (equalIgnoringCase(kind, "TextDescriptions"))
861         settings->setShouldDisplayTextDescriptions(enabled);
862     else
863         ec = SYNTAX_ERR;
864 #else
865     UNUSED_PARAM(kind);
866     UNUSED_PARAM(enabled);
867 #endif
868 }
869
870 bool Internals::shouldDisplayTrackKind(Document* document, const String& kind, ExceptionCode& ec)
871 {
872     if (!document || !document->frame() || !document->frame()->settings()) {
873         ec = INVALID_ACCESS_ERR;
874         return false;
875     }
876     
877 #if ENABLE(VIDEO_TRACK)
878     Settings* settings = document->frame()->settings();
879     
880     if (equalIgnoringCase(kind, "Subtitles"))
881         return settings->shouldDisplaySubtitles();
882     if (equalIgnoringCase(kind, "Captions"))
883         return settings->shouldDisplayCaptions();
884     if (equalIgnoringCase(kind, "TextDescriptions"))
885         return settings->shouldDisplayTextDescriptions();
886
887     ec = SYNTAX_ERR;
888     return false;
889 #else
890     UNUSED_PARAM(kind);
891     return false;
892 #endif
893 }
894
895 unsigned Internals::wheelEventHandlerCount(Document* document, ExceptionCode& ec)
896 {
897     if (!document) {
898         ec = INVALID_ACCESS_ERR;
899         return 0;
900     }
901
902     return document->wheelEventHandlerCount();
903 }
904
905 unsigned Internals::touchEventHandlerCount(Document* document, ExceptionCode& ec)
906 {
907     if (!document) {
908         ec = INVALID_ACCESS_ERR;
909         return 0;
910     }
911
912     return document->touchEventHandlerCount();
913 }
914
915 PassRefPtr<NodeList> Internals::nodesFromRect(Document* document, int x, int y, unsigned topPadding, unsigned rightPadding,
916     unsigned bottomPadding, unsigned leftPadding, bool ignoreClipping, bool allowShadowContent, ExceptionCode& ec) const
917 {
918     if (!document || !document->frame() || !document->frame()->view()) {
919         ec = INVALID_ACCESS_ERR;
920         return 0;
921     }
922
923     return document->nodesFromRect(x, y, topPadding, rightPadding, bottomPadding, leftPadding, ignoreClipping, allowShadowContent);
924 }
925
926 void Internals::emitInspectorDidBeginFrame()
927 {
928     InspectorInstrumentation::didBeginFrame(frame()->page());
929 }
930
931 void Internals::emitInspectorDidCancelFrame()
932 {
933     InspectorInstrumentation::didCancelFrame(frame()->page());
934 }
935
936 void Internals::setBatteryStatus(Document* document, const String& eventType, bool charging, double chargingTime, double dischargingTime, double level, ExceptionCode& ec)
937 {
938     if (!document || !document->page()) {
939         ec = INVALID_ACCESS_ERR;
940         return;
941     }
942
943 #if ENABLE(BATTERY_STATUS)
944     BatteryController::from(document->page())->didChangeBatteryStatus(eventType, BatteryStatus::create(charging, chargingTime, dischargingTime, level));
945 #else
946     UNUSED_PARAM(eventType);
947     UNUSED_PARAM(charging);
948     UNUSED_PARAM(chargingTime);
949     UNUSED_PARAM(dischargingTime);
950     UNUSED_PARAM(level);
951 #endif
952 }
953
954 void Internals::setNetworkInformation(Document* document, const String& eventType, long bandwidth, bool metered, ExceptionCode& ec)
955 {
956     if (!document || !document->page()) {
957         ec = INVALID_ACCESS_ERR;
958         return;
959     }
960
961 #if ENABLE(NETWORK_INFO)
962     NetworkInfoController::from(document->page())->didChangeNetworkInformation(eventType, NetworkInfo::create(bandwidth, metered));
963 #else
964     UNUSED_PARAM(eventType);
965     UNUSED_PARAM(bandwidth);
966     UNUSED_PARAM(metered);
967 #endif
968 }
969
970 bool Internals::hasSpellingMarker(Document* document, int from, int length, ExceptionCode&)
971 {
972     if (!document || !document->frame())
973         return 0;
974
975     return document->frame()->editor()->selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
976 }
977
978 #if ENABLE(INSPECTOR)
979 unsigned Internals::numberOfLiveNodes() const
980 {
981     return InspectorCounters::counterValue(InspectorCounters::NodeCounter);
982 }
983
984 unsigned Internals::numberOfLiveDocuments() const
985 {
986     return InspectorCounters::counterValue(InspectorCounters::DocumentCounter);
987 }
988
989 Vector<String> Internals::consoleMessageArgumentCounts(Document* document) const
990 {
991     InstrumentingAgents* instrumentingAgents = instrumentationForPage(document->page());
992     if (!instrumentingAgents)
993         return Vector<String>();
994     InspectorConsoleAgent* consoleAgent = instrumentingAgents->inspectorConsoleAgent();
995     if (!consoleAgent)
996         return Vector<String>();
997     Vector<unsigned> counts = consoleAgent->consoleMessageArgumentCounts();
998     Vector<String> result(counts.size());
999     for (size_t i = 0; i < counts.size(); i++)
1000         result[i] = String::number(counts[i]);
1001     return result;
1002 }
1003 #endif // ENABLE(INSPECTOR)
1004
1005 bool Internals::hasGrammarMarker(Document* document, int from, int length, ExceptionCode&)
1006 {
1007     if (!document || !document->frame())
1008         return 0;
1009
1010     return document->frame()->editor()->selectionStartHasMarkerFor(DocumentMarker::Grammar, from, length);
1011 }
1012
1013 unsigned Internals::numberOfScrollableAreas(Document* document, ExceptionCode&)
1014 {
1015     unsigned count = 0;
1016     Frame* frame = document->frame();
1017     if (frame->view()->scrollableAreas())
1018         count += frame->view()->scrollableAreas()->size();
1019
1020     for (Frame* child = frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
1021         if (child->view() && child->view()->scrollableAreas())
1022             count += child->view()->scrollableAreas()->size();
1023     }
1024
1025     return count;
1026 }
1027     
1028 bool Internals::isPageBoxVisible(Document* document, int pageNumber, ExceptionCode& ec)
1029 {
1030     if (!document) {
1031         ec = INVALID_ACCESS_ERR;
1032         return false;
1033     }
1034
1035     return document->isPageBoxVisible(pageNumber);
1036 }
1037
1038 void Internals::suspendAnimations(Document* document, ExceptionCode& ec) const
1039 {
1040     if (!document || !document->frame()) {
1041         ec = INVALID_ACCESS_ERR;
1042         return;
1043     }
1044
1045     AnimationController* controller = document->frame()->animation();
1046     if (!controller)
1047         return;
1048
1049     controller->suspendAnimations();
1050 }
1051
1052 void Internals::resumeAnimations(Document* document, ExceptionCode& ec) const
1053 {
1054     if (!document || !document->frame()) {
1055         ec = INVALID_ACCESS_ERR;
1056         return;
1057     }
1058
1059     AnimationController* controller = document->frame()->animation();
1060     if (!controller)
1061         return;
1062
1063     controller->resumeAnimations();
1064 }
1065
1066 void Internals::allowRoundingHacks() const
1067 {
1068     TextRun::setAllowsRoundingHacks(true);
1069 }
1070
1071 String Internals::counterValue(Element* element)
1072 {
1073     if (!element)
1074         return String();
1075
1076     return counterValueForElement(element);
1077 }
1078
1079 #if ENABLE(FULLSCREEN_API)
1080 void Internals::webkitWillEnterFullScreenForElement(Document* document, Element* element)
1081 {
1082     if (!document)
1083         return;
1084     document->webkitWillEnterFullScreenForElement(element);
1085 }
1086
1087 void Internals::webkitDidEnterFullScreenForElement(Document* document, Element* element)
1088 {
1089     if (!document)
1090         return;
1091     document->webkitDidEnterFullScreenForElement(element);
1092 }
1093
1094 void Internals::webkitWillExitFullScreenForElement(Document* document, Element* element)
1095 {
1096     if (!document)
1097         return;
1098     document->webkitWillExitFullScreenForElement(element);
1099 }
1100
1101 void Internals::webkitDidExitFullScreenForElement(Document* document, Element* element)
1102 {
1103     if (!document)
1104         return;
1105     document->webkitDidExitFullScreenForElement(element);
1106 }
1107 #endif
1108 }