1/*
2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 * Copyright (C) 2013 Apple Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1.  Redistributions of source code must retain the above copyright
10 *     notice, this list of conditions and the following disclaimer.
11 * 2.  Redistributions in binary form must reproduce the above copyright
12 *     notice, this list of conditions and the following disclaimer in the
13 *     documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "config.h"
28#include "Internals.h"
29
30#include <v8.h>
31#include "HTMLNames.h"
32#include "InspectorFrontendClientLocal.h"
33#include "InternalProfilers.h"
34#include "InternalRuntimeFlags.h"
35#include "InternalSettings.h"
36#include "LayerRect.h"
37#include "LayerRectList.h"
38#include "MallocStatistics.h"
39#include "MockPagePopupDriver.h"
40#include "RuntimeEnabledFeatures.h"
41#include "TypeConversions.h"
42#include "bindings/v8/ExceptionState.h"
43#include "bindings/v8/SerializedScriptValue.h"
44#include "bindings/v8/V8ThrowException.h"
45#include "core/animation/DocumentTimeline.h"
46#include "core/css/StyleSheetContents.h"
47#include "core/css/resolver/StyleResolver.h"
48#include "core/css/resolver/StyleResolverStats.h"
49#include "core/css/resolver/ViewportStyleResolver.h"
50#include "core/dom/ClientRect.h"
51#include "core/dom/ClientRectList.h"
52#include "core/dom/DOMStringList.h"
53#include "core/dom/Document.h"
54#include "core/dom/DocumentMarker.h"
55#include "core/dom/DocumentMarkerController.h"
56#include "core/dom/Element.h"
57#include "core/dom/ExceptionCode.h"
58#include "core/dom/FullscreenElementStack.h"
59#include "core/dom/PseudoElement.h"
60#include "core/dom/Range.h"
61#include "core/dom/StaticNodeList.h"
62#include "core/dom/TreeScope.h"
63#include "core/dom/ViewportDescription.h"
64#include "core/dom/WheelController.h"
65#include "core/dom/shadow/ComposedTreeWalker.h"
66#include "core/dom/shadow/ElementShadow.h"
67#include "core/dom/shadow/SelectRuleFeatureSet.h"
68#include "core/dom/shadow/ShadowRoot.h"
69#include "core/editing/Editor.h"
70#include "core/editing/PlainTextRange.h"
71#include "core/editing/SpellCheckRequester.h"
72#include "core/editing/SpellChecker.h"
73#include "core/editing/TextIterator.h"
74#include "core/fetch/MemoryCache.h"
75#include "core/fetch/ResourceFetcher.h"
76#include "core/frame/DOMPoint.h"
77#include "core/frame/Frame.h"
78#include "core/history/HistoryItem.h"
79#include "core/html/HTMLIFrameElement.h"
80#include "core/html/HTMLInputElement.h"
81#include "core/html/HTMLMediaElement.h"
82#include "core/html/HTMLSelectElement.h"
83#include "core/html/HTMLTextAreaElement.h"
84#include "core/html/forms/FormController.h"
85#include "core/html/shadow/HTMLContentElement.h"
86#include "core/inspector/InspectorClient.h"
87#include "core/inspector/InspectorConsoleAgent.h"
88#include "core/inspector/InspectorController.h"
89#include "core/inspector/InspectorCounters.h"
90#include "core/inspector/InspectorFrontendChannel.h"
91#include "core/inspector/InspectorInstrumentation.h"
92#include "core/inspector/InspectorOverlay.h"
93#include "core/inspector/InstrumentingAgents.h"
94#include "core/loader/FrameLoader.h"
95#include "core/page/Chrome.h"
96#include "core/page/ChromeClient.h"
97#include "core/frame/DOMWindow.h"
98#include "core/page/EventHandler.h"
99#include "core/frame/FrameView.h"
100#include "core/page/Page.h"
101#include "core/page/PagePopupController.h"
102#include "core/page/PrintContext.h"
103#include "core/frame/Settings.h"
104#include "core/frame/animation/AnimationController.h"
105#include "core/rendering/CompositedLayerMapping.h"
106#include "core/rendering/RenderLayer.h"
107#include "core/rendering/RenderLayerCompositor.h"
108#include "core/rendering/RenderMenuList.h"
109#include "core/rendering/RenderObject.h"
110#include "core/rendering/RenderTreeAsText.h"
111#include "core/rendering/RenderView.h"
112#include "core/testing/GCObservation.h"
113#include "core/workers/WorkerThread.h"
114#include "platform/ColorChooser.h"
115#include "platform/Cursor.h"
116#include "platform/Language.h"
117#include "platform/TraceEvent.h"
118#include "platform/geometry/IntRect.h"
119#include "platform/geometry/LayoutRect.h"
120#include "platform/graphics/GraphicsLayer.h"
121#include "platform/graphics/filters/FilterOperation.h"
122#include "platform/graphics/filters/FilterOperations.h"
123#include "platform/graphics/gpu/SharedGraphicsContext3D.h"
124#include "platform/weborigin/SchemeRegistry.h"
125#include "public/platform/WebLayer.h"
126#include "wtf/InstanceCounter.h"
127#include "wtf/dtoa.h"
128#include "wtf/text/StringBuffer.h"
129
130namespace WebCore {
131
132static MockPagePopupDriver* s_pagePopupDriver = 0;
133
134using namespace HTMLNames;
135
136class InspectorFrontendChannelDummy : public InspectorFrontendChannel {
137public:
138    explicit InspectorFrontendChannelDummy(Page*);
139    virtual ~InspectorFrontendChannelDummy() { }
140    virtual bool sendMessageToFrontend(const String& message) OVERRIDE;
141
142private:
143    Page* m_frontendPage;
144};
145
146InspectorFrontendChannelDummy::InspectorFrontendChannelDummy(Page* page)
147    : m_frontendPage(page)
148{
149}
150
151bool InspectorFrontendChannelDummy::sendMessageToFrontend(const String& message)
152{
153    return InspectorClient::doDispatchMessageOnFrontendPage(m_frontendPage, message);
154}
155
156static bool markerTypesFrom(const String& markerType, DocumentMarker::MarkerTypes& result)
157{
158    if (markerType.isEmpty() || equalIgnoringCase(markerType, "all"))
159        result = DocumentMarker::AllMarkers();
160    else if (equalIgnoringCase(markerType, "Spelling"))
161        result =  DocumentMarker::Spelling;
162    else if (equalIgnoringCase(markerType, "Grammar"))
163        result =  DocumentMarker::Grammar;
164    else if (equalIgnoringCase(markerType, "TextMatch"))
165        result =  DocumentMarker::TextMatch;
166    else
167        return false;
168
169    return true;
170}
171
172static SpellCheckRequester* spellCheckRequester(Document* document)
173{
174    if (!document || !document->frame())
175        return 0;
176    return &document->frame()->spellChecker().spellCheckRequester();
177}
178
179const char* Internals::internalsId = "internals";
180
181PassRefPtr<Internals> Internals::create(Document* document)
182{
183    return adoptRef(new Internals(document));
184}
185
186Internals::~Internals()
187{
188}
189
190void Internals::resetToConsistentState(Page* page)
191{
192    ASSERT(page);
193
194    page->setDeviceScaleFactor(1);
195    page->setIsCursorVisible(true);
196    page->setPageScaleFactor(1, IntPoint(0, 0));
197    page->setPagination(Pagination());
198    TextRun::setAllowsRoundingHacks(false);
199    WebCore::overrideUserPreferredLanguages(Vector<String>());
200    delete s_pagePopupDriver;
201    s_pagePopupDriver = 0;
202    page->chrome().client().resetPagePopupDriver();
203    if (!page->mainFrame()->spellChecker().isContinuousSpellCheckingEnabled())
204        page->mainFrame()->spellChecker().toggleContinuousSpellChecking();
205    if (page->mainFrame()->editor().isOverwriteModeEnabled())
206        page->mainFrame()->editor().toggleOverwriteModeEnabled();
207
208    if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
209        scrollingCoordinator->reset();
210
211    page->mainFrame()->view()->clear();
212}
213
214Internals::Internals(Document* document)
215    : ContextLifecycleObserver(document)
216    , m_runtimeFlags(InternalRuntimeFlags::create())
217    , m_scrollingCoordinator(document->page() ? document->page()->scrollingCoordinator() : 0)
218{
219}
220
221Document* Internals::contextDocument() const
222{
223    return toDocument(executionContext());
224}
225
226Frame* Internals::frame() const
227{
228    if (!contextDocument())
229        return 0;
230    return contextDocument()->frame();
231}
232
233InternalSettings* Internals::settings() const
234{
235    Document* document = contextDocument();
236    if (!document)
237        return 0;
238    Page* page = document->page();
239    if (!page)
240        return 0;
241    return InternalSettings::from(page);
242}
243
244InternalRuntimeFlags* Internals::runtimeFlags() const
245{
246    return m_runtimeFlags.get();
247}
248
249InternalProfilers* Internals::profilers()
250{
251    if (!m_profilers)
252        m_profilers = InternalProfilers::create();
253    return m_profilers.get();
254}
255
256unsigned Internals::workerThreadCount() const
257{
258    return WorkerThread::workerThreadCount();
259}
260
261String Internals::address(Node* node)
262{
263    char buf[32];
264    sprintf(buf, "%p", node);
265
266    return String(buf);
267}
268
269PassRefPtr<GCObservation> Internals::observeGC(ScriptValue scriptValue)
270{
271    v8::Handle<v8::Value> observedValue = scriptValue.v8Value();
272    ASSERT(!observedValue.IsEmpty());
273    if (observedValue->IsNull() || observedValue->IsUndefined()) {
274        V8ThrowException::throwTypeError("value to observe is null or undefined", v8::Isolate::GetCurrent());
275        return 0;
276    }
277
278    return GCObservation::create(observedValue);
279}
280
281unsigned Internals::updateStyleAndReturnAffectedElementCount(ExceptionState& exceptionState) const
282{
283    Document* document = contextDocument();
284    if (!document) {
285        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
286        return 0;
287    }
288
289    unsigned beforeCount = document->styleEngine()->resolverAccessCount();
290    document->updateStyleIfNeeded();
291    return document->styleEngine()->resolverAccessCount() - beforeCount;
292}
293
294bool Internals::isPreloaded(const String& url)
295{
296    Document* document = contextDocument();
297    return document->fetcher()->isPreloaded(url);
298}
299
300bool Internals::isLoadingFromMemoryCache(const String& url)
301{
302    if (!contextDocument())
303        return false;
304    Resource* resource = memoryCache()->resourceForURL(contextDocument()->completeURL(url));
305    return resource && resource->status() == Resource::Cached;
306}
307
308void Internals::crash()
309{
310    CRASH();
311}
312
313void Internals::setStyleResolverStatsEnabled(bool enabled)
314{
315    Document* document = contextDocument();
316    if (enabled)
317        document->ensureStyleResolver().enableStats(StyleResolver::ReportSlowStats);
318    else
319        document->ensureStyleResolver().disableStats();
320}
321
322String Internals::styleResolverStatsReport(ExceptionState& exceptionState) const
323{
324    Document* document = contextDocument();
325    if (!document->ensureStyleResolver().stats()) {
326        exceptionState.throwDOMException(InvalidStateError, "Style resolver stats not enabled");
327        return String();
328    }
329    return document->ensureStyleResolver().stats()->report();
330}
331
332String Internals::styleResolverStatsTotalsReport(ExceptionState& exceptionState) const
333{
334    Document* document = contextDocument();
335    if (!document->ensureStyleResolver().statsTotals()) {
336        exceptionState.throwDOMException(InvalidStateError, "Style resolver stats not enabled");
337        return String();
338    }
339    return document->ensureStyleResolver().statsTotals()->report();
340}
341
342PassRefPtr<Element> Internals::createContentElement(ExceptionState& exceptionState)
343{
344    Document* document = contextDocument();
345    if (!document) {
346        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
347        return 0;
348    }
349
350    return HTMLContentElement::create(*document);
351}
352
353bool Internals::isValidContentSelect(Element* insertionPoint, ExceptionState& exceptionState)
354{
355    if (!insertionPoint || !insertionPoint->isInsertionPoint()) {
356        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
357        return false;
358    }
359
360    return isHTMLContentElement(insertionPoint) && toHTMLContentElement(insertionPoint)->isSelectValid();
361}
362
363Node* Internals::treeScopeRootNode(Node* node, ExceptionState& exceptionState)
364{
365    if (!node) {
366        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
367        return 0;
368    }
369
370    return node->treeScope().rootNode();
371}
372
373Node* Internals::parentTreeScope(Node* node, ExceptionState& exceptionState)
374{
375    if (!node) {
376        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
377        return 0;
378    }
379    const TreeScope* parentTreeScope = node->treeScope().parentTreeScope();
380    return parentTreeScope ? parentTreeScope->rootNode() : 0;
381}
382
383bool Internals::hasSelectorForIdInShadow(Element* host, const String& idValue, ExceptionState& exceptionState)
384{
385    if (!host || !host->shadow()) {
386        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
387        return 0;
388    }
389
390    return host->shadow()->ensureSelectFeatureSet().hasSelectorForId(idValue);
391}
392
393bool Internals::hasSelectorForClassInShadow(Element* host, const String& className, ExceptionState& exceptionState)
394{
395    if (!host || !host->shadow()) {
396        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
397        return 0;
398    }
399
400    return host->shadow()->ensureSelectFeatureSet().hasSelectorForClass(className);
401}
402
403bool Internals::hasSelectorForAttributeInShadow(Element* host, const String& attributeName, ExceptionState& exceptionState)
404{
405    if (!host || !host->shadow()) {
406        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
407        return 0;
408    }
409
410    return host->shadow()->ensureSelectFeatureSet().hasSelectorForAttribute(attributeName);
411}
412
413bool Internals::hasSelectorForPseudoClassInShadow(Element* host, const String& pseudoClass, ExceptionState& exceptionState)
414{
415    if (!host || !host->shadow()) {
416        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
417        return 0;
418    }
419
420    const SelectRuleFeatureSet& featureSet = host->shadow()->ensureSelectFeatureSet();
421    if (pseudoClass == "checked")
422        return featureSet.hasSelectorForChecked();
423    if (pseudoClass == "enabled")
424        return featureSet.hasSelectorForEnabled();
425    if (pseudoClass == "disabled")
426        return featureSet.hasSelectorForDisabled();
427    if (pseudoClass == "indeterminate")
428        return featureSet.hasSelectorForIndeterminate();
429    if (pseudoClass == "link")
430        return featureSet.hasSelectorForLink();
431    if (pseudoClass == "target")
432        return featureSet.hasSelectorForTarget();
433    if (pseudoClass == "visited")
434        return featureSet.hasSelectorForVisited();
435
436    ASSERT_NOT_REACHED();
437    return false;
438}
439
440unsigned short Internals::compareTreeScopePosition(const Node* node1, const Node* node2, ExceptionState& exceptionState) const
441{
442    if (!node1 || !node2) {
443        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
444        return 0;
445    }
446    const TreeScope* treeScope1 = node1->isDocumentNode() ? static_cast<const TreeScope*>(toDocument(node1)) :
447        node1->isShadowRoot() ? static_cast<const TreeScope*>(toShadowRoot(node1)) : 0;
448    const TreeScope* treeScope2 = node2->isDocumentNode() ? static_cast<const TreeScope*>(toDocument(node2)) :
449        node2->isShadowRoot() ? static_cast<const TreeScope*>(toShadowRoot(node2)) : 0;
450    if (!treeScope1 || !treeScope2) {
451        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
452        return 0;
453    }
454    return treeScope1->comparePosition(*treeScope2);
455}
456
457unsigned Internals::numberOfActiveAnimations() const
458{
459    Frame* contextFrame = frame();
460    Document* document = contextFrame->document();
461    if (RuntimeEnabledFeatures::webAnimationsCSSEnabled())
462        return document->timeline()->numberOfActiveAnimationsForTesting() + document->transitionTimeline()->numberOfActiveAnimationsForTesting();
463    return contextFrame->animation().numberOfActiveAnimations(document);
464}
465
466void Internals::pauseAnimations(double pauseTime, ExceptionState& exceptionState)
467{
468    if (pauseTime < 0) {
469        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
470        return;
471    }
472
473    if (RuntimeEnabledFeatures::webAnimationsCSSEnabled()) {
474        frame()->document()->timeline()->pauseAnimationsForTesting(pauseTime);
475        frame()->document()->transitionTimeline()->pauseAnimationsForTesting(pauseTime);
476    } else {
477        frame()->animation().pauseAnimationsForTesting(pauseTime);
478    }
479}
480
481bool Internals::hasShadowInsertionPoint(const Node* root, ExceptionState& exceptionState) const
482{
483    if (root && root->isShadowRoot())
484        return toShadowRoot(root)->containsShadowElements();
485
486    exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
487    return 0;
488}
489
490bool Internals::hasContentElement(const Node* root, ExceptionState& exceptionState) const
491{
492    if (root && root->isShadowRoot())
493        return toShadowRoot(root)->containsContentElements();
494
495    exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
496    return 0;
497}
498
499size_t Internals::countElementShadow(const Node* root, ExceptionState& exceptionState) const
500{
501    if (!root || !root->isShadowRoot()) {
502        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
503        return 0;
504    }
505    return toShadowRoot(root)->childShadowRootCount();
506}
507
508Node* Internals::nextSiblingByWalker(Node* node, ExceptionState& exceptionState)
509{
510    if (!node) {
511        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
512        return 0;
513    }
514    ComposedTreeWalker walker(node);
515    walker.nextSibling();
516    return walker.get();
517}
518
519Node* Internals::firstChildByWalker(Node* node, ExceptionState& exceptionState)
520{
521    if (!node) {
522        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
523        return 0;
524    }
525    ComposedTreeWalker walker(node);
526    walker.firstChild();
527    return walker.get();
528}
529
530Node* Internals::lastChildByWalker(Node* node, ExceptionState& exceptionState)
531{
532    if (!node) {
533        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
534        return 0;
535    }
536    ComposedTreeWalker walker(node);
537    walker.lastChild();
538    return walker.get();
539}
540
541Node* Internals::nextNodeByWalker(Node* node, ExceptionState& exceptionState)
542{
543    if (!node) {
544        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
545        return 0;
546    }
547    ComposedTreeWalker walker(node);
548    walker.next();
549    return walker.get();
550}
551
552Node* Internals::previousNodeByWalker(Node* node, ExceptionState& exceptionState)
553{
554    if (!node) {
555        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
556        return 0;
557    }
558    ComposedTreeWalker walker(node);
559    walker.previous();
560    return walker.get();
561}
562
563String Internals::elementRenderTreeAsText(Element* element, ExceptionState& exceptionState)
564{
565    if (!element) {
566        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
567        return String();
568    }
569
570    String representation = externalRepresentation(element);
571    if (representation.isEmpty()) {
572        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
573        return String();
574    }
575
576    return representation;
577}
578
579size_t Internals::numberOfScopedHTMLStyleChildren(const Node* scope, ExceptionState& exceptionState) const
580{
581    if (scope && (scope->isElementNode() || scope->isShadowRoot()))
582        return scope->numberOfScopedHTMLStyleChildren();
583
584    exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
585    return 0;
586}
587
588PassRefPtr<CSSComputedStyleDeclaration> Internals::computedStyleIncludingVisitedInfo(Node* node, ExceptionState& exceptionState) const
589{
590    if (!node) {
591        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
592        return 0;
593    }
594
595    bool allowVisitedStyle = true;
596    return CSSComputedStyleDeclaration::create(node, allowVisitedStyle);
597}
598
599ShadowRoot* Internals::ensureShadowRoot(Element* host, ExceptionState& exceptionState)
600{
601    if (!host) {
602        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
603        return 0;
604    }
605
606    if (ElementShadow* shadow = host->shadow())
607        return shadow->youngestShadowRoot();
608
609    return host->createShadowRoot(exceptionState).get();
610}
611
612ShadowRoot* Internals::shadowRoot(Element* host, ExceptionState& exceptionState)
613{
614    // FIXME: Internals::shadowRoot() in tests should be converted to youngestShadowRoot() or oldestShadowRoot().
615    // https://bugs.webkit.org/show_bug.cgi?id=78465
616    return youngestShadowRoot(host, exceptionState);
617}
618
619ShadowRoot* Internals::youngestShadowRoot(Element* host, ExceptionState& exceptionState)
620{
621    if (!host) {
622        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
623        return 0;
624    }
625
626    if (ElementShadow* shadow = host->shadow())
627        return shadow->youngestShadowRoot();
628    return 0;
629}
630
631ShadowRoot* Internals::oldestShadowRoot(Element* host, ExceptionState& exceptionState)
632{
633    if (!host) {
634        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
635        return 0;
636    }
637
638    if (ElementShadow* shadow = host->shadow())
639        return shadow->oldestShadowRoot();
640    return 0;
641}
642
643ShadowRoot* Internals::youngerShadowRoot(Node* shadow, ExceptionState& exceptionState)
644{
645    if (!shadow || !shadow->isShadowRoot()) {
646        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
647        return 0;
648    }
649
650    return toShadowRoot(shadow)->youngerShadowRoot();
651}
652
653ShadowRoot* Internals::olderShadowRoot(Node* shadow, ExceptionState& exceptionState)
654{
655    if (!shadow || !shadow->isShadowRoot()) {
656        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
657        return 0;
658    }
659
660    return toShadowRoot(shadow)->olderShadowRoot();
661}
662
663String Internals::shadowRootType(const Node* root, ExceptionState& exceptionState) const
664{
665    if (!root || !root->isShadowRoot()) {
666        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
667        return String();
668    }
669
670    switch (toShadowRoot(root)->type()) {
671    case ShadowRoot::UserAgentShadowRoot:
672        return String("UserAgentShadowRoot");
673    case ShadowRoot::AuthorShadowRoot:
674        return String("AuthorShadowRoot");
675    default:
676        ASSERT_NOT_REACHED();
677        return String("Unknown");
678    }
679}
680
681String Internals::shadowPseudoId(Element* element, ExceptionState& exceptionState)
682{
683    if (!element) {
684        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
685        return String();
686    }
687
688    return element->shadowPseudoId().string();
689}
690
691void Internals::setShadowPseudoId(Element* element, const String& id, ExceptionState& exceptionState)
692{
693    if (!element) {
694        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
695        return;
696    }
697
698    return element->setPseudo(id);
699}
700
701String Internals::visiblePlaceholder(Element* element)
702{
703    if (element && isHTMLTextFormControlElement(element)) {
704        if (toHTMLTextFormControlElement(element)->placeholderShouldBeVisible())
705            return toHTMLTextFormControlElement(element)->placeholderElement()->textContent();
706    }
707
708    return String();
709}
710
711void Internals::selectColorInColorChooser(Element* element, const String& colorValue)
712{
713    if (!element->hasTagName(inputTag))
714        return;
715    toHTMLInputElement(element)->selectColorInColorChooser(Color(colorValue));
716}
717
718Vector<String> Internals::formControlStateOfHistoryItem(ExceptionState& exceptionState)
719{
720    HistoryItem* mainItem = frame()->loader().currentItem();
721    if (!mainItem) {
722        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
723        return Vector<String>();
724    }
725    return mainItem->documentState();
726}
727
728void Internals::setFormControlStateOfHistoryItem(const Vector<String>& state, ExceptionState& exceptionState)
729{
730    HistoryItem* mainItem = frame()->loader().currentItem();
731    if (!mainItem) {
732        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
733        return;
734    }
735    mainItem->setDocumentState(state);
736}
737
738void Internals::setEnableMockPagePopup(bool enabled, ExceptionState& exceptionState)
739{
740    Document* document = contextDocument();
741    if (!document || !document->page())
742        return;
743    Page* page = document->page();
744    if (!enabled) {
745        page->chrome().client().resetPagePopupDriver();
746        return;
747    }
748    if (!s_pagePopupDriver)
749        s_pagePopupDriver = MockPagePopupDriver::create(page->mainFrame()).leakPtr();
750    page->chrome().client().setPagePopupDriver(s_pagePopupDriver);
751}
752
753PassRefPtr<PagePopupController> Internals::pagePopupController()
754{
755    return s_pagePopupDriver ? s_pagePopupDriver->pagePopupController() : 0;
756}
757
758PassRefPtr<ClientRect> Internals::unscaledViewportRect(ExceptionState& exceptionState)
759{
760    Document* document = contextDocument();
761    if (!document || !document->view()) {
762        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
763        return ClientRect::create();
764    }
765
766    return ClientRect::create(document->view()->visibleContentRect());
767}
768
769PassRefPtr<ClientRect> Internals::absoluteCaretBounds(ExceptionState& exceptionState)
770{
771    Document* document = contextDocument();
772    if (!document || !document->frame()) {
773        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
774        return ClientRect::create();
775    }
776
777    return ClientRect::create(document->frame()->selection().absoluteCaretBounds());
778}
779
780PassRefPtr<ClientRect> Internals::boundingBox(Element* element, ExceptionState& exceptionState)
781{
782    if (!element) {
783        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
784        return ClientRect::create();
785    }
786
787    element->document().updateLayoutIgnorePendingStylesheets();
788    RenderObject* renderer = element->renderer();
789    if (!renderer)
790        return ClientRect::create();
791    return ClientRect::create(renderer->absoluteBoundingBoxRectIgnoringTransforms());
792}
793
794PassRefPtr<ClientRectList> Internals::inspectorHighlightRects(Document* document, ExceptionState& exceptionState)
795{
796    if (!document || !document->page()) {
797        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
798        return ClientRectList::create();
799    }
800
801    Highlight highlight;
802    document->page()->inspectorController().getHighlight(&highlight);
803    return ClientRectList::create(highlight.quads);
804}
805
806unsigned Internals::markerCountForNode(Node* node, const String& markerType, ExceptionState& exceptionState)
807{
808    if (!node) {
809        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
810        return 0;
811    }
812
813    DocumentMarker::MarkerTypes markerTypes = 0;
814    if (!markerTypesFrom(markerType, markerTypes)) {
815        exceptionState.throwUninformativeAndGenericDOMException(SyntaxError);
816        return 0;
817    }
818
819    return node->document().markers()->markersFor(node, markerTypes).size();
820}
821
822unsigned Internals::activeMarkerCountForNode(Node* node, ExceptionState& exceptionState)
823{
824    if (!node) {
825        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
826        return 0;
827    }
828
829    // Only TextMatch markers can be active.
830    DocumentMarker::MarkerType markerType = DocumentMarker::TextMatch;
831    Vector<DocumentMarker*> markers = node->document().markers()->markersFor(node, markerType);
832
833    unsigned activeMarkerCount = 0;
834    for (Vector<DocumentMarker*>::iterator iter = markers.begin(); iter != markers.end(); ++iter) {
835        if ((*iter)->activeMatch())
836            activeMarkerCount++;
837    }
838
839    return activeMarkerCount;
840}
841
842DocumentMarker* Internals::markerAt(Node* node, const String& markerType, unsigned index, ExceptionState& exceptionState)
843{
844    if (!node) {
845        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
846        return 0;
847    }
848
849    DocumentMarker::MarkerTypes markerTypes = 0;
850    if (!markerTypesFrom(markerType, markerTypes)) {
851        exceptionState.throwUninformativeAndGenericDOMException(SyntaxError);
852        return 0;
853    }
854
855    Vector<DocumentMarker*> markers = node->document().markers()->markersFor(node, markerTypes);
856    if (markers.size() <= index)
857        return 0;
858    return markers[index];
859}
860
861PassRefPtr<Range> Internals::markerRangeForNode(Node* node, const String& markerType, unsigned index, ExceptionState& exceptionState)
862{
863    DocumentMarker* marker = markerAt(node, markerType, index, exceptionState);
864    if (!marker)
865        return 0;
866    return Range::create(node->document(), node, marker->startOffset(), node, marker->endOffset());
867}
868
869String Internals::markerDescriptionForNode(Node* node, const String& markerType, unsigned index, ExceptionState& exceptionState)
870{
871    DocumentMarker* marker = markerAt(node, markerType, index, exceptionState);
872    if (!marker)
873        return String();
874    return marker->description();
875}
876
877void Internals::addTextMatchMarker(const Range* range, bool isActive)
878{
879    range->ownerDocument().updateLayoutIgnorePendingStylesheets();
880    range->ownerDocument().markers()->addTextMatchMarker(range, isActive);
881}
882
883void Internals::setMarkersActive(Node* node, unsigned startOffset, unsigned endOffset, bool active, ExceptionState& exceptionState)
884{
885    if (!node) {
886        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
887        return;
888    }
889
890    node->document().markers()->setMarkersActive(node, startOffset, endOffset, active);
891}
892
893void Internals::setScrollViewPosition(Document* document, long x, long y, ExceptionState& exceptionState)
894{
895    if (!document || !document->view()) {
896        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
897        return;
898    }
899
900    FrameView* frameView = document->view();
901    bool constrainsScrollingToContentEdgeOldValue = frameView->constrainsScrollingToContentEdge();
902    bool scrollbarsSuppressedOldValue = frameView->scrollbarsSuppressed();
903
904    frameView->setConstrainsScrollingToContentEdge(false);
905    frameView->setScrollbarsSuppressed(false);
906    frameView->setScrollOffsetFromInternals(IntPoint(x, y));
907    frameView->setScrollbarsSuppressed(scrollbarsSuppressedOldValue);
908    frameView->setConstrainsScrollingToContentEdge(constrainsScrollingToContentEdgeOldValue);
909}
910
911void Internals::setPagination(Document* document, const String& mode, int gap, int pageLength, ExceptionState& exceptionState)
912{
913    if (!document || !document->page()) {
914        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
915        return;
916    }
917    Page* page = document->page();
918
919    Pagination pagination;
920    if (mode == "Unpaginated")
921        pagination.mode = Pagination::Unpaginated;
922    else if (mode == "LeftToRightPaginated")
923        pagination.mode = Pagination::LeftToRightPaginated;
924    else if (mode == "RightToLeftPaginated")
925        pagination.mode = Pagination::RightToLeftPaginated;
926    else if (mode == "TopToBottomPaginated")
927        pagination.mode = Pagination::TopToBottomPaginated;
928    else if (mode == "BottomToTopPaginated")
929        pagination.mode = Pagination::BottomToTopPaginated;
930    else {
931        exceptionState.throwUninformativeAndGenericDOMException(SyntaxError);
932        return;
933    }
934
935    pagination.gap = gap;
936    pagination.pageLength = pageLength;
937    page->setPagination(pagination);
938}
939
940String Internals::viewportAsText(Document* document, float, int availableWidth, int availableHeight, ExceptionState& exceptionState)
941{
942    if (!document || !document->page()) {
943        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
944        return String();
945    }
946
947    document->updateLayoutIgnorePendingStylesheets();
948
949    Page* page = document->page();
950
951    // Update initial viewport size.
952    IntSize initialViewportSize(availableWidth, availableHeight);
953    document->page()->mainFrame()->view()->setFrameRect(IntRect(IntPoint::zero(), initialViewportSize));
954
955    ViewportDescription description = page->viewportDescription();
956    PageScaleConstraints constraints = description.resolve(initialViewportSize);
957
958    constraints.fitToContentsWidth(constraints.layoutSize.width(), availableWidth);
959
960    StringBuilder builder;
961
962    builder.appendLiteral("viewport size ");
963    builder.append(String::number(constraints.layoutSize.width()));
964    builder.append('x');
965    builder.append(String::number(constraints.layoutSize.height()));
966
967    builder.appendLiteral(" scale ");
968    builder.append(String::number(constraints.initialScale));
969    builder.appendLiteral(" with limits [");
970    builder.append(String::number(constraints.minimumScale));
971    builder.appendLiteral(", ");
972    builder.append(String::number(constraints.maximumScale));
973
974    builder.appendLiteral("] and userScalable ");
975    builder.append(description.userZoom ? "true" : "false");
976
977    return builder.toString();
978}
979
980bool Internals::wasLastChangeUserEdit(Element* textField, ExceptionState& exceptionState)
981{
982    if (!textField) {
983        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
984        return false;
985    }
986
987    if (textField->hasTagName(inputTag))
988        return toHTMLInputElement(textField)->lastChangeWasUserEdit();
989
990    // FIXME: We should be using hasTagName instead but Windows port doesn't link QualifiedNames properly.
991    if (textField->tagName() == "TEXTAREA")
992        return toHTMLTextAreaElement(textField)->lastChangeWasUserEdit();
993
994    exceptionState.throwUninformativeAndGenericDOMException(InvalidNodeTypeError);
995    return false;
996}
997
998bool Internals::elementShouldAutoComplete(Element* element, ExceptionState& exceptionState)
999{
1000    if (!element) {
1001        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1002        return false;
1003    }
1004
1005    if (element->hasTagName(inputTag))
1006        return toHTMLInputElement(element)->shouldAutocomplete();
1007
1008    exceptionState.throwUninformativeAndGenericDOMException(InvalidNodeTypeError);
1009    return false;
1010}
1011
1012String Internals::suggestedValue(Element* element, ExceptionState& exceptionState)
1013{
1014    if (!element) {
1015        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1016        return String();
1017    }
1018
1019    if (!element->hasTagName(inputTag)) {
1020        exceptionState.throwUninformativeAndGenericDOMException(InvalidNodeTypeError);
1021        return String();
1022    }
1023
1024    return toHTMLInputElement(element)->suggestedValue();
1025}
1026
1027void Internals::setSuggestedValue(Element* element, const String& value, ExceptionState& exceptionState)
1028{
1029    if (!element) {
1030        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1031        return;
1032    }
1033
1034    if (!element->hasTagName(inputTag)) {
1035        exceptionState.throwUninformativeAndGenericDOMException(InvalidNodeTypeError);
1036        return;
1037    }
1038
1039    toHTMLInputElement(element)->setSuggestedValue(value);
1040}
1041
1042void Internals::setEditingValue(Element* element, const String& value, ExceptionState& exceptionState)
1043{
1044    if (!element) {
1045        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1046        return;
1047    }
1048
1049    if (!element->hasTagName(inputTag)) {
1050        exceptionState.throwUninformativeAndGenericDOMException(InvalidNodeTypeError);
1051        return;
1052    }
1053
1054    toHTMLInputElement(element)->setEditingValue(value);
1055}
1056
1057void Internals::setAutofilled(Element* element, bool enabled, ExceptionState& exceptionState)
1058{
1059    if (!element->isFormControlElement()) {
1060        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1061        return;
1062    }
1063    toHTMLFormControlElement(element)->setAutofilled(enabled);
1064}
1065
1066void Internals::scrollElementToRect(Element* element, long x, long y, long w, long h, ExceptionState& exceptionState)
1067{
1068    if (!element || !element->document().view()) {
1069        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1070        return;
1071    }
1072    FrameView* frameView = element->document().view();
1073    frameView->scrollElementToRect(element, IntRect(x, y, w, h));
1074}
1075
1076void Internals::paintControlTints(Document* document, ExceptionState& exceptionState)
1077{
1078    if (!document || !document->view()) {
1079        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1080        return;
1081    }
1082
1083    FrameView* frameView = document->view();
1084    frameView->paintControlTints();
1085}
1086
1087PassRefPtr<Range> Internals::rangeFromLocationAndLength(Element* scope, int rangeLocation, int rangeLength, ExceptionState& exceptionState)
1088{
1089    if (!scope) {
1090        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1091        return 0;
1092    }
1093
1094    // TextIterator depends on Layout information, make sure layout it up to date.
1095    scope->document().updateLayoutIgnorePendingStylesheets();
1096
1097    return PlainTextRange(rangeLocation, rangeLocation + rangeLength).createRange(*scope);
1098}
1099
1100unsigned Internals::locationFromRange(Element* scope, const Range* range, ExceptionState& exceptionState)
1101{
1102    if (!scope || !range) {
1103        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1104        return 0;
1105    }
1106
1107    // PlainTextRange depends on Layout information, make sure layout it up to date.
1108    scope->document().updateLayoutIgnorePendingStylesheets();
1109
1110    return PlainTextRange::create(*scope, *range).start();
1111}
1112
1113unsigned Internals::lengthFromRange(Element* scope, const Range* range, ExceptionState& exceptionState)
1114{
1115    if (!scope || !range) {
1116        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1117        return 0;
1118    }
1119
1120    // PlainTextRange depends on Layout information, make sure layout it up to date.
1121    scope->document().updateLayoutIgnorePendingStylesheets();
1122
1123    return PlainTextRange::create(*scope, *range).length();
1124}
1125
1126String Internals::rangeAsText(const Range* range, ExceptionState& exceptionState)
1127{
1128    if (!range) {
1129        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1130        return String();
1131    }
1132
1133    return range->text();
1134}
1135
1136PassRefPtr<DOMPoint> Internals::touchPositionAdjustedToBestClickableNode(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState)
1137{
1138    if (!document || !document->frame()) {
1139        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1140        return 0;
1141    }
1142
1143    document->updateLayout();
1144
1145    IntSize radius(width / 2, height / 2);
1146    IntPoint point(x + radius.width(), y + radius.height());
1147
1148    Node* targetNode;
1149    IntPoint adjustedPoint;
1150
1151    bool foundNode = document->frame()->eventHandler().bestClickableNodeForTouchPoint(point, radius, adjustedPoint, targetNode);
1152    if (foundNode)
1153        return DOMPoint::create(adjustedPoint.x(), adjustedPoint.y());
1154
1155    return 0;
1156}
1157
1158Node* Internals::touchNodeAdjustedToBestClickableNode(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState)
1159{
1160    if (!document || !document->frame()) {
1161        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1162        return 0;
1163    }
1164
1165    document->updateLayout();
1166
1167    IntSize radius(width / 2, height / 2);
1168    IntPoint point(x + radius.width(), y + radius.height());
1169
1170    Node* targetNode;
1171    IntPoint adjustedPoint;
1172    document->frame()->eventHandler().bestClickableNodeForTouchPoint(point, radius, adjustedPoint, targetNode);
1173    return targetNode;
1174}
1175
1176PassRefPtr<DOMPoint> Internals::touchPositionAdjustedToBestContextMenuNode(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState)
1177{
1178    if (!document || !document->frame()) {
1179        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1180        return 0;
1181    }
1182
1183    document->updateLayout();
1184
1185    IntSize radius(width / 2, height / 2);
1186    IntPoint point(x + radius.width(), y + radius.height());
1187
1188    Node* targetNode = 0;
1189    IntPoint adjustedPoint;
1190
1191    bool foundNode = document->frame()->eventHandler().bestContextMenuNodeForTouchPoint(point, radius, adjustedPoint, targetNode);
1192    if (foundNode)
1193        return DOMPoint::create(adjustedPoint.x(), adjustedPoint.y());
1194
1195    return DOMPoint::create(x, y);
1196}
1197
1198Node* Internals::touchNodeAdjustedToBestContextMenuNode(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState)
1199{
1200    if (!document || !document->frame()) {
1201        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1202        return 0;
1203    }
1204
1205    document->updateLayout();
1206
1207    IntSize radius(width / 2, height / 2);
1208    IntPoint point(x + radius.width(), y + radius.height());
1209
1210    Node* targetNode = 0;
1211    IntPoint adjustedPoint;
1212    document->frame()->eventHandler().bestContextMenuNodeForTouchPoint(point, radius, adjustedPoint, targetNode);
1213    return targetNode;
1214}
1215
1216PassRefPtr<ClientRect> Internals::bestZoomableAreaForTouchPoint(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState)
1217{
1218    if (!document || !document->frame()) {
1219        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1220        return 0;
1221    }
1222
1223    document->updateLayout();
1224
1225    IntSize radius(width / 2, height / 2);
1226    IntPoint point(x + radius.width(), y + radius.height());
1227
1228    Node* targetNode;
1229    IntRect zoomableArea;
1230    bool foundNode = document->frame()->eventHandler().bestZoomableAreaForTouchPoint(point, radius, zoomableArea, targetNode);
1231    if (foundNode)
1232        return ClientRect::create(zoomableArea);
1233
1234    return 0;
1235}
1236
1237
1238int Internals::lastSpellCheckRequestSequence(Document* document, ExceptionState& exceptionState)
1239{
1240    SpellCheckRequester* requester = spellCheckRequester(document);
1241
1242    if (!requester) {
1243        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1244        return -1;
1245    }
1246
1247    return requester->lastRequestSequence();
1248}
1249
1250int Internals::lastSpellCheckProcessedSequence(Document* document, ExceptionState& exceptionState)
1251{
1252    SpellCheckRequester* requester = spellCheckRequester(document);
1253
1254    if (!requester) {
1255        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1256        return -1;
1257    }
1258
1259    return requester->lastProcessedSequence();
1260}
1261
1262Vector<String> Internals::userPreferredLanguages() const
1263{
1264    return WebCore::userPreferredLanguages();
1265}
1266
1267void Internals::setUserPreferredLanguages(const Vector<String>& languages)
1268{
1269    WebCore::overrideUserPreferredLanguages(languages);
1270}
1271
1272unsigned Internals::wheelEventHandlerCount(Document* document, ExceptionState& exceptionState)
1273{
1274    if (!document) {
1275        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1276        return 0;
1277    }
1278
1279    return WheelController::from(document)->wheelEventHandlerCount();
1280}
1281
1282unsigned Internals::touchEventHandlerCount(Document* document, ExceptionState& exceptionState)
1283{
1284    if (!document) {
1285        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1286        return 0;
1287    }
1288
1289    const TouchEventTargetSet* touchHandlers = document->touchEventTargets();
1290    if (!touchHandlers)
1291        return 0;
1292
1293    unsigned count = 0;
1294    for (TouchEventTargetSet::const_iterator iter = touchHandlers->begin(); iter != touchHandlers->end(); ++iter)
1295        count += iter->value;
1296    return count;
1297}
1298
1299static RenderLayer* findRenderLayerForGraphicsLayer(RenderLayer* searchRoot, GraphicsLayer* graphicsLayer, String* layerType)
1300{
1301    if (searchRoot->hasCompositedLayerMapping() && graphicsLayer == searchRoot->compositedLayerMapping()->mainGraphicsLayer())
1302        return searchRoot;
1303
1304    GraphicsLayer* layerForScrolling = searchRoot->scrollableArea() ? searchRoot->scrollableArea()->layerForScrolling() : 0;
1305    if (graphicsLayer == layerForScrolling) {
1306        *layerType = "scrolling";
1307        return searchRoot;
1308    }
1309
1310    GraphicsLayer* layerForHorizontalScrollbar = searchRoot->scrollableArea() ? searchRoot->scrollableArea()->layerForHorizontalScrollbar() : 0;
1311    if (graphicsLayer == layerForHorizontalScrollbar) {
1312        *layerType = "horizontalScrollbar";
1313        return searchRoot;
1314    }
1315
1316    GraphicsLayer* layerForVerticalScrollbar = searchRoot->scrollableArea() ? searchRoot->scrollableArea()->layerForVerticalScrollbar() : 0;
1317    if (graphicsLayer == layerForVerticalScrollbar) {
1318        *layerType = "verticalScrollbar";
1319        return searchRoot;
1320    }
1321
1322    GraphicsLayer* layerForScrollCorner = searchRoot->scrollableArea() ? searchRoot->scrollableArea()->layerForScrollCorner() : 0;
1323    if (graphicsLayer == layerForScrollCorner) {
1324        *layerType = "scrollCorner";
1325        return searchRoot;
1326    }
1327
1328    for (RenderLayer* child = searchRoot->firstChild(); child; child = child->nextSibling()) {
1329        RenderLayer* foundLayer = findRenderLayerForGraphicsLayer(child, graphicsLayer, layerType);
1330        if (foundLayer)
1331            return foundLayer;
1332    }
1333
1334    return 0;
1335}
1336
1337// Given a vector of rects, merge those that are adjacent, leaving empty rects
1338// in the place of no longer used slots. This is intended to simplify the list
1339// of rects returned by an SkRegion (which have been split apart for sorting
1340// purposes). No attempt is made to do this efficiently (eg. by relying on the
1341// sort criteria of SkRegion).
1342static void mergeRects(blink::WebVector<blink::WebRect>& rects)
1343{
1344    for (size_t i = 0; i < rects.size(); ++i) {
1345        if (rects[i].isEmpty())
1346            continue;
1347        bool updated;
1348        do {
1349            updated = false;
1350            for (size_t j = i+1; j < rects.size(); ++j) {
1351                if (rects[j].isEmpty())
1352                    continue;
1353                // Try to merge rects[j] into rects[i] along the 4 possible edges.
1354                if (rects[i].y == rects[j].y && rects[i].height == rects[j].height) {
1355                    if (rects[i].x + rects[i].width == rects[j].x) {
1356                        rects[i].width += rects[j].width;
1357                        rects[j] = blink::WebRect();
1358                        updated = true;
1359                    } else if (rects[i].x == rects[j].x + rects[j].width) {
1360                        rects[i].x = rects[j].x;
1361                        rects[i].width += rects[j].width;
1362                        rects[j] = blink::WebRect();
1363                        updated = true;
1364                    }
1365                } else if (rects[i].x == rects[j].x && rects[i].width == rects[j].width) {
1366                    if (rects[i].y + rects[i].height == rects[j].y) {
1367                        rects[i].height += rects[j].height;
1368                        rects[j] = blink::WebRect();
1369                        updated = true;
1370                    } else if (rects[i].y == rects[j].y + rects[j].height) {
1371                        rects[i].y = rects[j].y;
1372                        rects[i].height += rects[j].height;
1373                        rects[j] = blink::WebRect();
1374                        updated = true;
1375                    }
1376                }
1377            }
1378        } while (updated);
1379    }
1380}
1381
1382static void accumulateLayerRectList(RenderLayerCompositor* compositor, GraphicsLayer* graphicsLayer, LayerRectList* rects)
1383{
1384    blink::WebVector<blink::WebRect> layerRects = graphicsLayer->platformLayer()->touchEventHandlerRegion();
1385    if (!layerRects.isEmpty()) {
1386        mergeRects(layerRects);
1387        String layerType;
1388        RenderLayer* renderLayer = findRenderLayerForGraphicsLayer(compositor->rootRenderLayer(), graphicsLayer, &layerType);
1389        Node* node = renderLayer ? renderLayer->renderer()->node() : 0;
1390        for (size_t i = 0; i < layerRects.size(); ++i) {
1391            if (!layerRects[i].isEmpty())
1392                rects->append(node, layerType, ClientRect::create(layerRects[i]));
1393        }
1394    }
1395
1396    size_t numChildren = graphicsLayer->children().size();
1397    for (size_t i = 0; i < numChildren; ++i)
1398        accumulateLayerRectList(compositor, graphicsLayer->children()[i], rects);
1399}
1400
1401PassRefPtr<LayerRectList> Internals::touchEventTargetLayerRects(Document* document, ExceptionState& exceptionState)
1402{
1403    if (!document || !document->view() || !document->page() || document != contextDocument()) {
1404        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1405        return 0;
1406    }
1407
1408    // Do any pending layout and compositing update (which may call touchEventTargetRectsChange) to ensure this
1409    // really takes any previous changes into account.
1410    forceCompositingUpdate(document, exceptionState);
1411    if (exceptionState.hadException())
1412        return 0;
1413
1414    if (RenderView* view = document->renderView()) {
1415        if (RenderLayerCompositor* compositor = view->compositor()) {
1416            if (GraphicsLayer* rootLayer = compositor->rootGraphicsLayer()) {
1417                RefPtr<LayerRectList> rects = LayerRectList::create();
1418                accumulateLayerRectList(compositor, rootLayer, rects.get());
1419                return rects;
1420            }
1421        }
1422    }
1423
1424    return 0;
1425}
1426
1427PassRefPtr<NodeList> Internals::nodesFromRect(Document* document, int centerX, int centerY, unsigned topPadding, unsigned rightPadding,
1428    unsigned bottomPadding, unsigned leftPadding, bool ignoreClipping, bool allowShadowContent, bool allowChildFrameContent, ExceptionState& exceptionState) const
1429{
1430    if (!document || !document->frame() || !document->frame()->view()) {
1431        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1432        return 0;
1433    }
1434
1435    Frame* frame = document->frame();
1436    FrameView* frameView = document->view();
1437    RenderView* renderView = document->renderView();
1438
1439    if (!renderView)
1440        return 0;
1441
1442    float zoomFactor = frame->pageZoomFactor();
1443    LayoutPoint point = roundedLayoutPoint(FloatPoint(centerX * zoomFactor + frameView->scrollX(), centerY * zoomFactor + frameView->scrollY()));
1444
1445    HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active;
1446    if (ignoreClipping)
1447        hitType |= HitTestRequest::IgnoreClipping;
1448    if (!allowShadowContent)
1449        hitType |= HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent;
1450    if (allowChildFrameContent)
1451        hitType |= HitTestRequest::AllowChildFrameContent;
1452
1453    HitTestRequest request(hitType);
1454
1455    // When ignoreClipping is false, this method returns null for coordinates outside of the viewport.
1456    if (!request.ignoreClipping() && !frameView->visibleContentRect().intersects(HitTestLocation::rectForPoint(point, topPadding, rightPadding, bottomPadding, leftPadding)))
1457        return 0;
1458
1459    Vector<RefPtr<Node> > matches;
1460
1461    // Need padding to trigger a rect based hit test, but we want to return a NodeList
1462    // so we special case this.
1463    if (!topPadding && !rightPadding && !bottomPadding && !leftPadding) {
1464        HitTestResult result(point);
1465        renderView->hitTest(request, result);
1466        if (result.innerNode())
1467            matches.append(result.innerNode()->deprecatedShadowAncestorNode());
1468    } else {
1469        HitTestResult result(point, topPadding, rightPadding, bottomPadding, leftPadding);
1470        renderView->hitTest(request, result);
1471        copyToVector(result.rectBasedTestResult(), matches);
1472    }
1473
1474    return StaticNodeList::adopt(matches);
1475}
1476
1477void Internals::emitInspectorDidBeginFrame(int frameId)
1478{
1479    contextDocument()->page()->inspectorController().didBeginFrame(frameId);
1480}
1481
1482void Internals::emitInspectorDidCancelFrame()
1483{
1484    contextDocument()->page()->inspectorController().didCancelFrame();
1485}
1486
1487bool Internals::hasSpellingMarker(Document* document, int from, int length, ExceptionState&)
1488{
1489    if (!document || !document->frame())
1490        return 0;
1491
1492    return document->frame()->spellChecker().selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
1493}
1494
1495void Internals::setContinuousSpellCheckingEnabled(bool enabled, ExceptionState&)
1496{
1497    if (!contextDocument() || !contextDocument()->frame())
1498        return;
1499
1500    if (enabled != contextDocument()->frame()->spellChecker().isContinuousSpellCheckingEnabled())
1501        contextDocument()->frame()->spellChecker().toggleContinuousSpellChecking();
1502}
1503
1504bool Internals::isOverwriteModeEnabled(Document* document, ExceptionState&)
1505{
1506    if (!document || !document->frame())
1507        return 0;
1508
1509    return document->frame()->editor().isOverwriteModeEnabled();
1510}
1511
1512void Internals::toggleOverwriteModeEnabled(Document* document, ExceptionState&)
1513{
1514    if (!document || !document->frame())
1515        return;
1516
1517    document->frame()->editor().toggleOverwriteModeEnabled();
1518}
1519
1520unsigned Internals::numberOfLiveNodes() const
1521{
1522    return InspectorCounters::counterValue(InspectorCounters::NodeCounter);
1523}
1524
1525unsigned Internals::numberOfLiveDocuments() const
1526{
1527    return InspectorCounters::counterValue(InspectorCounters::DocumentCounter);
1528}
1529
1530String Internals::dumpRefCountedInstanceCounts() const
1531{
1532    return WTF::dumpRefCountedInstanceCounts();
1533}
1534
1535Vector<String> Internals::consoleMessageArgumentCounts(Document* document) const
1536{
1537    InstrumentingAgents* instrumentingAgents = instrumentationForPage(document->page());
1538    if (!instrumentingAgents)
1539        return Vector<String>();
1540    InspectorConsoleAgent* consoleAgent = instrumentingAgents->inspectorConsoleAgent();
1541    if (!consoleAgent)
1542        return Vector<String>();
1543    Vector<unsigned> counts = consoleAgent->consoleMessageArgumentCounts();
1544    Vector<String> result(counts.size());
1545    for (size_t i = 0; i < counts.size(); i++)
1546        result[i] = String::number(counts[i]);
1547    return result;
1548}
1549
1550PassRefPtr<DOMWindow> Internals::openDummyInspectorFrontend(const String& url)
1551{
1552    Page* page = contextDocument()->frame()->page();
1553    ASSERT(page);
1554
1555    DOMWindow* window = page->mainFrame()->domWindow();
1556    ASSERT(window);
1557
1558    m_frontendWindow = window->open(url, "", "", window, window);
1559    ASSERT(m_frontendWindow);
1560
1561    Page* frontendPage = m_frontendWindow->document()->page();
1562    ASSERT(frontendPage);
1563
1564    OwnPtr<InspectorFrontendClientLocal> frontendClient = adoptPtr(new InspectorFrontendClientLocal(page->inspectorController(), frontendPage));
1565
1566    frontendPage->inspectorController().setInspectorFrontendClient(frontendClient.release());
1567
1568    m_frontendChannel = adoptPtr(new InspectorFrontendChannelDummy(frontendPage));
1569
1570    page->inspectorController().connectFrontend(m_frontendChannel.get());
1571
1572    return m_frontendWindow;
1573}
1574
1575void Internals::closeDummyInspectorFrontend()
1576{
1577    Page* page = contextDocument()->frame()->page();
1578    ASSERT(page);
1579    ASSERT(m_frontendWindow);
1580
1581    page->inspectorController().disconnectFrontend();
1582
1583    m_frontendChannel.release();
1584
1585    m_frontendWindow->close(m_frontendWindow->executionContext());
1586    m_frontendWindow.release();
1587}
1588
1589Vector<unsigned long> Internals::setMemoryCacheCapacities(unsigned long minDeadBytes, unsigned long maxDeadBytes, unsigned long totalBytes)
1590{
1591    Vector<unsigned long> result;
1592    result.append(memoryCache()->minDeadCapacity());
1593    result.append(memoryCache()->maxDeadCapacity());
1594    result.append(memoryCache()->capacity());
1595    memoryCache()->setCapacities(minDeadBytes, maxDeadBytes, totalBytes);
1596    return result;
1597}
1598
1599void Internals::setInspectorResourcesDataSizeLimits(int maximumResourcesContentSize, int maximumSingleResourceContentSize, ExceptionState& exceptionState)
1600{
1601    Page* page = contextDocument()->frame()->page();
1602    if (!page) {
1603        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1604        return;
1605    }
1606    page->inspectorController().setResourcesDataSizeLimitsFromInternals(maximumResourcesContentSize, maximumSingleResourceContentSize);
1607}
1608
1609bool Internals::hasGrammarMarker(Document* document, int from, int length, ExceptionState&)
1610{
1611    if (!document || !document->frame())
1612        return 0;
1613
1614    return document->frame()->spellChecker().selectionStartHasMarkerFor(DocumentMarker::Grammar, from, length);
1615}
1616
1617unsigned Internals::numberOfScrollableAreas(Document* document, ExceptionState&)
1618{
1619    unsigned count = 0;
1620    Frame* frame = document->frame();
1621    if (frame->view()->scrollableAreas())
1622        count += frame->view()->scrollableAreas()->size();
1623
1624    for (Frame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
1625        if (child->view() && child->view()->scrollableAreas())
1626            count += child->view()->scrollableAreas()->size();
1627    }
1628
1629    return count;
1630}
1631
1632bool Internals::isPageBoxVisible(Document* document, int pageNumber, ExceptionState& exceptionState)
1633{
1634    if (!document) {
1635        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1636        return false;
1637    }
1638
1639    return document->isPageBoxVisible(pageNumber);
1640}
1641
1642String Internals::layerTreeAsText(Document* document, ExceptionState& exceptionState) const
1643{
1644    return layerTreeAsText(document, 0, exceptionState);
1645}
1646
1647String Internals::elementLayerTreeAsText(Element* element, ExceptionState& exceptionState) const
1648{
1649    return elementLayerTreeAsText(element, 0, exceptionState);
1650}
1651
1652static PassRefPtr<NodeList> paintOrderList(Element* element, ExceptionState& exceptionState, RenderLayerStackingNode::PaintOrderListType type)
1653{
1654    if (!element) {
1655        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1656        return 0;
1657    }
1658
1659    element->document().updateLayout();
1660
1661    RenderObject* renderer = element->renderer();
1662    if (!renderer || !renderer->isBox()) {
1663        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1664        return 0;
1665    }
1666
1667    RenderLayer* layer = toRenderBox(renderer)->layer();
1668    if (!layer) {
1669        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1670        return 0;
1671    }
1672
1673    Vector<RefPtr<Node> > nodes;
1674    layer->stackingNode()->computePaintOrderList(type, nodes);
1675    return StaticNodeList::adopt(nodes);
1676}
1677
1678PassRefPtr<NodeList> Internals::paintOrderListBeforePromote(Element* element, ExceptionState& exceptionState)
1679{
1680    return paintOrderList(element, exceptionState, RenderLayerStackingNode::BeforePromote);
1681}
1682
1683PassRefPtr<NodeList> Internals::paintOrderListAfterPromote(Element* element, ExceptionState& exceptionState)
1684{
1685    return paintOrderList(element, exceptionState, RenderLayerStackingNode::AfterPromote);
1686}
1687
1688bool Internals::scrollsWithRespectTo(Element* element1, Element* element2, ExceptionState& exceptionState)
1689{
1690    if (!element1 || !element2) {
1691        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1692        return 0;
1693    }
1694
1695    element1->document().updateLayout();
1696
1697    RenderObject* renderer1 = element1->renderer();
1698    RenderObject* renderer2 = element2->renderer();
1699    if (!renderer1 || !renderer2 || !renderer1->isBox() || !renderer2->isBox()) {
1700        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1701        return 0;
1702    }
1703
1704    RenderLayer* layer1 = toRenderBox(renderer1)->layer();
1705    RenderLayer* layer2 = toRenderBox(renderer2)->layer();
1706    if (!layer1 || !layer2) {
1707        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1708        return 0;
1709    }
1710
1711    return layer1->scrollsWithRespectTo(layer2);
1712}
1713
1714bool Internals::isUnclippedDescendant(Element* element, ExceptionState& exceptionState)
1715{
1716    if (!element) {
1717        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1718        return 0;
1719    }
1720
1721    element->document().updateLayout();
1722
1723    RenderObject* renderer = element->renderer();
1724    if (!renderer || !renderer->isBox()) {
1725        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1726        return 0;
1727    }
1728
1729    RenderLayer* layer = toRenderBox(renderer)->layer();
1730    if (!layer) {
1731        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1732        return 0;
1733    }
1734
1735    return layer->isUnclippedDescendant();
1736}
1737
1738bool Internals::needsCompositedScrolling(Element* element, ExceptionState& exceptionState)
1739{
1740    if (!element) {
1741        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1742        return 0;
1743    }
1744
1745    element->document().updateLayout();
1746
1747    RenderObject* renderer = element->renderer();
1748    if (!renderer || !renderer->isBox()) {
1749        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1750        return 0;
1751    }
1752
1753    RenderLayer* layer = toRenderBox(renderer)->layer();
1754    if (!layer) {
1755        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1756        return 0;
1757    }
1758
1759    return layer->needsCompositedScrolling();
1760}
1761
1762String Internals::layerTreeAsText(Document* document, unsigned flags, ExceptionState& exceptionState) const
1763{
1764    if (!document || !document->frame()) {
1765        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1766        return String();
1767    }
1768
1769    return document->frame()->layerTreeAsText(flags);
1770}
1771
1772String Internals::elementLayerTreeAsText(Element* element, unsigned flags, ExceptionState& exceptionState) const
1773{
1774    if (!element) {
1775        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1776        return String();
1777    }
1778
1779    element->document().updateLayout();
1780
1781    RenderObject* renderer = element->renderer();
1782    if (!renderer || !renderer->isBox()) {
1783        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1784        return String();
1785    }
1786
1787    RenderLayer* layer = toRenderBox(renderer)->layer();
1788    if (!layer
1789        || !layer->hasCompositedLayerMapping()
1790        || !layer->compositedLayerMapping()->mainGraphicsLayer()) {
1791        // Don't raise exception in these cases which may be normally used in tests.
1792        return String();
1793    }
1794
1795    return layer->compositedLayerMapping()->mainGraphicsLayer()->layerTreeAsText(flags);
1796}
1797
1798static RenderLayer* getRenderLayerForElement(Element* element, ExceptionState& exceptionState)
1799{
1800    if (!element) {
1801        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1802        return 0;
1803    }
1804
1805    RenderObject* renderer = element->renderer();
1806    if (!renderer || !renderer->isBox()) {
1807        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1808        return 0;
1809    }
1810
1811    RenderLayer* layer = toRenderBox(renderer)->layer();
1812    if (!layer) {
1813        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1814        return 0;
1815    }
1816
1817    return layer;
1818}
1819
1820void Internals::setNeedsCompositedScrolling(Element* element, unsigned needsCompositedScrolling, ExceptionState& exceptionState)
1821{
1822    if (!element) {
1823        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1824        return;
1825    }
1826
1827    element->document().updateLayout();
1828
1829    if (RenderLayer* layer = getRenderLayerForElement(element, exceptionState))
1830        layer->scrollableArea()->setForceNeedsCompositedScrolling(static_cast<ForceNeedsCompositedScrollingMode>(needsCompositedScrolling));
1831}
1832
1833String Internals::repaintRectsAsText(Document* document, ExceptionState& exceptionState) const
1834{
1835    if (!document || !document->frame()) {
1836        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1837        return String();
1838    }
1839
1840    return document->frame()->trackedRepaintRectsAsText();
1841}
1842
1843PassRefPtr<ClientRectList> Internals::repaintRects(Element* element, ExceptionState& exceptionState) const
1844{
1845    if (!element) {
1846        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1847        return 0;
1848    }
1849
1850    if (RenderLayer* layer = getRenderLayerForElement(element, exceptionState)) {
1851        if (layer->compositingState() == PaintsIntoOwnBacking) {
1852            OwnPtr<Vector<FloatRect> > rects = layer->collectTrackedRepaintRects();
1853            ASSERT(rects.get());
1854            Vector<FloatQuad> quads(rects->size());
1855            for (size_t i = 0; i < rects->size(); ++i)
1856                quads[i] = FloatRect(rects->at(i));
1857            return ClientRectList::create(quads);
1858        }
1859    }
1860
1861    // It's an error to call this on an element that's not composited.
1862    exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1863    return 0;
1864}
1865
1866String Internals::scrollingStateTreeAsText(Document* document, ExceptionState& exceptionState) const
1867{
1868    return String();
1869}
1870
1871String Internals::mainThreadScrollingReasons(Document* document, ExceptionState& exceptionState) const
1872{
1873    if (!document || !document->frame()) {
1874        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1875        return String();
1876    }
1877
1878    // Force a re-layout and a compositing update.
1879    document->updateLayout();
1880    RenderView* view = document->renderView();
1881    if (view->compositor())
1882        view->compositor()->updateCompositingLayers(CompositingUpdateFinishAllDeferredWork);
1883
1884    Page* page = document->page();
1885    if (!page)
1886        return String();
1887
1888    return page->mainThreadScrollingReasonsAsText();
1889}
1890
1891PassRefPtr<ClientRectList> Internals::nonFastScrollableRects(Document* document, ExceptionState& exceptionState) const
1892{
1893    if (!document || !document->frame()) {
1894        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1895        return 0;
1896    }
1897
1898    Page* page = document->page();
1899    if (!page)
1900        return 0;
1901
1902    return page->nonFastScrollableRects(document->frame());
1903}
1904
1905void Internals::garbageCollectDocumentResources(Document* document, ExceptionState& exceptionState) const
1906{
1907    if (!document) {
1908        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1909        return;
1910    }
1911    ResourceFetcher* fetcher = document->fetcher();
1912    if (!fetcher)
1913        return;
1914    fetcher->garbageCollectDocumentResources();
1915}
1916
1917void Internals::evictAllResources() const
1918{
1919    memoryCache()->evictResources();
1920}
1921
1922void Internals::allowRoundingHacks() const
1923{
1924    TextRun::setAllowsRoundingHacks(true);
1925}
1926
1927String Internals::counterValue(Element* element)
1928{
1929    if (!element)
1930        return String();
1931
1932    return counterValueForElement(element);
1933}
1934
1935int Internals::pageNumber(Element* element, float pageWidth, float pageHeight)
1936{
1937    if (!element)
1938        return 0;
1939
1940    return PrintContext::pageNumberForElement(element, FloatSize(pageWidth, pageHeight));
1941}
1942
1943Vector<String> Internals::iconURLs(Document* document, int iconTypesMask) const
1944{
1945    Vector<IconURL> iconURLs = document->iconURLs(iconTypesMask);
1946    Vector<String> array;
1947
1948    Vector<IconURL>::const_iterator iter(iconURLs.begin());
1949    for (; iter != iconURLs.end(); ++iter)
1950        array.append(iter->m_iconURL.string());
1951
1952    return array;
1953}
1954
1955Vector<String> Internals::shortcutIconURLs(Document* document) const
1956{
1957    return iconURLs(document, Favicon);
1958}
1959
1960Vector<String> Internals::allIconURLs(Document* document) const
1961{
1962    return iconURLs(document, Favicon | TouchIcon | TouchPrecomposedIcon);
1963}
1964
1965int Internals::numberOfPages(float pageWidth, float pageHeight)
1966{
1967    if (!frame())
1968        return -1;
1969
1970    return PrintContext::numberOfPages(frame(), FloatSize(pageWidth, pageHeight));
1971}
1972
1973String Internals::pageProperty(String propertyName, int pageNumber, ExceptionState& exceptionState) const
1974{
1975    if (!frame()) {
1976        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1977        return String();
1978    }
1979
1980    return PrintContext::pageProperty(frame(), propertyName.utf8().data(), pageNumber);
1981}
1982
1983String Internals::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft, ExceptionState& exceptionState) const
1984{
1985    if (!frame()) {
1986        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1987        return String();
1988    }
1989
1990    return PrintContext::pageSizeAndMarginsInPixels(frame(), pageNumber, width, height, marginTop, marginRight, marginBottom, marginLeft);
1991}
1992
1993void Internals::setDeviceScaleFactor(float scaleFactor, ExceptionState& exceptionState)
1994{
1995    Document* document = contextDocument();
1996    if (!document || !document->page()) {
1997        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
1998        return;
1999    }
2000    Page* page = document->page();
2001    page->setDeviceScaleFactor(scaleFactor);
2002}
2003
2004void Internals::setIsCursorVisible(Document* document, bool isVisible, ExceptionState& exceptionState)
2005{
2006    if (!document || !document->page()) {
2007        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
2008        return;
2009    }
2010    document->page()->setIsCursorVisible(isVisible);
2011}
2012
2013void Internals::webkitWillEnterFullScreenForElement(Document* document, Element* element)
2014{
2015    if (!document)
2016        return;
2017    FullscreenElementStack::from(document)->webkitWillEnterFullScreenForElement(element);
2018}
2019
2020void Internals::webkitDidEnterFullScreenForElement(Document* document, Element* element)
2021{
2022    if (!document)
2023        return;
2024    FullscreenElementStack::from(document)->webkitDidEnterFullScreenForElement(element);
2025}
2026
2027void Internals::webkitWillExitFullScreenForElement(Document* document, Element* element)
2028{
2029    if (!document)
2030        return;
2031    FullscreenElementStack::from(document)->webkitWillExitFullScreenForElement(element);
2032}
2033
2034void Internals::webkitDidExitFullScreenForElement(Document* document, Element* element)
2035{
2036    if (!document)
2037        return;
2038    FullscreenElementStack::from(document)->webkitDidExitFullScreenForElement(element);
2039}
2040
2041void Internals::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme)
2042{
2043    SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
2044}
2045
2046void Internals::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(const String& scheme)
2047{
2048    SchemeRegistry::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(scheme);
2049}
2050
2051PassRefPtr<MallocStatistics> Internals::mallocStatistics() const
2052{
2053    return MallocStatistics::create();
2054}
2055
2056PassRefPtr<TypeConversions> Internals::typeConversions() const
2057{
2058    return TypeConversions::create();
2059}
2060
2061Vector<String> Internals::getReferencedFilePaths() const
2062{
2063    frame()->loader().saveDocumentAndScrollState();
2064    return FormController::getReferencedFilePaths(frame()->loader().currentItem()->documentState());
2065}
2066
2067void Internals::startTrackingRepaints(Document* document, ExceptionState& exceptionState)
2068{
2069    if (!document || !document->view()) {
2070        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
2071        return;
2072    }
2073
2074    FrameView* frameView = document->view();
2075    frameView->setTracksRepaints(true);
2076}
2077
2078void Internals::stopTrackingRepaints(Document* document, ExceptionState& exceptionState)
2079{
2080    if (!document || !document->view()) {
2081        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
2082        return;
2083    }
2084
2085    FrameView* frameView = document->view();
2086    frameView->setTracksRepaints(false);
2087}
2088
2089void Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(ExceptionState& exceptionState)
2090{
2091    updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(0, exceptionState);
2092}
2093
2094void Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(Node* node, ExceptionState& exceptionState)
2095{
2096    Document* document;
2097    if (!node) {
2098        document = contextDocument();
2099    } else if (node->isDocumentNode()) {
2100        document = toDocument(node);
2101    } else if (node->hasTagName(HTMLNames::iframeTag)) {
2102        document = toHTMLIFrameElement(node)->contentDocument();
2103    } else {
2104        exceptionState.throwUninformativeAndGenericDOMException(TypeError);
2105        return;
2106    }
2107    document->updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasksSynchronously);
2108}
2109
2110PassRefPtr<ClientRectList> Internals::draggableRegions(Document* document, ExceptionState& exceptionState)
2111{
2112    return annotatedRegions(document, true, exceptionState);
2113}
2114
2115PassRefPtr<ClientRectList> Internals::nonDraggableRegions(Document* document, ExceptionState& exceptionState)
2116{
2117    return annotatedRegions(document, false, exceptionState);
2118}
2119
2120PassRefPtr<ClientRectList> Internals::annotatedRegions(Document* document, bool draggable, ExceptionState& exceptionState)
2121{
2122    if (!document || !document->view()) {
2123        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
2124        return ClientRectList::create();
2125    }
2126
2127    document->updateLayout();
2128    document->view()->updateAnnotatedRegions();
2129    Vector<AnnotatedRegionValue> regions = document->annotatedRegions();
2130
2131    Vector<FloatQuad> quads;
2132    for (size_t i = 0; i < regions.size(); ++i) {
2133        if (regions[i].draggable == draggable)
2134            quads.append(FloatQuad(regions[i].bounds));
2135    }
2136    return ClientRectList::create(quads);
2137}
2138
2139static const char* cursorTypeToString(Cursor::Type cursorType)
2140{
2141    switch (cursorType) {
2142    case Cursor::Pointer: return "Pointer";
2143    case Cursor::Cross: return "Cross";
2144    case Cursor::Hand: return "Hand";
2145    case Cursor::IBeam: return "IBeam";
2146    case Cursor::Wait: return "Wait";
2147    case Cursor::Help: return "Help";
2148    case Cursor::EastResize: return "EastResize";
2149    case Cursor::NorthResize: return "NorthResize";
2150    case Cursor::NorthEastResize: return "NorthEastResize";
2151    case Cursor::NorthWestResize: return "NorthWestResize";
2152    case Cursor::SouthResize: return "SouthResize";
2153    case Cursor::SouthEastResize: return "SouthEastResize";
2154    case Cursor::SouthWestResize: return "SouthWestResize";
2155    case Cursor::WestResize: return "WestResize";
2156    case Cursor::NorthSouthResize: return "NorthSouthResize";
2157    case Cursor::EastWestResize: return "EastWestResize";
2158    case Cursor::NorthEastSouthWestResize: return "NorthEastSouthWestResize";
2159    case Cursor::NorthWestSouthEastResize: return "NorthWestSouthEastResize";
2160    case Cursor::ColumnResize: return "ColumnResize";
2161    case Cursor::RowResize: return "RowResize";
2162    case Cursor::MiddlePanning: return "MiddlePanning";
2163    case Cursor::EastPanning: return "EastPanning";
2164    case Cursor::NorthPanning: return "NorthPanning";
2165    case Cursor::NorthEastPanning: return "NorthEastPanning";
2166    case Cursor::NorthWestPanning: return "NorthWestPanning";
2167    case Cursor::SouthPanning: return "SouthPanning";
2168    case Cursor::SouthEastPanning: return "SouthEastPanning";
2169    case Cursor::SouthWestPanning: return "SouthWestPanning";
2170    case Cursor::WestPanning: return "WestPanning";
2171    case Cursor::Move: return "Move";
2172    case Cursor::VerticalText: return "VerticalText";
2173    case Cursor::Cell: return "Cell";
2174    case Cursor::ContextMenu: return "ContextMenu";
2175    case Cursor::Alias: return "Alias";
2176    case Cursor::Progress: return "Progress";
2177    case Cursor::NoDrop: return "NoDrop";
2178    case Cursor::Copy: return "Copy";
2179    case Cursor::None: return "None";
2180    case Cursor::NotAllowed: return "NotAllowed";
2181    case Cursor::ZoomIn: return "ZoomIn";
2182    case Cursor::ZoomOut: return "ZoomOut";
2183    case Cursor::Grab: return "Grab";
2184    case Cursor::Grabbing: return "Grabbing";
2185    case Cursor::Custom: return "Custom";
2186    }
2187
2188    ASSERT_NOT_REACHED();
2189    return "UNKNOWN";
2190}
2191
2192String Internals::getCurrentCursorInfo(Document* document, ExceptionState& exceptionState)
2193{
2194    if (!document || !document->frame()) {
2195        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
2196        return String();
2197    }
2198
2199    Cursor cursor = document->frame()->eventHandler().currentMouseCursor();
2200
2201    StringBuilder result;
2202    result.append("type=");
2203    result.append(cursorTypeToString(cursor.type()));
2204    result.append(" hotSpot=");
2205    result.appendNumber(cursor.hotSpot().x());
2206    result.append(",");
2207    result.appendNumber(cursor.hotSpot().y());
2208    if (cursor.image()) {
2209        IntSize size = cursor.image()->size();
2210        result.append(" image=");
2211        result.appendNumber(size.width());
2212        result.append("x");
2213        result.appendNumber(size.height());
2214    }
2215    if (cursor.imageScaleFactor() != 1) {
2216        result.append(" scale=");
2217        NumberToStringBuffer buffer;
2218        result.append(numberToFixedPrecisionString(cursor.imageScaleFactor(), 8, buffer, true));
2219    }
2220
2221    return result.toString();
2222}
2223
2224PassRefPtr<ArrayBuffer> Internals::serializeObject(PassRefPtr<SerializedScriptValue> value) const
2225{
2226    String stringValue = value->toWireString();
2227    RefPtr<ArrayBuffer> buffer = ArrayBuffer::createUninitialized(stringValue.length(), sizeof(UChar));
2228    stringValue.copyTo(static_cast<UChar*>(buffer->data()), 0, stringValue.length());
2229    return buffer.release();
2230}
2231
2232PassRefPtr<SerializedScriptValue> Internals::deserializeBuffer(PassRefPtr<ArrayBuffer> buffer) const
2233{
2234    String value(static_cast<const UChar*>(buffer->data()), buffer->byteLength() / sizeof(UChar));
2235    return SerializedScriptValue::createFromWire(value);
2236}
2237
2238void Internals::forceReload(bool endToEnd)
2239{
2240    frame()->loader().reload(endToEnd ? EndToEndReload : NormalReload);
2241}
2242
2243PassRefPtr<ClientRect> Internals::selectionBounds(ExceptionState& exceptionState)
2244{
2245    Document* document = contextDocument();
2246    if (!document || !document->frame()) {
2247        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
2248        return 0;
2249    }
2250
2251    return ClientRect::create(document->frame()->selection().bounds());
2252}
2253
2254String Internals::markerTextForListItem(Element* element, ExceptionState& exceptionState)
2255{
2256    if (!element) {
2257        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
2258        return String();
2259    }
2260    return WebCore::markerTextForListItem(element);
2261}
2262
2263String Internals::getImageSourceURL(Element* element, ExceptionState& exceptionState)
2264{
2265    if (!element) {
2266        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
2267        return String();
2268    }
2269    return element->imageSourceURL();
2270}
2271
2272String Internals::baseURL(Document* document, ExceptionState& exceptionState)
2273{
2274    if (!document) {
2275        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
2276        return String();
2277    }
2278
2279    return document->baseURL().string();
2280}
2281
2282bool Internals::isSelectPopupVisible(Node* node)
2283{
2284    if (!node->hasTagName(HTMLNames::selectTag))
2285        return false;
2286
2287    HTMLSelectElement* select = toHTMLSelectElement(node);
2288
2289    RenderObject* renderer = select->renderer();
2290    if (!renderer->isMenuList())
2291        return false;
2292
2293    RenderMenuList* menuList = toRenderMenuList(renderer);
2294    return menuList->popupIsVisible();
2295}
2296
2297bool Internals::loseSharedGraphicsContext3D()
2298{
2299    RefPtr<GraphicsContext3D> sharedContext = SharedGraphicsContext3D::get();
2300    if (!sharedContext)
2301        return false;
2302    sharedContext->extensions()->loseContextCHROMIUM(Extensions3D::GUILTY_CONTEXT_RESET_ARB, Extensions3D::INNOCENT_CONTEXT_RESET_ARB);
2303    // To prevent tests that call loseSharedGraphicsContext3D from being
2304    // flaky, we call finish so that the context is guaranteed to be lost
2305    // synchronously (i.e. before returning).
2306    sharedContext->finish();
2307    return true;
2308}
2309
2310void Internals::forceCompositingUpdate(Document* document, ExceptionState& exceptionState)
2311{
2312    if (!document || !document->renderView()) {
2313        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
2314        return;
2315    }
2316
2317    document->updateLayout();
2318
2319    RenderView* view = document->renderView();
2320    if (view->compositor())
2321        view->compositor()->updateCompositingLayers(CompositingUpdateFinishAllDeferredWork);
2322}
2323
2324bool Internals::isCompositorFramePending(Document* document, ExceptionState& exceptionState)
2325{
2326    if (!document || !document->renderView()) {
2327        exceptionState.throwDOMException(InvalidAccessError, document ? "The document's render view cannot be retrieved." : "The document provided is invalid.");
2328        return false;
2329    }
2330
2331    return document->page()->chrome().client().isCompositorFramePending();
2332}
2333
2334void Internals::setZoomFactor(float factor)
2335{
2336    frame()->setPageZoomFactor(factor);
2337}
2338
2339}
2340