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