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