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