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