ff8289aea74c627b7fafce320281419e992f8038
[WebKit.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 "BackForwardController.h"
30 #include "CachedResourceLoader.h"
31 #include "Chrome.h"
32 #include "ChromeClient.h"
33 #include "ClientRect.h"
34 #include "ClientRectList.h"
35 #include "ComposedShadowTreeWalker.h"
36 #include "Cursor.h"
37 #include "DOMStringList.h"
38 #include "DOMWindow.h"
39 #include "Document.h"
40 #include "DocumentMarker.h"
41 #include "DocumentMarkerController.h"
42 #include "Element.h"
43 #include "ElementShadow.h"
44 #include "EventHandler.h"
45 #include "ExceptionCode.h"
46 #include "FormController.h"
47 #include "Frame.h"
48 #include "FrameView.h"
49 #include "HTMLContentElement.h"
50 #include "HTMLInputElement.h"
51 #include "HTMLNames.h"
52 #include "HTMLTextAreaElement.h"
53 #include "HistoryItem.h"
54 #include "InspectorClient.h"
55 #include "InspectorConsoleAgent.h"
56 #include "InspectorController.h"
57 #include "InspectorCounters.h"
58 #include "InspectorFrontendChannel.h"
59 #include "InspectorFrontendClientLocal.h"
60 #include "InspectorInstrumentation.h"
61 #include "InspectorOverlay.h"
62 #include "InstrumentingAgents.h"
63 #include "InternalSettings.h"
64 #include "IntRect.h"
65 #include "Language.h"
66 #include "MallocStatistics.h"
67 #include "MockPagePopupDriver.h"
68 #include "NodeRenderingContext.h"
69 #include "Page.h"
70 #include "PrintContext.h"
71 #include "Range.h"
72 #include "RenderObject.h"
73 #include "RenderTreeAsText.h"
74 #include "RuntimeEnabledFeatures.h"
75 #include "SchemeRegistry.h"
76 #include "SelectRuleFeatureSet.h"
77 #include "SerializedScriptValue.h"
78 #include "Settings.h"
79 #include "ShadowRoot.h"
80 #include "SpellChecker.h"
81 #include "StyleSheetContents.h"
82 #include "TextIterator.h"
83 #include "TreeScope.h"
84 #include "ViewportArguments.h"
85 #include <wtf/text/StringBuffer.h>
86
87 #if ENABLE(INPUT_TYPE_COLOR)
88 #include "ColorChooser.h"
89 #endif
90
91 #if ENABLE(BATTERY_STATUS)
92 #include "BatteryController.h"
93 #endif
94
95 #if ENABLE(NETWORK_INFO)
96 #include "NetworkInfo.h"
97 #include "NetworkInfoController.h"
98 #endif
99
100 #if ENABLE(PAGE_POPUP)
101 #include "PagePopupController.h"
102 #endif
103
104 #if ENABLE(TOUCH_ADJUSTMENT)
105 #include "WebKitPoint.h"
106 #endif
107
108 #if ENABLE(MOUSE_CURSOR_SCALE)
109 #include <wtf/dtoa.h>
110 #endif
111
112 #if PLATFORM(CHROMIUM)
113 #include "FilterOperation.h"
114 #include "FilterOperations.h"
115 #include "GraphicsLayer.h"
116 #include "GraphicsLayerChromium.h"
117 #include "RenderLayerBacking.h"
118 #endif
119
120 namespace WebCore {
121
122 #if ENABLE(PAGE_POPUP)
123 static MockPagePopupDriver* s_pagePopupDriver = 0;
124 #endif
125
126 using namespace HTMLNames;
127
128 #if ENABLE(INSPECTOR)
129 class InspectorFrontendClientDummy : public InspectorFrontendClientLocal {
130 public:
131     InspectorFrontendClientDummy(InspectorController*, Page*);
132     virtual ~InspectorFrontendClientDummy() { }
133     virtual void attachWindow() OVERRIDE { }
134     virtual void detachWindow() OVERRIDE { }
135
136     virtual String localizedStringsURL() OVERRIDE { return String(); }
137     virtual String hiddenPanels() OVERRIDE { return String(); }
138
139     virtual void bringToFront() OVERRIDE { }
140     virtual void closeWindow() OVERRIDE { }
141
142     virtual void inspectedURLChanged(const String&) OVERRIDE { }
143
144 protected:
145     virtual void setAttachedWindowHeight(unsigned) OVERRIDE { }
146 };
147
148 InspectorFrontendClientDummy::InspectorFrontendClientDummy(InspectorController* controller, Page* page)
149     : InspectorFrontendClientLocal(controller, page, adoptPtr(new InspectorFrontendClientLocal::Settings()))
150 {
151 }
152
153 class InspectorFrontendChannelDummy : public InspectorFrontendChannel {
154 public:
155     explicit InspectorFrontendChannelDummy(Page*);
156     virtual ~InspectorFrontendChannelDummy() { }
157     virtual bool sendMessageToFrontend(const String& message) OVERRIDE;
158
159 private:
160     Page* m_frontendPage;
161 };
162
163 InspectorFrontendChannelDummy::InspectorFrontendChannelDummy(Page* page)
164     : m_frontendPage(page)
165 {
166 }
167
168 bool InspectorFrontendChannelDummy::sendMessageToFrontend(const String& message)
169 {
170     return InspectorClient::doDispatchMessageOnFrontendPage(m_frontendPage, message);
171 }
172 #endif // ENABLE(INSPECTOR)
173
174 static bool markerTypesFrom(const String& markerType, DocumentMarker::MarkerTypes& result)
175 {
176     if (markerType.isEmpty() || equalIgnoringCase(markerType, "all"))
177         result = DocumentMarker::AllMarkers();
178     else if (equalIgnoringCase(markerType, "Spelling"))
179         result =  DocumentMarker::Spelling;
180     else if (equalIgnoringCase(markerType, "Grammar"))
181         result =  DocumentMarker::Grammar;
182     else if (equalIgnoringCase(markerType, "TextMatch"))
183         result =  DocumentMarker::TextMatch;
184     else if (equalIgnoringCase(markerType, "Replacement"))
185         result =  DocumentMarker::Replacement;
186     else if (equalIgnoringCase(markerType, "CorrectionIndicator"))
187         result =  DocumentMarker::CorrectionIndicator;
188     else if (equalIgnoringCase(markerType, "RejectedCorrection"))
189         result =  DocumentMarker::RejectedCorrection;
190     else if (equalIgnoringCase(markerType, "Autocorrected"))
191         result =  DocumentMarker::Autocorrected;
192     else if (equalIgnoringCase(markerType, "SpellCheckingExemption"))
193         result =  DocumentMarker::SpellCheckingExemption;
194     else if (equalIgnoringCase(markerType, "DeletedAutocorrection"))
195         result =  DocumentMarker::DeletedAutocorrection;
196     else if (equalIgnoringCase(markerType, "DictationAlternatives"))
197         result =  DocumentMarker::DictationAlternatives;
198     else
199         return false;
200
201     return true;
202 }
203
204 static SpellChecker* spellchecker(Document* document)
205 {
206     if (!document || !document->frame() || !document->frame()->editor())
207         return 0;
208
209     return document->frame()->editor()->spellChecker();
210 }
211
212 const char* Internals::internalsId = "internals";
213
214 PassRefPtr<Internals> Internals::create(Document* document)
215 {
216     return adoptRef(new Internals(document));
217 }
218
219 Internals::~Internals()
220 {
221 }
222
223 void Internals::resetToConsistentState(Page* page)
224 {
225     ASSERT(page);
226
227     page->setPageScaleFactor(1, IntPoint(0, 0));
228     page->setPagination(Pagination());
229     TextRun::setAllowsRoundingHacks(false);
230     WebCore::overrideUserPreferredLanguages(Vector<String>());
231     WebCore::Settings::setUsesOverlayScrollbars(false);
232 #if ENABLE(PAGE_POPUP)
233     delete s_pagePopupDriver;
234     s_pagePopupDriver = 0;
235     if (page->chrome())
236         page->chrome()->client()->resetPagePopupDriver();
237 #endif
238 #if ENABLE(INSPECTOR) && ENABLE(JAVASCRIPT_DEBUGGER)
239     if (page->inspectorController())
240         page->inspectorController()->setProfilerEnabled(false);
241 #endif
242 }
243
244 Internals::Internals(Document* document)
245     : ContextDestructionObserver(document)
246 {
247 }
248
249 Document* Internals::contextDocument() const
250 {
251     return static_cast<Document*>(scriptExecutionContext());
252 }
253
254 Frame* Internals::frame() const
255 {
256     if (!contextDocument())
257         return 0;
258     return contextDocument()->frame();
259 }
260
261 InternalSettings* Internals::settings() const
262 {
263     Document* document = contextDocument();
264     if (!document)
265         return 0;
266     Page* page = document->page();
267     if (!page)
268         return 0;
269     return InternalSettings::from(page);
270 }
271
272 String Internals::address(Node* node)
273 {
274     char buf[32];
275     sprintf(buf, "%p", node);
276
277     return String(buf);
278 }
279
280 bool Internals::isPreloaded(Document* document, const String& url)
281 {
282     if (!document)
283         return false;
284
285     return document->cachedResourceLoader()->isPreloaded(url);
286 }
287
288 PassRefPtr<Element> Internals::createContentElement(Document* document, ExceptionCode& ec)
289 {
290     if (!document) {
291         ec = INVALID_ACCESS_ERR;
292         return 0;
293     }
294
295     return HTMLContentElement::create(document);
296 }
297
298 bool Internals::isValidContentSelect(Element* insertionPoint, ExceptionCode& ec)
299 {
300     if (!insertionPoint || !insertionPoint->isInsertionPoint()) {
301         ec = INVALID_ACCESS_ERR;
302         return false;
303     }
304
305     return toInsertionPoint(insertionPoint)->isSelectValid();
306 }
307
308 Node* Internals::treeScopeRootNode(Node* node, ExceptionCode& ec)
309 {
310     if (!node) {
311         ec = INVALID_ACCESS_ERR;
312         return 0;
313     }
314
315     return node->treeScope()->rootNode();
316 }
317
318 Node* Internals::parentTreeScope(Node* node, ExceptionCode& ec)
319 {
320     if (!node) {
321         ec = INVALID_ACCESS_ERR;
322         return 0;
323     }
324     const TreeScope* parentTreeScope = node->treeScope()->parentTreeScope();
325     return parentTreeScope ? parentTreeScope->rootNode() : 0;
326 }
327
328 bool Internals::hasSelectorForIdInShadow(Element* host, const String& idValue, ExceptionCode& ec)
329 {
330     if (!host || !host->shadow()) {
331         ec = INVALID_ACCESS_ERR;
332         return 0;
333     }
334
335     host->shadow()->ensureSelectFeatureSetCollected();
336     return host->shadow()->selectRuleFeatureSet().hasSelectorForId(idValue);
337 }
338
339 bool Internals::hasSelectorForClassInShadow(Element* host, const String& className, ExceptionCode& ec)
340 {
341     if (!host || !host->shadow()) {
342         ec = INVALID_ACCESS_ERR;
343         return 0;
344     }
345
346     host->shadow()->ensureSelectFeatureSetCollected();
347     return host->shadow()->selectRuleFeatureSet().hasSelectorForClass(className);
348 }
349
350 bool Internals::hasSelectorForAttributeInShadow(Element* host, const String& attributeName, ExceptionCode& ec)
351 {
352     if (!host || !host->shadow()) {
353         ec = INVALID_ACCESS_ERR;
354         return 0;
355     }
356
357     host->shadow()->ensureSelectFeatureSetCollected();
358     return host->shadow()->selectRuleFeatureSet().hasSelectorForAttribute(attributeName);
359 }
360
361 bool Internals::hasSelectorForPseudoClassInShadow(Element* host, const String& pseudoClass, ExceptionCode& ec)
362 {
363     if (!host || !host->shadow()) {
364         ec = INVALID_ACCESS_ERR;
365         return 0;
366     }
367
368     host->shadow()->ensureSelectFeatureSetCollected();
369     const SelectRuleFeatureSet& featureSet = host->shadow()->selectRuleFeatureSet();
370     if (pseudoClass == "checked")
371         return featureSet.hasSelectorForChecked();
372     if (pseudoClass == "enabled")
373         return featureSet.hasSelectorForEnabled();
374     if (pseudoClass == "disabled")
375         return featureSet.hasSelectorForDisabled();
376     if (pseudoClass == "indeterminate")
377         return featureSet.hasSelectorForIndeterminate();
378     if (pseudoClass == "link")
379         return featureSet.hasSelectorForLink();
380     if (pseudoClass == "target")
381         return featureSet.hasSelectorForTarget();
382     if (pseudoClass == "visited")
383         return featureSet.hasSelectorForVisited();
384
385     ASSERT_NOT_REACHED();
386     return false;
387 }
388
389 bool Internals::hasShadowInsertionPoint(const Node* root, ExceptionCode& ec) const
390 {
391     if (root && root->isShadowRoot())
392         return toShadowRoot(root)->hasShadowInsertionPoint();
393
394     ec = INVALID_ACCESS_ERR;
395     return 0;
396 }
397
398 bool Internals::hasContentElement(const Node* root, ExceptionCode& ec) const
399 {
400     if (root && root->isShadowRoot())
401         return toShadowRoot(root)->hasContentElement();
402
403     ec = INVALID_ACCESS_ERR;
404     return 0;
405 }
406
407 size_t Internals::countElementShadow(const Node* root, ExceptionCode& ec) const
408 {
409     if (!root || !root->isShadowRoot()) {
410         ec = INVALID_ACCESS_ERR;
411         return 0;
412     }
413
414     return toShadowRoot(root)->countElementShadow();
415 }
416
417 bool Internals::attached(Node* node, ExceptionCode& ec)
418 {
419     if (!node) {
420         ec = INVALID_ACCESS_ERR;
421         return false;
422     }
423
424     return node->attached();
425 }
426
427 Node* Internals::nextSiblingByWalker(Node* node, ExceptionCode& ec)
428 {
429     if (!node) {
430         ec = INVALID_ACCESS_ERR;
431         return 0;
432     }
433     ComposedShadowTreeWalker walker(node);
434     walker.nextSibling();
435     return walker.get();
436 }
437
438 Node* Internals::firstChildByWalker(Node* node, ExceptionCode& ec)
439 {
440     if (!node) {
441         ec = INVALID_ACCESS_ERR;
442         return 0;
443     }
444     ComposedShadowTreeWalker walker(node);
445     walker.firstChild();
446     return walker.get();
447 }
448
449 Node* Internals::lastChildByWalker(Node* node, ExceptionCode& ec)
450 {
451     if (!node) {
452         ec = INVALID_ACCESS_ERR;
453         return 0;
454     }
455     ComposedShadowTreeWalker walker(node);
456     walker.lastChild();
457     return walker.get();
458 }
459
460 Node* Internals::nextNodeByWalker(Node* node, ExceptionCode& ec)
461 {
462     if (!node) {
463         ec = INVALID_ACCESS_ERR;
464         return 0;
465     }
466     ComposedShadowTreeWalker walker(node);
467     walker.next();
468     return walker.get();
469 }
470
471 Node* Internals::previousNodeByWalker(Node* node, ExceptionCode& ec)
472 {
473     if (!node) {
474         ec = INVALID_ACCESS_ERR;
475         return 0;
476     }
477     ComposedShadowTreeWalker walker(node);
478     walker.previous();
479     return walker.get();
480 }
481
482 String Internals::elementRenderTreeAsText(Element* element, ExceptionCode& ec)
483 {
484     if (!element) {
485         ec = INVALID_ACCESS_ERR;
486         return String();
487     }
488
489     String representation = externalRepresentation(element);
490     if (representation.isEmpty()) {
491         ec = INVALID_ACCESS_ERR;
492         return String();
493     }
494
495     return representation;
496 }
497
498 size_t Internals::numberOfScopedHTMLStyleChildren(const Node* scope, ExceptionCode& ec) const
499 {
500     if (scope && (scope->isElementNode() || scope->isShadowRoot()))
501 #if ENABLE(STYLE_SCOPED)
502         return scope->numberOfScopedHTMLStyleChildren();
503 #else
504         return 0;
505 #endif
506
507     ec = INVALID_ACCESS_ERR;
508     return 0;
509 }
510
511 Internals::ShadowRootIfShadowDOMEnabledOrNode* Internals::ensureShadowRoot(Element* host, ExceptionCode& ec)
512 {
513     if (!host) {
514         ec = INVALID_ACCESS_ERR;
515         return 0;
516     }
517
518     if (ElementShadow* shadow = host->shadow())
519         return shadow->youngestShadowRoot();
520
521     return ShadowRoot::create(host, ec).get();
522 }
523
524 Internals::ShadowRootIfShadowDOMEnabledOrNode* Internals::shadowRoot(Element* host, ExceptionCode& ec)
525 {
526     // FIXME: Internals::shadowRoot() in tests should be converted to youngestShadowRoot() or oldestShadowRoot().
527     // https://bugs.webkit.org/show_bug.cgi?id=78465
528     return youngestShadowRoot(host, ec);
529 }
530
531 Internals::ShadowRootIfShadowDOMEnabledOrNode* Internals::youngestShadowRoot(Element* host, ExceptionCode& ec)
532 {
533     if (!host) {
534         ec = INVALID_ACCESS_ERR;
535         return 0;
536     }
537
538     if (ElementShadow* shadow = host->shadow())
539         return shadow->youngestShadowRoot();
540     return 0;
541 }
542
543 Internals::ShadowRootIfShadowDOMEnabledOrNode* Internals::oldestShadowRoot(Element* host, ExceptionCode& ec)
544 {
545     if (!host) {
546         ec = INVALID_ACCESS_ERR;
547         return 0;
548     }
549
550     if (ElementShadow* shadow = host->shadow())
551         return shadow->oldestShadowRoot();
552     return 0;
553 }
554
555 Internals::ShadowRootIfShadowDOMEnabledOrNode* Internals::youngerShadowRoot(Node* shadow, ExceptionCode& ec)
556 {
557     if (!shadow || !shadow->isShadowRoot()) {
558         ec = INVALID_ACCESS_ERR;
559         return 0;
560     }
561
562     return toShadowRoot(shadow)->youngerShadowRoot();
563 }
564
565 Internals::ShadowRootIfShadowDOMEnabledOrNode* Internals::olderShadowRoot(Node* shadow, ExceptionCode& ec)
566 {
567     if (!shadow || !shadow->isShadowRoot()) {
568         ec = INVALID_ACCESS_ERR;
569         return 0;
570     }
571
572     return toShadowRoot(shadow)->olderShadowRoot();
573 }
574
575 String Internals::shadowRootType(const Node* root, ExceptionCode& ec) const
576 {
577     if (!root || !root->isShadowRoot()) {
578         ec = INVALID_ACCESS_ERR;
579         return String();
580     }
581
582     switch (toShadowRoot(root)->type()) {
583     case ShadowRoot::UserAgentShadowRoot:
584         return String("UserAgentShadowRoot");
585     case ShadowRoot::AuthorShadowRoot:
586         return String("AuthorShadowRoot");
587     default:
588         ASSERT_NOT_REACHED();
589         return String("Unknown");
590     }
591 }
592
593 Element* Internals::includerFor(Node* node, ExceptionCode& ec)
594 {
595     if (!node) {
596         ec = INVALID_ACCESS_ERR;
597         return 0;
598     }
599
600     return NodeRenderingContext(node).insertionPoint();
601 }
602
603 String Internals::shadowPseudoId(Element* element, ExceptionCode& ec)
604 {
605     if (!element) {
606         ec = INVALID_ACCESS_ERR;
607         return String();
608     }
609
610     return element->shadowPseudoId().string();
611 }
612
613 void Internals::setShadowPseudoId(Element* element, const String& id, ExceptionCode& ec)
614 {
615     if (!element) {
616         ec = INVALID_ACCESS_ERR;
617         return;
618     }
619
620     return element->setPseudo(id);
621 }
622
623 String Internals::visiblePlaceholder(Element* element)
624 {
625     HTMLTextFormControlElement* textControl = toTextFormControl(element);
626     if (textControl && textControl->placeholderShouldBeVisible())
627         return textControl->placeholderElement()->textContent();
628     return String();
629 }
630
631 #if ENABLE(INPUT_TYPE_COLOR)
632 void Internals::selectColorInColorChooser(Element* element, const String& colorValue)
633 {
634     if (!element->hasTagName(inputTag))
635         return;
636     HTMLInputElement* inputElement = element->toInputElement();
637     if (!inputElement)
638         return;
639     inputElement->selectColorInColorChooser(Color(colorValue));
640 }
641 #endif
642
643 PassRefPtr<DOMStringList> Internals::formControlStateOfPreviousHistoryItem(ExceptionCode& ec)
644 {
645     HistoryItem* mainItem = frame()->loader()->history()->previousItem();
646     if (!mainItem) {
647         ec = INVALID_ACCESS_ERR;
648         return 0;
649     }
650     String uniqueName = frame()->tree()->uniqueName();
651     if (mainItem->target() != uniqueName && !mainItem->childItemWithTarget(uniqueName)) {
652         ec = INVALID_ACCESS_ERR;
653         return 0;
654     }
655     const Vector<String>& state = mainItem->target() == uniqueName ? mainItem->documentState() : mainItem->childItemWithTarget(uniqueName)->documentState();
656     RefPtr<DOMStringList> stringList = DOMStringList::create();
657     for (unsigned i = 0; i < state.size(); ++i)
658         stringList->append(state[i]);
659     return stringList.release();
660 }
661
662 void Internals::setFormControlStateOfPreviousHistoryItem(PassRefPtr<DOMStringList> state, ExceptionCode& ec)
663 {
664     HistoryItem* mainItem = frame()->loader()->history()->previousItem();
665     if (!state || !mainItem) {
666         ec = INVALID_ACCESS_ERR;
667         return;
668     }
669     String uniqueName = frame()->tree()->uniqueName();
670     if (mainItem->target() == uniqueName)
671         mainItem->setDocumentState(*state.get());
672     else if (HistoryItem* subItem = mainItem->childItemWithTarget(uniqueName))
673         subItem->setDocumentState(*state.get());
674     else
675         ec = INVALID_ACCESS_ERR;
676 }
677
678 void Internals::setEnableMockPagePopup(bool enabled, ExceptionCode& ec)
679 {
680 #if ENABLE(PAGE_POPUP)
681     Document* document = contextDocument();
682     if (!document || !document->page() || !document->page()->chrome())
683         return;
684     Page* page = document->page();
685     if (!enabled) {
686         page->chrome()->client()->resetPagePopupDriver();
687         return;
688     }
689     if (!s_pagePopupDriver)
690         s_pagePopupDriver = MockPagePopupDriver::create(page->mainFrame()).leakPtr();
691     page->chrome()->client()->setPagePopupDriver(s_pagePopupDriver);
692 #else
693     UNUSED_PARAM(enabled);
694     UNUSED_PARAM(ec);
695 #endif
696 }
697
698 #if ENABLE(PAGE_POPUP)
699 PassRefPtr<PagePopupController> Internals::pagePopupController()
700 {
701     return s_pagePopupDriver ? s_pagePopupDriver->pagePopupController() : 0;
702 }
703 #endif
704
705 PassRefPtr<ClientRect> Internals::absoluteCaretBounds(Document* document, ExceptionCode& ec)
706 {
707     if (!document || !document->frame() || !document->frame()->selection()) {
708         ec = INVALID_ACCESS_ERR;
709         return ClientRect::create();
710     }
711
712     return ClientRect::create(document->frame()->selection()->absoluteCaretBounds());
713 }
714
715 PassRefPtr<ClientRect> Internals::boundingBox(Element* element, ExceptionCode& ec)
716 {
717     if (!element) {
718         ec = INVALID_ACCESS_ERR;
719         return ClientRect::create();
720     }
721
722     element->document()->updateLayoutIgnorePendingStylesheets();
723     RenderObject* renderer = element->renderer();
724     if (!renderer)
725         return ClientRect::create();
726     return ClientRect::create(renderer->absoluteBoundingBoxRectIgnoringTransforms());
727 }
728
729 PassRefPtr<ClientRectList> Internals::inspectorHighlightRects(Document* document, ExceptionCode& ec)
730 {
731 #if ENABLE(INSPECTOR)
732     if (!document || !document->page() || !document->page()->inspectorController()) {
733         ec = INVALID_ACCESS_ERR;
734         return ClientRectList::create();
735     }
736
737     Highlight highlight;
738     document->page()->inspectorController()->getHighlight(&highlight);
739     return ClientRectList::create(highlight.quads);
740 #else
741     UNUSED_PARAM(document);
742     UNUSED_PARAM(ec);
743     return ClientRectList::create();
744 #endif
745 }
746
747 #if PLATFORM(CHROMIUM)
748 void Internals::setBackgroundBlurOnNode(Node* node, int blurLength, ExceptionCode& ec)
749 {
750     if (!node) {
751         ec = INVALID_ACCESS_ERR;
752         return;
753     }
754
755     RenderObject* renderObject = node->renderer();
756     if (!renderObject) {
757         ec = INVALID_NODE_TYPE_ERR;
758         return;
759     }
760
761     RenderLayer* renderLayer = renderObject->enclosingLayer();
762     if (!renderLayer || !renderLayer->isComposited()) {
763         ec = INVALID_STATE_ERR;
764         return;
765     }
766
767     GraphicsLayer* graphicsLayer = renderLayer->backing()->graphicsLayer();
768     if (!graphicsLayer) {
769         ec = INVALID_NODE_TYPE_ERR;
770         return;
771     }
772
773     FilterOperations filters;
774     filters.operations().append(BlurFilterOperation::create(Length(blurLength, Fixed), FilterOperation::BLUR));
775     static_cast<GraphicsLayerChromium*>(graphicsLayer)->setBackgroundFilters(filters);
776 }
777 #else
778 void Internals::setBackgroundBlurOnNode(Node*, int, ExceptionCode&)
779 {
780 }
781 #endif
782
783 unsigned Internals::markerCountForNode(Node* node, const String& markerType, ExceptionCode& ec)
784 {
785     if (!node) {
786         ec = INVALID_ACCESS_ERR;
787         return 0;
788     }
789
790     DocumentMarker::MarkerTypes markerTypes = 0;
791     if (!markerTypesFrom(markerType, markerTypes)) {
792         ec = SYNTAX_ERR;
793         return 0;
794     }
795
796     return node->document()->markers()->markersFor(node, markerTypes).size();
797 }
798
799 DocumentMarker* Internals::markerAt(Node* node, const String& markerType, unsigned index, ExceptionCode& ec)
800 {
801     if (!node) {
802         ec = INVALID_ACCESS_ERR;
803         return 0;
804     }
805
806     DocumentMarker::MarkerTypes markerTypes = 0;
807     if (!markerTypesFrom(markerType, markerTypes)) {
808         ec = SYNTAX_ERR;
809         return 0;
810     }
811
812     Vector<DocumentMarker*> markers = node->document()->markers()->markersFor(node, markerTypes);
813     if (markers.size() <= index)
814         return 0;
815     return markers[index];
816 }
817
818 PassRefPtr<Range> Internals::markerRangeForNode(Node* node, const String& markerType, unsigned index, ExceptionCode& ec)
819 {
820     DocumentMarker* marker = markerAt(node, markerType, index, ec);
821     if (!marker)
822         return 0;
823     return Range::create(node->document(), node, marker->startOffset(), node, marker->endOffset());
824 }
825
826 String Internals::markerDescriptionForNode(Node* node, const String& markerType, unsigned index, ExceptionCode& ec)
827 {
828     DocumentMarker* marker = markerAt(node, markerType, index, ec);
829     if (!marker)
830         return String();
831     return marker->description();
832 }
833
834 void Internals::addTextMatchMarker(const Range* range, bool isActive)
835 {
836     range->ownerDocument()->updateLayoutIgnorePendingStylesheets();
837     range->ownerDocument()->markers()->addTextMatchMarker(range, isActive);
838 }
839
840 void Internals::setScrollViewPosition(Document* document, long x, long y, ExceptionCode& ec)
841 {
842     if (!document || !document->view()) {
843         ec = INVALID_ACCESS_ERR;
844         return;
845     }
846
847     FrameView* frameView = document->view();
848     bool constrainsScrollingToContentEdgeOldValue = frameView->constrainsScrollingToContentEdge();
849     bool scrollbarsSuppressedOldValue = frameView->scrollbarsSuppressed();
850
851     frameView->setConstrainsScrollingToContentEdge(false);
852     frameView->setScrollbarsSuppressed(false);
853     frameView->setScrollOffsetFromInternals(IntPoint(x, y));
854     frameView->setScrollbarsSuppressed(scrollbarsSuppressedOldValue);
855     frameView->setConstrainsScrollingToContentEdge(constrainsScrollingToContentEdgeOldValue);
856 }
857
858 void Internals::setPagination(Document* document, const String& mode, int gap, int pageLength, ExceptionCode& ec)
859 {
860     if (!document || !document->page()) {
861         ec = INVALID_ACCESS_ERR;
862         return;
863     }
864     Page* page = document->page();
865
866     Pagination pagination;
867     if (mode == "Unpaginated")
868         pagination.mode = Pagination::Unpaginated;
869     else if (mode == "LeftToRightPaginated")
870         pagination.mode = Pagination::LeftToRightPaginated;
871     else if (mode == "RightToLeftPaginated")
872         pagination.mode = Pagination::RightToLeftPaginated;
873     else if (mode == "TopToBottomPaginated")
874         pagination.mode = Pagination::TopToBottomPaginated;
875     else if (mode == "BottomToTopPaginated")
876         pagination.mode = Pagination::BottomToTopPaginated;
877     else {
878         ec = SYNTAX_ERR;
879         return;
880     }
881
882     pagination.gap = gap;
883     pagination.pageLength = pageLength;
884     page->setPagination(pagination);
885 }
886
887 String Internals::configurationForViewport(Document* document, float devicePixelRatio, int deviceWidth, int deviceHeight, int availableWidth, int availableHeight, ExceptionCode& ec)
888 {
889     if (!document || !document->page()) {
890         ec = INVALID_ACCESS_ERR;
891         return String();
892     }
893     Page* page = document->page();
894
895     const int defaultLayoutWidthForNonMobilePages = 980;
896
897     ViewportArguments arguments = page->viewportArguments();
898     ViewportAttributes attributes = computeViewportAttributes(arguments, defaultLayoutWidthForNonMobilePages, deviceWidth, deviceHeight, devicePixelRatio, IntSize(availableWidth, availableHeight));
899     restrictMinimumScaleFactorToViewportSize(attributes, IntSize(availableWidth, availableHeight), devicePixelRatio);
900     restrictScaleFactorToInitialScaleIfNotUserScalable(attributes);
901
902     return "viewport size " + String::number(attributes.layoutSize.width()) + "x" + String::number(attributes.layoutSize.height()) + " scale " + String::number(attributes.initialScale) + " with limits [" + String::number(attributes.minimumScale) + ", " + String::number(attributes.maximumScale) + "] and userScalable " + (attributes.userScalable ? "true" : "false");
903 }
904
905 bool Internals::wasLastChangeUserEdit(Element* textField, ExceptionCode& ec)
906 {
907     if (!textField) {
908         ec = INVALID_ACCESS_ERR;
909         return false;
910     }
911
912     if (HTMLInputElement* inputElement = textField->toInputElement())
913         return inputElement->lastChangeWasUserEdit();
914
915     // FIXME: We should be using hasTagName instead but Windows port doesn't link QualifiedNames properly.
916     if (textField->tagName() == "TEXTAREA")
917         return static_cast<HTMLTextAreaElement*>(textField)->lastChangeWasUserEdit();
918
919     ec = INVALID_NODE_TYPE_ERR;
920     return false;
921 }
922
923 String Internals::suggestedValue(Element* element, ExceptionCode& ec)
924 {
925     if (!element) {
926         ec = INVALID_ACCESS_ERR;
927         return String();
928     }
929
930     HTMLInputElement* inputElement = element->toInputElement();
931     if (!inputElement) {
932         ec = INVALID_NODE_TYPE_ERR;
933         return String();
934     }
935
936     return inputElement->suggestedValue();
937 }
938
939 void Internals::setSuggestedValue(Element* element, const String& value, ExceptionCode& ec)
940 {
941     if (!element) {
942         ec = INVALID_ACCESS_ERR;
943         return;
944     }
945
946     HTMLInputElement* inputElement = element->toInputElement();
947     if (!inputElement) {
948         ec = INVALID_NODE_TYPE_ERR;
949         return;
950     }
951
952     inputElement->setSuggestedValue(value);
953 }
954
955 void Internals::setEditingValue(Element* element, const String& value, ExceptionCode& ec)
956 {
957     if (!element) {
958         ec = INVALID_ACCESS_ERR;
959         return;
960     }
961
962     HTMLInputElement* inputElement = element->toInputElement();
963     if (!inputElement) {
964         ec = INVALID_NODE_TYPE_ERR;
965         return;
966     }
967
968     inputElement->setEditingValue(value);
969 }
970
971 void Internals::scrollElementToRect(Element* element, long x, long y, long w, long h, ExceptionCode& ec)
972 {
973     if (!element || !element->document() || !element->document()->view()) {
974         ec = INVALID_ACCESS_ERR;
975         return;
976     }
977     FrameView* frameView = element->document()->view();
978     frameView->scrollElementToRect(element, IntRect(x, y, w, h));
979 }
980
981 void Internals::paintControlTints(Document* document, ExceptionCode& ec)
982 {
983     if (!document || !document->view()) {
984         ec = INVALID_ACCESS_ERR;
985         return;
986     }
987
988     FrameView* frameView = document->view();
989     frameView->paintControlTints();
990 }
991
992 PassRefPtr<Range> Internals::rangeFromLocationAndLength(Element* scope, int rangeLocation, int rangeLength, ExceptionCode& ec)
993 {
994     if (!scope) {
995         ec = INVALID_ACCESS_ERR;
996         return 0;
997     }
998
999     return TextIterator::rangeFromLocationAndLength(scope, rangeLocation, rangeLength);
1000 }
1001
1002 unsigned Internals::locationFromRange(Element* scope, const Range* range, ExceptionCode& ec)
1003 {
1004     if (!scope || !range) {
1005         ec = INVALID_ACCESS_ERR;
1006         return 0;
1007     }
1008
1009     size_t location = 0;
1010     size_t unusedLength = 0;
1011     TextIterator::getLocationAndLengthFromRange(scope, range, location, unusedLength);
1012     return location;
1013 }
1014
1015 unsigned Internals::lengthFromRange(Element* scope, const Range* range, ExceptionCode& ec)
1016 {
1017     if (!scope || !range) {
1018         ec = INVALID_ACCESS_ERR;
1019         return 0;
1020     }
1021
1022     size_t unusedLocation = 0;
1023     size_t length = 0;
1024     TextIterator::getLocationAndLengthFromRange(scope, range, unusedLocation, length);
1025     return length;
1026 }
1027
1028 String Internals::rangeAsText(const Range* range, ExceptionCode& ec)
1029 {
1030     if (!range) {
1031         ec = INVALID_ACCESS_ERR;
1032         return String();
1033     }
1034
1035     return range->text();
1036 }
1037
1038 void Internals::setDelegatesScrolling(bool enabled, Document* document, ExceptionCode& ec)
1039 {
1040     // Delegate scrolling is valid only on mainframe's view.
1041     if (!document || !document->view() || !document->page() || document->page()->mainFrame() != document->frame()) {
1042         ec = INVALID_ACCESS_ERR;
1043         return;
1044     }
1045
1046     document->view()->setDelegatesScrolling(enabled);
1047 }
1048
1049 #if ENABLE(TOUCH_ADJUSTMENT)
1050 PassRefPtr<WebKitPoint> Internals::touchPositionAdjustedToBestClickableNode(long x, long y, long width, long height, Document* document, ExceptionCode& ec)
1051 {
1052     if (!document || !document->frame()) {
1053         ec = INVALID_ACCESS_ERR;
1054         return 0;
1055     }
1056
1057     IntSize radius(width / 2, height / 2);
1058     IntPoint point(x + radius.width(), y + radius.height());
1059
1060     Node* targetNode;
1061     IntPoint adjustedPoint;
1062
1063     bool foundNode = document->frame()->eventHandler()->bestClickableNodeForTouchPoint(point, radius, adjustedPoint, targetNode);
1064     if (foundNode)
1065         return WebKitPoint::create(adjustedPoint.x(), adjustedPoint.y());
1066
1067     return 0;
1068 }
1069
1070 Node* Internals::touchNodeAdjustedToBestClickableNode(long x, long y, long width, long height, Document* document, ExceptionCode& ec)
1071 {
1072     if (!document || !document->frame()) {
1073         ec = INVALID_ACCESS_ERR;
1074         return 0;
1075     }
1076
1077     IntSize radius(width / 2, height / 2);
1078     IntPoint point(x + radius.width(), y + radius.height());
1079
1080     Node* targetNode;
1081     IntPoint adjustedPoint;
1082     document->frame()->eventHandler()->bestClickableNodeForTouchPoint(point, radius, adjustedPoint, targetNode);
1083     return targetNode;
1084 }
1085
1086 PassRefPtr<WebKitPoint> Internals::touchPositionAdjustedToBestContextMenuNode(long x, long y, long width, long height, Document* document, ExceptionCode& ec)
1087 {
1088     if (!document || !document->frame()) {
1089         ec = INVALID_ACCESS_ERR;
1090         return 0;
1091     }
1092
1093     IntSize radius(width / 2, height / 2);
1094     IntPoint point(x + radius.width(), y + radius.height());
1095
1096     Node* targetNode = 0;
1097     IntPoint adjustedPoint;
1098
1099     bool foundNode = document->frame()->eventHandler()->bestContextMenuNodeForTouchPoint(point, radius, adjustedPoint, targetNode);
1100     if (foundNode)
1101         return WebKitPoint::create(adjustedPoint.x(), adjustedPoint.y());
1102
1103     return WebKitPoint::create(x, y);
1104 }
1105
1106 Node* Internals::touchNodeAdjustedToBestContextMenuNode(long x, long y, long width, long height, Document* document, ExceptionCode& ec)
1107 {
1108     if (!document || !document->frame()) {
1109         ec = INVALID_ACCESS_ERR;
1110         return 0;
1111     }
1112
1113     IntSize radius(width / 2, height / 2);
1114     IntPoint point(x + radius.width(), y + radius.height());
1115
1116     Node* targetNode = 0;
1117     IntPoint adjustedPoint;
1118     document->frame()->eventHandler()->bestContextMenuNodeForTouchPoint(point, radius, adjustedPoint, targetNode);
1119     return targetNode;
1120 }
1121
1122 PassRefPtr<ClientRect> Internals::bestZoomableAreaForTouchPoint(long x, long y, long width, long height, Document* document, ExceptionCode& ec)
1123 {
1124     if (!document || !document->frame()) {
1125         ec = INVALID_ACCESS_ERR;
1126         return 0;
1127     }
1128
1129     IntSize radius(width / 2, height / 2);
1130     IntPoint point(x + radius.width(), y + radius.height());
1131
1132     Node* targetNode;
1133     IntRect zoomableArea;
1134     bool foundNode = document->frame()->eventHandler()->bestZoomableAreaForTouchPoint(point, radius, zoomableArea, targetNode);
1135     if (foundNode)
1136         return ClientRect::create(zoomableArea);
1137
1138     return 0;
1139 }
1140 #endif
1141
1142
1143 int Internals::lastSpellCheckRequestSequence(Document* document, ExceptionCode& ec)
1144 {
1145     SpellChecker* checker = spellchecker(document);
1146
1147     if (!checker) {
1148         ec = INVALID_ACCESS_ERR;
1149         return -1;
1150     }
1151
1152     return checker->lastRequestSequence();
1153 }
1154
1155 int Internals::lastSpellCheckProcessedSequence(Document* document, ExceptionCode& ec)
1156 {
1157     SpellChecker* checker = spellchecker(document);
1158
1159     if (!checker) {
1160         ec = INVALID_ACCESS_ERR;
1161         return -1;
1162     }
1163
1164     return checker->lastProcessedSequence();
1165 }
1166
1167 Vector<String> Internals::userPreferredLanguages() const
1168 {
1169     return WebCore::userPreferredLanguages();
1170 }
1171
1172 void Internals::setUserPreferredLanguages(const Vector<String>& languages)
1173 {
1174     WebCore::overrideUserPreferredLanguages(languages);
1175 }
1176
1177 unsigned Internals::wheelEventHandlerCount(Document* document, ExceptionCode& ec)
1178 {
1179     if (!document) {
1180         ec = INVALID_ACCESS_ERR;
1181         return 0;
1182     }
1183
1184     return document->wheelEventHandlerCount();
1185 }
1186
1187 unsigned Internals::touchEventHandlerCount(Document* document, ExceptionCode& ec)
1188 {
1189     if (!document) {
1190         ec = INVALID_ACCESS_ERR;
1191         return 0;
1192     }
1193
1194     return document->touchEventHandlerCount();
1195 }
1196
1197 PassRefPtr<NodeList> Internals::nodesFromRect(Document* document, int x, int y, unsigned topPadding, unsigned rightPadding,
1198     unsigned bottomPadding, unsigned leftPadding, bool ignoreClipping, bool allowShadowContent, ExceptionCode& ec) const
1199 {
1200     if (!document || !document->frame() || !document->frame()->view()) {
1201         ec = INVALID_ACCESS_ERR;
1202         return 0;
1203     }
1204
1205     return document->nodesFromRect(x, y, topPadding, rightPadding, bottomPadding, leftPadding, ignoreClipping, allowShadowContent);
1206 }
1207
1208 void Internals::emitInspectorDidBeginFrame()
1209 {
1210     InspectorInstrumentation::didBeginFrame(contextDocument()->frame()->page());
1211 }
1212
1213 void Internals::emitInspectorDidCancelFrame()
1214 {
1215     InspectorInstrumentation::didCancelFrame(contextDocument()->frame()->page());
1216 }
1217
1218 void Internals::setBatteryStatus(Document* document, const String& eventType, bool charging, double chargingTime, double dischargingTime, double level, ExceptionCode& ec)
1219 {
1220     if (!document || !document->page()) {
1221         ec = INVALID_ACCESS_ERR;
1222         return;
1223     }
1224
1225 #if ENABLE(BATTERY_STATUS)
1226     BatteryController::from(document->page())->didChangeBatteryStatus(eventType, BatteryStatus::create(charging, chargingTime, dischargingTime, level));
1227 #else
1228     UNUSED_PARAM(eventType);
1229     UNUSED_PARAM(charging);
1230     UNUSED_PARAM(chargingTime);
1231     UNUSED_PARAM(dischargingTime);
1232     UNUSED_PARAM(level);
1233 #endif
1234 }
1235
1236 void Internals::setNetworkInformation(Document* document, const String& eventType, double bandwidth, bool metered, ExceptionCode& ec)
1237 {
1238     if (!document || !document->page()) {
1239         ec = INVALID_ACCESS_ERR;
1240         return;
1241     }
1242
1243 #if ENABLE(NETWORK_INFO)
1244     NetworkInfoController::from(document->page())->didChangeNetworkInformation(eventType, NetworkInfo::create(bandwidth, metered));
1245 #else
1246     UNUSED_PARAM(eventType);
1247     UNUSED_PARAM(bandwidth);
1248     UNUSED_PARAM(metered);
1249 #endif
1250 }
1251
1252 bool Internals::hasSpellingMarker(Document* document, int from, int length, ExceptionCode&)
1253 {
1254     if (!document || !document->frame())
1255         return 0;
1256
1257     return document->frame()->editor()->selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
1258 }
1259     
1260 bool Internals::hasAutocorrectedMarker(Document* document, int from, int length, ExceptionCode&)
1261 {
1262     if (!document || !document->frame())
1263         return 0;
1264     
1265     return document->frame()->editor()->selectionStartHasMarkerFor(DocumentMarker::Autocorrected, from, length);
1266 }
1267
1268 #if ENABLE(INSPECTOR)
1269 unsigned Internals::numberOfLiveNodes() const
1270 {
1271     return InspectorCounters::counterValue(InspectorCounters::NodeCounter);
1272 }
1273
1274 unsigned Internals::numberOfLiveDocuments() const
1275 {
1276     return InspectorCounters::counterValue(InspectorCounters::DocumentCounter);
1277 }
1278
1279 Vector<String> Internals::consoleMessageArgumentCounts(Document* document) const
1280 {
1281     InstrumentingAgents* instrumentingAgents = instrumentationForPage(document->page());
1282     if (!instrumentingAgents)
1283         return Vector<String>();
1284     InspectorConsoleAgent* consoleAgent = instrumentingAgents->inspectorConsoleAgent();
1285     if (!consoleAgent)
1286         return Vector<String>();
1287     Vector<unsigned> counts = consoleAgent->consoleMessageArgumentCounts();
1288     Vector<String> result(counts.size());
1289     for (size_t i = 0; i < counts.size(); i++)
1290         result[i] = String::number(counts[i]);
1291     return result;
1292 }
1293
1294 PassRefPtr<DOMWindow> Internals::openDummyInspectorFrontend(const String& url)
1295 {
1296     Page* page = contextDocument()->frame()->page();
1297     ASSERT(page);
1298
1299     DOMWindow* window = page->mainFrame()->document()->domWindow();
1300     ASSERT(window);
1301
1302     m_frontendWindow = window->open(url, "", "", window, window);
1303     ASSERT(m_frontendWindow);
1304
1305     Page* frontendPage = m_frontendWindow->document()->page();
1306     ASSERT(frontendPage);
1307
1308     OwnPtr<InspectorFrontendClientDummy> frontendClient = adoptPtr(new InspectorFrontendClientDummy(page->inspectorController(), frontendPage));
1309
1310     frontendPage->inspectorController()->setInspectorFrontendClient(frontendClient.release());
1311
1312     m_frontendChannel = adoptPtr(new InspectorFrontendChannelDummy(frontendPage));
1313
1314     page->inspectorController()->connectFrontend(m_frontendChannel.get());
1315
1316     return m_frontendWindow;
1317 }
1318
1319 void Internals::closeDummyInspectorFrontend()
1320 {
1321     Page* page = contextDocument()->frame()->page();
1322     ASSERT(page);
1323     ASSERT(m_frontendWindow);
1324
1325     page->inspectorController()->disconnectFrontend();
1326
1327     m_frontendChannel.release();
1328
1329     m_frontendWindow->close(m_frontendWindow->scriptExecutionContext());
1330     m_frontendWindow.release();
1331 }
1332
1333 void Internals::setInspectorResourcesDataSizeLimits(int maximumResourcesContentSize, int maximumSingleResourceContentSize, ExceptionCode& ec)
1334 {
1335     Page* page = contextDocument()->frame()->page();
1336     if (!page || !page->inspectorController()) {
1337         ec = INVALID_ACCESS_ERR;
1338         return;
1339     }
1340     page->inspectorController()->setResourcesDataSizeLimitsFromInternals(maximumResourcesContentSize, maximumSingleResourceContentSize);
1341 }
1342
1343 void Internals::setJavaScriptProfilingEnabled(bool enabled, ExceptionCode& ec)
1344 {
1345     Page* page = contextDocument()->frame()->page();
1346     if (!page || !page->inspectorController()) {
1347         ec = INVALID_ACCESS_ERR;
1348         return;
1349     }
1350
1351     page->inspectorController()->setProfilerEnabled(enabled);
1352 }
1353 #endif // ENABLE(INSPECTOR)
1354
1355 bool Internals::hasGrammarMarker(Document* document, int from, int length, ExceptionCode&)
1356 {
1357     if (!document || !document->frame())
1358         return 0;
1359
1360     return document->frame()->editor()->selectionStartHasMarkerFor(DocumentMarker::Grammar, from, length);
1361 }
1362
1363 unsigned Internals::numberOfScrollableAreas(Document* document, ExceptionCode&)
1364 {
1365     unsigned count = 0;
1366     Frame* frame = document->frame();
1367     if (frame->view()->scrollableAreas())
1368         count += frame->view()->scrollableAreas()->size();
1369
1370     for (Frame* child = frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
1371         if (child->view() && child->view()->scrollableAreas())
1372             count += child->view()->scrollableAreas()->size();
1373     }
1374
1375     return count;
1376 }
1377     
1378 bool Internals::isPageBoxVisible(Document* document, int pageNumber, ExceptionCode& ec)
1379 {
1380     if (!document) {
1381         ec = INVALID_ACCESS_ERR;
1382         return false;
1383     }
1384
1385     return document->isPageBoxVisible(pageNumber);
1386 }
1387
1388 void Internals::suspendAnimations(Document* document, ExceptionCode& ec) const
1389 {
1390     if (!document || !document->frame()) {
1391         ec = INVALID_ACCESS_ERR;
1392         return;
1393     }
1394
1395     AnimationController* controller = document->frame()->animation();
1396     if (!controller)
1397         return;
1398
1399     controller->suspendAnimations();
1400 }
1401
1402 void Internals::resumeAnimations(Document* document, ExceptionCode& ec) const
1403 {
1404     if (!document || !document->frame()) {
1405         ec = INVALID_ACCESS_ERR;
1406         return;
1407     }
1408
1409     AnimationController* controller = document->frame()->animation();
1410     if (!controller)
1411         return;
1412
1413     controller->resumeAnimations();
1414 }
1415
1416 String Internals::layerTreeAsText(Document* document, ExceptionCode& ec) const
1417 {
1418     return layerTreeAsText(document, 0, ec);
1419 }
1420
1421 String Internals::layerTreeAsText(Document* document, unsigned flags, ExceptionCode& ec) const
1422 {
1423     if (!document || !document->frame()) {
1424         ec = INVALID_ACCESS_ERR;
1425         return String();
1426     }
1427
1428     LayerTreeFlags layerTreeFlags = 0;
1429     if (flags & LAYER_TREE_INCLUDES_VISIBLE_RECTS)
1430         layerTreeFlags |= LayerTreeFlagsIncludeVisibleRects;
1431     if (flags & LAYER_TREE_INCLUDES_TILE_CACHES)
1432         layerTreeFlags |= LayerTreeFlagsIncludeTileCaches;
1433     if (flags & LAYER_TREE_INCLUDES_REPAINT_RECTS)
1434         layerTreeFlags |= LayerTreeFlagsIncludeRepaintRects;
1435
1436     return document->frame()->layerTreeAsText(layerTreeFlags);
1437 }
1438
1439 String Internals::repaintRectsAsText(Document* document, ExceptionCode& ec) const
1440 {
1441     if (!document || !document->frame()) {
1442         ec = INVALID_ACCESS_ERR;
1443         return String();
1444     }
1445
1446     return document->frame()->trackedRepaintRectsAsText();
1447 }
1448
1449 String Internals::scrollingStateTreeAsText(Document* document, ExceptionCode& ec) const
1450 {
1451     if (!document || !document->frame()) {
1452         ec = INVALID_ACCESS_ERR;
1453         return String();
1454     }
1455
1456     Page* page = document->page();
1457     if (!page)
1458         return String();
1459
1460     return page->scrollingStateTreeAsText();
1461 }
1462
1463 void Internals::garbageCollectDocumentResources(Document* document, ExceptionCode& ec) const
1464 {
1465     if (!document) {
1466         ec = INVALID_ACCESS_ERR;
1467         return;
1468     }
1469
1470     CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader();
1471     if (!cachedResourceLoader)
1472         return;
1473     cachedResourceLoader->garbageCollectDocumentResources();
1474 }
1475
1476 void Internals::allowRoundingHacks() const
1477 {
1478     TextRun::setAllowsRoundingHacks(true);
1479 }
1480
1481 void Internals::insertAuthorCSS(Document* document, const String& css) const
1482 {
1483     RefPtr<StyleSheetContents> parsedSheet = StyleSheetContents::create(document);
1484     parsedSheet->setIsUserStyleSheet(false);
1485     parsedSheet->parseString(css);
1486     document->styleSheetCollection()->addAuthorSheet(parsedSheet);
1487 }
1488
1489 void Internals::insertUserCSS(Document* document, const String& css) const
1490 {
1491     RefPtr<StyleSheetContents> parsedSheet = StyleSheetContents::create(document);
1492     parsedSheet->setIsUserStyleSheet(true);
1493     parsedSheet->parseString(css);
1494     document->styleSheetCollection()->addUserSheet(parsedSheet);
1495 }
1496
1497 String Internals::counterValue(Element* element)
1498 {
1499     if (!element)
1500         return String();
1501
1502     return counterValueForElement(element);
1503 }
1504
1505 int Internals::pageNumber(Element* element, float pageWidth, float pageHeight)
1506 {
1507     if (!element)
1508         return 0;
1509
1510     return PrintContext::pageNumberForElement(element, FloatSize(pageWidth, pageHeight));
1511 }
1512
1513 PassRefPtr<DOMStringList> Internals::iconURLs(Document* document) const
1514 {
1515     Vector<IconURL> iconURLs = document->iconURLs();
1516     RefPtr<DOMStringList> stringList = DOMStringList::create();
1517
1518     Vector<IconURL>::const_iterator iter(iconURLs.begin());
1519     for (; iter != iconURLs.end(); ++iter)
1520         stringList->append(iter->m_iconURL.string());
1521
1522     return stringList.release();
1523 }
1524
1525 int Internals::numberOfPages(float pageWidth, float pageHeight)
1526 {
1527     if (!frame())
1528         return -1;
1529
1530     return PrintContext::numberOfPages(frame(), FloatSize(pageWidth, pageHeight));
1531 }
1532
1533 String Internals::pageProperty(String propertyName, int pageNumber, ExceptionCode& ec) const
1534 {
1535     if (!frame()) {
1536         ec = INVALID_ACCESS_ERR;
1537         return String();
1538     }
1539
1540     return PrintContext::pageProperty(frame(), propertyName.utf8().data(), pageNumber);
1541 }
1542
1543 String Internals::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft, ExceptionCode& ec) const
1544 {
1545     if (!frame()) {
1546         ec = INVALID_ACCESS_ERR;
1547         return String();
1548     }
1549
1550     return PrintContext::pageSizeAndMarginsInPixels(frame(), pageNumber, width, height, marginTop, marginRight, marginBottom, marginLeft);
1551 }
1552
1553 void Internals::setPageScaleFactor(float scaleFactor, int x, int y, ExceptionCode& ec)
1554 {
1555     Document* document = contextDocument();
1556     if (!document || !document->page()) {
1557         ec = INVALID_ACCESS_ERR;
1558         return;
1559     }
1560     Page* page = document->page();
1561     page->setPageScaleFactor(scaleFactor, IntPoint(x, y));
1562 }
1563
1564 #if ENABLE(FULLSCREEN_API)
1565 void Internals::webkitWillEnterFullScreenForElement(Document* document, Element* element)
1566 {
1567     if (!document)
1568         return;
1569     document->webkitWillEnterFullScreenForElement(element);
1570 }
1571
1572 void Internals::webkitDidEnterFullScreenForElement(Document* document, Element* element)
1573 {
1574     if (!document)
1575         return;
1576     document->webkitDidEnterFullScreenForElement(element);
1577 }
1578
1579 void Internals::webkitWillExitFullScreenForElement(Document* document, Element* element)
1580 {
1581     if (!document)
1582         return;
1583     document->webkitWillExitFullScreenForElement(element);
1584 }
1585
1586 void Internals::webkitDidExitFullScreenForElement(Document* document, Element* element)
1587 {
1588     if (!document)
1589         return;
1590     document->webkitDidExitFullScreenForElement(element);
1591 }
1592 #endif
1593
1594 void Internals::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme)
1595 {
1596     SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
1597 }
1598
1599 void Internals::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(const String& scheme)
1600 {
1601     SchemeRegistry::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(scheme);
1602 }
1603
1604 PassRefPtr<MallocStatistics> Internals::mallocStatistics() const
1605 {
1606     return MallocStatistics::create();
1607 }
1608
1609 PassRefPtr<DOMStringList> Internals::getReferencedFilePaths() const
1610 {
1611     RefPtr<DOMStringList> stringList = DOMStringList::create();
1612     frame()->loader()->history()->saveDocumentAndScrollState();
1613     const Vector<String>& filePaths = FormController::getReferencedFilePaths(frame()->loader()->history()->currentItem()->documentState());
1614     for (size_t i = 0; i < filePaths.size(); ++i)
1615         stringList->append(filePaths[i]);
1616     return stringList.release();
1617 }
1618
1619 void Internals::startTrackingRepaints(Document* document, ExceptionCode& ec)
1620 {
1621     if (!document || !document->view()) {
1622         ec = INVALID_ACCESS_ERR;
1623         return;
1624     }
1625
1626     FrameView* frameView = document->view();
1627     frameView->setTracksRepaints(true);
1628 }
1629
1630 void Internals::stopTrackingRepaints(Document* document, ExceptionCode& ec)
1631 {
1632     if (!document || !document->view()) {
1633         ec = INVALID_ACCESS_ERR;
1634         return;
1635     }
1636
1637     FrameView* frameView = document->view();
1638     frameView->setTracksRepaints(false);
1639 }
1640
1641 #if USE(LAZY_NATIVE_CURSOR)
1642 static const char* cursorTypeToString(Cursor::Type cursorType)
1643 {
1644     switch (cursorType) {
1645     case Cursor::Pointer: return "Pointer";
1646     case Cursor::Cross: return "Cross";
1647     case Cursor::Hand: return "Hand";
1648     case Cursor::IBeam: return "IBeam";
1649     case Cursor::Wait: return "Wait";
1650     case Cursor::Help: return "Help";
1651     case Cursor::EastResize: return "EastResize";
1652     case Cursor::NorthResize: return "NorthResize";
1653     case Cursor::NorthEastResize: return "NorthEastResize";
1654     case Cursor::NorthWestResize: return "NorthWestResize";
1655     case Cursor::SouthResize: return "SouthResize";
1656     case Cursor::SouthEastResize: return "SouthEastResize";
1657     case Cursor::SouthWestResize: return "SouthWestResize";
1658     case Cursor::WestResize: return "WestResize";
1659     case Cursor::NorthSouthResize: return "NorthSouthResize";
1660     case Cursor::EastWestResize: return "EastWestResize";
1661     case Cursor::NorthEastSouthWestResize: return "NorthEastSouthWestResize";
1662     case Cursor::NorthWestSouthEastResize: return "NorthWestSouthEastResize";
1663     case Cursor::ColumnResize: return "ColumnResize";
1664     case Cursor::RowResize: return "RowResize";
1665     case Cursor::MiddlePanning: return "MiddlePanning";
1666     case Cursor::EastPanning: return "EastPanning";
1667     case Cursor::NorthPanning: return "NorthPanning";
1668     case Cursor::NorthEastPanning: return "NorthEastPanning";
1669     case Cursor::NorthWestPanning: return "NorthWestPanning";
1670     case Cursor::SouthPanning: return "SouthPanning";
1671     case Cursor::SouthEastPanning: return "SouthEastPanning";
1672     case Cursor::SouthWestPanning: return "SouthWestPanning";
1673     case Cursor::WestPanning: return "WestPanning";
1674     case Cursor::Move: return "Move";
1675     case Cursor::VerticalText: return "VerticalText";
1676     case Cursor::Cell: return "Cell";
1677     case Cursor::ContextMenu: return "ContextMenu";
1678     case Cursor::Alias: return "Alias";
1679     case Cursor::Progress: return "Progress";
1680     case Cursor::NoDrop: return "NoDrop";
1681     case Cursor::Copy: return "Copy";
1682     case Cursor::None: return "None";
1683     case Cursor::NotAllowed: return "NotAllowed";
1684     case Cursor::ZoomIn: return "ZoomIn";
1685     case Cursor::ZoomOut: return "ZoomOut";
1686     case Cursor::Grab: return "Grab";
1687     case Cursor::Grabbing: return "Grabbing";
1688     case Cursor::Custom: return "Custom";
1689     }
1690
1691     ASSERT_NOT_REACHED();
1692     return "UNKNOWN";
1693 }
1694 #endif
1695
1696 String Internals::getCurrentCursorInfo(Document* document, ExceptionCode& ec)
1697 {
1698     if (!document || !document->frame()) {
1699         ec = INVALID_ACCESS_ERR;
1700         return String();
1701     }
1702
1703     Cursor cursor = document->frame()->eventHandler()->currentMouseCursor();
1704
1705 #if USE(LAZY_NATIVE_CURSOR)
1706     StringBuilder result;
1707     result.append("type=");
1708     result.append(cursorTypeToString(cursor.type()));
1709     result.append(" hotSpot=");
1710     result.appendNumber(cursor.hotSpot().x());
1711     result.append(",");
1712     result.appendNumber(cursor.hotSpot().y());
1713     if (cursor.image()) {
1714         IntSize size = cursor.image()->size();
1715         result.append(" image=");
1716         result.appendNumber(size.width());
1717         result.append("x");
1718         result.appendNumber(size.height());
1719     }
1720 #if ENABLE(MOUSE_CURSOR_SCALE)
1721     if (cursor.imageScaleFactor() != 1) {
1722         result.append(" scale=");
1723         NumberToStringBuffer buffer;
1724         result.append(numberToFixedPrecisionString(cursor.imageScaleFactor(), 8, buffer, true));
1725     }
1726 #endif
1727     return result.toString();
1728 #else
1729     return "FAIL: Cursor details not available on this platform.";
1730 #endif
1731 }
1732
1733 PassRefPtr<ArrayBuffer> Internals::serializeObject(PassRefPtr<SerializedScriptValue> value) const
1734 {
1735     String stringValue = value->toWireString();
1736     return ArrayBuffer::create(static_cast<const void*>(stringValue.impl()->characters()), stringValue.sizeInBytes());
1737 }
1738
1739 PassRefPtr<SerializedScriptValue> Internals::deserializeBuffer(PassRefPtr<ArrayBuffer> buffer) const
1740 {
1741     String value(static_cast<const UChar*>(buffer->data()), buffer->byteLength() / sizeof(UChar));
1742     return SerializedScriptValue::createFromWire(value);
1743 }
1744
1745 void Internals::setUsesOverlayScrollbars(bool enabled)
1746 {
1747     WebCore::Settings::setUsesOverlayScrollbars(enabled);
1748 }
1749
1750 }