Move parseFontFaceDescriptor to CSSPropertyParser.cpp
[chromium-blink-merge.git] / third_party / WebKit / Source / core / testing / Internals.cpp
blobc76ec67a169bd412dc1815b1b02c6edfbab2c86d
1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 * Copyright (C) 2013 Apple Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
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.
27 #include "config.h"
28 #include "core/testing/Internals.h"
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/SerializedScriptValueFactory.h"
37 #include "bindings/core/v8/V8IteratorResultValue.h"
38 #include "bindings/core/v8/V8ThrowException.h"
39 #include "core/HTMLNames.h"
40 #include "core/SVGNames.h"
41 #include "core/animation/AnimationTimeline.h"
42 #include "core/css/StyleSheetContents.h"
43 #include "core/css/resolver/StyleResolver.h"
44 #include "core/css/resolver/StyleResolverStats.h"
45 #include "core/css/resolver/ViewportStyleResolver.h"
46 #include "core/dom/ClientRect.h"
47 #include "core/dom/ClientRectList.h"
48 #include "core/dom/DOMArrayBuffer.h"
49 #include "core/dom/DOMPoint.h"
50 #include "core/dom/DOMStringList.h"
51 #include "core/dom/Document.h"
52 #include "core/dom/Element.h"
53 #include "core/dom/ExceptionCode.h"
54 #include "core/dom/Iterator.h"
55 #include "core/dom/NodeComputedStyle.h"
56 #include "core/dom/PseudoElement.h"
57 #include "core/dom/Range.h"
58 #include "core/dom/StaticNodeList.h"
59 #include "core/dom/StyleEngine.h"
60 #include "core/dom/TreeScope.h"
61 #include "core/dom/ViewportDescription.h"
62 #include "core/dom/shadow/ComposedTreeTraversal.h"
63 #include "core/dom/shadow/ElementShadow.h"
64 #include "core/dom/shadow/SelectRuleFeatureSet.h"
65 #include "core/dom/shadow/ShadowRoot.h"
66 #include "core/editing/Editor.h"
67 #include "core/editing/PlainTextRange.h"
68 #include "core/editing/SurroundingText.h"
69 #include "core/editing/iterators/TextIterator.h"
70 #include "core/editing/markers/DocumentMarker.h"
71 #include "core/editing/markers/DocumentMarkerController.h"
72 #include "core/editing/serializers/Serialization.h"
73 #include "core/editing/spellcheck/SpellCheckRequester.h"
74 #include "core/editing/spellcheck/SpellChecker.h"
75 #include "core/fetch/MemoryCache.h"
76 #include "core/fetch/ResourceFetcher.h"
77 #include "core/frame/EventHandlerRegistry.h"
78 #include "core/frame/FrameConsole.h"
79 #include "core/frame/FrameView.h"
80 #include "core/frame/LocalDOMWindow.h"
81 #include "core/frame/LocalFrame.h"
82 #include "core/frame/Settings.h"
83 #include "core/html/HTMLContentElement.h"
84 #include "core/html/HTMLIFrameElement.h"
85 #include "core/html/HTMLImageElement.h"
86 #include "core/html/HTMLInputElement.h"
87 #include "core/html/HTMLMediaElement.h"
88 #include "core/html/HTMLSelectElement.h"
89 #include "core/html/HTMLTextAreaElement.h"
90 #include "core/html/canvas/CanvasFontCache.h"
91 #include "core/html/canvas/CanvasRenderingContext.h"
92 #include "core/html/forms/FormController.h"
93 #include "core/html/shadow/ShadowElementNames.h"
94 #include "core/html/shadow/TextControlInnerElements.h"
95 #include "core/input/EventHandler.h"
96 #include "core/inspector/ConsoleMessageStorage.h"
97 #include "core/inspector/InspectorConsoleAgent.h"
98 #include "core/inspector/InspectorFrontendChannel.h"
99 #include "core/inspector/InspectorInstrumentation.h"
100 #include "core/inspector/InstanceCounters.h"
101 #include "core/inspector/InstrumentingAgents.h"
102 #include "core/layout/LayoutMenuList.h"
103 #include "core/layout/LayoutObject.h"
104 #include "core/layout/LayoutTreeAsText.h"
105 #include "core/layout/LayoutView.h"
106 #include "core/layout/compositing/CompositedDeprecatedPaintLayerMapping.h"
107 #include "core/layout/compositing/DeprecatedPaintLayerCompositor.h"
108 #include "core/loader/FrameLoader.h"
109 #include "core/loader/HistoryItem.h"
110 #include "core/page/ChromeClient.h"
111 #include "core/page/FocusController.h"
112 #include "core/page/NetworkStateNotifier.h"
113 #include "core/page/Page.h"
114 #include "core/page/PrintContext.h"
115 #include "core/page/scrolling/ScrollState.h"
116 #include "core/paint/DeprecatedPaintLayer.h"
117 #include "core/svg/SVGImageElement.h"
118 #include "core/testing/DictionaryTest.h"
119 #include "core/testing/GCObservation.h"
120 #include "core/testing/InternalRuntimeFlags.h"
121 #include "core/testing/InternalSettings.h"
122 #include "core/testing/LayerRect.h"
123 #include "core/testing/LayerRectList.h"
124 #include "core/testing/PrivateScriptTest.h"
125 #include "core/testing/TypeConversions.h"
126 #include "core/testing/UnionTypesTest.h"
127 #include "core/workers/WorkerThread.h"
128 #include "platform/Cursor.h"
129 #include "platform/Language.h"
130 #include "platform/PlatformKeyboardEvent.h"
131 #include "platform/RuntimeEnabledFeatures.h"
132 #include "platform/TraceEvent.h"
133 #include "platform/geometry/IntRect.h"
134 #include "platform/geometry/LayoutRect.h"
135 #include "platform/graphics/GraphicsLayer.h"
136 #include "platform/graphics/filters/FilterOperation.h"
137 #include "platform/graphics/filters/FilterOperations.h"
138 #include "platform/heap/Handle.h"
139 #include "platform/weborigin/SchemeRegistry.h"
140 #include "public/platform/Platform.h"
141 #include "public/platform/WebConnectionType.h"
142 #include "public/platform/WebGraphicsContext3D.h"
143 #include "public/platform/WebGraphicsContext3DProvider.h"
144 #include "public/platform/WebLayer.h"
145 #include "wtf/InstanceCounter.h"
146 #include "wtf/PassOwnPtr.h"
147 #include "wtf/dtoa.h"
148 #include "wtf/text/StringBuffer.h"
149 #include <v8.h>
151 namespace blink {
153 namespace {
155 class InternalsIterationSource final : public ValueIterable<int>::IterationSource {
156 public:
157 bool next(ScriptState* scriptState, int& value, ExceptionState& exceptionState) override
159 if (m_index >= 5)
160 return false;
161 value = m_index * m_index;
162 return true;
166 } // namespace
168 static bool markerTypesFrom(const String& markerType, DocumentMarker::MarkerTypes& result)
170 if (markerType.isEmpty() || equalIgnoringCase(markerType, "all"))
171 result = DocumentMarker::AllMarkers();
172 else if (equalIgnoringCase(markerType, "Spelling"))
173 result = DocumentMarker::Spelling;
174 else if (equalIgnoringCase(markerType, "Grammar"))
175 result = DocumentMarker::Grammar;
176 else if (equalIgnoringCase(markerType, "TextMatch"))
177 result = DocumentMarker::TextMatch;
178 else
179 return false;
181 return true;
184 static SpellCheckRequester* spellCheckRequester(Document* document)
186 if (!document || !document->frame())
187 return 0;
188 return &document->frame()->spellChecker().spellCheckRequester();
191 const char* Internals::internalsId = "internals";
193 Internals* Internals::create(ScriptState* scriptState)
195 return new Internals(scriptState);
198 Internals::~Internals()
202 void Internals::resetToConsistentState(Page* page)
204 ASSERT(page);
206 page->setDeviceScaleFactor(1);
207 page->setIsCursorVisible(true);
208 page->setPageScaleFactor(1);
209 page->deprecatedLocalMainFrame()->view()->layoutViewportScrollableArea()->setScrollPosition(IntPoint(0, 0), ProgrammaticScroll);
210 overrideUserPreferredLanguages(Vector<AtomicString>());
211 if (!page->deprecatedLocalMainFrame()->spellChecker().isContinuousSpellCheckingEnabled())
212 page->deprecatedLocalMainFrame()->spellChecker().toggleContinuousSpellChecking();
213 if (page->deprecatedLocalMainFrame()->editor().isOverwriteModeEnabled())
214 page->deprecatedLocalMainFrame()->editor().toggleOverwriteModeEnabled();
216 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
217 scrollingCoordinator->reset();
219 page->deprecatedLocalMainFrame()->view()->clear();
220 PlatformKeyboardEvent::setCurrentCapsLockState(PlatformKeyboardEvent::OverrideCapsLockState::Default);
223 Internals::Internals(ScriptState* scriptState)
224 : ContextLifecycleObserver(scriptState->executionContext())
225 , m_runtimeFlags(InternalRuntimeFlags::create())
229 Document* Internals::contextDocument() const
231 return toDocument(executionContext());
234 LocalFrame* Internals::frame() const
236 if (!contextDocument())
237 return 0;
238 return contextDocument()->frame();
241 InternalSettings* Internals::settings() const
243 Document* document = contextDocument();
244 if (!document)
245 return 0;
246 Page* page = document->page();
247 if (!page)
248 return 0;
249 return InternalSettings::from(*page);
252 InternalRuntimeFlags* Internals::runtimeFlags() const
254 return m_runtimeFlags.get();
257 unsigned Internals::workerThreadCount() const
259 return WorkerThread::workerThreadCount();
262 String Internals::address(Node* node)
264 char buf[32];
265 sprintf(buf, "%p", node);
267 return String(buf);
270 GCObservation* Internals::observeGC(ScriptValue scriptValue)
272 v8::Local<v8::Value> observedValue = scriptValue.v8Value();
273 ASSERT(!observedValue.IsEmpty());
274 if (observedValue->IsNull() || observedValue->IsUndefined()) {
275 V8ThrowException::throwTypeError(v8::Isolate::GetCurrent(), "value to observe is null or undefined");
276 return nullptr;
279 return GCObservation::create(observedValue);
282 unsigned Internals::updateStyleAndReturnAffectedElementCount(ExceptionState& exceptionState) const
284 Document* document = contextDocument();
285 if (!document) {
286 exceptionState.throwDOMException(InvalidAccessError, "No context document is available.");
287 return 0;
290 unsigned beforeCount = document->styleEngine().resolverAccessCount();
291 document->updateLayoutTreeIfNeeded();
292 return document->styleEngine().resolverAccessCount() - beforeCount;
295 unsigned Internals::needsLayoutCount(ExceptionState& exceptionState) const
297 LocalFrame* contextFrame = frame();
298 if (!contextFrame) {
299 exceptionState.throwDOMException(InvalidAccessError, "No context frame is available.");
300 return 0;
303 bool isPartial;
304 unsigned needsLayoutObjects;
305 unsigned totalObjects;
306 contextFrame->view()->countObjectsNeedingLayout(needsLayoutObjects, totalObjects, isPartial);
307 return needsLayoutObjects;
310 unsigned Internals::hitTestCount(Document* doc, ExceptionState& exceptionState) const
312 if (!doc) {
313 exceptionState.throwDOMException(InvalidAccessError, "Must supply document to check");
314 return 0;
317 return doc->layoutView()->hitTestCount();
320 unsigned Internals::hitTestCacheHits(Document* doc, ExceptionState& exceptionState) const
322 if (!doc) {
323 exceptionState.throwDOMException(InvalidAccessError, "Must supply document to check");
324 return 0;
327 return doc->layoutView()->hitTestCacheHits();
330 Element* Internals::elementFromPoint(Document* doc, double x, double y, bool ignoreClipping, bool allowChildFrameContent, ExceptionState& exceptionState) const
332 if (!doc) {
333 exceptionState.throwDOMException(InvalidAccessError, "Must supply document to check");
334 return 0;
337 if (!doc->layoutView())
338 return 0;
340 HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active;
341 if (ignoreClipping)
342 hitType |= HitTestRequest::IgnoreClipping;
343 if (allowChildFrameContent)
344 hitType |= HitTestRequest::AllowChildFrameContent;
346 HitTestRequest request(hitType);
348 return doc->hitTestPoint(x, y, request);
351 void Internals::clearHitTestCache(Document* doc, ExceptionState& exceptionState) const
353 if (!doc) {
354 exceptionState.throwDOMException(InvalidAccessError, "Must supply document to check");
355 return;
358 if (!doc->layoutView())
359 return;
361 doc->layoutView()->clearHitTestCache();
364 bool Internals::isPreloaded(const String& url)
366 return isPreloadedBy(url, contextDocument());
369 bool Internals::isPreloadedBy(const String& url, Document* document)
371 if (!document)
372 return false;
373 return document->fetcher()->isPreloaded(document->completeURL(url));
376 bool Internals::isLoadingFromMemoryCache(const String& url)
378 if (!contextDocument())
379 return false;
380 const String cacheIdentifier = contextDocument()->fetcher()->getCacheIdentifier();
381 Resource* resource = memoryCache()->resourceForURL(contextDocument()->completeURL(url), cacheIdentifier);
382 return resource && resource->status() == Resource::Cached;
385 bool Internals::isSharingStyle(Element* element1, Element* element2) const
387 ASSERT(element1 && element2);
388 return element1->computedStyle() == element2->computedStyle();
391 bool Internals::isValidContentSelect(Element* insertionPoint, ExceptionState& exceptionState)
393 ASSERT(insertionPoint);
394 if (!insertionPoint->isInsertionPoint()) {
395 exceptionState.throwDOMException(InvalidAccessError, "The element is not an insertion point.");
396 return false;
399 return isHTMLContentElement(*insertionPoint) && toHTMLContentElement(*insertionPoint).isSelectValid();
402 Node* Internals::treeScopeRootNode(Node* node)
404 ASSERT(node);
405 return &node->treeScope().rootNode();
408 Node* Internals::parentTreeScope(Node* node)
410 ASSERT(node);
411 const TreeScope* parentTreeScope = node->treeScope().parentTreeScope();
412 return parentTreeScope ? &parentTreeScope->rootNode() : 0;
415 bool Internals::hasSelectorForIdInShadow(Element* host, const AtomicString& idValue, ExceptionState& exceptionState)
417 ASSERT(host);
418 if (!host->shadow()) {
419 exceptionState.throwDOMException(InvalidAccessError, "The host element does not have a shadow.");
420 return false;
423 return host->shadow()->ensureSelectFeatureSet().hasSelectorForId(idValue);
426 bool Internals::hasSelectorForClassInShadow(Element* host, const AtomicString& className, ExceptionState& exceptionState)
428 ASSERT(host);
429 if (!host->shadow()) {
430 exceptionState.throwDOMException(InvalidAccessError, "The host element does not have a shadow.");
431 return false;
434 return host->shadow()->ensureSelectFeatureSet().hasSelectorForClass(className);
437 bool Internals::hasSelectorForAttributeInShadow(Element* host, const AtomicString& attributeName, ExceptionState& exceptionState)
439 ASSERT(host);
440 if (!host->shadow()) {
441 exceptionState.throwDOMException(InvalidAccessError, "The host element does not have a shadow.");
442 return false;
445 return host->shadow()->ensureSelectFeatureSet().hasSelectorForAttribute(attributeName);
448 unsigned short Internals::compareTreeScopePosition(const Node* node1, const Node* node2, ExceptionState& exceptionState) const
450 ASSERT(node1 && node2);
451 const TreeScope* treeScope1 = node1->isDocumentNode() ? static_cast<const TreeScope*>(toDocument(node1)) :
452 node1->isShadowRoot() ? static_cast<const TreeScope*>(toShadowRoot(node1)) : 0;
453 const TreeScope* treeScope2 = node2->isDocumentNode() ? static_cast<const TreeScope*>(toDocument(node2)) :
454 node2->isShadowRoot() ? static_cast<const TreeScope*>(toShadowRoot(node2)) : 0;
455 if (!treeScope1 || !treeScope2) {
456 exceptionState.throwDOMException(InvalidAccessError, String::format("The %s node is neither a document node, nor a shadow root.", treeScope1 ? "second" : "first"));
457 return 0;
459 return treeScope1->comparePosition(*treeScope2);
462 void Internals::pauseAnimations(double pauseTime, ExceptionState& exceptionState)
464 if (pauseTime < 0) {
465 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::indexExceedsMinimumBound("pauseTime", pauseTime, 0.0));
466 return;
469 frame()->view()->updateAllLifecyclePhases();
470 frame()->document()->timeline().pauseAnimationsForTesting(pauseTime);
473 bool Internals::isCompositedAnimation(Animation* animation)
475 return animation->hasActiveAnimationsOnCompositor();
478 void Internals::disableCompositedAnimation(Animation* animation)
480 animation->disableCompositedAnimationForTesting();
483 void Internals::advanceTimeForImage(Element* image, double deltaTimeInSeconds, ExceptionState& exceptionState)
485 ASSERT(image);
486 if (deltaTimeInSeconds < 0) {
487 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::indexExceedsMinimumBound("deltaTimeInSeconds", deltaTimeInSeconds, 0.0));
488 return;
491 ImageResource* resource = nullptr;
492 if (isHTMLImageElement(*image)) {
493 resource = toHTMLImageElement(*image).cachedImage();
494 } else if (isSVGImageElement(*image)) {
495 resource = toSVGImageElement(*image).cachedImage();
496 } else {
497 exceptionState.throwDOMException(InvalidAccessError, "The element provided is not a image element.");
498 return;
501 if (!resource || !resource->hasImage()) {
502 exceptionState.throwDOMException(InvalidAccessError, "The image resource is not available.");
503 return;
506 Image* imageData = resource->image();
507 if (!imageData->isBitmapImage()) {
508 exceptionState.throwDOMException(InvalidAccessError, "The image resource is not a BitmapImage type.");
509 return;
512 imageData->advanceTime(deltaTimeInSeconds);
515 void Internals::advanceImageAnimation(Element* image, ExceptionState& exceptionState)
517 ASSERT(image);
519 ImageResource* resource = nullptr;
520 if (isHTMLImageElement(*image)) {
521 resource = toHTMLImageElement(*image).cachedImage();
522 } else if (isSVGImageElement(*image)) {
523 resource = toSVGImageElement(*image).cachedImage();
524 } else {
525 exceptionState.throwDOMException(InvalidAccessError, "The element provided is not a image element.");
526 return;
529 if (!resource || !resource->hasImage()) {
530 exceptionState.throwDOMException(InvalidAccessError, "The image resource is not available.");
531 return;
534 Image* imageData = resource->image();
535 imageData->advanceAnimationForTesting();
538 bool Internals::hasShadowInsertionPoint(const Node* root, ExceptionState& exceptionState) const
540 ASSERT(root);
541 if (!root->isShadowRoot()) {
542 exceptionState.throwDOMException(InvalidAccessError, "The node argument is not a shadow root.");
543 return false;
545 return toShadowRoot(root)->containsShadowElements();
548 bool Internals::hasContentElement(const Node* root, ExceptionState& exceptionState) const
550 ASSERT(root);
551 if (!root->isShadowRoot()) {
552 exceptionState.throwDOMException(InvalidAccessError, "The node argument is not a shadow root.");
553 return false;
555 return toShadowRoot(root)->containsContentElements();
558 size_t Internals::countElementShadow(const Node* root, ExceptionState& exceptionState) const
560 ASSERT(root);
561 if (!root->isShadowRoot()) {
562 exceptionState.throwDOMException(InvalidAccessError, "The node argument is not a shadow root.");
563 return 0;
565 return toShadowRoot(root)->childShadowRootCount();
568 Node* Internals::nextSiblingInComposedTree(Node* node, ExceptionState& exceptionState)
570 ASSERT(node);
571 if (!node->canParticipateInComposedTree()) {
572 exceptionState.throwDOMException(InvalidAccessError, "The node argument doesn't particite in the composed tree.");
573 return 0;
575 return ComposedTreeTraversal::nextSibling(*node);
578 Node* Internals::firstChildInComposedTree(Node* node, ExceptionState& exceptionState)
580 ASSERT(node);
581 if (!node->canParticipateInComposedTree()) {
582 exceptionState.throwDOMException(InvalidAccessError, "The node argument doesn't particite in the composed tree");
583 return 0;
585 return ComposedTreeTraversal::firstChild(*node);
588 Node* Internals::lastChildInComposedTree(Node* node, ExceptionState& exceptionState)
590 ASSERT(node);
591 if (!node->canParticipateInComposedTree()) {
592 exceptionState.throwDOMException(InvalidAccessError, "The node argument doesn't particite in the composed tree.");
593 return 0;
595 return ComposedTreeTraversal::lastChild(*node);
598 Node* Internals::nextInComposedTree(Node* node, ExceptionState& exceptionState)
600 ASSERT(node);
601 if (!node->canParticipateInComposedTree()) {
602 exceptionState.throwDOMException(InvalidAccessError, "The node argument doesn't particite in the composed tree.");
603 return 0;
605 return ComposedTreeTraversal::next(*node);
608 Node* Internals::previousInComposedTree(Node* node, ExceptionState& exceptionState)
610 ASSERT(node);
611 if (!node->canParticipateInComposedTree()) {
612 exceptionState.throwDOMException(InvalidAccessError, "The node argument doesn't particite in the composed tree.");
613 return 0;
615 return ComposedTreeTraversal::previous(*node);
618 String Internals::elementLayoutTreeAsText(Element* element, ExceptionState& exceptionState)
620 ASSERT(element);
621 String representation = externalRepresentation(element);
622 if (representation.isEmpty()) {
623 exceptionState.throwDOMException(InvalidAccessError, "The element provided has no external representation.");
624 return String();
627 return representation;
630 PassRefPtrWillBeRawPtr<CSSStyleDeclaration> Internals::computedStyleIncludingVisitedInfo(Node* node) const
632 ASSERT(node);
633 bool allowVisitedStyle = true;
634 return CSSComputedStyleDeclaration::create(node, allowVisitedStyle);
637 PassRefPtrWillBeRawPtr<ShadowRoot> Internals::createUserAgentShadowRoot(Element* host)
639 ASSERT(host);
640 return PassRefPtrWillBeRawPtr<ShadowRoot>(host->ensureUserAgentShadowRoot());
643 ShadowRoot* Internals::shadowRoot(Element* host)
645 // FIXME: Internals::shadowRoot() in tests should be converted to youngestShadowRoot() or oldestShadowRoot().
646 // https://bugs.webkit.org/show_bug.cgi?id=78465
647 return youngestShadowRoot(host);
650 ShadowRoot* Internals::youngestShadowRoot(Element* host)
652 ASSERT(host);
653 if (ElementShadow* shadow = host->shadow())
654 return shadow->youngestShadowRoot();
655 return 0;
658 ShadowRoot* Internals::oldestShadowRoot(Element* host)
660 ASSERT(host);
661 if (ElementShadow* shadow = host->shadow())
662 return shadow->oldestShadowRoot();
663 return 0;
666 ShadowRoot* Internals::youngerShadowRoot(Node* shadow, ExceptionState& exceptionState)
668 ASSERT(shadow);
669 if (!shadow->isShadowRoot()) {
670 exceptionState.throwDOMException(InvalidAccessError, "The node provided is not a shadow root.");
671 return 0;
674 return toShadowRoot(shadow)->youngerShadowRoot();
677 String Internals::shadowRootType(const Node* root, ExceptionState& exceptionState) const
679 ASSERT(root);
680 if (!root->isShadowRoot()) {
681 exceptionState.throwDOMException(InvalidAccessError, "The node provided is not a shadow root.");
682 return String();
685 switch (toShadowRoot(root)->type()) {
686 case ShadowRootType::UserAgent:
687 return String("UserAgentShadowRoot");
688 case ShadowRootType::OpenByDefault:
689 return String("OpenByDefaultShadowRoot");
690 case ShadowRootType::Open:
691 return String("OpenShadowRoot");
692 case ShadowRootType::Closed:
693 return String("ClosedShadowRoot");
694 default:
695 ASSERT_NOT_REACHED();
696 return String("Unknown");
700 const AtomicString& Internals::shadowPseudoId(Element* element)
702 ASSERT(element);
703 return element->shadowPseudoId();
706 String Internals::visiblePlaceholder(Element* element)
708 if (element && isHTMLTextFormControlElement(*element)) {
709 const HTMLTextFormControlElement& textFormControlElement = toHTMLTextFormControlElement(*element);
710 if (!textFormControlElement.isPlaceholderVisible())
711 return String();
712 if (HTMLElement* placeholderElement = textFormControlElement.placeholderElement())
713 return placeholderElement->textContent();
716 return String();
719 void Internals::selectColorInColorChooser(Element* element, const String& colorValue)
721 ASSERT(element);
722 if (!isHTMLInputElement(*element))
723 return;
724 Color color;
725 if (!color.setFromString(colorValue))
726 return;
727 toHTMLInputElement(*element).selectColorInColorChooser(color);
730 void Internals::endColorChooser(Element* element)
732 ASSERT(element);
733 if (!isHTMLInputElement(*element))
734 return;
735 toHTMLInputElement(*element).endColorChooser();
738 bool Internals::hasAutofocusRequest(Document* document)
740 if (!document)
741 document = contextDocument();
742 return document->autofocusElement();
745 bool Internals::hasAutofocusRequest()
747 return hasAutofocusRequest(0);
750 Vector<String> Internals::formControlStateOfHistoryItem(ExceptionState& exceptionState)
752 HistoryItem* mainItem = frame()->loader().currentItem();
753 if (!mainItem) {
754 exceptionState.throwDOMException(InvalidAccessError, "No history item is available.");
755 return Vector<String>();
757 return mainItem->documentState();
760 void Internals::setFormControlStateOfHistoryItem(const Vector<String>& state, ExceptionState& exceptionState)
762 HistoryItem* mainItem = frame()->loader().currentItem();
763 if (!mainItem) {
764 exceptionState.throwDOMException(InvalidAccessError, "No history item is available.");
765 return;
767 mainItem->clearDocumentState();
768 mainItem->setDocumentState(state);
771 DOMWindow* Internals::pagePopupWindow() const
773 Document* document = contextDocument();
774 if (!document)
775 return nullptr;
776 if (Page* page = document->page())
777 return page->chromeClient().pagePopupWindowForTesting();
778 return nullptr;
781 ClientRect* Internals::absoluteCaretBounds(ExceptionState& exceptionState)
783 Document* document = contextDocument();
784 if (!document || !document->frame()) {
785 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's frame cannot be retrieved." : "No context document can be obtained.");
786 return ClientRect::create();
789 return ClientRect::create(document->frame()->selection().absoluteCaretBounds());
792 ClientRect* Internals::boundingBox(Element* element)
794 ASSERT(element);
796 element->document().updateLayoutIgnorePendingStylesheets();
797 LayoutObject* layoutObject = element->layoutObject();
798 if (!layoutObject)
799 return ClientRect::create();
800 return ClientRect::create(layoutObject->absoluteBoundingBoxRectIgnoringTransforms());
803 unsigned Internals::markerCountForNode(Node* node, const String& markerType, ExceptionState& exceptionState)
805 ASSERT(node);
806 DocumentMarker::MarkerTypes markerTypes = 0;
807 if (!markerTypesFrom(markerType, markerTypes)) {
808 exceptionState.throwDOMException(SyntaxError, "The marker type provided ('" + markerType + "') is invalid.");
809 return 0;
812 return node->document().markers().markersFor(node, markerTypes).size();
815 unsigned Internals::activeMarkerCountForNode(Node* node)
817 ASSERT(node);
819 // Only TextMatch markers can be active.
820 DocumentMarker::MarkerType markerType = DocumentMarker::TextMatch;
821 DocumentMarkerVector markers = node->document().markers().markersFor(node, markerType);
823 unsigned activeMarkerCount = 0;
824 for (const auto& marker : markers) {
825 if (marker->activeMatch())
826 activeMarkerCount++;
829 return activeMarkerCount;
832 DocumentMarker* Internals::markerAt(Node* node, const String& markerType, unsigned index, ExceptionState& exceptionState)
834 ASSERT(node);
835 DocumentMarker::MarkerTypes markerTypes = 0;
836 if (!markerTypesFrom(markerType, markerTypes)) {
837 exceptionState.throwDOMException(SyntaxError, "The marker type provided ('" + markerType + "') is invalid.");
838 return 0;
841 DocumentMarkerVector markers = node->document().markers().markersFor(node, markerTypes);
842 if (markers.size() <= index)
843 return 0;
844 return markers[index];
847 PassRefPtrWillBeRawPtr<Range> Internals::markerRangeForNode(Node* node, const String& markerType, unsigned index, ExceptionState& exceptionState)
849 ASSERT(node);
850 DocumentMarker* marker = markerAt(node, markerType, index, exceptionState);
851 if (!marker)
852 return nullptr;
853 return Range::create(node->document(), node, marker->startOffset(), node, marker->endOffset());
856 String Internals::markerDescriptionForNode(Node* node, const String& markerType, unsigned index, ExceptionState& exceptionState)
858 DocumentMarker* marker = markerAt(node, markerType, index, exceptionState);
859 if (!marker)
860 return String();
861 return marker->description();
864 void Internals::addTextMatchMarker(const Range* range, bool isActive)
866 ASSERT(range);
867 range->ownerDocument().updateLayoutIgnorePendingStylesheets();
868 range->ownerDocument().markers().addTextMatchMarker(range, isActive);
871 void Internals::setMarkersActive(Node* node, unsigned startOffset, unsigned endOffset, bool active)
873 ASSERT(node);
874 node->document().markers().setMarkersActive(node, startOffset, endOffset, active);
877 void Internals::setMarkedTextMatchesAreHighlighted(Document* document, bool highlight)
879 if (!document || !document->frame())
880 return;
882 document->frame()->editor().setMarkedTextMatchesAreHighlighted(highlight);
885 void Internals::setFrameViewPosition(Document* document, long x, long y, ExceptionState& exceptionState)
887 ASSERT(document);
888 if (!document->view()) {
889 exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
890 return;
893 FrameView* frameView = document->view();
894 bool scrollbarsSuppressedOldValue = frameView->scrollbarsSuppressed();
896 frameView->setScrollbarsSuppressed(false);
897 frameView->setScrollOffsetFromInternals(IntPoint(x, y));
898 frameView->setScrollbarsSuppressed(scrollbarsSuppressedOldValue);
901 String Internals::viewportAsText(Document* document, float, int availableWidth, int availableHeight, ExceptionState& exceptionState)
903 ASSERT(document);
904 if (!document->page()) {
905 exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
906 return String();
909 document->updateLayoutIgnorePendingStylesheets();
911 Page* page = document->page();
913 // Update initial viewport size.
914 IntSize initialViewportSize(availableWidth, availableHeight);
915 document->page()->deprecatedLocalMainFrame()->view()->setFrameRect(IntRect(IntPoint::zero(), initialViewportSize));
917 ViewportDescription description = page->viewportDescription();
918 PageScaleConstraints constraints = description.resolve(initialViewportSize, Length());
920 constraints.fitToContentsWidth(constraints.layoutSize.width(), availableWidth);
921 constraints.resolveAutoInitialScale();
923 StringBuilder builder;
925 builder.appendLiteral("viewport size ");
926 builder.append(String::number(constraints.layoutSize.width()));
927 builder.append('x');
928 builder.append(String::number(constraints.layoutSize.height()));
930 builder.appendLiteral(" scale ");
931 builder.append(String::number(constraints.initialScale));
932 builder.appendLiteral(" with limits [");
933 builder.append(String::number(constraints.minimumScale));
934 builder.appendLiteral(", ");
935 builder.append(String::number(constraints.maximumScale));
937 builder.appendLiteral("] and userScalable ");
938 builder.append(description.userZoom ? "true" : "false");
940 return builder.toString();
943 bool Internals::wasLastChangeUserEdit(Element* textField, ExceptionState& exceptionState)
945 ASSERT(textField);
946 if (isHTMLInputElement(*textField))
947 return toHTMLInputElement(*textField).lastChangeWasUserEdit();
949 if (isHTMLTextAreaElement(*textField))
950 return toHTMLTextAreaElement(*textField).lastChangeWasUserEdit();
952 exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not a TEXTAREA.");
953 return false;
956 bool Internals::elementShouldAutoComplete(Element* element, ExceptionState& exceptionState)
958 ASSERT(element);
959 if (isHTMLInputElement(*element))
960 return toHTMLInputElement(*element).shouldAutocomplete();
962 exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not an INPUT.");
963 return false;
966 String Internals::suggestedValue(Element* element, ExceptionState& exceptionState)
968 ASSERT(element);
969 if (!element->isFormControlElement()) {
970 exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not a form control element.");
971 return String();
974 String suggestedValue;
975 if (isHTMLInputElement(*element))
976 suggestedValue = toHTMLInputElement(*element).suggestedValue();
978 if (isHTMLTextAreaElement(*element))
979 suggestedValue = toHTMLTextAreaElement(*element).suggestedValue();
981 if (isHTMLSelectElement(*element))
982 suggestedValue = toHTMLSelectElement(*element).suggestedValue();
984 return suggestedValue;
987 void Internals::setSuggestedValue(Element* element, const String& value, ExceptionState& exceptionState)
989 ASSERT(element);
990 if (!element->isFormControlElement()) {
991 exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not a form control element.");
992 return;
995 if (isHTMLInputElement(*element))
996 toHTMLInputElement(*element).setSuggestedValue(value);
998 if (isHTMLTextAreaElement(*element))
999 toHTMLTextAreaElement(*element).setSuggestedValue(value);
1001 if (isHTMLSelectElement(*element))
1002 toHTMLSelectElement(*element).setSuggestedValue(value);
1005 void Internals::setEditingValue(Element* element, const String& value, ExceptionState& exceptionState)
1007 ASSERT(element);
1008 if (!isHTMLInputElement(*element)) {
1009 exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not an INPUT.");
1010 return;
1013 toHTMLInputElement(*element).setEditingValue(value);
1016 void Internals::setAutofilled(Element* element, bool enabled, ExceptionState& exceptionState)
1018 ASSERT(element);
1019 if (!element->isFormControlElement()) {
1020 exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not a form control element.");
1021 return;
1023 toHTMLFormControlElement(element)->setAutofilled(enabled);
1026 void Internals::scrollElementToRect(Element* element, long x, long y, long w, long h, ExceptionState& exceptionState)
1028 ASSERT(element);
1029 if (!element->document().view()) {
1030 exceptionState.throwDOMException(InvalidNodeTypeError, element ? "No view can be obtained from the provided element's document." : ExceptionMessages::argumentNullOrIncorrectType(1, "Element"));
1031 return;
1034 FrameView* mainFrame = toLocalFrame(element->document().page()->mainFrame())->view();
1035 mainFrame->frame().document()->updateLayoutIgnorePendingStylesheets();
1037 FrameView* elementView = element->document().view();
1038 IntRect boundsInRootFrame = elementView->contentsToRootFrame(pixelSnappedIntRect(element->boundingBox()));
1039 IntRect boundsInRootContent = mainFrame->frameToContents(boundsInRootFrame);
1040 mainFrame->scrollableArea()->scrollIntoRect(LayoutRect(boundsInRootContent), FloatRect(x, y, w, h));
1043 PassRefPtrWillBeRawPtr<Range> Internals::rangeFromLocationAndLength(Element* scope, int rangeLocation, int rangeLength)
1045 ASSERT(scope);
1047 // TextIterator depends on Layout information, make sure layout it up to date.
1048 scope->document().updateLayoutIgnorePendingStylesheets();
1050 return createRange(PlainTextRange(rangeLocation, rangeLocation + rangeLength).createRange(*scope));
1053 unsigned Internals::locationFromRange(Element* scope, const Range* range)
1055 ASSERT(scope && range);
1056 // PlainTextRange depends on Layout information, make sure layout it up to date.
1057 scope->document().updateLayoutIgnorePendingStylesheets();
1059 return PlainTextRange::create(*scope, *range).start();
1062 unsigned Internals::lengthFromRange(Element* scope, const Range* range)
1064 ASSERT(scope && range);
1065 // PlainTextRange depends on Layout information, make sure layout it up to date.
1066 scope->document().updateLayoutIgnorePendingStylesheets();
1068 return PlainTextRange::create(*scope, *range).length();
1071 String Internals::rangeAsText(const Range* range)
1073 ASSERT(range);
1074 return range->text();
1077 // FIXME: The next four functions are very similar - combine them once
1078 // bestClickableNode/bestContextMenuNode have been combined..
1080 DOMPoint* Internals::touchPositionAdjustedToBestClickableNode(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState)
1082 ASSERT(document);
1083 if (!document->frame()) {
1084 exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1085 return 0;
1088 document->updateLayout();
1090 IntSize radius(width / 2, height / 2);
1091 IntPoint point(x + radius.width(), y + radius.height());
1093 EventHandler& eventHandler = document->frame()->eventHandler();
1094 IntPoint hitTestPoint = document->frame()->view()->rootFrameToContents(point);
1095 HitTestResult result = eventHandler.hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ListBased, LayoutSize(radius));
1097 Node* targetNode = 0;
1098 IntPoint adjustedPoint;
1100 bool foundNode = eventHandler.bestClickableNodeForHitTestResult(result, adjustedPoint, targetNode);
1101 if (foundNode)
1102 return DOMPoint::create(adjustedPoint.x(), adjustedPoint.y());
1104 return 0;
1107 Node* Internals::touchNodeAdjustedToBestClickableNode(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState)
1109 ASSERT(document);
1110 if (!document->frame()) {
1111 exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1112 return 0;
1115 document->updateLayout();
1117 IntSize radius(width / 2, height / 2);
1118 IntPoint point(x + radius.width(), y + radius.height());
1120 EventHandler& eventHandler = document->frame()->eventHandler();
1121 IntPoint hitTestPoint = document->frame()->view()->rootFrameToContents(point);
1122 HitTestResult result = eventHandler.hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ListBased, LayoutSize(radius));
1124 Node* targetNode = 0;
1125 IntPoint adjustedPoint;
1126 document->frame()->eventHandler().bestClickableNodeForHitTestResult(result, adjustedPoint, targetNode);
1127 return targetNode;
1130 DOMPoint* Internals::touchPositionAdjustedToBestContextMenuNode(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState)
1132 ASSERT(document);
1133 if (!document->frame()) {
1134 exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1135 return 0;
1138 document->updateLayout();
1140 IntSize radius(width / 2, height / 2);
1141 IntPoint point(x + radius.width(), y + radius.height());
1143 EventHandler& eventHandler = document->frame()->eventHandler();
1144 IntPoint hitTestPoint = document->frame()->view()->rootFrameToContents(point);
1145 HitTestResult result = eventHandler.hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ListBased, LayoutSize(radius));
1147 Node* targetNode = 0;
1148 IntPoint adjustedPoint;
1150 bool foundNode = eventHandler.bestContextMenuNodeForHitTestResult(result, adjustedPoint, targetNode);
1151 if (foundNode)
1152 return DOMPoint::create(adjustedPoint.x(), adjustedPoint.y());
1154 return DOMPoint::create(x, y);
1157 Node* Internals::touchNodeAdjustedToBestContextMenuNode(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState)
1159 ASSERT(document);
1160 if (!document->frame()) {
1161 exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1162 return 0;
1165 document->updateLayout();
1167 IntSize radius(width / 2, height / 2);
1168 IntPoint point(x + radius.width(), y + radius.height());
1170 EventHandler& eventHandler = document->frame()->eventHandler();
1171 IntPoint hitTestPoint = document->frame()->view()->rootFrameToContents(point);
1172 HitTestResult result = eventHandler.hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ListBased, LayoutSize(radius));
1174 Node* targetNode = 0;
1175 IntPoint adjustedPoint;
1176 eventHandler.bestContextMenuNodeForHitTestResult(result, adjustedPoint, targetNode);
1177 return targetNode;
1180 ClientRect* Internals::bestZoomableAreaForTouchPoint(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState)
1182 ASSERT(document);
1183 if (!document->frame()) {
1184 exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1185 return nullptr;
1188 document->updateLayout();
1190 IntSize radius(width / 2, height / 2);
1191 IntPoint point(x + radius.width(), y + radius.height());
1193 Node* targetNode = 0;
1194 IntRect zoomableArea;
1195 bool foundNode = document->frame()->eventHandler().bestZoomableAreaForTouchPoint(point, radius, zoomableArea, targetNode);
1196 if (foundNode)
1197 return ClientRect::create(zoomableArea);
1199 return nullptr;
1203 int Internals::lastSpellCheckRequestSequence(Document* document, ExceptionState& exceptionState)
1205 SpellCheckRequester* requester = spellCheckRequester(document);
1207 if (!requester) {
1208 exceptionState.throwDOMException(InvalidAccessError, "No spell check requestor can be obtained for the provided document.");
1209 return -1;
1212 return requester->lastRequestSequence();
1215 int Internals::lastSpellCheckProcessedSequence(Document* document, ExceptionState& exceptionState)
1217 SpellCheckRequester* requester = spellCheckRequester(document);
1219 if (!requester) {
1220 exceptionState.throwDOMException(InvalidAccessError, "No spell check requestor can be obtained for the provided document.");
1221 return -1;
1224 return requester->lastProcessedSequence();
1227 Vector<AtomicString> Internals::userPreferredLanguages() const
1229 return blink::userPreferredLanguages();
1232 // Optimally, the bindings generator would pass a Vector<AtomicString> here but
1233 // this is not supported yet.
1234 void Internals::setUserPreferredLanguages(const Vector<String>& languages)
1236 Vector<AtomicString> atomicLanguages;
1237 for (size_t i = 0; i < languages.size(); ++i)
1238 atomicLanguages.append(AtomicString(languages[i]));
1239 overrideUserPreferredLanguages(atomicLanguages);
1242 unsigned Internals::activeDOMObjectCount(Document* document)
1244 ASSERT(document);
1245 return document->activeDOMObjectCount();
1248 static unsigned eventHandlerCount(Document& document, EventHandlerRegistry::EventHandlerClass handlerClass)
1250 if (!document.frameHost())
1251 return 0;
1252 EventHandlerRegistry* registry = &document.frameHost()->eventHandlerRegistry();
1253 unsigned count = 0;
1254 const EventTargetSet* targets = registry->eventHandlerTargets(handlerClass);
1255 if (targets) {
1256 for (const auto& target : *targets)
1257 count += target.value;
1259 return count;
1262 unsigned Internals::wheelEventHandlerCount(Document* document)
1264 ASSERT(document);
1265 return eventHandlerCount(*document, EventHandlerRegistry::WheelEvent);
1268 unsigned Internals::scrollEventHandlerCount(Document* document)
1270 ASSERT(document);
1271 return eventHandlerCount(*document, EventHandlerRegistry::ScrollEvent);
1274 unsigned Internals::touchEventHandlerCount(Document* document)
1276 ASSERT(document);
1277 return eventHandlerCount(*document, EventHandlerRegistry::TouchEvent);
1280 static DeprecatedPaintLayer* findLayerForGraphicsLayer(DeprecatedPaintLayer* searchRoot, GraphicsLayer* graphicsLayer, IntSize* layerOffset, String* layerType)
1282 *layerOffset = IntSize();
1283 if (searchRoot->hasCompositedDeprecatedPaintLayerMapping() && graphicsLayer == searchRoot->compositedDeprecatedPaintLayerMapping()->mainGraphicsLayer()) {
1284 // If the |graphicsLayer| sets the scrollingContent layer as its
1285 // scroll parent, consider it belongs to the scrolling layer and
1286 // mark the layer type as "scrolling".
1287 if (!searchRoot->layoutObject()->hasTransformRelatedProperty() && searchRoot->scrollParent() && searchRoot->parent() == searchRoot->scrollParent()) {
1288 *layerType = "scrolling";
1289 // For hit-test rect visualization to work, the hit-test rect should
1290 // be relative to the scrolling layer and in this case the hit-test
1291 // rect is relative to the element's own GraphicsLayer. So we will have
1292 // to adjust the rect to be relative to the scrolling layer here.
1293 // Only when the element's offsetParent == scroller's offsetParent we
1294 // can compute the element's relative position to the scrolling content
1295 // in this way.
1296 if (searchRoot->layoutObject()->offsetParent() == searchRoot->parent()->layoutObject()->offsetParent()) {
1297 LayoutBoxModelObject* current = searchRoot->layoutObject();
1298 LayoutBoxModelObject* parent = searchRoot->parent()->layoutObject();
1299 layerOffset->setWidth((parent->offsetLeft() - current->offsetLeft()).toInt());
1300 layerOffset->setHeight((parent->offsetTop() - current->offsetTop()).toInt());
1301 return searchRoot->parent();
1305 LayoutRect rect;
1306 DeprecatedPaintLayer::mapRectToPaintBackingCoordinates(searchRoot->layoutObject(), rect);
1307 *layerOffset = IntSize(rect.x(), rect.y());
1308 return searchRoot;
1311 // If the |graphicsLayer| is a scroller's scrollingContent layer,
1312 // consider this is a scrolling layer.
1313 GraphicsLayer* layerForScrolling = searchRoot->scrollableArea() ? searchRoot->scrollableArea()->layerForScrolling() : 0;
1314 if (graphicsLayer == layerForScrolling) {
1315 *layerType = "scrolling";
1316 return searchRoot;
1319 if (searchRoot->compositingState() == PaintsIntoGroupedBacking) {
1320 GraphicsLayer* squashingLayer = searchRoot->groupedMapping()->squashingLayer();
1321 if (graphicsLayer == squashingLayer) {
1322 *layerType ="squashing";
1323 LayoutRect rect;
1324 DeprecatedPaintLayer::mapRectToPaintBackingCoordinates(searchRoot->layoutObject(), rect);
1325 *layerOffset = IntSize(rect.x(), rect.y());
1326 return searchRoot;
1330 GraphicsLayer* layerForHorizontalScrollbar = searchRoot->scrollableArea() ? searchRoot->scrollableArea()->layerForHorizontalScrollbar() : 0;
1331 if (graphicsLayer == layerForHorizontalScrollbar) {
1332 *layerType = "horizontalScrollbar";
1333 return searchRoot;
1336 GraphicsLayer* layerForVerticalScrollbar = searchRoot->scrollableArea() ? searchRoot->scrollableArea()->layerForVerticalScrollbar() : 0;
1337 if (graphicsLayer == layerForVerticalScrollbar) {
1338 *layerType = "verticalScrollbar";
1339 return searchRoot;
1342 GraphicsLayer* layerForScrollCorner = searchRoot->scrollableArea() ? searchRoot->scrollableArea()->layerForScrollCorner() : 0;
1343 if (graphicsLayer == layerForScrollCorner) {
1344 *layerType = "scrollCorner";
1345 return searchRoot;
1348 // Search right to left to increase the chances that we'll choose the top-most layers in a
1349 // grouped mapping for squashing.
1350 for (DeprecatedPaintLayer* child = searchRoot->lastChild(); child; child = child->previousSibling()) {
1351 DeprecatedPaintLayer* foundLayer = findLayerForGraphicsLayer(child, graphicsLayer, layerOffset, layerType);
1352 if (foundLayer)
1353 return foundLayer;
1356 return 0;
1359 // Given a vector of rects, merge those that are adjacent, leaving empty rects
1360 // in the place of no longer used slots. This is intended to simplify the list
1361 // of rects returned by an SkRegion (which have been split apart for sorting
1362 // purposes). No attempt is made to do this efficiently (eg. by relying on the
1363 // sort criteria of SkRegion).
1364 static void mergeRects(WebVector<blink::WebRect>& rects)
1366 for (size_t i = 0; i < rects.size(); ++i) {
1367 if (rects[i].isEmpty())
1368 continue;
1369 bool updated;
1370 do {
1371 updated = false;
1372 for (size_t j = i+1; j < rects.size(); ++j) {
1373 if (rects[j].isEmpty())
1374 continue;
1375 // Try to merge rects[j] into rects[i] along the 4 possible edges.
1376 if (rects[i].y == rects[j].y && rects[i].height == rects[j].height) {
1377 if (rects[i].x + rects[i].width == rects[j].x) {
1378 rects[i].width += rects[j].width;
1379 rects[j] = blink::WebRect();
1380 updated = true;
1381 } else if (rects[i].x == rects[j].x + rects[j].width) {
1382 rects[i].x = rects[j].x;
1383 rects[i].width += rects[j].width;
1384 rects[j] = blink::WebRect();
1385 updated = true;
1387 } else if (rects[i].x == rects[j].x && rects[i].width == rects[j].width) {
1388 if (rects[i].y + rects[i].height == rects[j].y) {
1389 rects[i].height += rects[j].height;
1390 rects[j] = blink::WebRect();
1391 updated = true;
1392 } else if (rects[i].y == rects[j].y + rects[j].height) {
1393 rects[i].y = rects[j].y;
1394 rects[i].height += rects[j].height;
1395 rects[j] = blink::WebRect();
1396 updated = true;
1400 } while (updated);
1404 static void accumulateLayerRectList(DeprecatedPaintLayerCompositor* compositor, GraphicsLayer* graphicsLayer, LayerRectList* rects)
1406 WebVector<blink::WebRect> layerRects = graphicsLayer->platformLayer()->touchEventHandlerRegion();
1407 if (!layerRects.isEmpty()) {
1408 mergeRects(layerRects);
1409 String layerType;
1410 IntSize layerOffset;
1411 DeprecatedPaintLayer* paintLayer = findLayerForGraphicsLayer(compositor->rootLayer(), graphicsLayer, &layerOffset, &layerType);
1412 Node* node = paintLayer ? paintLayer->layoutObject()->node() : 0;
1413 for (size_t i = 0; i < layerRects.size(); ++i) {
1414 if (!layerRects[i].isEmpty()) {
1415 rects->append(node, layerType, layerOffset.width(), layerOffset.height(), ClientRect::create(layerRects[i]));
1420 size_t numChildren = graphicsLayer->children().size();
1421 for (size_t i = 0; i < numChildren; ++i)
1422 accumulateLayerRectList(compositor, graphicsLayer->children()[i], rects);
1425 LayerRectList* Internals::touchEventTargetLayerRects(Document* document, ExceptionState& exceptionState)
1427 ASSERT(document);
1428 if (!document->view() || !document->page() || document != contextDocument()) {
1429 exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1430 return nullptr;
1433 // Do any pending layout and compositing update (which may call touchEventTargetRectsChange) to ensure this
1434 // really takes any previous changes into account.
1435 forceCompositingUpdate(document, exceptionState);
1436 if (exceptionState.hadException())
1437 return nullptr;
1439 if (LayoutView* view = document->layoutView()) {
1440 if (DeprecatedPaintLayerCompositor* compositor = view->compositor()) {
1441 if (GraphicsLayer* rootLayer = compositor->rootGraphicsLayer()) {
1442 LayerRectList* rects = LayerRectList::create();
1443 accumulateLayerRectList(compositor, rootLayer, rects);
1444 return rects;
1449 return nullptr;
1452 bool Internals::executeCommand(Document* document, const String& name, const String& value, ExceptionState& exceptionState)
1454 ASSERT(document);
1455 if (!document->frame()) {
1456 exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1457 return false;
1460 LocalFrame* frame = document->frame();
1461 return frame->editor().executeCommand(name, value);
1464 AtomicString Internals::htmlNamespace()
1466 return HTMLNames::xhtmlNamespaceURI;
1469 Vector<AtomicString> Internals::htmlTags()
1471 Vector<AtomicString> tags(HTMLNames::HTMLTagsCount);
1472 OwnPtr<const HTMLQualifiedName*[]> qualifiedNames = HTMLNames::getHTMLTags();
1473 for (size_t i = 0; i < HTMLNames::HTMLTagsCount; ++i)
1474 tags[i] = qualifiedNames[i]->localName();
1475 return tags;
1478 AtomicString Internals::svgNamespace()
1480 return SVGNames::svgNamespaceURI;
1483 Vector<AtomicString> Internals::svgTags()
1485 Vector<AtomicString> tags(SVGNames::SVGTagsCount);
1486 OwnPtr<const SVGQualifiedName*[]> qualifiedNames = SVGNames::getSVGTags();
1487 for (size_t i = 0; i < SVGNames::SVGTagsCount; ++i)
1488 tags[i] = qualifiedNames[i]->localName();
1489 return tags;
1492 PassRefPtrWillBeRawPtr<StaticNodeList> Internals::nodesFromRect(Document* document, int centerX, int centerY, unsigned topPadding, unsigned rightPadding,
1493 unsigned bottomPadding, unsigned leftPadding, bool ignoreClipping, bool allowChildFrameContent, ExceptionState& exceptionState) const
1495 ASSERT(document);
1496 if (!document->frame() || !document->frame()->view()) {
1497 exceptionState.throwDOMException(InvalidAccessError, "No view can be obtained from the provided document.");
1498 return nullptr;
1501 LocalFrame* frame = document->frame();
1502 FrameView* frameView = document->view();
1503 LayoutView* layoutView = document->layoutView();
1505 if (!layoutView)
1506 return nullptr;
1508 float zoomFactor = frame->pageZoomFactor();
1509 LayoutPoint point = roundedLayoutPoint(FloatPoint(centerX * zoomFactor + frameView->scrollX(), centerY * zoomFactor + frameView->scrollY()));
1511 HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ListBased;
1512 if (ignoreClipping)
1513 hitType |= HitTestRequest::IgnoreClipping;
1514 if (allowChildFrameContent)
1515 hitType |= HitTestRequest::AllowChildFrameContent;
1517 HitTestRequest request(hitType);
1519 // When ignoreClipping is false, this method returns null for coordinates outside of the viewport.
1520 if (!request.ignoreClipping() && !frameView->visibleContentRect().intersects(HitTestLocation::rectForPoint(point, topPadding, rightPadding, bottomPadding, leftPadding)))
1521 return nullptr;
1523 WillBeHeapVector<RefPtrWillBeMember<Node>> matches;
1524 HitTestResult result(request, point, topPadding, rightPadding, bottomPadding, leftPadding);
1525 layoutView->hitTest(result);
1526 copyToVector(result.listBasedTestResult(), matches);
1528 return StaticNodeList::adopt(matches);
1531 bool Internals::hasSpellingMarker(Document* document, int from, int length)
1533 ASSERT(document);
1534 if (!document->frame())
1535 return false;
1537 return document->frame()->spellChecker().selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
1540 void Internals::setContinuousSpellCheckingEnabled(bool enabled)
1542 if (!contextDocument() || !contextDocument()->frame())
1543 return;
1545 if (enabled != contextDocument()->frame()->spellChecker().isContinuousSpellCheckingEnabled())
1546 contextDocument()->frame()->spellChecker().toggleContinuousSpellChecking();
1549 bool Internals::isOverwriteModeEnabled(Document* document)
1551 ASSERT(document);
1552 if (!document->frame())
1553 return false;
1555 return document->frame()->editor().isOverwriteModeEnabled();
1558 void Internals::toggleOverwriteModeEnabled(Document* document)
1560 ASSERT(document);
1561 if (!document->frame())
1562 return;
1564 document->frame()->editor().toggleOverwriteModeEnabled();
1567 unsigned Internals::numberOfLiveNodes() const
1569 return InstanceCounters::counterValue(InstanceCounters::NodeCounter);
1572 unsigned Internals::numberOfLiveDocuments() const
1574 return InstanceCounters::counterValue(InstanceCounters::DocumentCounter);
1577 String Internals::dumpRefCountedInstanceCounts() const
1579 return WTF::dumpRefCountedInstanceCounts();
1582 Vector<String> Internals::consoleMessageArgumentCounts(Document* document) const
1584 FrameHost* host = document->frameHost();
1585 if (!host)
1586 return Vector<String>();
1588 Vector<unsigned> counts = host->consoleMessageStorage().argumentCounts();
1589 Vector<String> result(counts.size());
1590 for (size_t i = 0; i < counts.size(); i++)
1591 result[i] = String::number(counts[i]);
1592 return result;
1595 Vector<unsigned long> Internals::setMemoryCacheCapacities(unsigned long minDeadBytes, unsigned long maxDeadBytes, unsigned long totalBytes)
1597 Vector<unsigned long> result;
1598 result.append(memoryCache()->minDeadCapacity());
1599 result.append(memoryCache()->maxDeadCapacity());
1600 result.append(memoryCache()->capacity());
1601 memoryCache()->setCapacities(minDeadBytes, maxDeadBytes, totalBytes);
1602 return result;
1605 bool Internals::hasGrammarMarker(Document* document, int from, int length)
1607 ASSERT(document);
1608 if (!document->frame())
1609 return false;
1611 return document->frame()->spellChecker().selectionStartHasMarkerFor(DocumentMarker::Grammar, from, length);
1614 unsigned Internals::numberOfScrollableAreas(Document* document)
1616 ASSERT(document);
1617 if (!document->frame())
1618 return 0;
1620 unsigned count = 0;
1621 LocalFrame* frame = document->frame();
1622 if (frame->view()->scrollableAreas())
1623 count += frame->view()->scrollableAreas()->size();
1625 for (Frame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
1626 if (child->isLocalFrame() && toLocalFrame(child)->view() && toLocalFrame(child)->view()->scrollableAreas())
1627 count += toLocalFrame(child)->view()->scrollableAreas()->size();
1630 return count;
1633 bool Internals::isPageBoxVisible(Document* document, int pageNumber)
1635 ASSERT(document);
1636 return document->isPageBoxVisible(pageNumber);
1639 String Internals::layerTreeAsText(Document* document, ExceptionState& exceptionState) const
1641 return layerTreeAsText(document, 0, exceptionState);
1644 String Internals::elementLayerTreeAsText(Element* element, ExceptionState& exceptionState) const
1646 ASSERT(element);
1647 FrameView* frameView = element->document().view();
1648 frameView->updateAllLifecyclePhases();
1650 return elementLayerTreeAsText(element, 0, exceptionState);
1653 bool Internals::scrollsWithRespectTo(Element* element1, Element* element2, ExceptionState& exceptionState)
1655 ASSERT(element1 && element2);
1656 element1->document().view()->updateAllLifecyclePhases();
1658 LayoutObject* layoutObject1 = element1->layoutObject();
1659 LayoutObject* layoutObject2 = element2->layoutObject();
1660 if (!layoutObject1 || !layoutObject1->isBox()) {
1661 exceptionState.throwDOMException(InvalidAccessError, layoutObject1 ? "The first provided element's layoutObject is not a box." : "The first provided element has no layoutObject.");
1662 return false;
1664 if (!layoutObject2 || !layoutObject2->isBox()) {
1665 exceptionState.throwDOMException(InvalidAccessError, layoutObject2 ? "The second provided element's layoutObject is not a box." : "The second provided element has no layoutObject.");
1666 return false;
1669 DeprecatedPaintLayer* layer1 = toLayoutBox(layoutObject1)->layer();
1670 DeprecatedPaintLayer* layer2 = toLayoutBox(layoutObject2)->layer();
1671 if (!layer1 || !layer2) {
1672 exceptionState.throwDOMException(InvalidAccessError, String::format("No DeprecatedPaintLayer can be obtained from the %s provided element.", layer1 ? "second" : "first"));
1673 return false;
1676 return layer1->scrollsWithRespectTo(layer2);
1679 String Internals::layerTreeAsText(Document* document, unsigned flags, ExceptionState& exceptionState) const
1681 ASSERT(document);
1682 if (!document->frame()) {
1683 exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1684 return String();
1687 document->view()->updateAllLifecyclePhases();
1689 return document->frame()->layerTreeAsText(flags);
1692 String Internals::elementLayerTreeAsText(Element* element, unsigned flags, ExceptionState& exceptionState) const
1694 ASSERT(element);
1695 element->document().updateLayout();
1697 LayoutObject* layoutObject = element->layoutObject();
1698 if (!layoutObject || !layoutObject->isBox()) {
1699 exceptionState.throwDOMException(InvalidAccessError, layoutObject ? "The provided element's layoutObject is not a box." : "The provided element has no layoutObject.");
1700 return String();
1703 DeprecatedPaintLayer* layer = toLayoutBox(layoutObject)->layer();
1704 if (!layer
1705 || !layer->hasCompositedDeprecatedPaintLayerMapping()
1706 || !layer->compositedDeprecatedPaintLayerMapping()->mainGraphicsLayer()) {
1707 // Don't raise exception in these cases which may be normally used in tests.
1708 return String();
1711 return layer->compositedDeprecatedPaintLayerMapping()->mainGraphicsLayer()->layerTreeAsText(flags);
1714 String Internals::scrollingStateTreeAsText(Document*) const
1716 return String();
1719 String Internals::mainThreadScrollingReasons(Document* document, ExceptionState& exceptionState) const
1721 ASSERT(document);
1722 if (!document->frame()) {
1723 exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1724 return String();
1727 document->frame()->view()->updateAllLifecyclePhases();
1729 Page* page = document->page();
1730 if (!page)
1731 return String();
1733 return page->mainThreadScrollingReasonsAsText();
1736 ClientRectList* Internals::nonFastScrollableRects(Document* document, ExceptionState& exceptionState) const
1738 ASSERT(document);
1739 if (!document->frame()) {
1740 exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1741 return nullptr;
1744 Page* page = document->page();
1745 if (!page)
1746 return nullptr;
1748 return page->nonFastScrollableRects(document->frame());
1751 void Internals::garbageCollectDocumentResources(Document* document) const
1753 ASSERT(document);
1754 ResourceFetcher* fetcher = document->fetcher();
1755 if (!fetcher)
1756 return;
1757 fetcher->garbageCollectDocumentResources();
1760 void Internals::evictAllResources() const
1762 memoryCache()->evictResources();
1765 String Internals::counterValue(Element* element)
1767 if (!element)
1768 return String();
1770 return counterValueForElement(element);
1773 int Internals::pageNumber(Element* element, float pageWidth, float pageHeight)
1775 if (!element)
1776 return 0;
1778 return PrintContext::pageNumberForElement(element, FloatSize(pageWidth, pageHeight));
1781 Vector<String> Internals::iconURLs(Document* document, int iconTypesMask) const
1783 Vector<IconURL> iconURLs = document->iconURLs(iconTypesMask);
1784 Vector<String> array;
1786 for (auto& iconURL : iconURLs)
1787 array.append(iconURL.m_iconURL.string());
1789 return array;
1792 Vector<String> Internals::shortcutIconURLs(Document* document) const
1794 return iconURLs(document, Favicon);
1797 Vector<String> Internals::allIconURLs(Document* document) const
1799 return iconURLs(document, Favicon | TouchIcon | TouchPrecomposedIcon);
1802 int Internals::numberOfPages(float pageWidth, float pageHeight)
1804 if (!frame())
1805 return -1;
1807 return PrintContext::numberOfPages(frame(), FloatSize(pageWidth, pageHeight));
1810 String Internals::pageProperty(String propertyName, int pageNumber, ExceptionState& exceptionState) const
1812 if (!frame()) {
1813 exceptionState.throwDOMException(InvalidAccessError, "No frame is available.");
1814 return String();
1817 return PrintContext::pageProperty(frame(), propertyName.utf8().data(), pageNumber);
1820 String Internals::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft, ExceptionState& exceptionState) const
1822 if (!frame()) {
1823 exceptionState.throwDOMException(InvalidAccessError, "No frame is available.");
1824 return String();
1827 return PrintContext::pageSizeAndMarginsInPixels(frame(), pageNumber, width, height, marginTop, marginRight, marginBottom, marginLeft);
1830 void Internals::setDeviceScaleFactor(float scaleFactor, ExceptionState& exceptionState)
1832 Document* document = contextDocument();
1833 if (!document || !document->page()) {
1834 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's page cannot be retrieved." : "No context document can be obtained.");
1835 return;
1837 Page* page = document->page();
1838 page->setDeviceScaleFactor(scaleFactor);
1841 void Internals::setPageScaleFactor(float scaleFactor, ExceptionState& exceptionState)
1843 Document* document = contextDocument();
1844 if (!document || !document->page()) {
1845 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's page cannot be retrieved." : "No context document can be obtained.");
1846 return;
1848 Page* page = document->page();
1849 page->frameHost().visualViewport().setScale(scaleFactor);
1852 void Internals::setPageScaleFactorLimits(float minScaleFactor, float maxScaleFactor, ExceptionState& exceptionState)
1854 Document* document = contextDocument();
1855 if (!document || !document->page()) {
1856 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's page cannot be retrieved." : "No context document can be obtained.");
1857 return;
1860 Page* page = document->page();
1861 page->frameHost().setDefaultPageScaleLimits(minScaleFactor, maxScaleFactor);
1864 bool Internals::magnifyScaleAroundAnchor(float scaleFactor, float x, float y)
1866 return frame()->host()->visualViewport().magnifyScaleAroundAnchor(scaleFactor, FloatPoint(x, y));
1869 void Internals::setIsCursorVisible(Document* document, bool isVisible, ExceptionState& exceptionState)
1871 ASSERT(document);
1872 if (!document->page()) {
1873 exceptionState.throwDOMException(InvalidAccessError, "No context document can be obtained.");
1874 return;
1876 document->page()->setIsCursorVisible(isVisible);
1879 double Internals::effectiveMediaVolume(HTMLMediaElement* mediaElement)
1881 ASSERT(mediaElement);
1882 return mediaElement->effectiveMediaVolume();
1885 void Internals::mediaPlayerRemoteRouteAvailabilityChanged(HTMLMediaElement* mediaElement, bool available)
1887 ASSERT(mediaElement);
1888 mediaElement->remoteRouteAvailabilityChanged(available);
1891 void Internals::mediaPlayerPlayingRemotelyChanged(HTMLMediaElement* mediaElement, bool remote)
1893 ASSERT(mediaElement);
1894 if (remote)
1895 mediaElement->connectedToRemoteDevice();
1896 else
1897 mediaElement->disconnectedFromRemoteDevice();
1900 void Internals::setAllowHiddenVolumeControls(HTMLMediaElement* mediaElement, bool allow)
1902 ASSERT(mediaElement);
1903 mediaElement->setAllowHiddenVolumeControls(allow);
1906 void Internals::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme)
1908 SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
1911 void Internals::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme, const Vector<String>& policyAreas)
1913 uint32_t policyAreasEnum = SchemeRegistry::PolicyAreaNone;
1914 for (const auto& policyArea : policyAreas) {
1915 if (policyArea == "img")
1916 policyAreasEnum |= SchemeRegistry::PolicyAreaImage;
1917 else if (policyArea == "style")
1918 policyAreasEnum |= SchemeRegistry::PolicyAreaStyle;
1920 SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(
1921 scheme, static_cast<SchemeRegistry::PolicyAreas>(policyAreasEnum));
1924 void Internals::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(const String& scheme)
1926 SchemeRegistry::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(scheme);
1929 TypeConversions* Internals::typeConversions() const
1931 return TypeConversions::create();
1934 PrivateScriptTest* Internals::privateScriptTest() const
1936 return PrivateScriptTest::create(frame()->document());
1939 DictionaryTest* Internals::dictionaryTest() const
1941 return DictionaryTest::create();
1944 UnionTypesTest* Internals::unionTypesTest() const
1946 return UnionTypesTest::create();
1949 Vector<String> Internals::getReferencedFilePaths() const
1951 return frame()->loader().currentItem()->getReferencedFilePaths();
1954 void Internals::startTrackingRepaints(Document* document, ExceptionState& exceptionState)
1956 ASSERT(document);
1957 if (!document->view()) {
1958 exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1959 return;
1962 FrameView* frameView = document->view();
1963 frameView->updateAllLifecyclePhases();
1964 frameView->setTracksPaintInvalidations(true);
1967 void Internals::stopTrackingRepaints(Document* document, ExceptionState& exceptionState)
1969 ASSERT(document);
1970 if (!document->view()) {
1971 exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
1972 return;
1975 FrameView* frameView = document->view();
1976 frameView->updateAllLifecyclePhases();
1977 frameView->setTracksPaintInvalidations(false);
1980 void Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(Node* node, ExceptionState& exceptionState)
1982 Document* document;
1983 if (!node) {
1984 document = contextDocument();
1985 } else if (node->isDocumentNode()) {
1986 document = toDocument(node);
1987 } else if (isHTMLIFrameElement(*node)) {
1988 document = toHTMLIFrameElement(*node).contentDocument();
1989 } else {
1990 exceptionState.throwTypeError("The node provided is neither a document nor an IFrame.");
1991 return;
1993 document->updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasksSynchronously);
1996 void Internals::forceFullRepaint(Document* document, ExceptionState& exceptionState)
1998 ASSERT(document);
1999 if (!document->view()) {
2000 exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
2001 return;
2004 if (LayoutView *layoutView = document->layoutView())
2005 layoutView->invalidatePaintForViewAndCompositedLayers();
2008 void Internals::startTrackingPaintInvalidationObjects()
2010 ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
2011 toLocalFrame(frame()->page()->mainFrame())->view()->layoutView()->layer()->graphicsLayerBacking()->displayItemList()->startTrackingPaintInvalidationObjects();
2014 void Internals::stopTrackingPaintInvalidationObjects()
2016 ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
2017 toLocalFrame(frame()->page()->mainFrame())->view()->layoutView()->layer()->graphicsLayerBacking()->displayItemList()->stopTrackingPaintInvalidationObjects();
2020 Vector<String> Internals::trackedPaintInvalidationObjects()
2022 ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
2023 return toLocalFrame(frame()->page()->mainFrame())->view()->layoutView()->layer()->graphicsLayerBacking()->displayItemList()->trackedPaintInvalidationObjects();
2026 ClientRectList* Internals::draggableRegions(Document* document, ExceptionState& exceptionState)
2028 return annotatedRegions(document, true, exceptionState);
2031 ClientRectList* Internals::nonDraggableRegions(Document* document, ExceptionState& exceptionState)
2033 return annotatedRegions(document, false, exceptionState);
2036 ClientRectList* Internals::annotatedRegions(Document* document, bool draggable, ExceptionState& exceptionState)
2038 ASSERT(document);
2039 if (!document->view()) {
2040 exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
2041 return ClientRectList::create();
2044 document->updateLayout();
2045 document->view()->updateAnnotatedRegions();
2046 Vector<AnnotatedRegionValue> regions = document->annotatedRegions();
2048 Vector<FloatQuad> quads;
2049 for (size_t i = 0; i < regions.size(); ++i) {
2050 if (regions[i].draggable == draggable)
2051 quads.append(FloatQuad(FloatRect(regions[i].bounds)));
2053 return ClientRectList::create(quads);
2056 static const char* cursorTypeToString(Cursor::Type cursorType)
2058 switch (cursorType) {
2059 case Cursor::Pointer: return "Pointer";
2060 case Cursor::Cross: return "Cross";
2061 case Cursor::Hand: return "Hand";
2062 case Cursor::IBeam: return "IBeam";
2063 case Cursor::Wait: return "Wait";
2064 case Cursor::Help: return "Help";
2065 case Cursor::EastResize: return "EastResize";
2066 case Cursor::NorthResize: return "NorthResize";
2067 case Cursor::NorthEastResize: return "NorthEastResize";
2068 case Cursor::NorthWestResize: return "NorthWestResize";
2069 case Cursor::SouthResize: return "SouthResize";
2070 case Cursor::SouthEastResize: return "SouthEastResize";
2071 case Cursor::SouthWestResize: return "SouthWestResize";
2072 case Cursor::WestResize: return "WestResize";
2073 case Cursor::NorthSouthResize: return "NorthSouthResize";
2074 case Cursor::EastWestResize: return "EastWestResize";
2075 case Cursor::NorthEastSouthWestResize: return "NorthEastSouthWestResize";
2076 case Cursor::NorthWestSouthEastResize: return "NorthWestSouthEastResize";
2077 case Cursor::ColumnResize: return "ColumnResize";
2078 case Cursor::RowResize: return "RowResize";
2079 case Cursor::MiddlePanning: return "MiddlePanning";
2080 case Cursor::EastPanning: return "EastPanning";
2081 case Cursor::NorthPanning: return "NorthPanning";
2082 case Cursor::NorthEastPanning: return "NorthEastPanning";
2083 case Cursor::NorthWestPanning: return "NorthWestPanning";
2084 case Cursor::SouthPanning: return "SouthPanning";
2085 case Cursor::SouthEastPanning: return "SouthEastPanning";
2086 case Cursor::SouthWestPanning: return "SouthWestPanning";
2087 case Cursor::WestPanning: return "WestPanning";
2088 case Cursor::Move: return "Move";
2089 case Cursor::VerticalText: return "VerticalText";
2090 case Cursor::Cell: return "Cell";
2091 case Cursor::ContextMenu: return "ContextMenu";
2092 case Cursor::Alias: return "Alias";
2093 case Cursor::Progress: return "Progress";
2094 case Cursor::NoDrop: return "NoDrop";
2095 case Cursor::Copy: return "Copy";
2096 case Cursor::None: return "None";
2097 case Cursor::NotAllowed: return "NotAllowed";
2098 case Cursor::ZoomIn: return "ZoomIn";
2099 case Cursor::ZoomOut: return "ZoomOut";
2100 case Cursor::Grab: return "Grab";
2101 case Cursor::Grabbing: return "Grabbing";
2102 case Cursor::Custom: return "Custom";
2105 ASSERT_NOT_REACHED();
2106 return "UNKNOWN";
2109 String Internals::getCurrentCursorInfo()
2111 Cursor cursor = frame()->page()->chromeClient().lastSetCursorForTesting();
2113 StringBuilder result;
2114 result.appendLiteral("type=");
2115 result.append(cursorTypeToString(cursor.type()));
2116 result.appendLiteral(" hotSpot=");
2117 result.appendNumber(cursor.hotSpot().x());
2118 result.append(',');
2119 result.appendNumber(cursor.hotSpot().y());
2120 if (cursor.image()) {
2121 IntSize size = cursor.image()->size();
2122 result.appendLiteral(" image=");
2123 result.appendNumber(size.width());
2124 result.append('x');
2125 result.appendNumber(size.height());
2127 if (cursor.imageScaleFactor() != 1) {
2128 result.appendLiteral(" scale=");
2129 NumberToStringBuffer buffer;
2130 result.append(numberToFixedPrecisionString(cursor.imageScaleFactor(), 8, buffer, true));
2133 return result.toString();
2136 bool Internals::cursorUpdatePending() const
2138 return frame()->eventHandler().cursorUpdatePending();
2141 PassRefPtr<DOMArrayBuffer> Internals::serializeObject(PassRefPtr<SerializedScriptValue> value) const
2143 String stringValue = value->toWireString();
2144 RefPtr<DOMArrayBuffer> buffer = DOMArrayBuffer::createUninitialized(stringValue.length(), sizeof(UChar));
2145 stringValue.copyTo(static_cast<UChar*>(buffer->data()), 0, stringValue.length());
2146 return buffer.release();
2149 PassRefPtr<SerializedScriptValue> Internals::deserializeBuffer(PassRefPtr<DOMArrayBuffer> buffer) const
2151 String value(static_cast<const UChar*>(buffer->data()), buffer->byteLength() / sizeof(UChar));
2152 return SerializedScriptValueFactory::instance().createFromWire(value);
2155 void Internals::forceReload(bool endToEnd)
2157 frame()->reload(endToEnd ? FrameLoadTypeReloadFromOrigin : FrameLoadTypeReload, NotClientRedirect);
2160 ClientRect* Internals::selectionBounds(ExceptionState& exceptionState)
2162 Document* document = contextDocument();
2163 if (!document || !document->frame()) {
2164 exceptionState.throwDOMException(InvalidAccessError, document ? "The document's frame cannot be retrieved." : "No context document can be obtained.");
2165 return nullptr;
2168 return ClientRect::create(FloatRect(document->frame()->selection().bounds()));
2171 String Internals::markerTextForListItem(Element* element)
2173 ASSERT(element);
2174 return blink::markerTextForListItem(element);
2177 String Internals::getImageSourceURL(Element* element)
2179 ASSERT(element);
2180 return element->imageSourceURL();
2183 String Internals::selectMenuListText(HTMLSelectElement* select)
2185 ASSERT(select);
2186 LayoutObject* layoutObject = select->layoutObject();
2187 if (!layoutObject || !layoutObject->isMenuList())
2188 return String();
2190 LayoutMenuList* menuList = toLayoutMenuList(layoutObject);
2191 return menuList->text();
2194 bool Internals::isSelectPopupVisible(Node* node)
2196 ASSERT(node);
2197 if (!isHTMLSelectElement(*node))
2198 return false;
2199 return toHTMLSelectElement(*node).popupIsVisible();
2202 bool Internals::selectPopupItemStyleIsRtl(Node* node, int itemIndex)
2204 if (!node || !isHTMLSelectElement(*node))
2205 return false;
2207 HTMLSelectElement& select = toHTMLSelectElement(*node);
2208 if (itemIndex < 0 || static_cast<size_t>(itemIndex) >= select.listItems().size())
2209 return false;
2210 const ComputedStyle* itemStyle = select.itemComputedStyle(*select.listItems()[itemIndex]);
2211 return itemStyle && itemStyle->direction() == RTL;
2214 int Internals::selectPopupItemStyleFontHeight(Node* node, int itemIndex)
2216 if (!node || !isHTMLSelectElement(*node))
2217 return false;
2219 HTMLSelectElement& select = toHTMLSelectElement(*node);
2220 if (itemIndex < 0 || static_cast<size_t>(itemIndex) >= select.listItems().size())
2221 return false;
2222 const ComputedStyle* itemStyle = select.itemComputedStyle(*select.listItems()[itemIndex]);
2223 return itemStyle ? itemStyle->font().fontMetrics().height() : 0;
2226 void Internals::resetTypeAheadSession(HTMLSelectElement* select)
2228 ASSERT(select);
2229 select->resetTypeAheadSessionForTesting();
2232 bool Internals::loseSharedGraphicsContext3D()
2234 OwnPtr<WebGraphicsContext3DProvider> sharedProvider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
2235 if (!sharedProvider)
2236 return false;
2237 WebGraphicsContext3D* sharedContext = sharedProvider->context3d();
2238 sharedContext->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_EXT, GL_INNOCENT_CONTEXT_RESET_EXT);
2239 // To prevent tests that call loseSharedGraphicsContext3D from being
2240 // flaky, we call finish so that the context is guaranteed to be lost
2241 // synchronously (i.e. before returning).
2242 sharedContext->finish();
2243 return true;
2246 void Internals::forceCompositingUpdate(Document* document, ExceptionState& exceptionState)
2248 ASSERT(document);
2249 if (!document->layoutView()) {
2250 exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
2251 return;
2254 document->frame()->view()->updateAllLifecyclePhases();
2257 void Internals::setZoomFactor(float factor)
2259 frame()->setPageZoomFactor(factor);
2262 void Internals::setShouldRevealPassword(Element* element, bool reveal, ExceptionState& exceptionState)
2264 ASSERT(element);
2265 if (!isHTMLInputElement(element)) {
2266 exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not an INPUT.");
2267 return;
2270 return toHTMLInputElement(*element).setShouldRevealPassword(reveal);
2273 namespace {
2275 class AddOneFunction : public ScriptFunction {
2276 public:
2277 static v8::Local<v8::Function> createFunction(ScriptState* scriptState)
2279 AddOneFunction* self = new AddOneFunction(scriptState);
2280 return self->bindToV8Function();
2283 private:
2284 explicit AddOneFunction(ScriptState* scriptState)
2285 : ScriptFunction(scriptState)
2289 ScriptValue call(ScriptValue value) override
2291 v8::Local<v8::Value> v8Value = value.v8Value();
2292 ASSERT(v8Value->IsNumber());
2293 int intValue = v8Value.As<v8::Integer>()->Value();
2294 return ScriptValue(scriptState(), v8::Integer::New(scriptState()->isolate(), intValue + 1));
2298 } // namespace
2300 ScriptPromise Internals::createResolvedPromise(ScriptState* scriptState, ScriptValue value)
2302 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
2303 ScriptPromise promise = resolver->promise();
2304 resolver->resolve(value);
2305 return promise;
2308 ScriptPromise Internals::createRejectedPromise(ScriptState* scriptState, ScriptValue value)
2310 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
2311 ScriptPromise promise = resolver->promise();
2312 resolver->reject(value);
2313 return promise;
2316 ScriptPromise Internals::addOneToPromise(ScriptState* scriptState, ScriptPromise promise)
2318 return promise.then(AddOneFunction::createFunction(scriptState));
2321 ScriptPromise Internals::promiseCheck(ScriptState* scriptState, long arg1, bool arg2, const Dictionary& arg3, const String& arg4, const Vector<String>& arg5, ExceptionState& exceptionState)
2323 if (arg2)
2324 return ScriptPromise::cast(scriptState, v8String(scriptState->isolate(), "done"));
2325 exceptionState.throwDOMException(InvalidStateError, "Thrown from the native implementation.");
2326 return ScriptPromise();
2329 ScriptPromise Internals::promiseCheckWithoutExceptionState(ScriptState* scriptState, const Dictionary& arg1, const String& arg2, const Vector<String>& arg3)
2331 return ScriptPromise::cast(scriptState, v8String(scriptState->isolate(), "done"));
2334 ScriptPromise Internals::promiseCheckRange(ScriptState* scriptState, long arg1)
2336 return ScriptPromise::cast(scriptState, v8String(scriptState->isolate(), "done"));
2339 ScriptPromise Internals::promiseCheckOverload(ScriptState* scriptState, Location*)
2341 return ScriptPromise::cast(scriptState, v8String(scriptState->isolate(), "done"));
2344 ScriptPromise Internals::promiseCheckOverload(ScriptState* scriptState, Document*)
2346 return ScriptPromise::cast(scriptState, v8String(scriptState->isolate(), "done"));
2349 ScriptPromise Internals::promiseCheckOverload(ScriptState* scriptState, Location*, long, long)
2351 return ScriptPromise::cast(scriptState, v8String(scriptState->isolate(), "done"));
2354 DEFINE_TRACE(Internals)
2356 visitor->trace(m_runtimeFlags);
2357 ContextLifecycleObserver::trace(visitor);
2360 void Internals::setValueForUser(Element* element, const String& value)
2362 toHTMLInputElement(element)->setValueForUser(value);
2365 String Internals::textSurroundingNode(Node* node, int x, int y, unsigned long maxLength)
2367 if (!node || !node->layoutObject())
2368 return String();
2369 blink::WebPoint point(x, y);
2370 SurroundingText surroundingText(createVisiblePosition(node->layoutObject()->positionForPoint(static_cast<IntPoint>(point))).deepEquivalent().parentAnchoredEquivalent(), maxLength);
2371 return surroundingText.content();
2374 void Internals::setFocused(bool focused)
2376 frame()->page()->focusController().setFocused(focused);
2379 void Internals::setInitialFocus(bool reverse)
2381 frame()->document()->setFocusedElement(nullptr);
2382 frame()->page()->focusController().setInitialFocus(reverse ? WebFocusTypeBackward : WebFocusTypeForward);
2385 bool Internals::ignoreLayoutWithPendingStylesheets(Document* document)
2387 ASSERT(document);
2388 return document->ignoreLayoutWithPendingStylesheets();
2391 void Internals::setNetworkStateNotifierTestOnly(bool testOnly)
2393 networkStateNotifier().setTestUpdatesOnly(testOnly);
2396 void Internals::setNetworkConnectionInfo(const String& type, double downlinkMaxMbps, ExceptionState& exceptionState)
2398 WebConnectionType webtype;
2399 if (type == "cellular") {
2400 webtype = WebConnectionTypeCellular;
2401 } else if (type == "bluetooth") {
2402 webtype = WebConnectionTypeBluetooth;
2403 } else if (type == "ethernet") {
2404 webtype = WebConnectionTypeEthernet;
2405 } else if (type == "wifi") {
2406 webtype = WebConnectionTypeWifi;
2407 } else if (type == "wimax") {
2408 webtype = WebConnectionTypeWimax;
2409 } else if (type == "other") {
2410 webtype = WebConnectionTypeOther;
2411 } else if (type == "none") {
2412 webtype = WebConnectionTypeNone;
2413 } else if (type == "unknown") {
2414 webtype = WebConnectionTypeUnknown;
2415 } else {
2416 exceptionState.throwDOMException(NotFoundError, ExceptionMessages::failedToEnumerate("connection type", type));
2417 return;
2419 networkStateNotifier().setWebConnectionForTest(webtype, downlinkMaxMbps);
2422 unsigned Internals::countHitRegions(CanvasRenderingContext* context)
2424 return context->hitRegionsCount();
2427 bool Internals::isInCanvasFontCache(Document* document, const String& fontString)
2429 return document->canvasFontCache()->isInCache(fontString);
2432 unsigned Internals::canvasFontCacheMaxFonts()
2434 return CanvasFontCache::maxFonts();
2437 ClientRect* Internals::boundsInViewportSpace(Element* element)
2439 ASSERT(element);
2440 return ClientRect::create(element->boundsInViewportSpace());
2443 void Internals::setScrollChain(
2444 ScrollState* scrollState, const WillBeHeapVector<RefPtrWillBeMember<Element>>& elements, ExceptionState&)
2446 WillBeHeapDeque<RefPtrWillBeMember<Element>> scrollChain;
2447 for (size_t i = 0; i < elements.size(); ++i)
2448 scrollChain.append(elements[i]);
2449 scrollState->setScrollChain(scrollChain);
2452 void Internals::forceBlinkGCWithoutV8GC()
2454 ThreadState::current()->setGCState(ThreadState::FullGCScheduled);
2457 String Internals::selectedHTMLForClipboard()
2459 return frame()->selection().selectedHTMLForClipboard();
2462 String Internals::selectedTextForClipboard()
2464 return frame()->selection().selectedTextForClipboard();
2467 void Internals::setVisualViewportOffset(int x, int y)
2469 frame()->host()->visualViewport().setLocation(FloatPoint(x, y));
2472 ValueIterable<int>::IterationSource* Internals::startIteration(ScriptState*, ExceptionState&)
2474 return new InternalsIterationSource();
2477 bool Internals::isUseCounted(Document* document, int useCounterId)
2479 if (useCounterId < 0 || useCounterId >= UseCounter::NumberOfFeatures)
2480 return false;
2481 return UseCounter::isCounted(*document, static_cast<UseCounter::Feature>(useCounterId));
2484 String Internals::unscopeableAttribute()
2486 return "unscopeableAttribute";
2489 String Internals::unscopeableMethod()
2491 return "unscopeableMethod";
2494 ClientRectList* Internals::focusRingRects(Element* element)
2496 Vector<LayoutRect> rects;
2497 if (element && element->layoutObject())
2498 element->layoutObject()->addOutlineRects(rects, LayoutPoint(), LayoutObject::IncludeBlockVisualOverflow);
2499 return ClientRectList::create(rects);
2502 ClientRectList* Internals::outlineRects(Element* element)
2504 Vector<LayoutRect> rects;
2505 if (element && element->layoutObject())
2506 element->layoutObject()->addOutlineRects(rects, LayoutPoint(), LayoutObject::DontIncludeBlockVisualOverflow);
2507 return ClientRectList::create(rects);
2510 void Internals::setCapsLockState(bool enabled)
2512 PlatformKeyboardEvent::setCurrentCapsLockState(enabled ?
2513 PlatformKeyboardEvent::OverrideCapsLockState::On : PlatformKeyboardEvent::OverrideCapsLockState::Off);
2516 void Internals::setSelectionPaintingWithoutSelectionGapsEnabled(bool enabled)
2518 RuntimeEnabledFeatures::setSelectionPaintingWithoutSelectionGapsEnabled(enabled);
2521 bool Internals::setScrollbarVisibilityInScrollableArea(Node* node, bool visible)
2523 LayoutObject* layoutObject = node->layoutObject();
2524 if (!layoutObject)
2525 return false;
2526 DeprecatedPaintLayer* layer = layoutObject->enclosingLayer();
2527 if (!layer)
2528 return false;
2529 ScrollableArea* scrollableArea = layer->scrollableArea();
2530 if (!scrollableArea)
2531 return false;
2532 ScrollAnimator* animator = layer->scrollableArea()->scrollAnimator();
2533 if (!animator)
2534 return false;
2536 return animator->setScrollbarsVisibleForTesting(visible);
2539 void Internals::forceRestrictIFramePermissions()
2541 RuntimeEnabledFeatures::setRestrictIFramePermissionsEnabled(true);
2544 } // namespace blink