Home | History | Annotate | Download | only in testing
      1 /*
      2  * Copyright (C) 2012 Google Inc. All rights reserved.
      3  * Copyright (C) 2013 Apple Inc. All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *
      9  * 1.  Redistributions of source code must retain the above copyright
     10  *     notice, this list of conditions and the following disclaimer.
     11  * 2.  Redistributions in binary form must reproduce the above copyright
     12  *     notice, this list of conditions and the following disclaimer in the
     13  *     documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     18  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 
     27 #include "config.h"
     28 #include "Internals.h"
     29 
     30 #include "HTMLNames.h"
     31 #include "InspectorFrontendClientLocal.h"
     32 #include "InternalProfilers.h"
     33 #include "InternalRuntimeFlags.h"
     34 #include "InternalSettings.h"
     35 #include "LayerRect.h"
     36 #include "LayerRectList.h"
     37 #include "MallocStatistics.h"
     38 #include "MockPagePopupDriver.h"
     39 #include "RuntimeEnabledFeatures.h"
     40 #include "TypeConversions.h"
     41 #include "bindings/v8/ExceptionState.h"
     42 #include "bindings/v8/SerializedScriptValue.h"
     43 #include "bindings/v8/V8ThrowException.h"
     44 #include "core/css/StyleSheetContents.h"
     45 #include "core/css/resolver/StyleResolver.h"
     46 #include "core/css/resolver/ViewportStyleResolver.h"
     47 #include "core/dom/ClientRect.h"
     48 #include "core/dom/ClientRectList.h"
     49 #include "core/dom/DOMStringList.h"
     50 #include "core/dom/Document.h"
     51 #include "core/dom/DocumentMarker.h"
     52 #include "core/dom/DocumentMarkerController.h"
     53 #include "core/dom/Element.h"
     54 #include "core/dom/ExceptionCode.h"
     55 #include "core/dom/FullscreenElementStack.h"
     56 #include "core/dom/NodeRenderingContext.h"
     57 #include "core/dom/PseudoElement.h"
     58 #include "core/dom/Range.h"
     59 #include "core/dom/StaticNodeList.h"
     60 #include "core/dom/TreeScope.h"
     61 #include "core/dom/ViewportArguments.h"
     62 #include "core/dom/shadow/ComposedShadowTreeWalker.h"
     63 #include "core/dom/shadow/ContentDistributor.h"
     64 #include "core/dom/shadow/ElementShadow.h"
     65 #include "core/dom/shadow/SelectRuleFeatureSet.h"
     66 #include "core/dom/shadow/ShadowRoot.h"
     67 #include "core/editing/Editor.h"
     68 #include "core/editing/SpellChecker.h"
     69 #include "core/editing/TextIterator.h"
     70 #include "core/history/BackForwardController.h"
     71 #include "core/history/HistoryItem.h"
     72 #include "core/html/FormController.h"
     73 #include "core/html/HTMLInputElement.h"
     74 #include "core/html/HTMLMediaElement.h"
     75 #include "core/html/HTMLSelectElement.h"
     76 #include "core/html/HTMLTextAreaElement.h"
     77 #include "core/html/shadow/HTMLContentElement.h"
     78 #include "core/inspector/InspectorClient.h"
     79 #include "core/inspector/InspectorConsoleAgent.h"
     80 #include "core/inspector/InspectorController.h"
     81 #include "core/inspector/InspectorCounters.h"
     82 #include "core/inspector/InspectorFrontendChannel.h"
     83 #include "core/inspector/InspectorInstrumentation.h"
     84 #include "core/inspector/InspectorOverlay.h"
     85 #include "core/inspector/InstrumentingAgents.h"
     86 #include "core/loader/FrameLoader.h"
     87 #include "core/loader/cache/MemoryCache.h"
     88 #include "core/loader/cache/ResourceFetcher.h"
     89 #include "core/page/Chrome.h"
     90 #include "core/page/ChromeClient.h"
     91 #include "core/page/DOMPoint.h"
     92 #include "core/page/DOMWindow.h"
     93 #include "core/page/EventHandler.h"
     94 #include "core/page/Frame.h"
     95 #include "core/page/FrameView.h"
     96 #include "core/page/Page.h"
     97 #include "core/page/PagePopupController.h"
     98 #include "core/page/PrintContext.h"
     99 #include "core/page/Settings.h"
    100 #include "core/page/animation/AnimationController.h"
    101 #include "core/page/scrolling/ScrollingCoordinator.h"
    102 #include "core/platform/ColorChooser.h"
    103 #include "core/platform/Cursor.h"
    104 #include "core/platform/Language.h"
    105 #include "core/platform/chromium/TraceEvent.h"
    106 #include "core/platform/graphics/GraphicsLayer.h"
    107 #include "core/platform/graphics/IntRect.h"
    108 #include "core/platform/graphics/filters/FilterOperation.h"
    109 #include "core/platform/graphics/filters/FilterOperations.h"
    110 #include "core/platform/graphics/gpu/SharedGraphicsContext3D.h"
    111 #include "core/platform/mock/PlatformSpeechSynthesizerMock.h"
    112 #include "core/rendering/RenderLayerBacking.h"
    113 #include "core/rendering/RenderMenuList.h"
    114 #include "core/rendering/RenderObject.h"
    115 #include "core/rendering/RenderTreeAsText.h"
    116 #include "core/rendering/RenderView.h"
    117 #include "core/testing/GCObservation.h"
    118 #include "core/workers/WorkerThread.h"
    119 #include "modules/speech/DOMWindowSpeechSynthesis.h"
    120 #include "modules/speech/SpeechSynthesis.h"
    121 #include "weborigin/SchemeRegistry.h"
    122 #include "wtf/dtoa.h"
    123 #include "wtf/text/StringBuffer.h"
    124 #include <v8.h>
    125 
    126 namespace WebCore {
    127 
    128 static MockPagePopupDriver* s_pagePopupDriver = 0;
    129 
    130 using namespace HTMLNames;
    131 
    132 class InspectorFrontendChannelDummy : public InspectorFrontendChannel {
    133 public:
    134     explicit InspectorFrontendChannelDummy(Page*);
    135     virtual ~InspectorFrontendChannelDummy() { }
    136     virtual bool sendMessageToFrontend(const String& message) OVERRIDE;
    137 
    138 private:
    139     Page* m_frontendPage;
    140 };
    141 
    142 InspectorFrontendChannelDummy::InspectorFrontendChannelDummy(Page* page)
    143     : m_frontendPage(page)
    144 {
    145 }
    146 
    147 bool InspectorFrontendChannelDummy::sendMessageToFrontend(const String& message)
    148 {
    149     return InspectorClient::doDispatchMessageOnFrontendPage(m_frontendPage, message);
    150 }
    151 
    152 static bool markerTypesFrom(const String& markerType, DocumentMarker::MarkerTypes& result)
    153 {
    154     if (markerType.isEmpty() || equalIgnoringCase(markerType, "all"))
    155         result = DocumentMarker::AllMarkers();
    156     else if (equalIgnoringCase(markerType, "Spelling"))
    157         result =  DocumentMarker::Spelling;
    158     else if (equalIgnoringCase(markerType, "Grammar"))
    159         result =  DocumentMarker::Grammar;
    160     else if (equalIgnoringCase(markerType, "TextMatch"))
    161         result =  DocumentMarker::TextMatch;
    162     else
    163         return false;
    164 
    165     return true;
    166 }
    167 
    168 static SpellChecker* spellchecker(Document* document)
    169 {
    170     if (!document || !document->frame() || !document->frame()->editor())
    171         return 0;
    172 
    173     return document->frame()->editor()->spellChecker();
    174 }
    175 
    176 const char* Internals::internalsId = "internals";
    177 
    178 PassRefPtr<Internals> Internals::create(Document* document)
    179 {
    180     return adoptRef(new Internals(document));
    181 }
    182 
    183 Internals::~Internals()
    184 {
    185     if (m_scrollingCoordinator) {
    186         m_scrollingCoordinator->removeTouchEventTargetRectsObserver(this);
    187     }
    188 }
    189 
    190 void Internals::resetToConsistentState(Page* page)
    191 {
    192     ASSERT(page);
    193 
    194     page->setDeviceScaleFactor(1);
    195     page->setPageScaleFactor(1, IntPoint(0, 0));
    196     page->setPagination(Pagination());
    197     TextRun::setAllowsRoundingHacks(false);
    198     WebCore::overrideUserPreferredLanguages(Vector<String>());
    199     WebCore::Settings::setUsesOverlayScrollbars(false);
    200     delete s_pagePopupDriver;
    201     s_pagePopupDriver = 0;
    202     page->chrome().client()->resetPagePopupDriver();
    203     if (!page->mainFrame()->editor()->isContinuousSpellCheckingEnabled())
    204         page->mainFrame()->editor()->toggleContinuousSpellChecking();
    205     if (page->mainFrame()->editor()->isOverwriteModeEnabled())
    206         page->mainFrame()->editor()->toggleOverwriteModeEnabled();
    207 }
    208 
    209 Internals::Internals(Document* document)
    210     : ContextLifecycleObserver(document)
    211     , m_runtimeFlags(InternalRuntimeFlags::create())
    212     , m_scrollingCoordinator(document->page() ? document->page()->scrollingCoordinator() : 0)
    213     , m_touchEventTargetRectUpdateCount(0)
    214 {
    215     if (m_scrollingCoordinator) {
    216         m_scrollingCoordinator->addTouchEventTargetRectsObserver(this);
    217     }
    218 }
    219 
    220 Document* Internals::contextDocument() const
    221 {
    222     return toDocument(scriptExecutionContext());
    223 }
    224 
    225 Frame* Internals::frame() const
    226 {
    227     if (!contextDocument())
    228         return 0;
    229     return contextDocument()->frame();
    230 }
    231 
    232 InternalSettings* Internals::settings() const
    233 {
    234     Document* document = contextDocument();
    235     if (!document)
    236         return 0;
    237     Page* page = document->page();
    238     if (!page)
    239         return 0;
    240     return InternalSettings::from(page);
    241 }
    242 
    243 InternalRuntimeFlags* Internals::runtimeFlags() const
    244 {
    245     return m_runtimeFlags.get();
    246 }
    247 
    248 InternalProfilers* Internals::profilers()
    249 {
    250     if (!m_profilers)
    251         m_profilers = InternalProfilers::create();
    252     return m_profilers.get();
    253 }
    254 
    255 unsigned Internals::workerThreadCount() const
    256 {
    257     return WorkerThread::workerThreadCount();
    258 }
    259 
    260 String Internals::address(Node* node)
    261 {
    262     char buf[32];
    263     sprintf(buf, "%p", node);
    264 
    265     return String(buf);
    266 }
    267 
    268 PassRefPtr<GCObservation> Internals::observeGC(ScriptValue scriptValue)
    269 {
    270     v8::Handle<v8::Value> observedValue = scriptValue.v8Value();
    271     ASSERT(!observedValue.IsEmpty());
    272     if (observedValue->IsNull() || observedValue->IsUndefined()) {
    273         V8ThrowException::throwTypeError("value to observe is null or undefined", v8::Isolate::GetCurrent());
    274         return 0;
    275     }
    276 
    277     return GCObservation::create(observedValue);
    278 }
    279 
    280 bool Internals::isPreloaded(const String& url)
    281 {
    282     Document* document = contextDocument();
    283     return document->fetcher()->isPreloaded(url);
    284 }
    285 
    286 bool Internals::isLoadingFromMemoryCache(const String& url)
    287 {
    288     if (!contextDocument())
    289         return false;
    290     Resource* resource = memoryCache()->resourceForURL(contextDocument()->completeURL(url));
    291     return resource && resource->status() == Resource::Cached;
    292 }
    293 
    294 void Internals::crash()
    295 {
    296     CRASH();
    297 }
    298 
    299 PassRefPtr<Element> Internals::createContentElement(ExceptionState& es)
    300 {
    301     Document* document = contextDocument();
    302     if (!document) {
    303         es.throwDOMException(InvalidAccessError);
    304         return 0;
    305     }
    306 
    307     return HTMLContentElement::create(document);
    308 }
    309 
    310 bool Internals::isValidContentSelect(Element* insertionPoint, ExceptionState& es)
    311 {
    312     if (!insertionPoint || !insertionPoint->isInsertionPoint()) {
    313         es.throwDOMException(InvalidAccessError);
    314         return false;
    315     }
    316 
    317     return isHTMLContentElement(insertionPoint) && toHTMLContentElement(insertionPoint)->isSelectValid();
    318 }
    319 
    320 Node* Internals::treeScopeRootNode(Node* node, ExceptionState& es)
    321 {
    322     if (!node) {
    323         es.throwDOMException(InvalidAccessError);
    324         return 0;
    325     }
    326 
    327     return node->treeScope()->rootNode();
    328 }
    329 
    330 Node* Internals::parentTreeScope(Node* node, ExceptionState& es)
    331 {
    332     if (!node) {
    333         es.throwDOMException(InvalidAccessError);
    334         return 0;
    335     }
    336     const TreeScope* parentTreeScope = node->treeScope()->parentTreeScope();
    337     return parentTreeScope ? parentTreeScope->rootNode() : 0;
    338 }
    339 
    340 bool Internals::hasSelectorForIdInShadow(Element* host, const String& idValue, ExceptionState& es)
    341 {
    342     if (!host || !host->shadow()) {
    343         es.throwDOMException(InvalidAccessError);
    344         return 0;
    345     }
    346 
    347     return host->shadow()->distributor().ensureSelectFeatureSet(host->shadow()).hasSelectorForId(idValue);
    348 }
    349 
    350 bool Internals::hasSelectorForClassInShadow(Element* host, const String& className, ExceptionState& es)
    351 {
    352     if (!host || !host->shadow()) {
    353         es.throwDOMException(InvalidAccessError);
    354         return 0;
    355     }
    356 
    357     return host->shadow()->distributor().ensureSelectFeatureSet(host->shadow()).hasSelectorForClass(className);
    358 }
    359 
    360 bool Internals::hasSelectorForAttributeInShadow(Element* host, const String& attributeName, ExceptionState& es)
    361 {
    362     if (!host || !host->shadow()) {
    363         es.throwDOMException(InvalidAccessError);
    364         return 0;
    365     }
    366 
    367     return host->shadow()->distributor().ensureSelectFeatureSet(host->shadow()).hasSelectorForAttribute(attributeName);
    368 }
    369 
    370 bool Internals::hasSelectorForPseudoClassInShadow(Element* host, const String& pseudoClass, ExceptionState& es)
    371 {
    372     if (!host || !host->shadow()) {
    373         es.throwDOMException(InvalidAccessError);
    374         return 0;
    375     }
    376 
    377     const SelectRuleFeatureSet& featureSet = host->shadow()->distributor().ensureSelectFeatureSet(host->shadow());
    378     if (pseudoClass == "checked")
    379         return featureSet.hasSelectorForChecked();
    380     if (pseudoClass == "enabled")
    381         return featureSet.hasSelectorForEnabled();
    382     if (pseudoClass == "disabled")
    383         return featureSet.hasSelectorForDisabled();
    384     if (pseudoClass == "indeterminate")
    385         return featureSet.hasSelectorForIndeterminate();
    386     if (pseudoClass == "link")
    387         return featureSet.hasSelectorForLink();
    388     if (pseudoClass == "target")
    389         return featureSet.hasSelectorForTarget();
    390     if (pseudoClass == "visited")
    391         return featureSet.hasSelectorForVisited();
    392 
    393     ASSERT_NOT_REACHED();
    394     return false;
    395 }
    396 
    397 unsigned short Internals::compareTreeScopePosition(const Node* node1, const Node* node2, ExceptionState& es) const
    398 {
    399     if (!node1 || !node2) {
    400         es.throwDOMException(InvalidAccessError);
    401         return 0;
    402     }
    403     const TreeScope* treeScope1 = node1->isDocumentNode() ? static_cast<const TreeScope*>(toDocument(node1)) :
    404         node1->isShadowRoot() ? static_cast<const TreeScope*>(toShadowRoot(node1)) : 0;
    405     const TreeScope* treeScope2 = node2->isDocumentNode() ? static_cast<const TreeScope*>(toDocument(node2)) :
    406         node2->isShadowRoot() ? static_cast<const TreeScope*>(toShadowRoot(node2)) : 0;
    407     if (!treeScope1 || !treeScope2) {
    408         es.throwDOMException(InvalidAccessError);
    409         return 0;
    410     }
    411     return treeScope1->comparePosition(treeScope2);
    412 }
    413 
    414 unsigned Internals::numberOfActiveAnimations() const
    415 {
    416     Frame* contextFrame = frame();
    417     if (!RuntimeEnabledFeatures::webAnimationsCSSEnabled()) {
    418         if (AnimationController* controller = contextFrame->animation())
    419             return controller->numberOfActiveAnimations(contextFrame->document());
    420     }
    421     return 0;
    422 }
    423 
    424 void Internals::suspendAnimations(Document* document, ExceptionState& es) const
    425 {
    426     if (!document || !document->frame()) {
    427         es.throwDOMException(InvalidAccessError);
    428         return;
    429     }
    430 
    431     if (!RuntimeEnabledFeatures::webAnimationsCSSEnabled()) {
    432         AnimationController* controller = document->frame()->animation();
    433         if (!controller)
    434             return;
    435 
    436         controller->suspendAnimations();
    437     }
    438 }
    439 
    440 void Internals::resumeAnimations(Document* document, ExceptionState& es) const
    441 {
    442     if (!document || !document->frame()) {
    443         es.throwDOMException(InvalidAccessError);
    444         return;
    445     }
    446 
    447     if (!RuntimeEnabledFeatures::webAnimationsCSSEnabled()) {
    448         AnimationController* controller = document->frame()->animation();
    449         if (!controller)
    450             return;
    451 
    452         controller->resumeAnimations();
    453     }
    454 }
    455 
    456 void Internals::pauseAnimations(double pauseTime, ExceptionState& es)
    457 {
    458     if (pauseTime < 0) {
    459         es.throwDOMException(InvalidAccessError);
    460         return;
    461     }
    462 
    463     if (!RuntimeEnabledFeatures::webAnimationsCSSEnabled())
    464         frame()->animation()->pauseAnimationsForTesting(pauseTime);
    465 }
    466 
    467 bool Internals::hasShadowInsertionPoint(const Node* root, ExceptionState& es) const
    468 {
    469     if (root && root->isShadowRoot())
    470         return toShadowRoot(root)->containsShadowElements();
    471 
    472     es.throwDOMException(InvalidAccessError);
    473     return 0;
    474 }
    475 
    476 bool Internals::hasContentElement(const Node* root, ExceptionState& es) const
    477 {
    478     if (root && root->isShadowRoot())
    479         return toShadowRoot(root)->containsContentElements();
    480 
    481     es.throwDOMException(InvalidAccessError);
    482     return 0;
    483 }
    484 
    485 size_t Internals::countElementShadow(const Node* root, ExceptionState& es) const
    486 {
    487     if (!root || !root->isShadowRoot()) {
    488         es.throwDOMException(InvalidAccessError);
    489         return 0;
    490     }
    491     if (const ScopeContentDistribution* distribution = toShadowRoot(root)->scopeDistribution())
    492         return distribution->numberOfElementShadowChildren();
    493     return 0;
    494 }
    495 
    496 bool Internals::attached(Node* node, ExceptionState& es)
    497 {
    498     if (!node) {
    499         es.throwDOMException(InvalidAccessError);
    500         return false;
    501     }
    502 
    503     return node->attached();
    504 }
    505 
    506 Node* Internals::nextSiblingByWalker(Node* node, ExceptionState& es)
    507 {
    508     if (!node) {
    509         es.throwDOMException(InvalidAccessError);
    510         return 0;
    511     }
    512     ComposedShadowTreeWalker walker(node);
    513     walker.nextSibling();
    514     return walker.get();
    515 }
    516 
    517 Node* Internals::firstChildByWalker(Node* node, ExceptionState& es)
    518 {
    519     if (!node) {
    520         es.throwDOMException(InvalidAccessError);
    521         return 0;
    522     }
    523     ComposedShadowTreeWalker walker(node);
    524     walker.firstChild();
    525     return walker.get();
    526 }
    527 
    528 Node* Internals::lastChildByWalker(Node* node, ExceptionState& es)
    529 {
    530     if (!node) {
    531         es.throwDOMException(InvalidAccessError);
    532         return 0;
    533     }
    534     ComposedShadowTreeWalker walker(node);
    535     walker.lastChild();
    536     return walker.get();
    537 }
    538 
    539 Node* Internals::nextNodeByWalker(Node* node, ExceptionState& es)
    540 {
    541     if (!node) {
    542         es.throwDOMException(InvalidAccessError);
    543         return 0;
    544     }
    545     ComposedShadowTreeWalker walker(node);
    546     walker.next();
    547     return walker.get();
    548 }
    549 
    550 Node* Internals::previousNodeByWalker(Node* node, ExceptionState& es)
    551 {
    552     if (!node) {
    553         es.throwDOMException(InvalidAccessError);
    554         return 0;
    555     }
    556     ComposedShadowTreeWalker walker(node);
    557     walker.previous();
    558     return walker.get();
    559 }
    560 
    561 String Internals::elementRenderTreeAsText(Element* element, ExceptionState& es)
    562 {
    563     if (!element) {
    564         es.throwDOMException(InvalidAccessError);
    565         return String();
    566     }
    567 
    568     String representation = externalRepresentation(element);
    569     if (representation.isEmpty()) {
    570         es.throwDOMException(InvalidAccessError);
    571         return String();
    572     }
    573 
    574     return representation;
    575 }
    576 
    577 size_t Internals::numberOfScopedHTMLStyleChildren(const Node* scope, ExceptionState& es) const
    578 {
    579     if (scope && (scope->isElementNode() || scope->isShadowRoot()))
    580         return scope->numberOfScopedHTMLStyleChildren();
    581 
    582     es.throwDOMException(InvalidAccessError);
    583     return 0;
    584 }
    585 
    586 PassRefPtr<CSSComputedStyleDeclaration> Internals::computedStyleIncludingVisitedInfo(Node* node, ExceptionState& es) const
    587 {
    588     if (!node) {
    589         es.throwDOMException(InvalidAccessError);
    590         return 0;
    591     }
    592 
    593     bool allowVisitedStyle = true;
    594     return CSSComputedStyleDeclaration::create(node, allowVisitedStyle);
    595 }
    596 
    597 ShadowRoot* Internals::ensureShadowRoot(Element* host, ExceptionState& es)
    598 {
    599     if (!host) {
    600         es.throwDOMException(InvalidAccessError);
    601         return 0;
    602     }
    603 
    604     if (ElementShadow* shadow = host->shadow())
    605         return shadow->youngestShadowRoot();
    606 
    607     return host->createShadowRoot(es).get();
    608 }
    609 
    610 ShadowRoot* Internals::shadowRoot(Element* host, ExceptionState& es)
    611 {
    612     // FIXME: Internals::shadowRoot() in tests should be converted to youngestShadowRoot() or oldestShadowRoot().
    613     // https://bugs.webkit.org/show_bug.cgi?id=78465
    614     return youngestShadowRoot(host, es);
    615 }
    616 
    617 ShadowRoot* Internals::youngestShadowRoot(Element* host, ExceptionState& es)
    618 {
    619     if (!host) {
    620         es.throwDOMException(InvalidAccessError);
    621         return 0;
    622     }
    623 
    624     if (ElementShadow* shadow = host->shadow())
    625         return shadow->youngestShadowRoot();
    626     return 0;
    627 }
    628 
    629 ShadowRoot* Internals::oldestShadowRoot(Element* host, ExceptionState& es)
    630 {
    631     if (!host) {
    632         es.throwDOMException(InvalidAccessError);
    633         return 0;
    634     }
    635 
    636     if (ElementShadow* shadow = host->shadow())
    637         return shadow->oldestShadowRoot();
    638     return 0;
    639 }
    640 
    641 ShadowRoot* Internals::youngerShadowRoot(Node* shadow, ExceptionState& es)
    642 {
    643     if (!shadow || !shadow->isShadowRoot()) {
    644         es.throwDOMException(InvalidAccessError);
    645         return 0;
    646     }
    647 
    648     return toShadowRoot(shadow)->youngerShadowRoot();
    649 }
    650 
    651 ShadowRoot* Internals::olderShadowRoot(Node* shadow, ExceptionState& es)
    652 {
    653     if (!shadow || !shadow->isShadowRoot()) {
    654         es.throwDOMException(InvalidAccessError);
    655         return 0;
    656     }
    657 
    658     return toShadowRoot(shadow)->olderShadowRoot();
    659 }
    660 
    661 String Internals::shadowRootType(const Node* root, ExceptionState& es) const
    662 {
    663     if (!root || !root->isShadowRoot()) {
    664         es.throwDOMException(InvalidAccessError);
    665         return String();
    666     }
    667 
    668     switch (toShadowRoot(root)->type()) {
    669     case ShadowRoot::UserAgentShadowRoot:
    670         return String("UserAgentShadowRoot");
    671     case ShadowRoot::AuthorShadowRoot:
    672         return String("AuthorShadowRoot");
    673     default:
    674         ASSERT_NOT_REACHED();
    675         return String("Unknown");
    676     }
    677 }
    678 
    679 Element* Internals::includerFor(Node* node, ExceptionState& es)
    680 {
    681     if (!node) {
    682         es.throwDOMException(InvalidAccessError);
    683         return 0;
    684     }
    685 
    686     NodeRenderingTraversal::ParentDetails parentDetails;
    687     NodeRenderingTraversal::parent(node, &parentDetails);
    688     return parentDetails.insertionPoint();
    689 }
    690 
    691 String Internals::shadowPseudoId(Element* element, ExceptionState& es)
    692 {
    693     if (!element) {
    694         es.throwDOMException(InvalidAccessError);
    695         return String();
    696     }
    697 
    698     return element->shadowPseudoId().string();
    699 }
    700 
    701 void Internals::setShadowPseudoId(Element* element, const String& id, ExceptionState& es)
    702 {
    703     if (!element) {
    704         es.throwDOMException(InvalidAccessError);
    705         return;
    706     }
    707 
    708     return element->setPart(id);
    709 }
    710 
    711 String Internals::visiblePlaceholder(Element* element)
    712 {
    713     if (element && isHTMLTextFormControlElement(element)) {
    714         if (toHTMLTextFormControlElement(element)->placeholderShouldBeVisible())
    715             return toHTMLTextFormControlElement(element)->placeholderElement()->textContent();
    716     }
    717 
    718     return String();
    719 }
    720 
    721 void Internals::selectColorInColorChooser(Element* element, const String& colorValue)
    722 {
    723     if (!element->hasTagName(inputTag))
    724         return;
    725     toHTMLInputElement(element)->selectColorInColorChooser(StyleColor(colorValue).color());
    726 }
    727 
    728 Vector<String> Internals::formControlStateOfPreviousHistoryItem(ExceptionState& es)
    729 {
    730     HistoryItem* mainItem = frame()->loader()->history()->previousItem();
    731     if (!mainItem) {
    732         es.throwDOMException(InvalidAccessError);
    733         return Vector<String>();
    734     }
    735     String uniqueName = frame()->tree()->uniqueName();
    736     if (mainItem->target() != uniqueName && !mainItem->childItemWithTarget(uniqueName)) {
    737         es.throwDOMException(InvalidAccessError);
    738         return Vector<String>();
    739     }
    740     return mainItem->target() == uniqueName ? mainItem->documentState() : mainItem->childItemWithTarget(uniqueName)->documentState();
    741 }
    742 
    743 void Internals::setFormControlStateOfPreviousHistoryItem(const Vector<String>& state, ExceptionState& es)
    744 {
    745     HistoryItem* mainItem = frame()->loader()->history()->previousItem();
    746     if (!mainItem) {
    747         es.throwDOMException(InvalidAccessError);
    748         return;
    749     }
    750     String uniqueName = frame()->tree()->uniqueName();
    751     if (mainItem->target() == uniqueName)
    752         mainItem->setDocumentState(state);
    753     else if (HistoryItem* subItem = mainItem->childItemWithTarget(uniqueName))
    754         subItem->setDocumentState(state);
    755     else
    756         es.throwDOMException(InvalidAccessError);
    757 }
    758 
    759 void Internals::enableMockSpeechSynthesizer()
    760 {
    761     Document* document = contextDocument();
    762     if (!document || !document->domWindow())
    763         return;
    764     SpeechSynthesis* synthesis = DOMWindowSpeechSynthesis::speechSynthesis(document->domWindow());
    765     if (!synthesis)
    766         return;
    767 
    768     synthesis->setPlatformSynthesizer(PlatformSpeechSynthesizerMock::create(synthesis));
    769 }
    770 
    771 void Internals::setEnableMockPagePopup(bool enabled, ExceptionState& es)
    772 {
    773     Document* document = contextDocument();
    774     if (!document || !document->page())
    775         return;
    776     Page* page = document->page();
    777     if (!enabled) {
    778         page->chrome().client()->resetPagePopupDriver();
    779         return;
    780     }
    781     if (!s_pagePopupDriver)
    782         s_pagePopupDriver = MockPagePopupDriver::create(page->mainFrame()).leakPtr();
    783     page->chrome().client()->setPagePopupDriver(s_pagePopupDriver);
    784 }
    785 
    786 PassRefPtr<PagePopupController> Internals::pagePopupController()
    787 {
    788     return s_pagePopupDriver ? s_pagePopupDriver->pagePopupController() : 0;
    789 }
    790 
    791 PassRefPtr<ClientRect> Internals::absoluteCaretBounds(ExceptionState& es)
    792 {
    793     Document* document = contextDocument();
    794     if (!document || !document->frame() || !document->frame()->selection()) {
    795         es.throwDOMException(InvalidAccessError);
    796         return ClientRect::create();
    797     }
    798 
    799     return ClientRect::create(document->frame()->selection()->absoluteCaretBounds());
    800 }
    801 
    802 PassRefPtr<ClientRect> Internals::boundingBox(Element* element, ExceptionState& es)
    803 {
    804     if (!element) {
    805         es.throwDOMException(InvalidAccessError);
    806         return ClientRect::create();
    807     }
    808 
    809     element->document()->updateLayoutIgnorePendingStylesheets();
    810     RenderObject* renderer = element->renderer();
    811     if (!renderer)
    812         return ClientRect::create();
    813     return ClientRect::create(renderer->absoluteBoundingBoxRectIgnoringTransforms());
    814 }
    815 
    816 PassRefPtr<ClientRectList> Internals::inspectorHighlightRects(Document* document, ExceptionState& es)
    817 {
    818     if (!document || !document->page() || !document->page()->inspectorController()) {
    819         es.throwDOMException(InvalidAccessError);
    820         return ClientRectList::create();
    821     }
    822 
    823     Highlight highlight;
    824     document->page()->inspectorController()->getHighlight(&highlight);
    825     return ClientRectList::create(highlight.quads);
    826 }
    827 
    828 unsigned Internals::markerCountForNode(Node* node, const String& markerType, ExceptionState& es)
    829 {
    830     if (!node) {
    831         es.throwDOMException(InvalidAccessError);
    832         return 0;
    833     }
    834 
    835     DocumentMarker::MarkerTypes markerTypes = 0;
    836     if (!markerTypesFrom(markerType, markerTypes)) {
    837         es.throwDOMException(SyntaxError);
    838         return 0;
    839     }
    840 
    841     return node->document()->markers()->markersFor(node, markerTypes).size();
    842 }
    843 
    844 DocumentMarker* Internals::markerAt(Node* node, const String& markerType, unsigned index, ExceptionState& es)
    845 {
    846     if (!node) {
    847         es.throwDOMException(InvalidAccessError);
    848         return 0;
    849     }
    850 
    851     DocumentMarker::MarkerTypes markerTypes = 0;
    852     if (!markerTypesFrom(markerType, markerTypes)) {
    853         es.throwDOMException(SyntaxError);
    854         return 0;
    855     }
    856 
    857     Vector<DocumentMarker*> markers = node->document()->markers()->markersFor(node, markerTypes);
    858     if (markers.size() <= index)
    859         return 0;
    860     return markers[index];
    861 }
    862 
    863 PassRefPtr<Range> Internals::markerRangeForNode(Node* node, const String& markerType, unsigned index, ExceptionState& es)
    864 {
    865     DocumentMarker* marker = markerAt(node, markerType, index, es);
    866     if (!marker)
    867         return 0;
    868     return Range::create(node->document(), node, marker->startOffset(), node, marker->endOffset());
    869 }
    870 
    871 String Internals::markerDescriptionForNode(Node* node, const String& markerType, unsigned index, ExceptionState& es)
    872 {
    873     DocumentMarker* marker = markerAt(node, markerType, index, es);
    874     if (!marker)
    875         return String();
    876     return marker->description();
    877 }
    878 
    879 void Internals::addTextMatchMarker(const Range* range, bool isActive)
    880 {
    881     range->ownerDocument()->updateLayoutIgnorePendingStylesheets();
    882     range->ownerDocument()->markers()->addTextMatchMarker(range, isActive);
    883 }
    884 
    885 void Internals::setScrollViewPosition(Document* document, long x, long y, ExceptionState& es)
    886 {
    887     if (!document || !document->view()) {
    888         es.throwDOMException(InvalidAccessError);
    889         return;
    890     }
    891 
    892     FrameView* frameView = document->view();
    893     bool constrainsScrollingToContentEdgeOldValue = frameView->constrainsScrollingToContentEdge();
    894     bool scrollbarsSuppressedOldValue = frameView->scrollbarsSuppressed();
    895 
    896     frameView->setConstrainsScrollingToContentEdge(false);
    897     frameView->setScrollbarsSuppressed(false);
    898     frameView->setScrollOffsetFromInternals(IntPoint(x, y));
    899     frameView->setScrollbarsSuppressed(scrollbarsSuppressedOldValue);
    900     frameView->setConstrainsScrollingToContentEdge(constrainsScrollingToContentEdgeOldValue);
    901 }
    902 
    903 void Internals::setPagination(Document* document, const String& mode, int gap, int pageLength, ExceptionState& es)
    904 {
    905     if (!document || !document->page()) {
    906         es.throwDOMException(InvalidAccessError);
    907         return;
    908     }
    909     Page* page = document->page();
    910 
    911     Pagination pagination;
    912     if (mode == "Unpaginated")
    913         pagination.mode = Pagination::Unpaginated;
    914     else if (mode == "LeftToRightPaginated")
    915         pagination.mode = Pagination::LeftToRightPaginated;
    916     else if (mode == "RightToLeftPaginated")
    917         pagination.mode = Pagination::RightToLeftPaginated;
    918     else if (mode == "TopToBottomPaginated")
    919         pagination.mode = Pagination::TopToBottomPaginated;
    920     else if (mode == "BottomToTopPaginated")
    921         pagination.mode = Pagination::BottomToTopPaginated;
    922     else {
    923         es.throwDOMException(SyntaxError);
    924         return;
    925     }
    926 
    927     pagination.gap = gap;
    928     pagination.pageLength = pageLength;
    929     page->setPagination(pagination);
    930 }
    931 
    932 String Internals::configurationForViewport(Document* document, float, int deviceWidth, int deviceHeight, int availableWidth, int availableHeight, ExceptionState& es)
    933 {
    934     if (!document || !document->page()) {
    935         es.throwDOMException(InvalidAccessError);
    936         return String();
    937     }
    938     Page* page = document->page();
    939 
    940     // Update initial viewport size.
    941     IntSize initialViewportSize(availableWidth, availableHeight);
    942     document->page()->mainFrame()->view()->setFrameRect(IntRect(IntPoint::zero(), initialViewportSize));
    943     document->styleResolver()->viewportStyleResolver()->resolve();
    944 
    945     ViewportArguments arguments = page->viewportArguments();
    946     PageScaleConstraints constraints = arguments.resolve(initialViewportSize, FloatSize(deviceWidth, deviceHeight), 980 /* defaultLayoutWidthForNonMobilePages */);
    947 
    948     constraints.fitToContentsWidth(constraints.layoutSize.width(), availableWidth);
    949 
    950     StringBuilder builder;
    951 
    952     builder.appendLiteral("viewport size ");
    953     builder.append(String::number(constraints.layoutSize.width()));
    954     builder.append('x');
    955     builder.append(String::number(constraints.layoutSize.height()));
    956 
    957     builder.appendLiteral(" scale ");
    958     builder.append(String::number(constraints.initialScale));
    959     builder.appendLiteral(" with limits [");
    960     builder.append(String::number(constraints.minimumScale));
    961     builder.appendLiteral(", ");
    962     builder.append(String::number(constraints.maximumScale));
    963 
    964     builder.appendLiteral("] and userScalable ");
    965     builder.append(arguments.userZoom ? "true" : "false");
    966 
    967     return builder.toString();
    968 }
    969 
    970 bool Internals::wasLastChangeUserEdit(Element* textField, ExceptionState& es)
    971 {
    972     if (!textField) {
    973         es.throwDOMException(InvalidAccessError);
    974         return false;
    975     }
    976 
    977     if (textField->hasTagName(inputTag))
    978         return toHTMLInputElement(textField)->lastChangeWasUserEdit();
    979 
    980     // FIXME: We should be using hasTagName instead but Windows port doesn't link QualifiedNames properly.
    981     if (textField->tagName() == "TEXTAREA")
    982         return toHTMLTextAreaElement(textField)->lastChangeWasUserEdit();
    983 
    984     es.throwDOMException(InvalidNodeTypeError);
    985     return false;
    986 }
    987 
    988 bool Internals::elementShouldAutoComplete(Element* element, ExceptionState& es)
    989 {
    990     if (!element) {
    991         es.throwDOMException(InvalidAccessError);
    992         return false;
    993     }
    994 
    995     if (element->hasTagName(inputTag))
    996         return toHTMLInputElement(element)->shouldAutocomplete();
    997 
    998     es.throwDOMException(InvalidNodeTypeError);
    999     return false;
   1000 }
   1001 
   1002 String Internals::suggestedValue(Element* element, ExceptionState& es)
   1003 {
   1004     if (!element) {
   1005         es.throwDOMException(InvalidAccessError);
   1006         return String();
   1007     }
   1008 
   1009     if (!element->hasTagName(inputTag)) {
   1010         es.throwDOMException(InvalidNodeTypeError);
   1011         return String();
   1012     }
   1013 
   1014     return toHTMLInputElement(element)->suggestedValue();
   1015 }
   1016 
   1017 void Internals::setSuggestedValue(Element* element, const String& value, ExceptionState& es)
   1018 {
   1019     if (!element) {
   1020         es.throwDOMException(InvalidAccessError);
   1021         return;
   1022     }
   1023 
   1024     if (!element->hasTagName(inputTag)) {
   1025         es.throwDOMException(InvalidNodeTypeError);
   1026         return;
   1027     }
   1028 
   1029     toHTMLInputElement(element)->setSuggestedValue(value);
   1030 }
   1031 
   1032 void Internals::setEditingValue(Element* element, const String& value, ExceptionState& es)
   1033 {
   1034     if (!element) {
   1035         es.throwDOMException(InvalidAccessError);
   1036         return;
   1037     }
   1038 
   1039     if (!element->hasTagName(inputTag)) {
   1040         es.throwDOMException(InvalidNodeTypeError);
   1041         return;
   1042     }
   1043 
   1044     toHTMLInputElement(element)->setEditingValue(value);
   1045 }
   1046 
   1047 void Internals::setAutofilled(Element* element, bool enabled, ExceptionState& es)
   1048 {
   1049     if (!element->hasTagName(inputTag)) {
   1050         es.throwDOMException(InvalidAccessError);
   1051         return;
   1052     }
   1053     toHTMLInputElement(element)->setAutofilled(enabled);
   1054 }
   1055 
   1056 void Internals::scrollElementToRect(Element* element, long x, long y, long w, long h, ExceptionState& es)
   1057 {
   1058     if (!element || !element->document() || !element->document()->view()) {
   1059         es.throwDOMException(InvalidAccessError);
   1060         return;
   1061     }
   1062     FrameView* frameView = element->document()->view();
   1063     frameView->scrollElementToRect(element, IntRect(x, y, w, h));
   1064 }
   1065 
   1066 void Internals::paintControlTints(Document* document, ExceptionState& es)
   1067 {
   1068     if (!document || !document->view()) {
   1069         es.throwDOMException(InvalidAccessError);
   1070         return;
   1071     }
   1072 
   1073     FrameView* frameView = document->view();
   1074     frameView->paintControlTints();
   1075 }
   1076 
   1077 PassRefPtr<Range> Internals::rangeFromLocationAndLength(Element* scope, int rangeLocation, int rangeLength, ExceptionState& es)
   1078 {
   1079     if (!scope) {
   1080         es.throwDOMException(InvalidAccessError);
   1081         return 0;
   1082     }
   1083 
   1084     return TextIterator::rangeFromLocationAndLength(scope, rangeLocation, rangeLength);
   1085 }
   1086 
   1087 unsigned Internals::locationFromRange(Element* scope, const Range* range, ExceptionState& es)
   1088 {
   1089     if (!scope || !range) {
   1090         es.throwDOMException(InvalidAccessError);
   1091         return 0;
   1092     }
   1093 
   1094     size_t location = 0;
   1095     size_t unusedLength = 0;
   1096     TextIterator::getLocationAndLengthFromRange(scope, range, location, unusedLength);
   1097     return location;
   1098 }
   1099 
   1100 unsigned Internals::lengthFromRange(Element* scope, const Range* range, ExceptionState& es)
   1101 {
   1102     if (!scope || !range) {
   1103         es.throwDOMException(InvalidAccessError);
   1104         return 0;
   1105     }
   1106 
   1107     size_t unusedLocation = 0;
   1108     size_t length = 0;
   1109     TextIterator::getLocationAndLengthFromRange(scope, range, unusedLocation, length);
   1110     return length;
   1111 }
   1112 
   1113 String Internals::rangeAsText(const Range* range, ExceptionState& es)
   1114 {
   1115     if (!range) {
   1116         es.throwDOMException(InvalidAccessError);
   1117         return String();
   1118     }
   1119 
   1120     return range->text();
   1121 }
   1122 
   1123 PassRefPtr<DOMPoint> Internals::touchPositionAdjustedToBestClickableNode(long x, long y, long width, long height, Document* document, ExceptionState& es)
   1124 {
   1125     if (!document || !document->frame()) {
   1126         es.throwDOMException(InvalidAccessError);
   1127         return 0;
   1128     }
   1129 
   1130     document->updateLayout();
   1131 
   1132     IntSize radius(width / 2, height / 2);
   1133     IntPoint point(x + radius.width(), y + radius.height());
   1134 
   1135     Node* targetNode;
   1136     IntPoint adjustedPoint;
   1137 
   1138     bool foundNode = document->frame()->eventHandler()->bestClickableNodeForTouchPoint(point, radius, adjustedPoint, targetNode);
   1139     if (foundNode)
   1140         return DOMPoint::create(adjustedPoint.x(), adjustedPoint.y());
   1141 
   1142     return 0;
   1143 }
   1144 
   1145 Node* Internals::touchNodeAdjustedToBestClickableNode(long x, long y, long width, long height, Document* document, ExceptionState& es)
   1146 {
   1147     if (!document || !document->frame()) {
   1148         es.throwDOMException(InvalidAccessError);
   1149         return 0;
   1150     }
   1151 
   1152     document->updateLayout();
   1153 
   1154     IntSize radius(width / 2, height / 2);
   1155     IntPoint point(x + radius.width(), y + radius.height());
   1156 
   1157     Node* targetNode;
   1158     IntPoint adjustedPoint;
   1159     document->frame()->eventHandler()->bestClickableNodeForTouchPoint(point, radius, adjustedPoint, targetNode);
   1160     return targetNode;
   1161 }
   1162 
   1163 PassRefPtr<DOMPoint> Internals::touchPositionAdjustedToBestContextMenuNode(long x, long y, long width, long height, Document* document, ExceptionState& es)
   1164 {
   1165     if (!document || !document->frame()) {
   1166         es.throwDOMException(InvalidAccessError);
   1167         return 0;
   1168     }
   1169 
   1170     document->updateLayout();
   1171 
   1172     IntSize radius(width / 2, height / 2);
   1173     IntPoint point(x + radius.width(), y + radius.height());
   1174 
   1175     Node* targetNode = 0;
   1176     IntPoint adjustedPoint;
   1177 
   1178     bool foundNode = document->frame()->eventHandler()->bestContextMenuNodeForTouchPoint(point, radius, adjustedPoint, targetNode);
   1179     if (foundNode)
   1180         return DOMPoint::create(adjustedPoint.x(), adjustedPoint.y());
   1181 
   1182     return DOMPoint::create(x, y);
   1183 }
   1184 
   1185 Node* Internals::touchNodeAdjustedToBestContextMenuNode(long x, long y, long width, long height, Document* document, ExceptionState& es)
   1186 {
   1187     if (!document || !document->frame()) {
   1188         es.throwDOMException(InvalidAccessError);
   1189         return 0;
   1190     }
   1191 
   1192     document->updateLayout();
   1193 
   1194     IntSize radius(width / 2, height / 2);
   1195     IntPoint point(x + radius.width(), y + radius.height());
   1196 
   1197     Node* targetNode = 0;
   1198     IntPoint adjustedPoint;
   1199     document->frame()->eventHandler()->bestContextMenuNodeForTouchPoint(point, radius, adjustedPoint, targetNode);
   1200     return targetNode;
   1201 }
   1202 
   1203 PassRefPtr<ClientRect> Internals::bestZoomableAreaForTouchPoint(long x, long y, long width, long height, Document* document, ExceptionState& es)
   1204 {
   1205     if (!document || !document->frame()) {
   1206         es.throwDOMException(InvalidAccessError);
   1207         return 0;
   1208     }
   1209 
   1210     document->updateLayout();
   1211 
   1212     IntSize radius(width / 2, height / 2);
   1213     IntPoint point(x + radius.width(), y + radius.height());
   1214 
   1215     Node* targetNode;
   1216     IntRect zoomableArea;
   1217     bool foundNode = document->frame()->eventHandler()->bestZoomableAreaForTouchPoint(point, radius, zoomableArea, targetNode);
   1218     if (foundNode)
   1219         return ClientRect::create(zoomableArea);
   1220 
   1221     return 0;
   1222 }
   1223 
   1224 
   1225 int Internals::lastSpellCheckRequestSequence(Document* document, ExceptionState& es)
   1226 {
   1227     SpellChecker* checker = spellchecker(document);
   1228 
   1229     if (!checker) {
   1230         es.throwDOMException(InvalidAccessError);
   1231         return -1;
   1232     }
   1233 
   1234     return checker->lastRequestSequence();
   1235 }
   1236 
   1237 int Internals::lastSpellCheckProcessedSequence(Document* document, ExceptionState& es)
   1238 {
   1239     SpellChecker* checker = spellchecker(document);
   1240 
   1241     if (!checker) {
   1242         es.throwDOMException(InvalidAccessError);
   1243         return -1;
   1244     }
   1245 
   1246     return checker->lastProcessedSequence();
   1247 }
   1248 
   1249 Vector<String> Internals::userPreferredLanguages() const
   1250 {
   1251     return WebCore::userPreferredLanguages();
   1252 }
   1253 
   1254 void Internals::setUserPreferredLanguages(const Vector<String>& languages)
   1255 {
   1256     WebCore::overrideUserPreferredLanguages(languages);
   1257 }
   1258 
   1259 unsigned Internals::wheelEventHandlerCount(Document* document, ExceptionState& es)
   1260 {
   1261     if (!document) {
   1262         es.throwDOMException(InvalidAccessError);
   1263         return 0;
   1264     }
   1265 
   1266     return document->wheelEventHandlerCount();
   1267 }
   1268 
   1269 unsigned Internals::touchEventHandlerCount(Document* document, ExceptionState& es)
   1270 {
   1271     if (!document) {
   1272         es.throwDOMException(InvalidAccessError);
   1273         return 0;
   1274     }
   1275 
   1276     const TouchEventTargetSet* touchHandlers = document->touchEventTargets();
   1277     if (!touchHandlers)
   1278         return 0;
   1279 
   1280     unsigned count = 0;
   1281     for (TouchEventTargetSet::const_iterator iter = touchHandlers->begin(); iter != touchHandlers->end(); ++iter)
   1282         count += iter->value;
   1283     return count;
   1284 }
   1285 
   1286 LayerRectList* Internals::touchEventTargetLayerRects(Document* document, ExceptionState& es)
   1287 {
   1288     if (!document || !document->view() || !document->page() || document != contextDocument()) {
   1289         es.throwDOMException(InvalidAccessError);
   1290         return 0;
   1291     }
   1292 
   1293     // Do any pending layouts (which may call touchEventTargetRectsChange) to ensure this
   1294     // really takes any previous changes into account.
   1295     document->updateLayout();
   1296     return m_currentTouchEventRects.get();
   1297 }
   1298 
   1299 unsigned Internals::touchEventTargetLayerRectsUpdateCount(Document* document, ExceptionState& es)
   1300 {
   1301     if (!document || !document->view() || !document->page() || document != contextDocument()) {
   1302         es.throwDOMException(InvalidAccessError);
   1303         return 0;
   1304     }
   1305 
   1306     // Do any pending layouts to ensure this really takes any previous changes into account.
   1307     document->updateLayout();
   1308 
   1309     return m_touchEventTargetRectUpdateCount;
   1310 }
   1311 
   1312 void Internals::touchEventTargetRectsChanged(const LayerHitTestRects& rects)
   1313 {
   1314     // When profiling content_shell, it can be handy to exclude this time (since it's only
   1315     // present for testing / debugging).
   1316     TRACE_EVENT0("input", "Internals::touchEventTargetRectsChanged");
   1317 
   1318     m_touchEventTargetRectUpdateCount++;
   1319 
   1320     // Since it's not safe to hang onto the pointers in a LayerHitTestRects, we immediately
   1321     // copy into a LayerRectList.
   1322     m_currentTouchEventRects = LayerRectList::create();
   1323     for (LayerHitTestRects::const_iterator iter = rects.begin(); iter != rects.end(); ++iter) {
   1324         for (size_t i = 0; i < iter->value.size(); ++i) {
   1325             m_currentTouchEventRects->append(iter->key->renderer()->node(), ClientRect::create(enclosingIntRect(iter->value[i])));
   1326         }
   1327     }
   1328 }
   1329 
   1330 PassRefPtr<NodeList> Internals::nodesFromRect(Document* document, int centerX, int centerY, unsigned topPadding, unsigned rightPadding,
   1331     unsigned bottomPadding, unsigned leftPadding, bool ignoreClipping, bool allowShadowContent, bool allowChildFrameContent, ExceptionState& es) const
   1332 {
   1333     if (!document || !document->frame() || !document->frame()->view()) {
   1334         es.throwDOMException(InvalidAccessError);
   1335         return 0;
   1336     }
   1337 
   1338     Frame* frame = document->frame();
   1339     FrameView* frameView = document->view();
   1340     RenderView* renderView = document->renderView();
   1341 
   1342     if (!renderView)
   1343         return 0;
   1344 
   1345     float zoomFactor = frame->pageZoomFactor();
   1346     LayoutPoint point = roundedLayoutPoint(FloatPoint(centerX * zoomFactor + frameView->scrollX(), centerY * zoomFactor + frameView->scrollY()));
   1347 
   1348     HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active;
   1349     if (ignoreClipping)
   1350         hitType |= HitTestRequest::IgnoreClipping;
   1351     if (!allowShadowContent)
   1352         hitType |= HitTestRequest::DisallowShadowContent;
   1353     if (allowChildFrameContent)
   1354         hitType |= HitTestRequest::AllowChildFrameContent;
   1355 
   1356     HitTestRequest request(hitType);
   1357 
   1358     // When ignoreClipping is false, this method returns null for coordinates outside of the viewport.
   1359     if (!request.ignoreClipping() && !frameView->visibleContentRect().intersects(HitTestLocation::rectForPoint(point, topPadding, rightPadding, bottomPadding, leftPadding)))
   1360         return 0;
   1361 
   1362     Vector<RefPtr<Node> > matches;
   1363 
   1364     // Need padding to trigger a rect based hit test, but we want to return a NodeList
   1365     // so we special case this.
   1366     if (!topPadding && !rightPadding && !bottomPadding && !leftPadding) {
   1367         HitTestResult result(point);
   1368         renderView->hitTest(request, result);
   1369         if (result.innerNode())
   1370             matches.append(result.innerNode()->deprecatedShadowAncestorNode());
   1371     } else {
   1372         HitTestResult result(point, topPadding, rightPadding, bottomPadding, leftPadding);
   1373         renderView->hitTest(request, result);
   1374         copyToVector(result.rectBasedTestResult(), matches);
   1375     }
   1376 
   1377     return StaticNodeList::adopt(matches);
   1378 }
   1379 
   1380 void Internals::emitInspectorDidBeginFrame()
   1381 {
   1382     InspectorController* inspectorController = contextDocument()->frame()->page()->inspectorController();
   1383     inspectorController->didBeginFrame();
   1384 }
   1385 
   1386 void Internals::emitInspectorDidCancelFrame()
   1387 {
   1388     InspectorController* inspectorController = contextDocument()->frame()->page()->inspectorController();
   1389     inspectorController->didCancelFrame();
   1390 }
   1391 
   1392 bool Internals::hasSpellingMarker(Document* document, int from, int length, ExceptionState&)
   1393 {
   1394     if (!document || !document->frame())
   1395         return 0;
   1396 
   1397     return document->frame()->editor()->selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
   1398 }
   1399 
   1400 void Internals::setContinuousSpellCheckingEnabled(bool enabled, ExceptionState&)
   1401 {
   1402     if (!contextDocument() || !contextDocument()->frame() || !contextDocument()->frame()->editor())
   1403         return;
   1404 
   1405     if (enabled != contextDocument()->frame()->editor()->isContinuousSpellCheckingEnabled())
   1406         contextDocument()->frame()->editor()->toggleContinuousSpellChecking();
   1407 }
   1408 
   1409 bool Internals::isOverwriteModeEnabled(Document* document, ExceptionState&)
   1410 {
   1411     if (!document || !document->frame())
   1412         return 0;
   1413 
   1414     return document->frame()->editor()->isOverwriteModeEnabled();
   1415 }
   1416 
   1417 void Internals::toggleOverwriteModeEnabled(Document* document, ExceptionState&)
   1418 {
   1419     if (!document || !document->frame())
   1420         return;
   1421 
   1422     document->frame()->editor()->toggleOverwriteModeEnabled();
   1423 }
   1424 
   1425 unsigned Internals::numberOfLiveNodes() const
   1426 {
   1427     return InspectorCounters::counterValue(InspectorCounters::NodeCounter);
   1428 }
   1429 
   1430 unsigned Internals::numberOfLiveDocuments() const
   1431 {
   1432     return InspectorCounters::counterValue(InspectorCounters::DocumentCounter);
   1433 }
   1434 
   1435 Vector<String> Internals::consoleMessageArgumentCounts(Document* document) const
   1436 {
   1437     InstrumentingAgents* instrumentingAgents = instrumentationForPage(document->page());
   1438     if (!instrumentingAgents)
   1439         return Vector<String>();
   1440     InspectorConsoleAgent* consoleAgent = instrumentingAgents->inspectorConsoleAgent();
   1441     if (!consoleAgent)
   1442         return Vector<String>();
   1443     Vector<unsigned> counts = consoleAgent->consoleMessageArgumentCounts();
   1444     Vector<String> result(counts.size());
   1445     for (size_t i = 0; i < counts.size(); i++)
   1446         result[i] = String::number(counts[i]);
   1447     return result;
   1448 }
   1449 
   1450 PassRefPtr<DOMWindow> Internals::openDummyInspectorFrontend(const String& url)
   1451 {
   1452     Page* page = contextDocument()->frame()->page();
   1453     ASSERT(page);
   1454 
   1455     DOMWindow* window = page->mainFrame()->domWindow();
   1456     ASSERT(window);
   1457 
   1458     m_frontendWindow = window->open(url, "", "", window, window);
   1459     ASSERT(m_frontendWindow);
   1460 
   1461     Page* frontendPage = m_frontendWindow->document()->page();
   1462     ASSERT(frontendPage);
   1463 
   1464     OwnPtr<InspectorFrontendClientLocal> frontendClient = adoptPtr(new InspectorFrontendClientLocal(page->inspectorController(), frontendPage));
   1465 
   1466     frontendPage->inspectorController()->setInspectorFrontendClient(frontendClient.release());
   1467 
   1468     m_frontendChannel = adoptPtr(new InspectorFrontendChannelDummy(frontendPage));
   1469 
   1470     page->inspectorController()->connectFrontend(m_frontendChannel.get());
   1471 
   1472     return m_frontendWindow;
   1473 }
   1474 
   1475 void Internals::closeDummyInspectorFrontend()
   1476 {
   1477     Page* page = contextDocument()->frame()->page();
   1478     ASSERT(page);
   1479     ASSERT(m_frontendWindow);
   1480 
   1481     page->inspectorController()->disconnectFrontend();
   1482 
   1483     m_frontendChannel.release();
   1484 
   1485     m_frontendWindow->close(m_frontendWindow->scriptExecutionContext());
   1486     m_frontendWindow.release();
   1487 }
   1488 
   1489 Vector<unsigned long> Internals::setMemoryCacheCapacities(unsigned long minDeadBytes, unsigned long maxDeadBytes, unsigned long totalBytes)
   1490 {
   1491     Vector<unsigned long> result;
   1492     result.append(memoryCache()->minDeadCapacity());
   1493     result.append(memoryCache()->maxDeadCapacity());
   1494     result.append(memoryCache()->capacity());
   1495     memoryCache()->setCapacities(minDeadBytes, maxDeadBytes, totalBytes);
   1496     return result;
   1497 }
   1498 
   1499 void Internals::setInspectorResourcesDataSizeLimits(int maximumResourcesContentSize, int maximumSingleResourceContentSize, ExceptionState& es)
   1500 {
   1501     Page* page = contextDocument()->frame()->page();
   1502     if (!page || !page->inspectorController()) {
   1503         es.throwDOMException(InvalidAccessError);
   1504         return;
   1505     }
   1506     page->inspectorController()->setResourcesDataSizeLimitsFromInternals(maximumResourcesContentSize, maximumSingleResourceContentSize);
   1507 }
   1508 
   1509 bool Internals::hasGrammarMarker(Document* document, int from, int length, ExceptionState&)
   1510 {
   1511     if (!document || !document->frame())
   1512         return 0;
   1513 
   1514     return document->frame()->editor()->selectionStartHasMarkerFor(DocumentMarker::Grammar, from, length);
   1515 }
   1516 
   1517 unsigned Internals::numberOfScrollableAreas(Document* document, ExceptionState&)
   1518 {
   1519     unsigned count = 0;
   1520     Frame* frame = document->frame();
   1521     if (frame->view()->scrollableAreas())
   1522         count += frame->view()->scrollableAreas()->size();
   1523 
   1524     for (Frame* child = frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
   1525         if (child->view() && child->view()->scrollableAreas())
   1526             count += child->view()->scrollableAreas()->size();
   1527     }
   1528 
   1529     return count;
   1530 }
   1531 
   1532 bool Internals::isPageBoxVisible(Document* document, int pageNumber, ExceptionState& es)
   1533 {
   1534     if (!document) {
   1535         es.throwDOMException(InvalidAccessError);
   1536         return false;
   1537     }
   1538 
   1539     return document->isPageBoxVisible(pageNumber);
   1540 }
   1541 
   1542 String Internals::layerTreeAsText(Document* document, ExceptionState& es) const
   1543 {
   1544     return layerTreeAsText(document, 0, es);
   1545 }
   1546 
   1547 String Internals::elementLayerTreeAsText(Element* element, ExceptionState& es) const
   1548 {
   1549     return elementLayerTreeAsText(element, 0, es);
   1550 }
   1551 
   1552 static PassRefPtr<NodeList> paintOrderList(Element* element, ExceptionState& es, RenderLayer::PaintOrderListType type)
   1553 {
   1554     if (!element) {
   1555         es.throwDOMException(InvalidAccessError);
   1556         return 0;
   1557     }
   1558 
   1559     element->document()->updateLayout();
   1560 
   1561     RenderObject* renderer = element->renderer();
   1562     if (!renderer || !renderer->isBox()) {
   1563         es.throwDOMException(InvalidAccessError);
   1564         return 0;
   1565     }
   1566 
   1567     RenderLayer* layer = toRenderBox(renderer)->layer();
   1568     if (!layer) {
   1569         es.throwDOMException(InvalidAccessError);
   1570         return 0;
   1571     }
   1572 
   1573     Vector<RefPtr<Node> > nodes;
   1574     layer->computePaintOrderList(type, nodes);
   1575     return StaticNodeList::adopt(nodes);
   1576 }
   1577 
   1578 PassRefPtr<NodeList> Internals::paintOrderListBeforePromote(Element* element, ExceptionState& es)
   1579 {
   1580     return paintOrderList(element, es, RenderLayer::BeforePromote);
   1581 }
   1582 
   1583 PassRefPtr<NodeList> Internals::paintOrderListAfterPromote(Element* element, ExceptionState& es)
   1584 {
   1585     return paintOrderList(element, es, RenderLayer::AfterPromote);
   1586 }
   1587 
   1588 String Internals::layerTreeAsText(Document* document, unsigned flags, ExceptionState& es) const
   1589 {
   1590     if (!document || !document->frame()) {
   1591         es.throwDOMException(InvalidAccessError);
   1592         return String();
   1593     }
   1594 
   1595     return document->frame()->layerTreeAsText(flags);
   1596 }
   1597 
   1598 String Internals::elementLayerTreeAsText(Element* element, unsigned flags, ExceptionState& es) const
   1599 {
   1600     if (!element) {
   1601         es.throwDOMException(InvalidAccessError);
   1602         return String();
   1603     }
   1604 
   1605     element->document()->updateLayout();
   1606 
   1607     RenderObject* renderer = element->renderer();
   1608     if (!renderer || !renderer->isBox()) {
   1609         es.throwDOMException(InvalidAccessError);
   1610         return String();
   1611     }
   1612 
   1613     RenderLayer* layer = toRenderBox(renderer)->layer();
   1614     if (!layer
   1615         || !layer->backing()
   1616         || !layer->backing()->graphicsLayer()) {
   1617         // Don't raise exception in these cases which may be normally used in tests.
   1618         return String();
   1619     }
   1620 
   1621     return layer->backing()->graphicsLayer()->layerTreeAsText(flags);
   1622 }
   1623 
   1624 void Internals::setNeedsCompositedScrolling(Element* element, unsigned needsCompositedScrolling, ExceptionState& es)
   1625 {
   1626     if (!element) {
   1627         es.throwDOMException(InvalidAccessError);
   1628         return;
   1629     }
   1630 
   1631     element->document()->updateLayout();
   1632 
   1633     RenderObject* renderer = element->renderer();
   1634     if (!renderer || !renderer->isBox()) {
   1635         es.throwDOMException(InvalidAccessError);
   1636         return;
   1637     }
   1638 
   1639     RenderLayer* layer = toRenderBox(renderer)->layer();
   1640     if (!layer) {
   1641         es.throwDOMException(InvalidAccessError);
   1642         return;
   1643     }
   1644 
   1645     layer->setForceNeedsCompositedScrolling(static_cast<RenderLayer::ForceNeedsCompositedScrollingMode>(needsCompositedScrolling));
   1646 }
   1647 
   1648 String Internals::repaintRectsAsText(Document* document, ExceptionState& es) const
   1649 {
   1650     if (!document || !document->frame()) {
   1651         es.throwDOMException(InvalidAccessError);
   1652         return String();
   1653     }
   1654 
   1655     return document->frame()->trackedRepaintRectsAsText();
   1656 }
   1657 
   1658 String Internals::scrollingStateTreeAsText(Document* document, ExceptionState& es) const
   1659 {
   1660     return String();
   1661 }
   1662 
   1663 String Internals::mainThreadScrollingReasons(Document* document, ExceptionState& es) const
   1664 {
   1665     if (!document || !document->frame()) {
   1666         es.throwDOMException(InvalidAccessError);
   1667         return String();
   1668     }
   1669 
   1670     Page* page = document->page();
   1671     if (!page)
   1672         return String();
   1673 
   1674     return page->mainThreadScrollingReasonsAsText();
   1675 }
   1676 
   1677 PassRefPtr<ClientRectList> Internals::nonFastScrollableRects(Document* document, ExceptionState& es) const
   1678 {
   1679     if (!document || !document->frame()) {
   1680         es.throwDOMException(InvalidAccessError);
   1681         return 0;
   1682     }
   1683 
   1684     Page* page = document->page();
   1685     if (!page)
   1686         return 0;
   1687 
   1688     return page->nonFastScrollableRects(document->frame());
   1689 }
   1690 
   1691 void Internals::garbageCollectDocumentResources(Document* document, ExceptionState& es) const
   1692 {
   1693     if (!document) {
   1694         es.throwDOMException(InvalidAccessError);
   1695         return;
   1696     }
   1697 
   1698     ResourceFetcher* fetcher = document->fetcher();
   1699     if (!fetcher)
   1700         return;
   1701     fetcher->garbageCollectDocumentResources();
   1702 }
   1703 
   1704 void Internals::evictAllResources() const
   1705 {
   1706     memoryCache()->evictResources();
   1707 }
   1708 
   1709 void Internals::allowRoundingHacks() const
   1710 {
   1711     TextRun::setAllowsRoundingHacks(true);
   1712 }
   1713 
   1714 void Internals::insertAuthorCSS(Document* document, const String& css) const
   1715 {
   1716     RefPtr<StyleSheetContents> parsedSheet = StyleSheetContents::create(document);
   1717     parsedSheet->setIsUserStyleSheet(false);
   1718     parsedSheet->parseString(css);
   1719     document->styleSheetCollection()->addAuthorSheet(parsedSheet);
   1720 }
   1721 
   1722 void Internals::insertUserCSS(Document* document, const String& css) const
   1723 {
   1724     RefPtr<StyleSheetContents> parsedSheet = StyleSheetContents::create(document);
   1725     parsedSheet->setIsUserStyleSheet(true);
   1726     parsedSheet->parseString(css);
   1727     document->styleSheetCollection()->addUserSheet(parsedSheet);
   1728 }
   1729 
   1730 String Internals::counterValue(Element* element)
   1731 {
   1732     if (!element)
   1733         return String();
   1734 
   1735     return counterValueForElement(element);
   1736 }
   1737 
   1738 int Internals::pageNumber(Element* element, float pageWidth, float pageHeight)
   1739 {
   1740     if (!element)
   1741         return 0;
   1742 
   1743     return PrintContext::pageNumberForElement(element, FloatSize(pageWidth, pageHeight));
   1744 }
   1745 
   1746 Vector<String> Internals::iconURLs(Document* document, int iconTypesMask) const
   1747 {
   1748     Vector<IconURL> iconURLs = document->iconURLs(iconTypesMask);
   1749     Vector<String> array;
   1750 
   1751     Vector<IconURL>::const_iterator iter(iconURLs.begin());
   1752     for (; iter != iconURLs.end(); ++iter)
   1753         array.append(iter->m_iconURL.string());
   1754 
   1755     return array;
   1756 }
   1757 
   1758 Vector<String> Internals::shortcutIconURLs(Document* document) const
   1759 {
   1760     return iconURLs(document, Favicon);
   1761 }
   1762 
   1763 Vector<String> Internals::allIconURLs(Document* document) const
   1764 {
   1765     return iconURLs(document, Favicon | TouchIcon | TouchPrecomposedIcon);
   1766 }
   1767 
   1768 int Internals::numberOfPages(float pageWidth, float pageHeight)
   1769 {
   1770     if (!frame())
   1771         return -1;
   1772 
   1773     return PrintContext::numberOfPages(frame(), FloatSize(pageWidth, pageHeight));
   1774 }
   1775 
   1776 String Internals::pageProperty(String propertyName, int pageNumber, ExceptionState& es) const
   1777 {
   1778     if (!frame()) {
   1779         es.throwDOMException(InvalidAccessError);
   1780         return String();
   1781     }
   1782 
   1783     return PrintContext::pageProperty(frame(), propertyName.utf8().data(), pageNumber);
   1784 }
   1785 
   1786 String Internals::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft, ExceptionState& es) const
   1787 {
   1788     if (!frame()) {
   1789         es.throwDOMException(InvalidAccessError);
   1790         return String();
   1791     }
   1792 
   1793     return PrintContext::pageSizeAndMarginsInPixels(frame(), pageNumber, width, height, marginTop, marginRight, marginBottom, marginLeft);
   1794 }
   1795 
   1796 void Internals::setDeviceScaleFactor(float scaleFactor, ExceptionState& es)
   1797 {
   1798     Document* document = contextDocument();
   1799     if (!document || !document->page()) {
   1800         es.throwDOMException(InvalidAccessError);
   1801         return;
   1802     }
   1803     Page* page = document->page();
   1804     page->setDeviceScaleFactor(scaleFactor);
   1805 }
   1806 
   1807 void Internals::setIsCursorVisible(Document* document, bool isVisible, ExceptionState& es)
   1808 {
   1809     if (!document || !document->page()) {
   1810         es.throwDOMException(InvalidAccessError);
   1811         return;
   1812     }
   1813     document->page()->setIsCursorVisible(isVisible);
   1814 }
   1815 
   1816 void Internals::webkitWillEnterFullScreenForElement(Document* document, Element* element)
   1817 {
   1818     if (!document)
   1819         return;
   1820     FullscreenElementStack::from(document)->webkitWillEnterFullScreenForElement(element);
   1821 }
   1822 
   1823 void Internals::webkitDidEnterFullScreenForElement(Document* document, Element* element)
   1824 {
   1825     if (!document)
   1826         return;
   1827     FullscreenElementStack::from(document)->webkitDidEnterFullScreenForElement(element);
   1828 }
   1829 
   1830 void Internals::webkitWillExitFullScreenForElement(Document* document, Element* element)
   1831 {
   1832     if (!document)
   1833         return;
   1834     FullscreenElementStack::from(document)->webkitWillExitFullScreenForElement(element);
   1835 }
   1836 
   1837 void Internals::webkitDidExitFullScreenForElement(Document* document, Element* element)
   1838 {
   1839     if (!document)
   1840         return;
   1841     FullscreenElementStack::from(document)->webkitDidExitFullScreenForElement(element);
   1842 }
   1843 
   1844 void Internals::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme)
   1845 {
   1846     SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
   1847 }
   1848 
   1849 void Internals::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(const String& scheme)
   1850 {
   1851     SchemeRegistry::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(scheme);
   1852 }
   1853 
   1854 PassRefPtr<MallocStatistics> Internals::mallocStatistics() const
   1855 {
   1856     return MallocStatistics::create();
   1857 }
   1858 
   1859 PassRefPtr<TypeConversions> Internals::typeConversions() const
   1860 {
   1861     return TypeConversions::create();
   1862 }
   1863 
   1864 Vector<String> Internals::getReferencedFilePaths() const
   1865 {
   1866     frame()->loader()->history()->saveDocumentAndScrollState();
   1867     return FormController::getReferencedFilePaths(frame()->loader()->history()->currentItem()->documentState());
   1868 }
   1869 
   1870 void Internals::startTrackingRepaints(Document* document, ExceptionState& es)
   1871 {
   1872     if (!document || !document->view()) {
   1873         es.throwDOMException(InvalidAccessError);
   1874         return;
   1875     }
   1876 
   1877     FrameView* frameView = document->view();
   1878     frameView->setTracksRepaints(true);
   1879 }
   1880 
   1881 void Internals::stopTrackingRepaints(Document* document, ExceptionState& es)
   1882 {
   1883     if (!document || !document->view()) {
   1884         es.throwDOMException(InvalidAccessError);
   1885         return;
   1886     }
   1887 
   1888     FrameView* frameView = document->view();
   1889     frameView->setTracksRepaints(false);
   1890 }
   1891 
   1892 static const char* cursorTypeToString(Cursor::Type cursorType)
   1893 {
   1894     switch (cursorType) {
   1895     case Cursor::Pointer: return "Pointer";
   1896     case Cursor::Cross: return "Cross";
   1897     case Cursor::Hand: return "Hand";
   1898     case Cursor::IBeam: return "IBeam";
   1899     case Cursor::Wait: return "Wait";
   1900     case Cursor::Help: return "Help";
   1901     case Cursor::EastResize: return "EastResize";
   1902     case Cursor::NorthResize: return "NorthResize";
   1903     case Cursor::NorthEastResize: return "NorthEastResize";
   1904     case Cursor::NorthWestResize: return "NorthWestResize";
   1905     case Cursor::SouthResize: return "SouthResize";
   1906     case Cursor::SouthEastResize: return "SouthEastResize";
   1907     case Cursor::SouthWestResize: return "SouthWestResize";
   1908     case Cursor::WestResize: return "WestResize";
   1909     case Cursor::NorthSouthResize: return "NorthSouthResize";
   1910     case Cursor::EastWestResize: return "EastWestResize";
   1911     case Cursor::NorthEastSouthWestResize: return "NorthEastSouthWestResize";
   1912     case Cursor::NorthWestSouthEastResize: return "NorthWestSouthEastResize";
   1913     case Cursor::ColumnResize: return "ColumnResize";
   1914     case Cursor::RowResize: return "RowResize";
   1915     case Cursor::MiddlePanning: return "MiddlePanning";
   1916     case Cursor::EastPanning: return "EastPanning";
   1917     case Cursor::NorthPanning: return "NorthPanning";
   1918     case Cursor::NorthEastPanning: return "NorthEastPanning";
   1919     case Cursor::NorthWestPanning: return "NorthWestPanning";
   1920     case Cursor::SouthPanning: return "SouthPanning";
   1921     case Cursor::SouthEastPanning: return "SouthEastPanning";
   1922     case Cursor::SouthWestPanning: return "SouthWestPanning";
   1923     case Cursor::WestPanning: return "WestPanning";
   1924     case Cursor::Move: return "Move";
   1925     case Cursor::VerticalText: return "VerticalText";
   1926     case Cursor::Cell: return "Cell";
   1927     case Cursor::ContextMenu: return "ContextMenu";
   1928     case Cursor::Alias: return "Alias";
   1929     case Cursor::Progress: return "Progress";
   1930     case Cursor::NoDrop: return "NoDrop";
   1931     case Cursor::Copy: return "Copy";
   1932     case Cursor::None: return "None";
   1933     case Cursor::NotAllowed: return "NotAllowed";
   1934     case Cursor::ZoomIn: return "ZoomIn";
   1935     case Cursor::ZoomOut: return "ZoomOut";
   1936     case Cursor::Grab: return "Grab";
   1937     case Cursor::Grabbing: return "Grabbing";
   1938     case Cursor::Custom: return "Custom";
   1939     }
   1940 
   1941     ASSERT_NOT_REACHED();
   1942     return "UNKNOWN";
   1943 }
   1944 
   1945 String Internals::getCurrentCursorInfo(Document* document, ExceptionState& es)
   1946 {
   1947     if (!document || !document->frame()) {
   1948         es.throwDOMException(InvalidAccessError);
   1949         return String();
   1950     }
   1951 
   1952     Cursor cursor = document->frame()->eventHandler()->currentMouseCursor();
   1953 
   1954     StringBuilder result;
   1955     result.append("type=");
   1956     result.append(cursorTypeToString(cursor.type()));
   1957     result.append(" hotSpot=");
   1958     result.appendNumber(cursor.hotSpot().x());
   1959     result.append(",");
   1960     result.appendNumber(cursor.hotSpot().y());
   1961     if (cursor.image()) {
   1962         IntSize size = cursor.image()->size();
   1963         result.append(" image=");
   1964         result.appendNumber(size.width());
   1965         result.append("x");
   1966         result.appendNumber(size.height());
   1967     }
   1968     if (cursor.imageScaleFactor() != 1) {
   1969         result.append(" scale=");
   1970         NumberToStringBuffer buffer;
   1971         result.append(numberToFixedPrecisionString(cursor.imageScaleFactor(), 8, buffer, true));
   1972     }
   1973 
   1974     return result.toString();
   1975 }
   1976 
   1977 PassRefPtr<ArrayBuffer> Internals::serializeObject(PassRefPtr<SerializedScriptValue> value) const
   1978 {
   1979     String stringValue = value->toWireString();
   1980     RefPtr<ArrayBuffer> buffer = ArrayBuffer::createUninitialized(stringValue.length(), sizeof(UChar));
   1981     stringValue.copyTo(static_cast<UChar*>(buffer->data()), 0, stringValue.length());
   1982     return buffer.release();
   1983 }
   1984 
   1985 PassRefPtr<SerializedScriptValue> Internals::deserializeBuffer(PassRefPtr<ArrayBuffer> buffer) const
   1986 {
   1987     String value(static_cast<const UChar*>(buffer->data()), buffer->byteLength() / sizeof(UChar));
   1988     return SerializedScriptValue::createFromWire(value);
   1989 }
   1990 
   1991 void Internals::setUsesOverlayScrollbars(bool enabled)
   1992 {
   1993     WebCore::Settings::setUsesOverlayScrollbars(enabled);
   1994 }
   1995 
   1996 void Internals::forceReload(bool endToEnd)
   1997 {
   1998     frame()->loader()->reload(endToEnd ? EndToEndReload : NormalReload);
   1999 }
   2000 
   2001 PassRefPtr<ClientRect> Internals::selectionBounds(ExceptionState& es)
   2002 {
   2003     Document* document = contextDocument();
   2004     if (!document || !document->frame() || !document->frame()->selection()) {
   2005         es.throwDOMException(InvalidAccessError);
   2006         return 0;
   2007     }
   2008 
   2009     return ClientRect::create(document->frame()->selection()->bounds());
   2010 }
   2011 
   2012 String Internals::markerTextForListItem(Element* element, ExceptionState& es)
   2013 {
   2014     if (!element) {
   2015         es.throwDOMException(InvalidAccessError);
   2016         return String();
   2017     }
   2018     return WebCore::markerTextForListItem(element);
   2019 }
   2020 
   2021 String Internals::getImageSourceURL(Element* element, ExceptionState& es)
   2022 {
   2023     if (!element) {
   2024         es.throwDOMException(InvalidAccessError);
   2025         return String();
   2026     }
   2027     return element->imageSourceURL();
   2028 }
   2029 
   2030 String Internals::baseURL(Document* document, ExceptionState& es)
   2031 {
   2032     if (!document) {
   2033         es.throwDOMException(InvalidAccessError);
   2034         return String();
   2035     }
   2036 
   2037     return document->baseURL().string();
   2038 }
   2039 
   2040 bool Internals::isSelectPopupVisible(Node* node)
   2041 {
   2042     if (!node->hasTagName(HTMLNames::selectTag))
   2043         return false;
   2044 
   2045     HTMLSelectElement* select = toHTMLSelectElement(node);
   2046 
   2047     RenderObject* renderer = select->renderer();
   2048     if (!renderer->isMenuList())
   2049         return false;
   2050 
   2051     RenderMenuList* menuList = toRenderMenuList(renderer);
   2052     return menuList->popupIsVisible();
   2053 }
   2054 
   2055 bool Internals::loseSharedGraphicsContext3D()
   2056 {
   2057     RefPtr<GraphicsContext3D> sharedContext = SharedGraphicsContext3D::get();
   2058     if (!sharedContext)
   2059         return false;
   2060     sharedContext->getExtensions()->loseContextCHROMIUM(Extensions3D::GUILTY_CONTEXT_RESET_ARB, Extensions3D::INNOCENT_CONTEXT_RESET_ARB);
   2061     // To prevent tests that call loseSharedGraphicsContext3D from being
   2062     // flaky, we call finish so that the context is guaranteed to be lost
   2063     // synchronously (i.e. before returning).
   2064     sharedContext->finish();
   2065     return true;
   2066 }
   2067 
   2068 }
   2069