Upstream version 11.39.250.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / testing / Internals.cpp
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