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