Upstream version 9.38.198.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 ShadowRoot* Internals::shadowRoot(Element* host)
573 {
574     // FIXME: Internals::shadowRoot() in tests should be converted to youngestShadowRoot() or oldestShadowRoot().
575     // https://bugs.webkit.org/show_bug.cgi?id=78465
576     return youngestShadowRoot(host);
577 }
578
579 ShadowRoot* Internals::youngestShadowRoot(Element* host)
580 {
581     ASSERT(host);
582     if (ElementShadow* shadow = host->shadow())
583         return shadow->youngestShadowRoot();
584     return 0;
585 }
586
587 ShadowRoot* Internals::oldestShadowRoot(Element* host)
588 {
589     ASSERT(host);
590     if (ElementShadow* shadow = host->shadow())
591         return shadow->oldestShadowRoot();
592     return 0;
593 }
594
595 ShadowRoot* Internals::youngerShadowRoot(Node* shadow, ExceptionState& exceptionState)
596 {
597     ASSERT(shadow);
598     if (!shadow->isShadowRoot()) {
599         exceptionState.throwDOMException(InvalidAccessError, "The node provided is not a shadow root.");
600         return 0;
601     }
602
603     return toShadowRoot(shadow)->youngerShadowRoot();
604 }
605
606 String Internals::shadowRootType(const Node* root, ExceptionState& exceptionState) const
607 {
608     ASSERT(root);
609     if (!root->isShadowRoot()) {
610         exceptionState.throwDOMException(InvalidAccessError, "The node provided is not a shadow root.");
611         return String();
612     }
613
614     switch (toShadowRoot(root)->type()) {
615     case ShadowRoot::UserAgentShadowRoot:
616         return String("UserAgentShadowRoot");
617     case ShadowRoot::AuthorShadowRoot:
618         return String("AuthorShadowRoot");
619     default:
620         ASSERT_NOT_REACHED();
621         return String("Unknown");
622     }
623 }
624
625 const AtomicString& Internals::shadowPseudoId(Element* element)
626 {
627     ASSERT(element);
628     return element->shadowPseudoId();
629 }
630
631 void Internals::setShadowPseudoId(Element* element, const AtomicString& id)
632 {
633     ASSERT(element);
634     return element->setShadowPseudoId(id);
635 }
636
637 String Internals::visiblePlaceholder(Element* element)
638 {
639     if (element && isHTMLTextFormControlElement(*element)) {
640         if (toHTMLTextFormControlElement(element)->placeholderShouldBeVisible())
641             return toHTMLTextFormControlElement(element)->placeholderElement()->textContent();
642     }
643
644     return String();
645 }
646
647 void Internals::selectColorInColorChooser(Element* element, const String& colorValue)
648 {
649     ASSERT(element);
650     if (!isHTMLInputElement(*element))
651         return;
652     Color color;
653     if (!color.setFromString(colorValue))
654         return;
655     toHTMLInputElement(*element).selectColorInColorChooser(color);
656 }
657
658 bool Internals::hasAutofocusRequest(Document* document)
659 {
660     if (!document)
661         document = contextDocument();
662     return document->autofocusElement();
663 }
664
665 bool Internals::hasAutofocusRequest()
666 {
667     return hasAutofocusRequest(0);
668 }
669
670 Vector<String> Internals::formControlStateOfHistoryItem(ExceptionState& exceptionState)
671 {
672     HistoryItem* mainItem = frame()->loader().currentItem();
673     if (!mainItem) {
674         exceptionState.throwDOMException(InvalidAccessError, "No history item is available.");
675         return Vector<String>();
676     }
677     return mainItem->documentState();
678 }
679
680 void Internals::setFormControlStateOfHistoryItem(const Vector<String>& state, ExceptionState& exceptionState)
681 {
682     HistoryItem* mainItem = frame()->loader().currentItem();
683     if (!mainItem) {
684         exceptionState.throwDOMException(InvalidAccessError, "No history item is available.");
685         return;
686     }
687     mainItem->clearDocumentState();
688     mainItem->setDocumentState(state);
689 }
690
691 void Internals::setEnableMockPagePopup(bool enabled, ExceptionState& exceptionState)
692 {
693     Document* document = contextDocument();
694     if (!document || !document->page())
695         return;
696     Page* page = document->page();
697     if (!enabled) {
698         page->chrome().client().resetPagePopupDriver();
699         return;
700     }
701     if (!s_pagePopupDriver)
702         s_pagePopupDriver = MockPagePopupDriver::create(page->deprecatedLocalMainFrame()).leakPtr();
703     page->chrome().client().setPagePopupDriver(s_pagePopupDriver);
704 }
705
706 PassRefPtrWillBeRawPtr<PagePopupController> Internals::pagePopupController()
707 {
708     return s_pagePopupDriver ? s_pagePopupDriver->pagePopupController() : 0;
709 }
710
711 PassRefPtrWillBeRawPtr<ClientRect> Internals::unscaledViewportRect(ExceptionState& exceptionState)
712 {
713     Document* document = contextDocument();
714     if (!document || !document->view()) {
715         exceptionState.throwDOMException(InvalidAccessError, document ? "The document's viewport cannot be retrieved." : "No context document can be obtained.");
716         return ClientRect::create();
717     }
718
719     return ClientRect::create(document->view()->visibleContentRect());
720 }
721
722 PassRefPtrWillBeRawPtr<ClientRect> Internals::absoluteCaretBounds(ExceptionState& exceptionState)
723 {
724     Document* document = contextDocument();
725     if (!document || !document->frame()) {
726         exceptionState.throwDOMException(InvalidAccessError, document ? "The document's frame cannot be retrieved." : "No context document can be obtained.");
727         return ClientRect::create();
728     }
729
730     return ClientRect::create(document->frame()->selection().absoluteCaretBounds());
731 }
732
733 PassRefPtrWillBeRawPtr<ClientRect> Internals::boundingBox(Element* element)
734 {
735     ASSERT(element);
736
737     element->document().updateLayoutIgnorePendingStylesheets();
738     RenderObject* renderer = element->renderer();
739     if (!renderer)
740         return ClientRect::create();
741     return ClientRect::create(renderer->absoluteBoundingBoxRectIgnoringTransforms());
742 }
743
744 unsigned Internals::markerCountForNode(Node* node, const String& markerType, ExceptionState& exceptionState)
745 {
746     ASSERT(node);
747     DocumentMarker::MarkerTypes markerTypes = 0;
748     if (!markerTypesFrom(markerType, markerTypes)) {
749         exceptionState.throwDOMException(SyntaxError, "The marker type provided ('" + markerType + "') is invalid.");
750         return 0;
751     }
752
753     return node->document().markers().markersFor(node, markerTypes).size();
754 }
755
756 unsigned Internals::activeMarkerCountForNode(Node* node)
757 {
758     ASSERT(node);
759
760     // Only TextMatch markers can be active.
761     DocumentMarker::MarkerType markerType = DocumentMarker::TextMatch;
762     DocumentMarkerVector markers = node->document().markers().markersFor(node, markerType);
763
764     unsigned activeMarkerCount = 0;
765     for (DocumentMarkerVector::iterator iter = markers.begin(); iter != markers.end(); ++iter) {
766         if ((*iter)->activeMatch())
767             activeMarkerCount++;
768     }
769
770     return activeMarkerCount;
771 }
772
773 DocumentMarker* Internals::markerAt(Node* node, const String& markerType, unsigned index, ExceptionState& exceptionState)
774 {
775     ASSERT(node);
776     DocumentMarker::MarkerTypes markerTypes = 0;
777     if (!markerTypesFrom(markerType, markerTypes)) {
778         exceptionState.throwDOMException(SyntaxError, "The marker type provided ('" + markerType + "') is invalid.");
779         return 0;
780     }
781
782     DocumentMarkerVector markers = node->document().markers().markersFor(node, markerTypes);
783     if (markers.size() <= index)
784         return 0;
785     return markers[index];
786 }
787
788 PassRefPtrWillBeRawPtr<Range> Internals::markerRangeForNode(Node* node, const String& markerType, unsigned index, ExceptionState& exceptionState)
789 {
790     ASSERT(node);
791     DocumentMarker* marker = markerAt(node, markerType, index, exceptionState);
792     if (!marker)
793         return nullptr;
794     return Range::create(node->document(), node, marker->startOffset(), node, marker->endOffset());
795 }
796
797 String Internals::markerDescriptionForNode(Node* node, const String& markerType, unsigned index, ExceptionState& exceptionState)
798 {
799     DocumentMarker* marker = markerAt(node, markerType, index, exceptionState);
800     if (!marker)
801         return String();
802     return marker->description();
803 }
804
805 void Internals::addTextMatchMarker(const Range* range, bool isActive)
806 {
807     ASSERT(range);
808     range->ownerDocument().updateLayoutIgnorePendingStylesheets();
809     range->ownerDocument().markers().addTextMatchMarker(range, isActive);
810 }
811
812 void Internals::setMarkersActive(Node* node, unsigned startOffset, unsigned endOffset, bool active)
813 {
814     ASSERT(node);
815     node->document().markers().setMarkersActive(node, startOffset, endOffset, active);
816 }
817
818 void Internals::setMarkedTextMatchesAreHighlighted(Document* document, bool highlight)
819 {
820     if (!document || !document->frame())
821         return;
822
823     document->frame()->editor().setMarkedTextMatchesAreHighlighted(highlight);
824 }
825
826 void Internals::setScrollViewPosition(Document* document, long x, long y, ExceptionState& exceptionState)
827 {
828     ASSERT(document);
829     if (!document->view()) {
830         exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
831         return;
832     }
833
834     FrameView* frameView = document->view();
835     bool constrainsScrollingToContentEdgeOldValue = frameView->constrainsScrollingToContentEdge();
836     bool scrollbarsSuppressedOldValue = frameView->scrollbarsSuppressed();
837
838     frameView->setConstrainsScrollingToContentEdge(false);
839     frameView->setScrollbarsSuppressed(false);
840     frameView->setScrollOffsetFromInternals(IntPoint(x, y));
841     frameView->setScrollbarsSuppressed(scrollbarsSuppressedOldValue);
842     frameView->setConstrainsScrollingToContentEdge(constrainsScrollingToContentEdgeOldValue);
843 }
844
845 String Internals::viewportAsText(Document* document, float, int availableWidth, int availableHeight, ExceptionState& exceptionState)
846 {
847     ASSERT(document);
848     if (!document->page()) {
849         exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
850         return String();
851     }
852
853     document->updateLayoutIgnorePendingStylesheets();
854
855     Page* page = document->page();
856
857     // Update initial viewport size.
858     IntSize initialViewportSize(availableWidth, availableHeight);
859     document->page()->deprecatedLocalMainFrame()->view()->setFrameRect(IntRect(IntPoint::zero(), initialViewportSize));
860
861     ViewportDescription description = page->viewportDescription();
862     PageScaleConstraints constraints = description.resolve(initialViewportSize, Length());
863
864     constraints.fitToContentsWidth(constraints.layoutSize.width(), availableWidth);
865
866     StringBuilder builder;
867
868     builder.appendLiteral("viewport size ");
869     builder.append(String::number(constraints.layoutSize.width()));
870     builder.append('x');
871     builder.append(String::number(constraints.layoutSize.height()));
872
873     builder.appendLiteral(" scale ");
874     builder.append(String::number(constraints.initialScale));
875     builder.appendLiteral(" with limits [");
876     builder.append(String::number(constraints.minimumScale));
877     builder.appendLiteral(", ");
878     builder.append(String::number(constraints.maximumScale));
879
880     builder.appendLiteral("] and userScalable ");
881     builder.append(description.userZoom ? "true" : "false");
882
883     return builder.toString();
884 }
885
886 bool Internals::wasLastChangeUserEdit(Element* textField, ExceptionState& exceptionState)
887 {
888     ASSERT(textField);
889     if (isHTMLInputElement(*textField))
890         return toHTMLInputElement(*textField).lastChangeWasUserEdit();
891
892     if (isHTMLTextAreaElement(*textField))
893         return toHTMLTextAreaElement(*textField).lastChangeWasUserEdit();
894
895     exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not a TEXTAREA.");
896     return false;
897 }
898
899 bool Internals::elementShouldAutoComplete(Element* element, ExceptionState& exceptionState)
900 {
901     ASSERT(element);
902     if (isHTMLInputElement(*element))
903         return toHTMLInputElement(*element).shouldAutocomplete();
904
905     exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not an INPUT.");
906     return false;
907 }
908
909 String Internals::suggestedValue(Element* element, ExceptionState& exceptionState)
910 {
911     ASSERT(element);
912     if (!element->isFormControlElement()) {
913         exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not a form control element.");
914         return String();
915     }
916
917     String suggestedValue;
918     if (isHTMLInputElement(*element))
919         suggestedValue = toHTMLInputElement(*element).suggestedValue();
920
921     if (isHTMLTextAreaElement(*element))
922         suggestedValue = toHTMLTextAreaElement(*element).suggestedValue();
923
924     if (isHTMLSelectElement(*element))
925         suggestedValue = toHTMLSelectElement(*element).suggestedValue();
926
927     return suggestedValue;
928 }
929
930 void Internals::setSuggestedValue(Element* element, const String& value, ExceptionState& exceptionState)
931 {
932     ASSERT(element);
933     if (!element->isFormControlElement()) {
934         exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not a form control element.");
935         return;
936     }
937
938     if (isHTMLInputElement(*element))
939         toHTMLInputElement(*element).setSuggestedValue(value);
940
941     if (isHTMLTextAreaElement(*element))
942         toHTMLTextAreaElement(*element).setSuggestedValue(value);
943
944     if (isHTMLSelectElement(*element))
945         toHTMLSelectElement(*element).setSuggestedValue(value);
946 }
947
948 void Internals::setEditingValue(Element* element, const String& value, ExceptionState& exceptionState)
949 {
950     ASSERT(element);
951     if (!isHTMLInputElement(*element)) {
952         exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not an INPUT.");
953         return;
954     }
955
956     toHTMLInputElement(*element).setEditingValue(value);
957 }
958
959 void Internals::setAutofilled(Element* element, bool enabled, ExceptionState& exceptionState)
960 {
961     ASSERT(element);
962     if (!element->isFormControlElement()) {
963         exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not a form control element.");
964         return;
965     }
966     toHTMLFormControlElement(element)->setAutofilled(enabled);
967 }
968
969 void Internals::scrollElementToRect(Element* element, long x, long y, long w, long h, ExceptionState& exceptionState)
970 {
971     ASSERT(element);
972     if (!element->document().view()) {
973         exceptionState.throwDOMException(InvalidNodeTypeError, element ? "No view can be obtained from the provided element's document." : ExceptionMessages::argumentNullOrIncorrectType(1, "Element"));
974         return;
975     }
976     FrameView* frameView = element->document().view();
977     frameView->scrollElementToRect(element, IntRect(x, y, w, h));
978 }
979
980 PassRefPtrWillBeRawPtr<Range> Internals::rangeFromLocationAndLength(Element* scope, int rangeLocation, int rangeLength)
981 {
982     ASSERT(scope);
983
984     // TextIterator depends on Layout information, make sure layout it up to date.
985     scope->document().updateLayoutIgnorePendingStylesheets();
986
987     return PlainTextRange(rangeLocation, rangeLocation + rangeLength).createRange(*scope);
988 }
989
990 unsigned Internals::locationFromRange(Element* scope, const Range* range)
991 {
992     ASSERT(scope && range);
993     // PlainTextRange depends on Layout information, make sure layout it up to date.
994     scope->document().updateLayoutIgnorePendingStylesheets();
995
996     return PlainTextRange::create(*scope, *range).start();
997 }
998
999 unsigned Internals::lengthFromRange(Element* scope, const Range* range)
1000 {
1001     ASSERT(scope && range);
1002     // PlainTextRange depends on Layout information, make sure layout it up to date.
1003     scope->document().updateLayoutIgnorePendingStylesheets();
1004
1005     return PlainTextRange::create(*scope, *range).length();
1006 }
1007
1008 String Internals::rangeAsText(const Range* range)
1009 {
1010     ASSERT(range);
1011     return range->text();
1012 }
1013
1014 // FIXME: The next four functions are very similar - combine them once
1015 // bestClickableNode/bestContextMenuNode have been combined..
1016
1017 PassRefPtrWillBeRawPtr<WebKitPoint> Internals::touchPositionAdjustedToBestClickableNode(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState)
1018 {
1019     ASSERT(document);
1020     if (!document->frame()) {
1021         exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1022         return nullptr;
1023     }
1024
1025     document->updateLayout();
1026
1027     IntSize radius(width / 2, height / 2);
1028     IntPoint point(x + radius.width(), y + radius.height());
1029
1030     EventHandler& eventHandler = document->frame()->eventHandler();
1031     IntPoint hitTestPoint = document->frame()->view()->windowToContents(point);
1032     HitTestResult result = eventHandler.hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active, radius);
1033
1034     Node* targetNode;
1035     IntPoint adjustedPoint;
1036
1037     bool foundNode = eventHandler.bestClickableNodeForHitTestResult(result, adjustedPoint, targetNode);
1038     if (foundNode)
1039         return WebKitPoint::create(adjustedPoint.x(), adjustedPoint.y());
1040
1041     return nullptr;
1042 }
1043
1044 Node* Internals::touchNodeAdjustedToBestClickableNode(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState)
1045 {
1046     ASSERT(document);
1047     if (!document->frame()) {
1048         exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1049         return 0;
1050     }
1051
1052     document->updateLayout();
1053
1054     IntSize radius(width / 2, height / 2);
1055     IntPoint point(x + radius.width(), y + radius.height());
1056
1057     EventHandler& eventHandler = document->frame()->eventHandler();
1058     IntPoint hitTestPoint = document->frame()->view()->windowToContents(point);
1059     HitTestResult result = eventHandler.hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active, radius);
1060
1061     Node* targetNode;
1062     IntPoint adjustedPoint;
1063     document->frame()->eventHandler().bestClickableNodeForHitTestResult(result, adjustedPoint, targetNode);
1064     return targetNode;
1065 }
1066
1067 PassRefPtrWillBeRawPtr<WebKitPoint> Internals::touchPositionAdjustedToBestContextMenuNode(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState)
1068 {
1069     ASSERT(document);
1070     if (!document->frame()) {
1071         exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1072         return nullptr;
1073     }
1074
1075     document->updateLayout();
1076
1077     IntSize radius(width / 2, height / 2);
1078     IntPoint point(x + radius.width(), y + radius.height());
1079
1080     EventHandler& eventHandler = document->frame()->eventHandler();
1081     IntPoint hitTestPoint = document->frame()->view()->windowToContents(point);
1082     HitTestResult result = eventHandler.hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active, radius);
1083
1084     Node* targetNode = 0;
1085     IntPoint adjustedPoint;
1086
1087     bool foundNode = eventHandler.bestContextMenuNodeForHitTestResult(result, adjustedPoint, targetNode);
1088     if (foundNode)
1089         return WebKitPoint::create(adjustedPoint.x(), adjustedPoint.y());
1090
1091     return WebKitPoint::create(x, y);
1092 }
1093
1094 Node* Internals::touchNodeAdjustedToBestContextMenuNode(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState)
1095 {
1096     ASSERT(document);
1097     if (!document->frame()) {
1098         exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1099         return 0;
1100     }
1101
1102     document->updateLayout();
1103
1104     IntSize radius(width / 2, height / 2);
1105     IntPoint point(x + radius.width(), y + radius.height());
1106
1107     EventHandler& eventHandler = document->frame()->eventHandler();
1108     IntPoint hitTestPoint = document->frame()->view()->windowToContents(point);
1109     HitTestResult result = eventHandler.hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active, radius);
1110
1111     Node* targetNode = 0;
1112     IntPoint adjustedPoint;
1113     eventHandler.bestContextMenuNodeForHitTestResult(result, adjustedPoint, targetNode);
1114     return targetNode;
1115 }
1116
1117 PassRefPtrWillBeRawPtr<ClientRect> Internals::bestZoomableAreaForTouchPoint(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState)
1118 {
1119     ASSERT(document);
1120     if (!document->frame()) {
1121         exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1122         return nullptr;
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     IntRect zoomableArea;
1132     bool foundNode = document->frame()->eventHandler().bestZoomableAreaForTouchPoint(point, radius, zoomableArea, targetNode);
1133     if (foundNode)
1134         return ClientRect::create(zoomableArea);
1135
1136     return nullptr;
1137 }
1138
1139
1140 int Internals::lastSpellCheckRequestSequence(Document* document, ExceptionState& exceptionState)
1141 {
1142     SpellCheckRequester* requester = spellCheckRequester(document);
1143
1144     if (!requester) {
1145         exceptionState.throwDOMException(InvalidAccessError, "No spell check requestor can be obtained for the provided document.");
1146         return -1;
1147     }
1148
1149     return requester->lastRequestSequence();
1150 }
1151
1152 int Internals::lastSpellCheckProcessedSequence(Document* document, ExceptionState& exceptionState)
1153 {
1154     SpellCheckRequester* requester = spellCheckRequester(document);
1155
1156     if (!requester) {
1157         exceptionState.throwDOMException(InvalidAccessError, "No spell check requestor can be obtained for the provided document.");
1158         return -1;
1159     }
1160
1161     return requester->lastProcessedSequence();
1162 }
1163
1164 Vector<AtomicString> Internals::userPreferredLanguages() const
1165 {
1166     return blink::userPreferredLanguages();
1167 }
1168
1169 // Optimally, the bindings generator would pass a Vector<AtomicString> here but
1170 // this is not supported yet.
1171 void Internals::setUserPreferredLanguages(const Vector<String>& languages)
1172 {
1173     Vector<AtomicString> atomicLanguages;
1174     for (size_t i = 0; i < languages.size(); ++i)
1175         atomicLanguages.append(AtomicString(languages[i]));
1176     blink::overrideUserPreferredLanguages(atomicLanguages);
1177 }
1178
1179 unsigned Internals::activeDOMObjectCount(Document* document)
1180 {
1181     ASSERT(document);
1182     return document->activeDOMObjectCount();
1183 }
1184
1185 static unsigned eventHandlerCount(Document& document, EventHandlerRegistry::EventHandlerClass handlerClass)
1186 {
1187     if (!document.frameHost())
1188         return 0;
1189     EventHandlerRegistry* registry = &document.frameHost()->eventHandlerRegistry();
1190     unsigned count = 0;
1191     const EventTargetSet* targets = registry->eventHandlerTargets(handlerClass);
1192     if (targets) {
1193         for (EventTargetSet::const_iterator iter = targets->begin(); iter != targets->end(); ++iter)
1194             count += iter->value;
1195     }
1196     return count;
1197 }
1198
1199 unsigned Internals::wheelEventHandlerCount(Document* document)
1200 {
1201     ASSERT(document);
1202     return eventHandlerCount(*document, EventHandlerRegistry::WheelEvent);
1203 }
1204
1205 unsigned Internals::scrollEventHandlerCount(Document* document)
1206 {
1207     ASSERT(document);
1208     return eventHandlerCount(*document, EventHandlerRegistry::ScrollEvent);
1209 }
1210
1211 unsigned Internals::touchEventHandlerCount(Document* document)
1212 {
1213     ASSERT(document);
1214     return eventHandlerCount(*document, EventHandlerRegistry::TouchEvent);
1215 }
1216
1217 static RenderLayer* findRenderLayerForGraphicsLayer(RenderLayer* searchRoot, GraphicsLayer* graphicsLayer, IntSize* layerOffset, String* layerType)
1218 {
1219     *layerOffset = IntSize();
1220     if (searchRoot->hasCompositedLayerMapping() && graphicsLayer == searchRoot->compositedLayerMapping()->mainGraphicsLayer()) {
1221         LayoutRect rect;
1222         RenderLayer::mapRectToPaintBackingCoordinates(searchRoot->renderer(), rect);
1223         *layerOffset = IntSize(rect.x(), rect.y());
1224         return searchRoot;
1225     }
1226
1227     GraphicsLayer* layerForScrolling = searchRoot->scrollableArea() ? searchRoot->scrollableArea()->layerForScrolling() : 0;
1228     if (graphicsLayer == layerForScrolling) {
1229         *layerType = "scrolling";
1230         return searchRoot;
1231     }
1232
1233     if (searchRoot->compositingState() == PaintsIntoGroupedBacking) {
1234         GraphicsLayer* squashingLayer = searchRoot->groupedMapping()->squashingLayer();
1235         if (graphicsLayer == squashingLayer) {
1236             *layerType ="squashing";
1237             LayoutRect rect;
1238             RenderLayer::mapRectToPaintBackingCoordinates(searchRoot->renderer(), rect);
1239             *layerOffset = IntSize(rect.x(), rect.y());
1240             return searchRoot;
1241         }
1242     }
1243
1244     GraphicsLayer* layerForHorizontalScrollbar = searchRoot->scrollableArea() ? searchRoot->scrollableArea()->layerForHorizontalScrollbar() : 0;
1245     if (graphicsLayer == layerForHorizontalScrollbar) {
1246         *layerType = "horizontalScrollbar";
1247         return searchRoot;
1248     }
1249
1250     GraphicsLayer* layerForVerticalScrollbar = searchRoot->scrollableArea() ? searchRoot->scrollableArea()->layerForVerticalScrollbar() : 0;
1251     if (graphicsLayer == layerForVerticalScrollbar) {
1252         *layerType = "verticalScrollbar";
1253         return searchRoot;
1254     }
1255
1256     GraphicsLayer* layerForScrollCorner = searchRoot->scrollableArea() ? searchRoot->scrollableArea()->layerForScrollCorner() : 0;
1257     if (graphicsLayer == layerForScrollCorner) {
1258         *layerType = "scrollCorner";
1259         return searchRoot;
1260     }
1261
1262     // Search right to left to increase the chances that we'll choose the top-most layers in a
1263     // grouped mapping for squashing.
1264     for (RenderLayer* child = searchRoot->lastChild(); child; child = child->previousSibling()) {
1265         RenderLayer* foundLayer = findRenderLayerForGraphicsLayer(child, graphicsLayer, layerOffset, layerType);
1266         if (foundLayer)
1267             return foundLayer;
1268     }
1269
1270     return 0;
1271 }
1272
1273 // Given a vector of rects, merge those that are adjacent, leaving empty rects
1274 // in the place of no longer used slots. This is intended to simplify the list
1275 // of rects returned by an SkRegion (which have been split apart for sorting
1276 // purposes). No attempt is made to do this efficiently (eg. by relying on the
1277 // sort criteria of SkRegion).
1278 static void mergeRects(blink::WebVector<blink::WebRect>& rects)
1279 {
1280     for (size_t i = 0; i < rects.size(); ++i) {
1281         if (rects[i].isEmpty())
1282             continue;
1283         bool updated;
1284         do {
1285             updated = false;
1286             for (size_t j = i+1; j < rects.size(); ++j) {
1287                 if (rects[j].isEmpty())
1288                     continue;
1289                 // Try to merge rects[j] into rects[i] along the 4 possible edges.
1290                 if (rects[i].y == rects[j].y && rects[i].height == rects[j].height) {
1291                     if (rects[i].x + rects[i].width == rects[j].x) {
1292                         rects[i].width += rects[j].width;
1293                         rects[j] = blink::WebRect();
1294                         updated = true;
1295                     } else if (rects[i].x == rects[j].x + rects[j].width) {
1296                         rects[i].x = rects[j].x;
1297                         rects[i].width += rects[j].width;
1298                         rects[j] = blink::WebRect();
1299                         updated = true;
1300                     }
1301                 } else if (rects[i].x == rects[j].x && rects[i].width == rects[j].width) {
1302                     if (rects[i].y + rects[i].height == rects[j].y) {
1303                         rects[i].height += rects[j].height;
1304                         rects[j] = blink::WebRect();
1305                         updated = true;
1306                     } else if (rects[i].y == rects[j].y + rects[j].height) {
1307                         rects[i].y = rects[j].y;
1308                         rects[i].height += rects[j].height;
1309                         rects[j] = blink::WebRect();
1310                         updated = true;
1311                     }
1312                 }
1313             }
1314         } while (updated);
1315     }
1316 }
1317
1318 static void accumulateLayerRectList(RenderLayerCompositor* compositor, GraphicsLayer* graphicsLayer, LayerRectList* rects)
1319 {
1320     blink::WebVector<blink::WebRect> layerRects = graphicsLayer->platformLayer()->touchEventHandlerRegion();
1321     if (!layerRects.isEmpty()) {
1322         mergeRects(layerRects);
1323         String layerType;
1324         IntSize layerOffset;
1325         RenderLayer* renderLayer = findRenderLayerForGraphicsLayer(compositor->rootRenderLayer(), graphicsLayer, &layerOffset, &layerType);
1326         Node* node = renderLayer ? renderLayer->renderer()->node() : 0;
1327         for (size_t i = 0; i < layerRects.size(); ++i) {
1328             if (!layerRects[i].isEmpty()) {
1329                 rects->append(node, layerType, layerOffset.width(), layerOffset.height(), ClientRect::create(layerRects[i]));
1330             }
1331         }
1332     }
1333
1334     size_t numChildren = graphicsLayer->children().size();
1335     for (size_t i = 0; i < numChildren; ++i)
1336         accumulateLayerRectList(compositor, graphicsLayer->children()[i], rects);
1337 }
1338
1339 PassRefPtrWillBeRawPtr<LayerRectList> Internals::touchEventTargetLayerRects(Document* document, ExceptionState& exceptionState)
1340 {
1341     ASSERT(document);
1342     if (!document->view() || !document->page() || document != contextDocument()) {
1343         exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1344         return nullptr;
1345     }
1346
1347     // Do any pending layout and compositing update (which may call touchEventTargetRectsChange) to ensure this
1348     // really takes any previous changes into account.
1349     forceCompositingUpdate(document, exceptionState);
1350     if (exceptionState.hadException())
1351         return nullptr;
1352
1353     if (RenderView* view = document->renderView()) {
1354         if (RenderLayerCompositor* compositor = view->compositor()) {
1355             if (GraphicsLayer* rootLayer = compositor->rootGraphicsLayer()) {
1356                 RefPtrWillBeRawPtr<LayerRectList> rects = LayerRectList::create();
1357                 accumulateLayerRectList(compositor, rootLayer, rects.get());
1358                 return rects;
1359             }
1360         }
1361     }
1362
1363     return nullptr;
1364 }
1365
1366 PassRefPtrWillBeRawPtr<StaticNodeList> Internals::nodesFromRect(Document* document, int centerX, int centerY, unsigned topPadding, unsigned rightPadding,
1367     unsigned bottomPadding, unsigned leftPadding, bool ignoreClipping, bool allowChildFrameContent, ExceptionState& exceptionState) const
1368 {
1369     ASSERT(document);
1370     if (!document->frame() || !document->frame()->view()) {
1371         exceptionState.throwDOMException(InvalidAccessError, "No view can be obtained from the provided document.");
1372         return nullptr;
1373     }
1374
1375     LocalFrame* frame = document->frame();
1376     FrameView* frameView = document->view();
1377     RenderView* renderView = document->renderView();
1378
1379     if (!renderView)
1380         return nullptr;
1381
1382     float zoomFactor = frame->pageZoomFactor();
1383     LayoutPoint point = roundedLayoutPoint(FloatPoint(centerX * zoomFactor + frameView->scrollX(), centerY * zoomFactor + frameView->scrollY()));
1384
1385     HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active;
1386     if (ignoreClipping)
1387         hitType |= HitTestRequest::IgnoreClipping;
1388     if (allowChildFrameContent)
1389         hitType |= HitTestRequest::AllowChildFrameContent;
1390
1391     HitTestRequest request(hitType);
1392
1393     // When ignoreClipping is false, this method returns null for coordinates outside of the viewport.
1394     if (!request.ignoreClipping() && !frameView->visibleContentRect().intersects(HitTestLocation::rectForPoint(point, topPadding, rightPadding, bottomPadding, leftPadding)))
1395         return nullptr;
1396
1397     WillBeHeapVector<RefPtrWillBeMember<Node> > matches;
1398
1399     // Need padding to trigger a rect based hit test, but we want to return a NodeList
1400     // so we special case this.
1401     if (!topPadding && !rightPadding && !bottomPadding && !leftPadding) {
1402         HitTestResult result(point);
1403         renderView->hitTest(request, result);
1404
1405         if (Node* innerNode = result.innerNode()) {
1406             if (innerNode->isInShadowTree())
1407                 innerNode = innerNode->shadowHost();
1408             matches.append(innerNode);
1409         }
1410     } else {
1411         HitTestResult result(point, topPadding, rightPadding, bottomPadding, leftPadding);
1412         renderView->hitTest(request, result);
1413         copyToVector(result.rectBasedTestResult(), matches);
1414     }
1415
1416     return StaticNodeList::adopt(matches);
1417 }
1418
1419 void Internals::emitInspectorDidBeginFrame(int frameId)
1420 {
1421     contextDocument()->page()->inspectorController().didBeginFrame(frameId);
1422 }
1423
1424 void Internals::emitInspectorDidCancelFrame()
1425 {
1426     contextDocument()->page()->inspectorController().didCancelFrame();
1427 }
1428
1429 bool Internals::hasSpellingMarker(Document* document, int from, int length)
1430 {
1431     ASSERT(document);
1432     if (!document->frame())
1433         return 0;
1434
1435     return document->frame()->spellChecker().selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
1436 }
1437
1438 void Internals::setContinuousSpellCheckingEnabled(bool enabled)
1439 {
1440     if (!contextDocument() || !contextDocument()->frame())
1441         return;
1442
1443     if (enabled != contextDocument()->frame()->spellChecker().isContinuousSpellCheckingEnabled())
1444         contextDocument()->frame()->spellChecker().toggleContinuousSpellChecking();
1445 }
1446
1447 bool Internals::isOverwriteModeEnabled(Document* document)
1448 {
1449     ASSERT(document);
1450     if (!document->frame())
1451         return 0;
1452
1453     return document->frame()->editor().isOverwriteModeEnabled();
1454 }
1455
1456 void Internals::toggleOverwriteModeEnabled(Document* document)
1457 {
1458     ASSERT(document);
1459     if (!document->frame())
1460         return;
1461
1462     document->frame()->editor().toggleOverwriteModeEnabled();
1463 }
1464
1465 unsigned Internals::numberOfLiveNodes() const
1466 {
1467     return InspectorCounters::counterValue(InspectorCounters::NodeCounter);
1468 }
1469
1470 unsigned Internals::numberOfLiveDocuments() const
1471 {
1472     return InspectorCounters::counterValue(InspectorCounters::DocumentCounter);
1473 }
1474
1475 String Internals::dumpRefCountedInstanceCounts() const
1476 {
1477     return WTF::dumpRefCountedInstanceCounts();
1478 }
1479
1480 Vector<String> Internals::consoleMessageArgumentCounts(Document* document) const
1481 {
1482     InstrumentingAgents* instrumentingAgents = instrumentationForPage(document->page());
1483     if (!instrumentingAgents)
1484         return Vector<String>();
1485     InspectorConsoleAgent* consoleAgent = instrumentingAgents->inspectorConsoleAgent();
1486     if (!consoleAgent)
1487         return Vector<String>();
1488     Vector<unsigned> counts = consoleAgent->consoleMessageArgumentCounts();
1489     Vector<String> result(counts.size());
1490     for (size_t i = 0; i < counts.size(); i++)
1491         result[i] = String::number(counts[i]);
1492     return result;
1493 }
1494
1495 Vector<unsigned long> Internals::setMemoryCacheCapacities(unsigned long minDeadBytes, unsigned long maxDeadBytes, unsigned long totalBytes)
1496 {
1497     Vector<unsigned long> result;
1498     result.append(memoryCache()->minDeadCapacity());
1499     result.append(memoryCache()->maxDeadCapacity());
1500     result.append(memoryCache()->capacity());
1501     memoryCache()->setCapacities(minDeadBytes, maxDeadBytes, totalBytes);
1502     return result;
1503 }
1504
1505 void Internals::setInspectorResourcesDataSizeLimits(int maximumResourcesContentSize, int maximumSingleResourceContentSize, ExceptionState& exceptionState)
1506 {
1507     Page* page = contextDocument()->frame()->page();
1508     if (!page) {
1509         exceptionState.throwDOMException(InvalidAccessError, "No page can be obtained from the current context document.");
1510         return;
1511     }
1512     page->inspectorController().setResourcesDataSizeLimitsFromInternals(maximumResourcesContentSize, maximumSingleResourceContentSize);
1513 }
1514
1515 bool Internals::hasGrammarMarker(Document* document, int from, int length)
1516 {
1517     ASSERT(document);
1518     if (!document->frame())
1519         return 0;
1520
1521     return document->frame()->spellChecker().selectionStartHasMarkerFor(DocumentMarker::Grammar, from, length);
1522 }
1523
1524 unsigned Internals::numberOfScrollableAreas(Document* document)
1525 {
1526     ASSERT(document);
1527     if (!document->frame())
1528         return 0;
1529
1530     unsigned count = 0;
1531     LocalFrame* frame = document->frame();
1532     if (frame->view()->scrollableAreas())
1533         count += frame->view()->scrollableAreas()->size();
1534
1535     for (Frame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
1536         if (child->isLocalFrame() && toLocalFrame(child)->view() && toLocalFrame(child)->view()->scrollableAreas())
1537             count += toLocalFrame(child)->view()->scrollableAreas()->size();
1538     }
1539
1540     return count;
1541 }
1542
1543 bool Internals::isPageBoxVisible(Document* document, int pageNumber)
1544 {
1545     ASSERT(document);
1546     return document->isPageBoxVisible(pageNumber);
1547 }
1548
1549 String Internals::layerTreeAsText(Document* document, ExceptionState& exceptionState) const
1550 {
1551     return layerTreeAsText(document, 0, exceptionState);
1552 }
1553
1554 String Internals::elementLayerTreeAsText(Element* element, ExceptionState& exceptionState) const
1555 {
1556     ASSERT(element);
1557     FrameView* frameView = element->document().view();
1558     frameView->updateLayoutAndStyleForPainting();
1559
1560     return elementLayerTreeAsText(element, 0, exceptionState);
1561 }
1562
1563 bool Internals::scrollsWithRespectTo(Element* element1, Element* element2, ExceptionState& exceptionState)
1564 {
1565     ASSERT(element1 && element2);
1566     element1->document().view()->updateLayoutAndStyleForPainting();
1567
1568     RenderObject* renderer1 = element1->renderer();
1569     RenderObject* renderer2 = element2->renderer();
1570     if (!renderer1 || !renderer1->isBox()) {
1571         exceptionState.throwDOMException(InvalidAccessError, renderer1 ? "The first provided element's renderer is not a box." : "The first provided element has no renderer.");
1572         return 0;
1573     }
1574     if (!renderer2 || !renderer2->isBox()) {
1575         exceptionState.throwDOMException(InvalidAccessError, renderer2 ? "The second provided element's renderer is not a box." : "The second provided element has no renderer.");
1576         return 0;
1577     }
1578
1579     RenderLayer* layer1 = toRenderBox(renderer1)->layer();
1580     RenderLayer* layer2 = toRenderBox(renderer2)->layer();
1581     if (!layer1 || !layer2) {
1582         exceptionState.throwDOMException(InvalidAccessError, String::format("No render layer can be obtained from the %s provided element.", layer1 ? "second" : "first"));
1583         return 0;
1584     }
1585
1586     return layer1->scrollsWithRespectTo(layer2);
1587 }
1588
1589 bool Internals::isUnclippedDescendant(Element* element, ExceptionState& exceptionState)
1590 {
1591     ASSERT(element);
1592     element->document().view()->updateLayoutAndStyleForPainting();
1593
1594     RenderObject* renderer = element->renderer();
1595     if (!renderer || !renderer->isBox()) {
1596         exceptionState.throwDOMException(InvalidAccessError, renderer ? "The provided element's renderer is not a box." : "The provided element has no renderer.");
1597         return 0;
1598     }
1599
1600     RenderLayer* layer = toRenderBox(renderer)->layer();
1601     if (!layer) {
1602         exceptionState.throwDOMException(InvalidAccessError, "No render layer can be obtained from the provided element.");
1603         return 0;
1604     }
1605
1606     // We used to compute isUnclippedDescendant only when acceleratedCompositingForOverflowScrollEnabled,
1607     // but now we compute it all the time.
1608     // FIXME: Remove this if statement and rebaseline the tests that make this assumption.
1609     if (!layer->compositor()->acceleratedCompositingForOverflowScrollEnabled())
1610         return false;
1611
1612     return layer->isUnclippedDescendant();
1613 }
1614
1615 String Internals::layerTreeAsText(Document* document, unsigned flags, ExceptionState& exceptionState) const
1616 {
1617     ASSERT(document);
1618     if (!document->frame()) {
1619         exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1620         return String();
1621     }
1622
1623     document->view()->updateLayoutAndStyleForPainting();
1624
1625     return document->frame()->layerTreeAsText(flags);
1626 }
1627
1628 String Internals::elementLayerTreeAsText(Element* element, unsigned flags, ExceptionState& exceptionState) const
1629 {
1630     ASSERT(element);
1631     element->document().updateLayout();
1632
1633     RenderObject* renderer = element->renderer();
1634     if (!renderer || !renderer->isBox()) {
1635         exceptionState.throwDOMException(InvalidAccessError, renderer ? "The provided element's renderer is not a box." : "The provided element has no renderer.");
1636         return String();
1637     }
1638
1639     RenderLayer* layer = toRenderBox(renderer)->layer();
1640     if (!layer
1641         || !layer->hasCompositedLayerMapping()
1642         || !layer->compositedLayerMapping()->mainGraphicsLayer()) {
1643         // Don't raise exception in these cases which may be normally used in tests.
1644         return String();
1645     }
1646
1647     return layer->compositedLayerMapping()->mainGraphicsLayer()->layerTreeAsText(flags);
1648 }
1649
1650 String Internals::scrollingStateTreeAsText(Document*) const
1651 {
1652     return String();
1653 }
1654
1655 String Internals::mainThreadScrollingReasons(Document* document, ExceptionState& exceptionState) const
1656 {
1657     ASSERT(document);
1658     if (!document->frame()) {
1659         exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1660         return String();
1661     }
1662
1663     document->frame()->view()->updateLayoutAndStyleForPainting();
1664
1665     Page* page = document->page();
1666     if (!page)
1667         return String();
1668
1669     return page->mainThreadScrollingReasonsAsText();
1670 }
1671
1672 PassRefPtrWillBeRawPtr<ClientRectList> Internals::nonFastScrollableRects(Document* document, ExceptionState& exceptionState) const
1673 {
1674     ASSERT(document);
1675     if (!document->frame()) {
1676         exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1677         return nullptr;
1678     }
1679
1680     Page* page = document->page();
1681     if (!page)
1682         return nullptr;
1683
1684     return page->nonFastScrollableRects(document->frame());
1685 }
1686
1687 void Internals::garbageCollectDocumentResources(Document* document) const
1688 {
1689     ASSERT(document);
1690     ResourceFetcher* fetcher = document->fetcher();
1691     if (!fetcher)
1692         return;
1693     fetcher->garbageCollectDocumentResources();
1694 }
1695
1696 void Internals::evictAllResources() const
1697 {
1698     memoryCache()->evictResources();
1699 }
1700
1701 String Internals::counterValue(Element* element)
1702 {
1703     if (!element)
1704         return String();
1705
1706     return counterValueForElement(element);
1707 }
1708
1709 int Internals::pageNumber(Element* element, float pageWidth, float pageHeight)
1710 {
1711     if (!element)
1712         return 0;
1713
1714     return PrintContext::pageNumberForElement(element, FloatSize(pageWidth, pageHeight));
1715 }
1716
1717 Vector<String> Internals::iconURLs(Document* document, int iconTypesMask) const
1718 {
1719     Vector<IconURL> iconURLs = document->iconURLs(iconTypesMask);
1720     Vector<String> array;
1721
1722     Vector<IconURL>::const_iterator iter(iconURLs.begin());
1723     for (; iter != iconURLs.end(); ++iter)
1724         array.append(iter->m_iconURL.string());
1725
1726     return array;
1727 }
1728
1729 Vector<String> Internals::shortcutIconURLs(Document* document) const
1730 {
1731     return iconURLs(document, Favicon);
1732 }
1733
1734 Vector<String> Internals::allIconURLs(Document* document) const
1735 {
1736     return iconURLs(document, Favicon | TouchIcon | TouchPrecomposedIcon);
1737 }
1738
1739 int Internals::numberOfPages(float pageWidth, float pageHeight)
1740 {
1741     if (!frame())
1742         return -1;
1743
1744     return PrintContext::numberOfPages(frame(), FloatSize(pageWidth, pageHeight));
1745 }
1746
1747 String Internals::pageProperty(String propertyName, int pageNumber, ExceptionState& exceptionState) const
1748 {
1749     if (!frame()) {
1750         exceptionState.throwDOMException(InvalidAccessError, "No frame is available.");
1751         return String();
1752     }
1753
1754     return PrintContext::pageProperty(frame(), propertyName.utf8().data(), pageNumber);
1755 }
1756
1757 String Internals::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft, ExceptionState& exceptionState) const
1758 {
1759     if (!frame()) {
1760         exceptionState.throwDOMException(InvalidAccessError, "No frame is available.");
1761         return String();
1762     }
1763
1764     return PrintContext::pageSizeAndMarginsInPixels(frame(), pageNumber, width, height, marginTop, marginRight, marginBottom, marginLeft);
1765 }
1766
1767 void Internals::setDeviceScaleFactor(float scaleFactor, ExceptionState& exceptionState)
1768 {
1769     Document* document = contextDocument();
1770     if (!document || !document->page()) {
1771         exceptionState.throwDOMException(InvalidAccessError, document ? "The document's page cannot be retrieved." : "No context document can be obtained.");
1772         return;
1773     }
1774     Page* page = document->page();
1775     page->setDeviceScaleFactor(scaleFactor);
1776 }
1777
1778 void Internals::setIsCursorVisible(Document* document, bool isVisible, ExceptionState& exceptionState)
1779 {
1780     ASSERT(document);
1781     if (!document->page()) {
1782         exceptionState.throwDOMException(InvalidAccessError, "No context document can be obtained.");
1783         return;
1784     }
1785     document->page()->setIsCursorVisible(isVisible);
1786 }
1787
1788 void Internals::mediaPlayerRequestFullscreen(HTMLMediaElement* mediaElement)
1789 {
1790     mediaElement->mediaPlayerRequestFullscreen();
1791 }
1792
1793 double Internals::effectiveMediaVolume(HTMLMediaElement* mediaElement)
1794 {
1795     return mediaElement->effectiveMediaVolume();
1796 }
1797
1798 void Internals::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme)
1799 {
1800     SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
1801 }
1802
1803 void Internals::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(const String& scheme)
1804 {
1805     SchemeRegistry::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(scheme);
1806 }
1807
1808 PassRefPtrWillBeRawPtr<TypeConversions> Internals::typeConversions() const
1809 {
1810     return TypeConversions::create();
1811 }
1812
1813 PrivateScriptTest* Internals::privateScriptTest() const
1814 {
1815     return PrivateScriptTest::create(frame());
1816 }
1817
1818 Vector<String> Internals::getReferencedFilePaths() const
1819 {
1820     return frame()->loader().currentItem()->getReferencedFilePaths();
1821 }
1822
1823 void Internals::startTrackingRepaints(Document* document, ExceptionState& exceptionState)
1824 {
1825     ASSERT(document);
1826     if (!document->view()) {
1827         exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1828         return;
1829     }
1830
1831     FrameView* frameView = document->view();
1832     frameView->updateLayoutAndStyleForPainting();
1833     frameView->setTracksPaintInvalidations(true);
1834 }
1835
1836 void Internals::stopTrackingRepaints(Document* document, ExceptionState& exceptionState)
1837 {
1838     ASSERT(document);
1839     if (!document->view()) {
1840         exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1841         return;
1842     }
1843
1844     FrameView* frameView = document->view();
1845     frameView->updateLayoutAndStyleForPainting();
1846     frameView->setTracksPaintInvalidations(false);
1847 }
1848
1849 void Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(ExceptionState& exceptionState)
1850 {
1851     updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(0, exceptionState);
1852 }
1853
1854 void Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(Node* node, ExceptionState& exceptionState)
1855 {
1856     Document* document;
1857     if (!node) {
1858         document = contextDocument();
1859     } else if (node->isDocumentNode()) {
1860         document = toDocument(node);
1861     } else if (isHTMLIFrameElement(*node)) {
1862         document = toHTMLIFrameElement(*node).contentDocument();
1863     } else {
1864         exceptionState.throwTypeError("The node provided is neither a document nor an IFrame.");
1865         return;
1866     }
1867     document->updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasksSynchronously);
1868 }
1869
1870 void Internals::forceFullRepaint(Document* document, ExceptionState& exceptionState)
1871 {
1872     ASSERT(document);
1873     if (!document->view()) {
1874         exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1875         return;
1876     }
1877
1878     if (RenderView *renderView = document->renderView())
1879         renderView->invalidatePaintForViewAndCompositedLayers();
1880 }
1881
1882 PassRefPtrWillBeRawPtr<ClientRectList> Internals::draggableRegions(Document* document, ExceptionState& exceptionState)
1883 {
1884     return annotatedRegions(document, true, exceptionState);
1885 }
1886
1887 PassRefPtrWillBeRawPtr<ClientRectList> Internals::nonDraggableRegions(Document* document, ExceptionState& exceptionState)
1888 {
1889     return annotatedRegions(document, false, exceptionState);
1890 }
1891
1892 PassRefPtrWillBeRawPtr<ClientRectList> Internals::annotatedRegions(Document* document, bool draggable, ExceptionState& exceptionState)
1893 {
1894     ASSERT(document);
1895     if (!document->view()) {
1896         exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1897         return ClientRectList::create();
1898     }
1899
1900     document->updateLayout();
1901     document->view()->updateAnnotatedRegions();
1902     Vector<AnnotatedRegionValue> regions = document->annotatedRegions();
1903
1904     Vector<FloatQuad> quads;
1905     for (size_t i = 0; i < regions.size(); ++i) {
1906         if (regions[i].draggable == draggable)
1907             quads.append(FloatQuad(regions[i].bounds));
1908     }
1909     return ClientRectList::create(quads);
1910 }
1911
1912 static const char* cursorTypeToString(Cursor::Type cursorType)
1913 {
1914     switch (cursorType) {
1915     case Cursor::Pointer: return "Pointer";
1916     case Cursor::Cross: return "Cross";
1917     case Cursor::Hand: return "Hand";
1918     case Cursor::IBeam: return "IBeam";
1919     case Cursor::Wait: return "Wait";
1920     case Cursor::Help: return "Help";
1921     case Cursor::EastResize: return "EastResize";
1922     case Cursor::NorthResize: return "NorthResize";
1923     case Cursor::NorthEastResize: return "NorthEastResize";
1924     case Cursor::NorthWestResize: return "NorthWestResize";
1925     case Cursor::SouthResize: return "SouthResize";
1926     case Cursor::SouthEastResize: return "SouthEastResize";
1927     case Cursor::SouthWestResize: return "SouthWestResize";
1928     case Cursor::WestResize: return "WestResize";
1929     case Cursor::NorthSouthResize: return "NorthSouthResize";
1930     case Cursor::EastWestResize: return "EastWestResize";
1931     case Cursor::NorthEastSouthWestResize: return "NorthEastSouthWestResize";
1932     case Cursor::NorthWestSouthEastResize: return "NorthWestSouthEastResize";
1933     case Cursor::ColumnResize: return "ColumnResize";
1934     case Cursor::RowResize: return "RowResize";
1935     case Cursor::MiddlePanning: return "MiddlePanning";
1936     case Cursor::EastPanning: return "EastPanning";
1937     case Cursor::NorthPanning: return "NorthPanning";
1938     case Cursor::NorthEastPanning: return "NorthEastPanning";
1939     case Cursor::NorthWestPanning: return "NorthWestPanning";
1940     case Cursor::SouthPanning: return "SouthPanning";
1941     case Cursor::SouthEastPanning: return "SouthEastPanning";
1942     case Cursor::SouthWestPanning: return "SouthWestPanning";
1943     case Cursor::WestPanning: return "WestPanning";
1944     case Cursor::Move: return "Move";
1945     case Cursor::VerticalText: return "VerticalText";
1946     case Cursor::Cell: return "Cell";
1947     case Cursor::ContextMenu: return "ContextMenu";
1948     case Cursor::Alias: return "Alias";
1949     case Cursor::Progress: return "Progress";
1950     case Cursor::NoDrop: return "NoDrop";
1951     case Cursor::Copy: return "Copy";
1952     case Cursor::None: return "None";
1953     case Cursor::NotAllowed: return "NotAllowed";
1954     case Cursor::ZoomIn: return "ZoomIn";
1955     case Cursor::ZoomOut: return "ZoomOut";
1956     case Cursor::Grab: return "Grab";
1957     case Cursor::Grabbing: return "Grabbing";
1958     case Cursor::Custom: return "Custom";
1959     }
1960
1961     ASSERT_NOT_REACHED();
1962     return "UNKNOWN";
1963 }
1964
1965 String Internals::getCurrentCursorInfo(Document* document, ExceptionState& exceptionState)
1966 {
1967     ASSERT(document);
1968     if (!document->frame()) {
1969         exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1970         return String();
1971     }
1972
1973     Cursor cursor = document->frame()->eventHandler().currentMouseCursor();
1974
1975     StringBuilder result;
1976     result.append("type=");
1977     result.append(cursorTypeToString(cursor.type()));
1978     result.append(" hotSpot=");
1979     result.appendNumber(cursor.hotSpot().x());
1980     result.append(",");
1981     result.appendNumber(cursor.hotSpot().y());
1982     if (cursor.image()) {
1983         IntSize size = cursor.image()->size();
1984         result.append(" image=");
1985         result.appendNumber(size.width());
1986         result.append("x");
1987         result.appendNumber(size.height());
1988     }
1989     if (cursor.imageScaleFactor() != 1) {
1990         result.append(" scale=");
1991         NumberToStringBuffer buffer;
1992         result.append(numberToFixedPrecisionString(cursor.imageScaleFactor(), 8, buffer, true));
1993     }
1994
1995     return result.toString();
1996 }
1997
1998 PassRefPtr<ArrayBuffer> Internals::serializeObject(PassRefPtr<SerializedScriptValue> value) const
1999 {
2000     String stringValue = value->toWireString();
2001     RefPtr<ArrayBuffer> buffer = ArrayBuffer::createUninitialized(stringValue.length(), sizeof(UChar));
2002     stringValue.copyTo(static_cast<UChar*>(buffer->data()), 0, stringValue.length());
2003     return buffer.release();
2004 }
2005
2006 PassRefPtr<SerializedScriptValue> Internals::deserializeBuffer(PassRefPtr<ArrayBuffer> buffer) const
2007 {
2008     String value(static_cast<const UChar*>(buffer->data()), buffer->byteLength() / sizeof(UChar));
2009     return SerializedScriptValue::createFromWire(value);
2010 }
2011
2012 void Internals::forceReload(bool endToEnd)
2013 {
2014     frame()->loader().reload(endToEnd ? EndToEndReload : NormalReload);
2015 }
2016
2017 PassRefPtrWillBeRawPtr<ClientRect> Internals::selectionBounds(ExceptionState& exceptionState)
2018 {
2019     Document* document = contextDocument();
2020     if (!document || !document->frame()) {
2021         exceptionState.throwDOMException(InvalidAccessError, document ? "The document's frame cannot be retrieved." : "No context document can be obtained.");
2022         return nullptr;
2023     }
2024
2025     return ClientRect::create(document->frame()->selection().bounds());
2026 }
2027
2028 String Internals::markerTextForListItem(Element* element)
2029 {
2030     ASSERT(element);
2031     return blink::markerTextForListItem(element);
2032 }
2033
2034 String Internals::getImageSourceURL(Element* element)
2035 {
2036     ASSERT(element);
2037     return element->imageSourceURL();
2038 }
2039
2040 String Internals::baseURL(Document* document)
2041 {
2042     ASSERT(document);
2043     return document->baseURL().string();
2044 }
2045
2046 bool Internals::isSelectPopupVisible(Node* node)
2047 {
2048     ASSERT(node);
2049     if (!isHTMLSelectElement(*node))
2050         return false;
2051
2052     HTMLSelectElement& select = toHTMLSelectElement(*node);
2053
2054     RenderObject* renderer = select.renderer();
2055     if (!renderer || !renderer->isMenuList())
2056         return false;
2057
2058     RenderMenuList* menuList = toRenderMenuList(renderer);
2059     return menuList->popupIsVisible();
2060 }
2061
2062 bool Internals::selectPopupItemStyleIsRtl(Node* node, int itemIndex)
2063 {
2064     if (!node || !isHTMLSelectElement(*node))
2065         return false;
2066
2067     HTMLSelectElement& select = toHTMLSelectElement(*node);
2068
2069     RenderObject* renderer = select.renderer();
2070     if (!renderer || !renderer->isMenuList())
2071         return false;
2072
2073     RenderMenuList& menuList = toRenderMenuList(*renderer);
2074     PopupMenuStyle itemStyle = menuList.itemStyle(itemIndex);
2075     return itemStyle.textDirection() == RTL;
2076 }
2077
2078 int Internals::selectPopupItemStyleFontHeight(Node* node, int itemIndex)
2079 {
2080     if (!node || !isHTMLSelectElement(*node))
2081         return false;
2082
2083     HTMLSelectElement& select = toHTMLSelectElement(*node);
2084
2085     RenderObject* renderer = select.renderer();
2086     if (!renderer || !renderer->isMenuList())
2087         return false;
2088
2089     RenderMenuList& menuList = toRenderMenuList(*renderer);
2090     PopupMenuStyle itemStyle = menuList.itemStyle(itemIndex);
2091     return itemStyle.font().fontMetrics().height();
2092 }
2093
2094 bool Internals::loseSharedGraphicsContext3D()
2095 {
2096     OwnPtr<blink::WebGraphicsContext3DProvider> sharedProvider = adoptPtr(blink::Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
2097     if (!sharedProvider)
2098         return false;
2099     blink::WebGraphicsContext3D* sharedContext = sharedProvider->context3d();
2100     sharedContext->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_EXT, GL_INNOCENT_CONTEXT_RESET_EXT);
2101     // To prevent tests that call loseSharedGraphicsContext3D from being
2102     // flaky, we call finish so that the context is guaranteed to be lost
2103     // synchronously (i.e. before returning).
2104     sharedContext->finish();
2105     return true;
2106 }
2107
2108 void Internals::forceCompositingUpdate(Document* document, ExceptionState& exceptionState)
2109 {
2110     ASSERT(document);
2111     if (!document->renderView()) {
2112         exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
2113         return;
2114     }
2115
2116     document->frame()->view()->updateLayoutAndStyleForPainting();
2117 }
2118
2119 void Internals::setZoomFactor(float factor)
2120 {
2121     frame()->setPageZoomFactor(factor);
2122 }
2123
2124 void Internals::setShouldRevealPassword(Element* element, bool reveal, ExceptionState& exceptionState)
2125 {
2126     ASSERT(element);
2127     if (!isHTMLInputElement(element)) {
2128         exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not an INPUT.");
2129         return;
2130     }
2131
2132     return toHTMLInputElement(*element).setShouldRevealPassword(reveal);
2133 }
2134
2135 namespace {
2136
2137 class AddOneFunction : public ScriptFunction {
2138 public:
2139     static PassOwnPtr<ScriptFunction> create(ExecutionContext* context)
2140     {
2141         return adoptPtr(new AddOneFunction(toIsolate(context)));
2142     }
2143
2144 private:
2145     AddOneFunction(v8::Isolate* isolate)
2146         : ScriptFunction(isolate)
2147     {
2148     }
2149
2150     virtual ScriptValue call(ScriptValue value) OVERRIDE
2151     {
2152         v8::Local<v8::Value> v8Value = value.v8Value();
2153         ASSERT(v8Value->IsNumber());
2154         int intValue = v8Value.As<v8::Integer>()->Value();
2155         ScriptValue result  = ScriptValue(ScriptState::current(isolate()), v8::Integer::New(isolate(), intValue + 1));
2156         return result;
2157     }
2158 };
2159
2160 } // namespace
2161
2162 ScriptPromise Internals::createResolvedPromise(ScriptState* scriptState, ScriptValue value)
2163 {
2164     RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState);
2165     ScriptPromise promise = resolver->promise();
2166     resolver->resolve(value);
2167     return promise;
2168 }
2169
2170 ScriptPromise Internals::createRejectedPromise(ScriptState* scriptState, ScriptValue value)
2171 {
2172     RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState);
2173     ScriptPromise promise = resolver->promise();
2174     resolver->reject(value);
2175     return promise;
2176 }
2177
2178 ScriptPromise Internals::addOneToPromise(ScriptState* scriptState, ScriptPromise promise)
2179 {
2180     return promise.then(AddOneFunction::create(scriptState->executionContext()));
2181 }
2182
2183 ScriptPromise Internals::promiseCheck(ScriptState* scriptState, long arg1, bool arg2, const Dictionary& arg3, const String& arg4, const Vector<String>& arg5, ExceptionState& exceptionState)
2184 {
2185     if (arg2)
2186         return ScriptPromise::cast(scriptState, v8String(scriptState->isolate(), "done"));
2187     exceptionState.throwDOMException(InvalidStateError, "Thrown from the native implementation.");
2188     return ScriptPromise();
2189 }
2190
2191 ScriptPromise Internals::promiseCheckWithoutExceptionState(ScriptState* scriptState, const Dictionary& arg1, const String& arg2, const Vector<String>& arg3)
2192 {
2193     return ScriptPromise::cast(scriptState, v8String(scriptState->isolate(), "done"));
2194 }
2195
2196 ScriptPromise Internals::promiseCheckRange(ScriptState* scriptState, long arg1)
2197 {
2198     return ScriptPromise::cast(scriptState, v8String(scriptState->isolate(), "done"));
2199 }
2200
2201 void Internals::trace(Visitor* visitor)
2202 {
2203     visitor->trace(m_runtimeFlags);
2204     visitor->trace(m_profilers);
2205 }
2206
2207 void Internals::setValueForUser(Element* element, const String& value)
2208 {
2209     toHTMLInputElement(element)->setValueForUser(value);
2210 }
2211
2212 String Internals::textSurroundingNode(Node* node, int x, int y, unsigned long maxLength)
2213 {
2214     if (!node)
2215         return String();
2216     blink::WebPoint point(x, y);
2217     SurroundingText surroundingText(VisiblePosition(node->renderer()->positionForPoint(static_cast<IntPoint>(point))).deepEquivalent().parentAnchoredEquivalent(), maxLength);
2218     return surroundingText.content();
2219 }
2220
2221 void Internals::setFocused(bool focused)
2222 {
2223     frame()->page()->focusController().setFocused(focused);
2224 }
2225
2226 bool Internals::ignoreLayoutWithPendingStylesheets(Document* document)
2227 {
2228     ASSERT(document);
2229     return document->ignoreLayoutWithPendingStylesheets();
2230 }
2231
2232 void Internals::setNetworkStateNotifierTestOnly(bool testOnly)
2233 {
2234     networkStateNotifier().setTestUpdatesOnly(testOnly);
2235 }
2236
2237 void Internals::setNetworkConnectionInfo(const String& type, ExceptionState& exceptionState)
2238 {
2239     blink::WebConnectionType webtype;
2240     if (type == "cellular") {
2241         webtype = blink::ConnectionTypeCellular;
2242     } else if (type == "bluetooth") {
2243         webtype = blink::ConnectionTypeBluetooth;
2244     } else if (type == "ethernet") {
2245         webtype = blink::ConnectionTypeEthernet;
2246     } else if (type == "wifi") {
2247         webtype = blink::ConnectionTypeWifi;
2248     } else if (type == "other") {
2249         webtype = blink::ConnectionTypeOther;
2250     } else if (type == "none") {
2251         webtype = blink::ConnectionTypeNone;
2252     } else if (type == "unknown") {
2253         webtype = blink::ConnectionTypeUnknown;
2254     } else {
2255         exceptionState.throwDOMException(NotFoundError, ExceptionMessages::failedToEnumerate("connection type", type));
2256         return;
2257     }
2258     networkStateNotifier().setWebConnectionTypeForTest(webtype);
2259 }
2260
2261 unsigned Internals::countHitRegions(CanvasRenderingContext2D* context)
2262 {
2263     return context->hitRegionsCount();
2264 }
2265
2266 String Internals::serializeNavigationMarkup()
2267 {
2268     Vector<Document::TransitionElementData> elementData;
2269     frame()->document()->getTransitionElementData(elementData);
2270
2271     StringBuilder markup;
2272     Vector<Document::TransitionElementData>::iterator iter = elementData.begin();
2273     for (; iter != elementData.end(); ++iter)
2274         markup.append(iter->markup);
2275
2276     return markup.toString();
2277 }
2278
2279 void Internals::hideAllTransitionElements()
2280 {
2281     Vector<Document::TransitionElementData> elementData;
2282     frame()->document()->getTransitionElementData(elementData);
2283
2284     Vector<Document::TransitionElementData>::iterator iter = elementData.begin();
2285     for (; iter != elementData.end(); ++iter)
2286         frame()->document()->hideTransitionElements(AtomicString(iter->selector));
2287 }
2288
2289 } // namespace blink