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