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