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