CTTE: More Document references please
[WebKit-https.git] / Source / WebCore / testing / Internals.cpp
1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  * Copyright (C) 2013 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "Internals.h"
29
30 #include "AnimationController.h"
31 #include "BackForwardController.h"
32 #include "CachedResourceLoader.h"
33 #include "Chrome.h"
34 #include "ChromeClient.h"
35 #include "ClientRect.h"
36 #include "ClientRectList.h"
37 #include "ContentDistributor.h"
38 #include "Cursor.h"
39 #include "DOMStringList.h"
40 #include "DOMWindow.h"
41 #include "Document.h"
42 #include "DocumentMarker.h"
43 #include "DocumentMarkerController.h"
44 #include "Editor.h"
45 #include "Element.h"
46 #include "EventHandler.h"
47 #include "ExceptionCode.h"
48 #include "FormController.h"
49 #include "Frame.h"
50 #include "FrameLoader.h"
51 #include "FrameView.h"
52 #include "HTMLInputElement.h"
53 #include "HTMLNames.h"
54 #include "HTMLSelectElement.h"
55 #include "HTMLTextAreaElement.h"
56 #include "HistoryController.h"
57 #include "HistoryItem.h"
58 #include "InspectorClient.h"
59 #include "InspectorConsoleAgent.h"
60 #include "InspectorController.h"
61 #include "InspectorCounters.h"
62 #include "InspectorFrontendChannel.h"
63 #include "InspectorFrontendClientLocal.h"
64 #include "InspectorInstrumentation.h"
65 #include "InspectorOverlay.h"
66 #include "InspectorValues.h"
67 #include "InstrumentingAgents.h"
68 #include "InternalSettings.h"
69 #include "IntRect.h"
70 #include "Language.h"
71 #include "MallocStatistics.h"
72 #include "MemoryCache.h"
73 #include "MemoryInfo.h"
74 #include "Page.h"
75 #include "PrintContext.h"
76 #include "PseudoElement.h"
77 #include "Range.h"
78 #include "RenderEmbeddedObject.h"
79 #include "RenderMenuList.h"
80 #include "RenderObject.h"
81 #include "RenderTreeAsText.h"
82 #include "RenderView.h"
83 #include "RuntimeEnabledFeatures.h"
84 #include "SchemeRegistry.h"
85 #include "ScrollingCoordinator.h"
86 #include "SerializedScriptValue.h"
87 #include "Settings.h"
88 #include "ShadowRoot.h"
89 #include "SpellChecker.h"
90 #include "StaticNodeList.h"
91 #include "StyleSheetContents.h"
92 #include "TextIterator.h"
93 #include "TreeScope.h"
94 #include "TypeConversions.h"
95 #include "ViewportArguments.h"
96 #include "WorkerThread.h"
97 #include <wtf/text/CString.h>
98 #include <wtf/text/StringBuffer.h>
99
100 #if ENABLE(INPUT_TYPE_COLOR)
101 #include "ColorChooser.h"
102 #endif
103
104 #if ENABLE(BATTERY_STATUS)
105 #include "BatteryController.h"
106 #endif
107
108 #if ENABLE(NETWORK_INFO)
109 #include "NetworkInfo.h"
110 #include "NetworkInfoController.h"
111 #endif
112
113 #if ENABLE(PROXIMITY_EVENTS)
114 #include "DeviceProximityController.h"
115 #endif
116
117 #if ENABLE(TOUCH_ADJUSTMENT)
118 #include "WebKitPoint.h"
119 #endif
120
121 #if ENABLE(MOUSE_CURSOR_SCALE)
122 #include <wtf/dtoa.h>
123 #endif
124
125 #if ENABLE(ENCRYPTED_MEDIA_V2)
126 #include "CDM.h"
127 #include "MockCDM.h"
128 #endif
129
130 #if ENABLE(VIDEO_TRACK)
131 #include "CaptionUserPreferences.h"
132 #include "PageGroup.h"
133 #endif
134
135 #if ENABLE(VIDEO)
136 #include "HTMLMediaElement.h"
137 #include "TimeRanges.h"
138 #endif
139
140 #if ENABLE(SPEECH_SYNTHESIS)
141 #include "DOMWindowSpeechSynthesis.h"
142 #include "PlatformSpeechSynthesizerMock.h"
143 #include "SpeechSynthesis.h"
144 #endif
145
146 #if ENABLE(VIBRATION)
147 #include "Vibration.h"
148 #endif
149
150 #if PLATFORM(QT)
151 #include "NetworkingContext.h"
152 #include <QNetworkAccessManager>
153 #endif
154
155 namespace WebCore {
156
157 using namespace HTMLNames;
158
159 #if ENABLE(INSPECTOR)
160 class InspectorFrontendClientDummy : public InspectorFrontendClientLocal {
161 public:
162     InspectorFrontendClientDummy(InspectorController*, Page*);
163     virtual ~InspectorFrontendClientDummy() { }
164     virtual void attachWindow(DockSide) OVERRIDE { }
165     virtual void detachWindow() OVERRIDE { }
166
167     virtual String localizedStringsURL() OVERRIDE { return String(); }
168
169     virtual void bringToFront() OVERRIDE { }
170     virtual void closeWindow() OVERRIDE { }
171
172     virtual void inspectedURLChanged(const String&) OVERRIDE { }
173
174 protected:
175     virtual void setAttachedWindowHeight(unsigned) OVERRIDE { }
176     virtual void setAttachedWindowWidth(unsigned) OVERRIDE { }
177     virtual void setToolbarHeight(unsigned) OVERRIDE { }
178 };
179
180 InspectorFrontendClientDummy::InspectorFrontendClientDummy(InspectorController* controller, Page* page)
181     : InspectorFrontendClientLocal(controller, page, adoptPtr(new InspectorFrontendClientLocal::Settings()))
182 {
183 }
184
185 class InspectorFrontendChannelDummy : public InspectorFrontendChannel {
186 public:
187     explicit InspectorFrontendChannelDummy(Page*);
188     virtual ~InspectorFrontendChannelDummy() { }
189     virtual bool sendMessageToFrontend(const String& message) OVERRIDE;
190
191 private:
192     Page* m_frontendPage;
193 };
194
195 InspectorFrontendChannelDummy::InspectorFrontendChannelDummy(Page* page)
196     : m_frontendPage(page)
197 {
198 }
199
200 bool InspectorFrontendChannelDummy::sendMessageToFrontend(const String& message)
201 {
202     return InspectorClient::doDispatchMessageOnFrontendPage(m_frontendPage, message);
203 }
204 #endif // ENABLE(INSPECTOR)
205
206 static bool markerTypesFrom(const String& markerType, DocumentMarker::MarkerTypes& result)
207 {
208     if (markerType.isEmpty() || equalIgnoringCase(markerType, "all"))
209         result = DocumentMarker::AllMarkers();
210     else if (equalIgnoringCase(markerType, "Spelling"))
211         result =  DocumentMarker::Spelling;
212     else if (equalIgnoringCase(markerType, "Grammar"))
213         result =  DocumentMarker::Grammar;
214     else if (equalIgnoringCase(markerType, "TextMatch"))
215         result =  DocumentMarker::TextMatch;
216     else if (equalIgnoringCase(markerType, "Replacement"))
217         result =  DocumentMarker::Replacement;
218     else if (equalIgnoringCase(markerType, "CorrectionIndicator"))
219         result =  DocumentMarker::CorrectionIndicator;
220     else if (equalIgnoringCase(markerType, "RejectedCorrection"))
221         result =  DocumentMarker::RejectedCorrection;
222     else if (equalIgnoringCase(markerType, "Autocorrected"))
223         result =  DocumentMarker::Autocorrected;
224     else if (equalIgnoringCase(markerType, "SpellCheckingExemption"))
225         result =  DocumentMarker::SpellCheckingExemption;
226     else if (equalIgnoringCase(markerType, "DeletedAutocorrection"))
227         result =  DocumentMarker::DeletedAutocorrection;
228     else if (equalIgnoringCase(markerType, "DictationAlternatives"))
229         result =  DocumentMarker::DictationAlternatives;
230     else
231         return false;
232
233     return true;
234 }
235
236 const char* Internals::internalsId = "internals";
237
238 PassRefPtr<Internals> Internals::create(Document* document)
239 {
240     return adoptRef(new Internals(document));
241 }
242
243 Internals::~Internals()
244 {
245 }
246
247 void Internals::resetToConsistentState(Page* page)
248 {
249     ASSERT(page);
250
251     page->setPageScaleFactor(1, IntPoint(0, 0));
252     page->setPagination(Pagination());
253
254 #if USE(ACCELERATED_COMPOSITING)
255     FrameView* mainFrameView = page->mainFrame().view();
256     if (mainFrameView) {
257         mainFrameView->setHeaderHeight(0);
258         mainFrameView->setFooterHeight(0);
259     }
260 #endif
261     TextRun::setAllowsRoundingHacks(false);
262     WebCore::overrideUserPreferredLanguages(Vector<String>());
263     WebCore::Settings::setUsesOverlayScrollbars(false);
264 #if ENABLE(INSPECTOR) && ENABLE(JAVASCRIPT_DEBUGGER)
265     if (page->inspectorController())
266         page->inspectorController()->setProfilerEnabled(false);
267 #endif
268 #if ENABLE(VIDEO_TRACK) && !PLATFORM(WIN)
269     page->group().captionPreferences()->setCaptionsStyleSheetOverride(emptyString());
270     page->group().captionPreferences()->setTestingMode(false);
271 #endif
272     if (!page->mainFrame().editor().isContinuousSpellCheckingEnabled())
273         page->mainFrame().editor().toggleContinuousSpellChecking();
274     if (page->mainFrame().editor().isOverwriteModeEnabled())
275         page->mainFrame().editor().toggleOverwriteModeEnabled();
276
277 #if PLATFORM(QT)
278     if (NetworkingContext* context = page->mainFrame().loader().networkingContext()) {
279         if (QNetworkAccessManager* qnam = context->networkAccessManager())
280             qnam->clearAccessCache();
281     }
282 #endif
283 }
284
285 Internals::Internals(Document* document)
286     : ContextDestructionObserver(document)
287 {
288 #if ENABLE(VIDEO_TRACK) && !PLATFORM(WIN)
289     if (document && document->page())
290         document->page()->group().captionPreferences()->setTestingMode(true);
291 #endif
292 }
293
294 Document* Internals::contextDocument() const
295 {
296     return toDocument(scriptExecutionContext());
297 }
298
299 Frame* Internals::frame() const
300 {
301     if (!contextDocument())
302         return 0;
303     return contextDocument()->frame();
304 }
305
306 InternalSettings* Internals::settings() const
307 {
308     Document* document = contextDocument();
309     if (!document)
310         return 0;
311     Page* page = document->page();
312     if (!page)
313         return 0;
314     return InternalSettings::from(page);
315 }
316
317 unsigned Internals::workerThreadCount() const
318 {
319 #if ENABLE(WORKERS)
320     return WorkerThread::workerThreadCount();
321 #else
322     return 0;
323 #endif
324 }
325
326 String Internals::address(Node* node)
327 {
328     char buf[32];
329     sprintf(buf, "%p", node);
330
331     return String(buf);
332 }
333
334 bool Internals::isPreloaded(const String& url)
335 {
336     Document* document = contextDocument();
337     return document->cachedResourceLoader()->isPreloaded(url);
338 }
339
340 bool Internals::isLoadingFromMemoryCache(const String& url)
341 {
342     if (!contextDocument())
343         return false;
344     CachedResource* resource = memoryCache()->resourceForURL(contextDocument()->completeURL(url));
345     return resource && resource->status() == CachedResource::Cached;
346 }
347
348
349 Node* Internals::treeScopeRootNode(Node* node, ExceptionCode& ec)
350 {
351     if (!node) {
352         ec = INVALID_ACCESS_ERR;
353         return 0;
354     }
355
356     return node->treeScope()->rootNode();
357 }
358
359 Node* Internals::parentTreeScope(Node* node, ExceptionCode& ec)
360 {
361     if (!node) {
362         ec = INVALID_ACCESS_ERR;
363         return 0;
364     }
365     const TreeScope* parentTreeScope = node->treeScope()->parentTreeScope();
366     return parentTreeScope ? parentTreeScope->rootNode() : 0;
367 }
368
369 unsigned Internals::lastSpatialNavigationCandidateCount(ExceptionCode& ec) const
370 {
371     if (!contextDocument() || !contextDocument()->page()) {
372         ec = INVALID_ACCESS_ERR;
373         return 0;
374     }
375
376     return contextDocument()->page()->lastSpatialNavigationCandidateCount();
377 }
378
379 unsigned Internals::numberOfActiveAnimations() const
380 {
381     return frame()->animation().numberOfActiveAnimations(frame()->document());
382 }
383
384 bool Internals::animationsAreSuspended(Document* document, ExceptionCode& ec) const
385 {
386     if (!document || !document->frame()) {
387         ec = INVALID_ACCESS_ERR;
388         return false;
389     }
390
391     return document->frame()->animation().isSuspended();
392 }
393
394 void Internals::suspendAnimations(Document* document, ExceptionCode& ec) const
395 {
396     if (!document || !document->frame()) {
397         ec = INVALID_ACCESS_ERR;
398         return;
399     }
400
401     document->frame()->animation().suspendAnimations();
402 }
403
404 void Internals::resumeAnimations(Document* document, ExceptionCode& ec) const
405 {
406     if (!document || !document->frame()) {
407         ec = INVALID_ACCESS_ERR;
408         return;
409     }
410
411     document->frame()->animation().resumeAnimations();
412 }
413
414 bool Internals::pauseAnimationAtTimeOnElement(const String& animationName, double pauseTime, Element* element, ExceptionCode& ec)
415 {
416     if (!element || pauseTime < 0) {
417         ec = INVALID_ACCESS_ERR;
418         return false;
419     }
420     return frame()->animation().pauseAnimationAtTime(element->renderer(), AtomicString(animationName), pauseTime);
421 }
422
423 bool Internals::pauseAnimationAtTimeOnPseudoElement(const String& animationName, double pauseTime, Element* element, const String& pseudoId, ExceptionCode& ec)
424 {
425     if (!element || pauseTime < 0) {
426         ec = INVALID_ACCESS_ERR;
427         return false;
428     }
429
430     if (pseudoId != "before" && pseudoId != "after") {
431         ec = INVALID_ACCESS_ERR;
432         return false;
433     }
434
435     PseudoElement* pseudoElement = pseudoId == "before" ? element->beforePseudoElement() : element->afterPseudoElement();
436     if (!pseudoElement) {
437         ec = INVALID_ACCESS_ERR;
438         return false;
439     }
440
441     return frame()->animation().pauseAnimationAtTime(pseudoElement->renderer(), AtomicString(animationName), pauseTime);
442 }
443
444 bool Internals::pauseTransitionAtTimeOnElement(const String& propertyName, double pauseTime, Element* element, ExceptionCode& ec)
445 {
446     if (!element || pauseTime < 0) {
447         ec = INVALID_ACCESS_ERR;
448         return false;
449     }
450     return frame()->animation().pauseTransitionAtTime(element->renderer(), propertyName, pauseTime);
451 }
452
453 bool Internals::pauseTransitionAtTimeOnPseudoElement(const String& property, double pauseTime, Element* element, const String& pseudoId, ExceptionCode& ec)
454 {
455     if (!element || pauseTime < 0) {
456         ec = INVALID_ACCESS_ERR;
457         return false;
458     }
459
460     if (pseudoId != "before" && pseudoId != "after") {
461         ec = INVALID_ACCESS_ERR;
462         return false;
463     }
464
465     PseudoElement* pseudoElement = pseudoId == "before" ? element->beforePseudoElement() : element->afterPseudoElement();
466     if (!pseudoElement) {
467         ec = INVALID_ACCESS_ERR;
468         return false;
469     }
470
471     return frame()->animation().pauseTransitionAtTime(pseudoElement->renderer(), property, pauseTime);
472 }
473
474 bool Internals::attached(Node* node, ExceptionCode& ec)
475 {
476     if (!node) {
477         ec = INVALID_ACCESS_ERR;
478         return false;
479     }
480
481     return node->attached();
482 }
483
484 String Internals::elementRenderTreeAsText(Element* element, ExceptionCode& ec)
485 {
486     if (!element) {
487         ec = INVALID_ACCESS_ERR;
488         return String();
489     }
490
491     String representation = externalRepresentation(element);
492     if (representation.isEmpty()) {
493         ec = INVALID_ACCESS_ERR;
494         return String();
495     }
496
497     return representation;
498 }
499
500 size_t Internals::numberOfScopedHTMLStyleChildren(const Node* scope, ExceptionCode& ec) const
501 {
502     if (scope && (scope->isElementNode() || scope->isShadowRoot()))
503 #if ENABLE(STYLE_SCOPED)
504         return scope->numberOfScopedHTMLStyleChildren();
505 #else
506         return 0;
507 #endif
508
509     ec = INVALID_ACCESS_ERR;
510     return 0;
511 }
512
513 PassRefPtr<CSSComputedStyleDeclaration> Internals::computedStyleIncludingVisitedInfo(Node* node, ExceptionCode& ec) const
514 {
515     if (!node) {
516         ec = INVALID_ACCESS_ERR;
517         return 0;
518     }
519
520     bool allowVisitedStyle = true;
521     return CSSComputedStyleDeclaration::create(node, allowVisitedStyle);
522 }
523
524 Internals::ShadowRootIfShadowDOMEnabledOrNode* Internals::ensureShadowRoot(Element* host, ExceptionCode& ec)
525 {
526     if (!host) {
527         ec = INVALID_ACCESS_ERR;
528         return 0;
529     }
530
531     if (ShadowRoot* shadowRoot = host->shadowRoot())
532         return shadowRoot;
533
534     return host->createShadowRoot(ec).get();
535 }
536
537 Internals::ShadowRootIfShadowDOMEnabledOrNode* Internals::createShadowRoot(Element* host, ExceptionCode& ec)
538 {
539     if (!host) {
540         ec = INVALID_ACCESS_ERR;
541         return 0;
542     }
543     return host->createShadowRoot(ec).get();
544 }
545
546 Internals::ShadowRootIfShadowDOMEnabledOrNode* Internals::shadowRoot(Element* host, ExceptionCode& ec)
547 {
548     if (!host) {
549         ec = INVALID_ACCESS_ERR;
550         return 0;
551     }
552     return host->shadowRoot();
553 }
554
555 String Internals::shadowRootType(const Node* root, ExceptionCode& ec) const
556 {
557     if (!root || !root->isShadowRoot()) {
558         ec = INVALID_ACCESS_ERR;
559         return String();
560     }
561
562     switch (toShadowRoot(root)->type()) {
563     case ShadowRoot::UserAgentShadowRoot:
564         return String("UserAgentShadowRoot");
565     case ShadowRoot::AuthorShadowRoot:
566         return String("AuthorShadowRoot");
567     default:
568         ASSERT_NOT_REACHED();
569         return String("Unknown");
570     }
571 }
572
573 Element* Internals::includerFor(Node*, ExceptionCode& ec)
574 {
575     ec = INVALID_ACCESS_ERR;
576     return 0;
577 }
578
579 String Internals::shadowPseudoId(Element* element, ExceptionCode& ec)
580 {
581     if (!element) {
582         ec = INVALID_ACCESS_ERR;
583         return String();
584     }
585
586     return element->shadowPseudoId().string();
587 }
588
589 void Internals::setShadowPseudoId(Element* element, const String& id, ExceptionCode& ec)
590 {
591     if (!element) {
592         ec = INVALID_ACCESS_ERR;
593         return;
594     }
595
596     return element->setPseudo(id);
597 }
598
599 String Internals::visiblePlaceholder(Element* element)
600 {
601     if (element && isHTMLTextFormControlElement(element)) {
602         if (toHTMLTextFormControlElement(element)->placeholderShouldBeVisible())
603             return toHTMLTextFormControlElement(element)->placeholderElement()->textContent();
604     }
605
606     return String();
607 }
608
609 #if ENABLE(INPUT_TYPE_COLOR)
610 void Internals::selectColorInColorChooser(Element* element, const String& colorValue)
611 {
612     if (!isHTMLInputElement(element))
613         return;
614     HTMLInputElement* inputElement = element->toInputElement();
615     if (!inputElement)
616         return;
617     inputElement->selectColorInColorChooser(Color(colorValue));
618 }
619 #endif
620
621 Vector<String> Internals::formControlStateOfPreviousHistoryItem(ExceptionCode& ec)
622 {
623     HistoryItem* mainItem = frame()->loader().history().previousItem();
624     if (!mainItem) {
625         ec = INVALID_ACCESS_ERR;
626         return Vector<String>();
627     }
628     String uniqueName = frame()->tree().uniqueName();
629     if (mainItem->target() != uniqueName && !mainItem->childItemWithTarget(uniqueName)) {
630         ec = INVALID_ACCESS_ERR;
631         return Vector<String>();
632     }
633     return mainItem->target() == uniqueName ? mainItem->documentState() : mainItem->childItemWithTarget(uniqueName)->documentState();
634 }
635
636 void Internals::setFormControlStateOfPreviousHistoryItem(const Vector<String>& state, ExceptionCode& ec)
637 {
638     HistoryItem* mainItem = frame()->loader().history().previousItem();
639     if (!mainItem) {
640         ec = INVALID_ACCESS_ERR;
641         return;
642     }
643     String uniqueName = frame()->tree().uniqueName();
644     if (mainItem->target() == uniqueName)
645         mainItem->setDocumentState(state);
646     else if (HistoryItem* subItem = mainItem->childItemWithTarget(uniqueName))
647         subItem->setDocumentState(state);
648     else
649         ec = INVALID_ACCESS_ERR;
650 }
651
652 #if ENABLE(SPEECH_SYNTHESIS)
653 void Internals::enableMockSpeechSynthesizer()
654 {
655     Document* document = contextDocument();
656     if (!document || !document->domWindow())
657         return;
658     SpeechSynthesis* synthesis = DOMWindowSpeechSynthesis::speechSynthesis(document->domWindow());
659     if (!synthesis)
660         return;
661     
662     synthesis->setPlatformSynthesizer(PlatformSpeechSynthesizerMock::create(synthesis));
663 }
664 #endif
665     
666 PassRefPtr<ClientRect> Internals::absoluteCaretBounds(ExceptionCode& ec)
667 {
668     Document* document = contextDocument();
669     if (!document || !document->frame()) {
670         ec = INVALID_ACCESS_ERR;
671         return ClientRect::create();
672     }
673
674     return ClientRect::create(document->frame()->selection().absoluteCaretBounds());
675 }
676
677 PassRefPtr<ClientRect> Internals::boundingBox(Element* element, ExceptionCode& ec)
678 {
679     if (!element) {
680         ec = INVALID_ACCESS_ERR;
681         return ClientRect::create();
682     }
683
684     element->document().updateLayoutIgnorePendingStylesheets();
685     RenderObject* renderer = element->renderer();
686     if (!renderer)
687         return ClientRect::create();
688     return ClientRect::create(renderer->absoluteBoundingBoxRectIgnoringTransforms());
689 }
690
691 PassRefPtr<ClientRectList> Internals::inspectorHighlightRects(Document* document, ExceptionCode& ec)
692 {
693 #if ENABLE(INSPECTOR)
694     if (!document || !document->page() || !document->page()->inspectorController()) {
695         ec = INVALID_ACCESS_ERR;
696         return ClientRectList::create();
697     }
698
699     Highlight highlight;
700     document->page()->inspectorController()->getHighlight(&highlight);
701     return ClientRectList::create(highlight.quads);
702 #else
703     UNUSED_PARAM(document);
704     UNUSED_PARAM(ec);
705     return ClientRectList::create();
706 #endif
707 }
708
709 String Internals::inspectorHighlightObject(Document* document, ExceptionCode& ec)
710 {
711 #if ENABLE(INSPECTOR)
712     if (!document || !document->page() || !document->page()->inspectorController()) {
713         ec = INVALID_ACCESS_ERR;
714         return String();
715     }
716     RefPtr<InspectorObject> object = document->page()->inspectorController()->buildObjectForHighlightedNode();
717     return object ? object->toJSONString() : String();
718 #else
719     UNUSED_PARAM(document);
720     UNUSED_PARAM(ec);
721     return String();
722 #endif
723 }
724
725 unsigned Internals::markerCountForNode(Node* node, const String& markerType, ExceptionCode& ec)
726 {
727     if (!node) {
728         ec = INVALID_ACCESS_ERR;
729         return 0;
730     }
731
732     DocumentMarker::MarkerTypes markerTypes = 0;
733     if (!markerTypesFrom(markerType, markerTypes)) {
734         ec = SYNTAX_ERR;
735         return 0;
736     }
737
738     return node->document().markers().markersFor(node, markerTypes).size();
739 }
740
741 DocumentMarker* Internals::markerAt(Node* node, const String& markerType, unsigned index, ExceptionCode& ec)
742 {
743     if (!node) {
744         ec = INVALID_ACCESS_ERR;
745         return 0;
746     }
747
748     DocumentMarker::MarkerTypes markerTypes = 0;
749     if (!markerTypesFrom(markerType, markerTypes)) {
750         ec = SYNTAX_ERR;
751         return 0;
752     }
753
754     Vector<DocumentMarker*> markers = node->document().markers().markersFor(node, markerTypes);
755     if (markers.size() <= index)
756         return 0;
757     return markers[index];
758 }
759
760 PassRefPtr<Range> Internals::markerRangeForNode(Node* node, const String& markerType, unsigned index, ExceptionCode& ec)
761 {
762     DocumentMarker* marker = markerAt(node, markerType, index, ec);
763     if (!marker)
764         return 0;
765     return Range::create(&node->document(), node, marker->startOffset(), node, marker->endOffset());
766 }
767
768 String Internals::markerDescriptionForNode(Node* node, const String& markerType, unsigned index, ExceptionCode& ec)
769 {
770     DocumentMarker* marker = markerAt(node, markerType, index, ec);
771     if (!marker)
772         return String();
773     return marker->description();
774 }
775
776 void Internals::addTextMatchMarker(const Range* range, bool isActive)
777 {
778     range->ownerDocument().updateLayoutIgnorePendingStylesheets();
779     range->ownerDocument().markers().addTextMatchMarker(range, isActive);
780 }
781
782 void Internals::setScrollViewPosition(Document* document, long x, long y, ExceptionCode& ec)
783 {
784     if (!document || !document->view()) {
785         ec = INVALID_ACCESS_ERR;
786         return;
787     }
788
789     FrameView* frameView = document->view();
790     bool constrainsScrollingToContentEdgeOldValue = frameView->constrainsScrollingToContentEdge();
791     bool scrollbarsSuppressedOldValue = frameView->scrollbarsSuppressed();
792
793     frameView->setConstrainsScrollingToContentEdge(false);
794     frameView->setScrollbarsSuppressed(false);
795     frameView->setScrollOffsetFromInternals(IntPoint(x, y));
796     frameView->setScrollbarsSuppressed(scrollbarsSuppressedOldValue);
797     frameView->setConstrainsScrollingToContentEdge(constrainsScrollingToContentEdgeOldValue);
798 }
799
800 void Internals::setPagination(Document* document, const String& mode, int gap, int pageLength, ExceptionCode& ec)
801 {
802     if (!document || !document->page()) {
803         ec = INVALID_ACCESS_ERR;
804         return;
805     }
806     Page* page = document->page();
807
808     Pagination pagination;
809     if (mode == "Unpaginated")
810         pagination.mode = Pagination::Unpaginated;
811     else if (mode == "LeftToRightPaginated")
812         pagination.mode = Pagination::LeftToRightPaginated;
813     else if (mode == "RightToLeftPaginated")
814         pagination.mode = Pagination::RightToLeftPaginated;
815     else if (mode == "TopToBottomPaginated")
816         pagination.mode = Pagination::TopToBottomPaginated;
817     else if (mode == "BottomToTopPaginated")
818         pagination.mode = Pagination::BottomToTopPaginated;
819     else {
820         ec = SYNTAX_ERR;
821         return;
822     }
823
824     pagination.gap = gap;
825     pagination.pageLength = pageLength;
826     page->setPagination(pagination);
827 }
828
829 String Internals::configurationForViewport(Document* document, float devicePixelRatio, int deviceWidth, int deviceHeight, int availableWidth, int availableHeight, ExceptionCode& ec)
830 {
831     if (!document || !document->page()) {
832         ec = INVALID_ACCESS_ERR;
833         return String();
834     }
835     Page* page = document->page();
836
837     const int defaultLayoutWidthForNonMobilePages = 980;
838
839     ViewportArguments arguments = page->viewportArguments();
840     ViewportAttributes attributes = computeViewportAttributes(arguments, defaultLayoutWidthForNonMobilePages, deviceWidth, deviceHeight, devicePixelRatio, IntSize(availableWidth, availableHeight));
841     restrictMinimumScaleFactorToViewportSize(attributes, IntSize(availableWidth, availableHeight), devicePixelRatio);
842     restrictScaleFactorToInitialScaleIfNotUserScalable(attributes);
843
844     return "viewport size " + String::number(attributes.layoutSize.width()) + "x" + String::number(attributes.layoutSize.height()) + " scale " + String::number(attributes.initialScale) + " with limits [" + String::number(attributes.minimumScale) + ", " + String::number(attributes.maximumScale) + "] and userScalable " + (attributes.userScalable ? "true" : "false");
845 }
846
847 bool Internals::wasLastChangeUserEdit(Element* textField, ExceptionCode& ec)
848 {
849     if (!textField) {
850         ec = INVALID_ACCESS_ERR;
851         return false;
852     }
853
854     if (HTMLInputElement* inputElement = textField->toInputElement())
855         return inputElement->lastChangeWasUserEdit();
856
857     // FIXME: We should be using hasTagName instead but Windows port doesn't link QualifiedNames properly.
858     if (textField->tagName() == "TEXTAREA")
859         return toHTMLTextAreaElement(textField)->lastChangeWasUserEdit();
860
861     ec = INVALID_NODE_TYPE_ERR;
862     return false;
863 }
864
865 bool Internals::elementShouldAutoComplete(Element* element, ExceptionCode& ec)
866 {
867     if (!element) {
868         ec = INVALID_ACCESS_ERR;
869         return false;
870     }
871
872     if (HTMLInputElement* inputElement = element->toInputElement())
873         return inputElement->shouldAutocomplete();
874
875     ec = INVALID_NODE_TYPE_ERR;
876     return false;
877 }
878
879 String Internals::suggestedValue(Element* element, ExceptionCode& ec)
880 {
881     if (!element) {
882         ec = INVALID_ACCESS_ERR;
883         return String();
884     }
885
886     HTMLInputElement* inputElement = element->toInputElement();
887     if (!inputElement) {
888         ec = INVALID_NODE_TYPE_ERR;
889         return String();
890     }
891
892     return inputElement->suggestedValue();
893 }
894
895 void Internals::setSuggestedValue(Element* element, const String& value, ExceptionCode& ec)
896 {
897     if (!element) {
898         ec = INVALID_ACCESS_ERR;
899         return;
900     }
901
902     HTMLInputElement* inputElement = element->toInputElement();
903     if (!inputElement) {
904         ec = INVALID_NODE_TYPE_ERR;
905         return;
906     }
907
908     inputElement->setSuggestedValue(value);
909 }
910
911 void Internals::setEditingValue(Element* element, const String& value, ExceptionCode& ec)
912 {
913     if (!element) {
914         ec = INVALID_ACCESS_ERR;
915         return;
916     }
917
918     HTMLInputElement* inputElement = element->toInputElement();
919     if (!inputElement) {
920         ec = INVALID_NODE_TYPE_ERR;
921         return;
922     }
923
924     inputElement->setEditingValue(value);
925 }
926
927 void Internals::setAutofilled(Element* element, bool enabled, ExceptionCode& ec)
928 {
929     HTMLInputElement* inputElement = element->toInputElement();
930     if (!inputElement) {
931         ec = INVALID_ACCESS_ERR;
932         return;
933     }
934     inputElement->setAutofilled(enabled);
935 }
936
937 void Internals::scrollElementToRect(Element* element, long x, long y, long w, long h, ExceptionCode& ec)
938 {
939     if (!element || !element->document().view()) {
940         ec = INVALID_ACCESS_ERR;
941         return;
942     }
943     FrameView* frameView = element->document().view();
944     frameView->scrollElementToRect(element, IntRect(x, y, w, h));
945 }
946
947 void Internals::paintControlTints(Document* document, ExceptionCode& ec)
948 {
949     if (!document || !document->view()) {
950         ec = INVALID_ACCESS_ERR;
951         return;
952     }
953
954     FrameView* frameView = document->view();
955     frameView->paintControlTints();
956 }
957
958 PassRefPtr<Range> Internals::rangeFromLocationAndLength(Element* scope, int rangeLocation, int rangeLength, ExceptionCode& ec)
959 {
960     if (!scope) {
961         ec = INVALID_ACCESS_ERR;
962         return 0;
963     }
964
965     return TextIterator::rangeFromLocationAndLength(scope, rangeLocation, rangeLength);
966 }
967
968 unsigned Internals::locationFromRange(Element* scope, const Range* range, ExceptionCode& ec)
969 {
970     if (!scope || !range) {
971         ec = INVALID_ACCESS_ERR;
972         return 0;
973     }
974
975     size_t location = 0;
976     size_t unusedLength = 0;
977     TextIterator::getLocationAndLengthFromRange(scope, range, location, unusedLength);
978     return location;
979 }
980
981 unsigned Internals::lengthFromRange(Element* scope, const Range* range, ExceptionCode& ec)
982 {
983     if (!scope || !range) {
984         ec = INVALID_ACCESS_ERR;
985         return 0;
986     }
987
988     size_t unusedLocation = 0;
989     size_t length = 0;
990     TextIterator::getLocationAndLengthFromRange(scope, range, unusedLocation, length);
991     return length;
992 }
993
994 String Internals::rangeAsText(const Range* range, ExceptionCode& ec)
995 {
996     if (!range) {
997         ec = INVALID_ACCESS_ERR;
998         return String();
999     }
1000
1001     return range->text();
1002 }
1003
1004 void Internals::setDelegatesScrolling(bool enabled, Document* document, ExceptionCode& ec)
1005 {
1006     // Delegate scrolling is valid only on mainframe's view.
1007     if (!document || !document->view() || !document->page() || &document->page()->mainFrame() != document->frame()) {
1008         ec = INVALID_ACCESS_ERR;
1009         return;
1010     }
1011
1012     document->view()->setDelegatesScrolling(enabled);
1013 }
1014
1015 #if ENABLE(TOUCH_ADJUSTMENT)
1016 PassRefPtr<WebKitPoint> Internals::touchPositionAdjustedToBestClickableNode(long x, long y, long width, long height, Document* document, ExceptionCode& ec)
1017 {
1018     if (!document || !document->frame()) {
1019         ec = INVALID_ACCESS_ERR;
1020         return 0;
1021     }
1022
1023     IntSize radius(width / 2, height / 2);
1024     IntPoint point(x + radius.width(), y + radius.height());
1025
1026     Node* targetNode;
1027     IntPoint adjustedPoint;
1028
1029     bool foundNode = document->frame()->eventHandler().bestClickableNodeForTouchPoint(point, radius, adjustedPoint, targetNode);
1030     if (foundNode)
1031         return WebKitPoint::create(adjustedPoint.x(), adjustedPoint.y());
1032
1033     return 0;
1034 }
1035
1036 Node* Internals::touchNodeAdjustedToBestClickableNode(long x, long y, long width, long height, Document* document, ExceptionCode& ec)
1037 {
1038     if (!document || !document->frame()) {
1039         ec = INVALID_ACCESS_ERR;
1040         return 0;
1041     }
1042
1043     IntSize radius(width / 2, height / 2);
1044     IntPoint point(x + radius.width(), y + radius.height());
1045
1046     Node* targetNode;
1047     IntPoint adjustedPoint;
1048     document->frame()->eventHandler().bestClickableNodeForTouchPoint(point, radius, adjustedPoint, targetNode);
1049     return targetNode;
1050 }
1051
1052 PassRefPtr<WebKitPoint> Internals::touchPositionAdjustedToBestContextMenuNode(long x, long y, long width, long height, Document* document, ExceptionCode& ec)
1053 {
1054     if (!document || !document->frame()) {
1055         ec = INVALID_ACCESS_ERR;
1056         return 0;
1057     }
1058
1059     IntSize radius(width / 2, height / 2);
1060     IntPoint point(x + radius.width(), y + radius.height());
1061
1062     Node* targetNode = 0;
1063     IntPoint adjustedPoint;
1064
1065     bool foundNode = document->frame()->eventHandler().bestContextMenuNodeForTouchPoint(point, radius, adjustedPoint, targetNode);
1066     if (foundNode)
1067         return WebKitPoint::create(adjustedPoint.x(), adjustedPoint.y());
1068
1069     return WebKitPoint::create(x, y);
1070 }
1071
1072 Node* Internals::touchNodeAdjustedToBestContextMenuNode(long x, long y, long width, long height, Document* document, ExceptionCode& ec)
1073 {
1074     if (!document || !document->frame()) {
1075         ec = INVALID_ACCESS_ERR;
1076         return 0;
1077     }
1078
1079     IntSize radius(width / 2, height / 2);
1080     IntPoint point(x + radius.width(), y + radius.height());
1081
1082     Node* targetNode = 0;
1083     IntPoint adjustedPoint;
1084     document->frame()->eventHandler().bestContextMenuNodeForTouchPoint(point, radius, adjustedPoint, targetNode);
1085     return targetNode;
1086 }
1087
1088 PassRefPtr<ClientRect> Internals::bestZoomableAreaForTouchPoint(long x, long y, long width, long height, Document* document, ExceptionCode& ec)
1089 {
1090     if (!document || !document->frame()) {
1091         ec = INVALID_ACCESS_ERR;
1092         return 0;
1093     }
1094
1095     IntSize radius(width / 2, height / 2);
1096     IntPoint point(x + radius.width(), y + radius.height());
1097
1098     Node* targetNode;
1099     IntRect zoomableArea;
1100     bool foundNode = document->frame()->eventHandler().bestZoomableAreaForTouchPoint(point, radius, zoomableArea, targetNode);
1101     if (foundNode)
1102         return ClientRect::create(zoomableArea);
1103
1104     return 0;
1105 }
1106 #endif
1107
1108
1109 int Internals::lastSpellCheckRequestSequence(Document* document, ExceptionCode& ec)
1110 {
1111     if (!document || !document->frame()) {
1112         ec = INVALID_ACCESS_ERR;
1113         return -1;
1114     }
1115
1116     return document->frame()->editor().spellChecker().lastRequestSequence();
1117 }
1118
1119 int Internals::lastSpellCheckProcessedSequence(Document* document, ExceptionCode& ec)
1120 {
1121     if (!document || !document->frame()) {
1122         ec = INVALID_ACCESS_ERR;
1123         return -1;
1124     }
1125
1126     return document->frame()->editor().spellChecker().lastProcessedSequence();
1127 }
1128
1129 Vector<String> Internals::userPreferredLanguages() const
1130 {
1131     return WebCore::userPreferredLanguages();
1132 }
1133
1134 void Internals::setUserPreferredLanguages(const Vector<String>& languages)
1135 {
1136     WebCore::overrideUserPreferredLanguages(languages);
1137 }
1138
1139 unsigned Internals::wheelEventHandlerCount(Document* document, ExceptionCode& ec)
1140 {
1141     if (!document) {
1142         ec = INVALID_ACCESS_ERR;
1143         return 0;
1144     }
1145
1146     return document->wheelEventHandlerCount();
1147 }
1148
1149 unsigned Internals::touchEventHandlerCount(Document* document, ExceptionCode& ec)
1150 {
1151     if (!document) {
1152         ec = INVALID_ACCESS_ERR;
1153         return 0;
1154     }
1155
1156     const TouchEventTargetSet* touchHandlers = document->touchEventTargets();
1157     if (!touchHandlers)
1158         return 0;
1159
1160     unsigned count = 0;
1161     for (TouchEventTargetSet::const_iterator iter = touchHandlers->begin(); iter != touchHandlers->end(); ++iter)
1162         count += iter->value;
1163     return count;
1164 }
1165
1166 #if ENABLE(TOUCH_EVENT_TRACKING)
1167 PassRefPtr<ClientRectList> Internals::touchEventTargetClientRects(Document* document, ExceptionCode& ec)
1168 {
1169     if (!document || !document->view() || !document->page()) {
1170         ec = INVALID_ACCESS_ERR;
1171         return 0;
1172     }
1173     if (!document->page()->scrollingCoordinator())
1174         return ClientRectList::create();
1175
1176     document->updateLayoutIgnorePendingStylesheets();
1177
1178     Vector<IntRect> absoluteRects;
1179     document->page()->scrollingCoordinator()->computeAbsoluteTouchEventTargetRects(document, absoluteRects);
1180     Vector<FloatQuad> absoluteQuads(absoluteRects.size());
1181
1182     for (size_t i = 0; i < absoluteRects.size(); ++i)
1183         absoluteQuads[i] = FloatQuad(absoluteRects[i]);
1184
1185     return ClientRectList::create(absoluteQuads);
1186 }
1187 #endif
1188
1189 PassRefPtr<NodeList> Internals::nodesFromRect(Document* document, int centerX, int centerY, unsigned topPadding, unsigned rightPadding,
1190     unsigned bottomPadding, unsigned leftPadding, bool ignoreClipping, bool allowShadowContent, bool allowChildFrameContent, ExceptionCode& ec) const
1191 {
1192     if (!document || !document->frame() || !document->frame()->view()) {
1193         ec = INVALID_ACCESS_ERR;
1194         return 0;
1195     }
1196
1197     Frame* frame = document->frame();
1198     FrameView* frameView = document->view();
1199     RenderView* renderView = document->renderView();
1200     if (!renderView)
1201         return 0;
1202
1203     float zoomFactor = frame->pageZoomFactor();
1204     LayoutPoint point = roundedLayoutPoint(FloatPoint(centerX * zoomFactor + frameView->scrollX(), centerY * zoomFactor + frameView->scrollY()));
1205
1206     HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active;
1207     if (ignoreClipping)
1208         hitType |= HitTestRequest::IgnoreClipping;
1209     if (!allowShadowContent)
1210         hitType |= HitTestRequest::DisallowShadowContent;
1211     if (allowChildFrameContent)
1212         hitType |= HitTestRequest::AllowChildFrameContent;
1213
1214     HitTestRequest request(hitType);
1215
1216     // When ignoreClipping is false, this method returns null for coordinates outside of the viewport.
1217     if (!request.ignoreClipping() && !frameView->visibleContentRect().intersects(HitTestLocation::rectForPoint(point, topPadding, rightPadding, bottomPadding, leftPadding)))
1218         return 0;
1219
1220     Vector<Ref<Node>> matches;
1221
1222     // Need padding to trigger a rect based hit test, but we want to return a NodeList
1223     // so we special case this.
1224     if (!topPadding && !rightPadding && !bottomPadding && !leftPadding) {
1225         HitTestResult result(point);
1226         renderView->hitTest(request, result);
1227         if (result.innerNode())
1228             matches.append(*result.innerNode()->deprecatedShadowAncestorNode());
1229     } else {
1230         HitTestResult result(point, topPadding, rightPadding, bottomPadding, leftPadding);
1231         renderView->hitTest(request, result);
1232         
1233         const HitTestResult::NodeSet& nodeSet = result.rectBasedTestResult();
1234         matches.reserveInitialCapacity(nodeSet.size());
1235         for (auto it = nodeSet.begin(), end = nodeSet.end(); it != end; ++it)
1236             matches.uncheckedAppend(*it->get());
1237     }
1238
1239     return StaticNodeList::adopt(matches);
1240 }
1241
1242 void Internals::emitInspectorDidBeginFrame()
1243 {
1244 #if ENABLE(INSPECTOR)
1245     InspectorController* inspectorController = contextDocument()->frame()->page()->inspectorController();
1246     inspectorController->didBeginFrame();
1247 #endif
1248 }
1249
1250 void Internals::emitInspectorDidCancelFrame()
1251 {
1252 #if ENABLE(INSPECTOR)
1253     InspectorController* inspectorController = contextDocument()->frame()->page()->inspectorController();
1254     inspectorController->didCancelFrame();
1255 #endif
1256 }
1257
1258 void Internals::setBatteryStatus(Document* document, const String& eventType, bool charging, double chargingTime, double dischargingTime, double level, ExceptionCode& ec)
1259 {
1260     if (!document || !document->page()) {
1261         ec = INVALID_ACCESS_ERR;
1262         return;
1263     }
1264
1265 #if ENABLE(BATTERY_STATUS)
1266     BatteryController::from(document->page())->didChangeBatteryStatus(eventType, BatteryStatus::create(charging, chargingTime, dischargingTime, level));
1267 #else
1268     UNUSED_PARAM(eventType);
1269     UNUSED_PARAM(charging);
1270     UNUSED_PARAM(chargingTime);
1271     UNUSED_PARAM(dischargingTime);
1272     UNUSED_PARAM(level);
1273 #endif
1274 }
1275
1276 void Internals::setNetworkInformation(Document* document, const String& eventType, double bandwidth, bool metered, ExceptionCode& ec)
1277 {
1278     if (!document || !document->page()) {
1279         ec = INVALID_ACCESS_ERR;
1280         return;
1281     }
1282
1283 #if ENABLE(NETWORK_INFO)
1284     NetworkInfoController::from(document->page())->didChangeNetworkInformation(eventType, NetworkInfo::create(bandwidth, metered));
1285 #else
1286     UNUSED_PARAM(eventType);
1287     UNUSED_PARAM(bandwidth);
1288     UNUSED_PARAM(metered);
1289 #endif
1290 }
1291
1292 void Internals::setDeviceProximity(Document* document, const String& eventType, double value, double min, double max, ExceptionCode& ec)
1293 {
1294     if (!document || !document->page()) {
1295         ec = INVALID_ACCESS_ERR;
1296         return;
1297     }
1298
1299 #if ENABLE(PROXIMITY_EVENTS)
1300     DeviceProximityController::from(document->page())->didChangeDeviceProximity(value, min, max);
1301 #else
1302     UNUSED_PARAM(eventType);
1303     UNUSED_PARAM(value);
1304     UNUSED_PARAM(min);
1305     UNUSED_PARAM(max);
1306 #endif
1307 }
1308
1309 bool Internals::hasSpellingMarker(Document* document, int from, int length, ExceptionCode&)
1310 {
1311     if (!document || !document->frame())
1312         return 0;
1313
1314     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
1315 }
1316     
1317 bool Internals::hasAutocorrectedMarker(Document* document, int from, int length, ExceptionCode&)
1318 {
1319     if (!document || !document->frame())
1320         return 0;
1321     
1322     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Autocorrected, from, length);
1323 }
1324
1325 void Internals::setContinuousSpellCheckingEnabled(bool enabled, ExceptionCode&)
1326 {
1327     if (!contextDocument() || !contextDocument()->frame())
1328         return;
1329
1330     if (enabled != contextDocument()->frame()->editor().isContinuousSpellCheckingEnabled())
1331         contextDocument()->frame()->editor().toggleContinuousSpellChecking();
1332 }
1333
1334 void Internals::setAutomaticQuoteSubstitutionEnabled(bool enabled, ExceptionCode&)
1335 {
1336     if (!contextDocument() || !contextDocument()->frame())
1337         return;
1338
1339 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1340     if (enabled != contextDocument()->frame()->editor().isAutomaticQuoteSubstitutionEnabled())
1341         contextDocument()->frame()->editor().toggleAutomaticQuoteSubstitution();
1342 #else
1343     UNUSED_PARAM(enabled);
1344 #endif
1345 }
1346
1347 void Internals::setAutomaticLinkDetectionEnabled(bool enabled, ExceptionCode&)
1348 {
1349     if (!contextDocument() || !contextDocument()->frame())
1350         return;
1351
1352 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1353     if (enabled != contextDocument()->frame()->editor().isAutomaticLinkDetectionEnabled())
1354         contextDocument()->frame()->editor().toggleAutomaticLinkDetection();
1355 #else
1356     UNUSED_PARAM(enabled);
1357 #endif
1358 }
1359
1360 void Internals::setAutomaticDashSubstitutionEnabled(bool enabled, ExceptionCode&)
1361 {
1362     if (!contextDocument() || !contextDocument()->frame())
1363         return;
1364
1365 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1366     if (enabled != contextDocument()->frame()->editor().isAutomaticDashSubstitutionEnabled())
1367         contextDocument()->frame()->editor().toggleAutomaticDashSubstitution();
1368 #else
1369     UNUSED_PARAM(enabled);
1370 #endif
1371 }
1372
1373 void Internals::setAutomaticTextReplacementEnabled(bool enabled, ExceptionCode&)
1374 {
1375     if (!contextDocument() || !contextDocument()->frame())
1376         return;
1377
1378 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1379     if (enabled != contextDocument()->frame()->editor().isAutomaticTextReplacementEnabled())
1380         contextDocument()->frame()->editor().toggleAutomaticTextReplacement();
1381 #else
1382     UNUSED_PARAM(enabled);
1383 #endif
1384 }
1385
1386 void Internals::setAutomaticSpellingCorrectionEnabled(bool enabled, ExceptionCode&)
1387 {
1388     if (!contextDocument() || !contextDocument()->frame())
1389         return;
1390
1391 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1392     if (enabled != contextDocument()->frame()->editor().isAutomaticSpellingCorrectionEnabled())
1393         contextDocument()->frame()->editor().toggleAutomaticSpellingCorrection();
1394 #else
1395     UNUSED_PARAM(enabled);
1396 #endif
1397 }
1398
1399 bool Internals::isOverwriteModeEnabled(Document* document, ExceptionCode&)
1400 {
1401     if (!document || !document->frame())
1402         return 0;
1403
1404     return document->frame()->editor().isOverwriteModeEnabled();
1405 }
1406
1407 void Internals::toggleOverwriteModeEnabled(Document* document, ExceptionCode&)
1408 {
1409     if (!document || !document->frame())
1410         return;
1411
1412     document->frame()->editor().toggleOverwriteModeEnabled();
1413 }
1414
1415 #if ENABLE(INSPECTOR)
1416 unsigned Internals::numberOfLiveNodes() const
1417 {
1418     return InspectorCounters::counterValue(InspectorCounters::NodeCounter);
1419 }
1420
1421 unsigned Internals::numberOfLiveDocuments() const
1422 {
1423     return InspectorCounters::counterValue(InspectorCounters::DocumentCounter);
1424 }
1425
1426 Vector<String> Internals::consoleMessageArgumentCounts(Document* document) const
1427 {
1428     InstrumentingAgents* instrumentingAgents = instrumentationForPage(document->page());
1429     if (!instrumentingAgents)
1430         return Vector<String>();
1431     InspectorConsoleAgent* consoleAgent = instrumentingAgents->inspectorConsoleAgent();
1432     if (!consoleAgent)
1433         return Vector<String>();
1434     Vector<unsigned> counts = consoleAgent->consoleMessageArgumentCounts();
1435     Vector<String> result(counts.size());
1436     for (size_t i = 0; i < counts.size(); i++)
1437         result[i] = String::number(counts[i]);
1438     return result;
1439 }
1440
1441 PassRefPtr<DOMWindow> Internals::openDummyInspectorFrontend(const String& url)
1442 {
1443     Page* page = contextDocument()->frame()->page();
1444     ASSERT(page);
1445
1446     DOMWindow* window = page->mainFrame().document()->domWindow();
1447     ASSERT(window);
1448
1449     m_frontendWindow = window->open(url, "", "", window, window);
1450     ASSERT(m_frontendWindow);
1451
1452     Page* frontendPage = m_frontendWindow->document()->page();
1453     ASSERT(frontendPage);
1454
1455     OwnPtr<InspectorFrontendClientDummy> frontendClient = adoptPtr(new InspectorFrontendClientDummy(page->inspectorController(), frontendPage));
1456
1457     frontendPage->inspectorController()->setInspectorFrontendClient(frontendClient.release());
1458
1459     m_frontendChannel = adoptPtr(new InspectorFrontendChannelDummy(frontendPage));
1460
1461     page->inspectorController()->connectFrontend(m_frontendChannel.get());
1462
1463     return m_frontendWindow;
1464 }
1465
1466 void Internals::closeDummyInspectorFrontend()
1467 {
1468     Page* page = contextDocument()->frame()->page();
1469     ASSERT(page);
1470     ASSERT(m_frontendWindow);
1471
1472     page->inspectorController()->disconnectFrontend();
1473
1474     m_frontendChannel.release();
1475
1476     m_frontendWindow->close(m_frontendWindow->scriptExecutionContext());
1477     m_frontendWindow.release();
1478 }
1479
1480 void Internals::setInspectorResourcesDataSizeLimits(int maximumResourcesContentSize, int maximumSingleResourceContentSize, ExceptionCode& ec)
1481 {
1482     Page* page = contextDocument()->frame()->page();
1483     if (!page || !page->inspectorController()) {
1484         ec = INVALID_ACCESS_ERR;
1485         return;
1486     }
1487     page->inspectorController()->setResourcesDataSizeLimitsFromInternals(maximumResourcesContentSize, maximumSingleResourceContentSize);
1488 }
1489
1490 void Internals::setJavaScriptProfilingEnabled(bool enabled, ExceptionCode& ec)
1491 {
1492     Page* page = contextDocument()->frame()->page();
1493     if (!page || !page->inspectorController()) {
1494         ec = INVALID_ACCESS_ERR;
1495         return;
1496     }
1497
1498     page->inspectorController()->setProfilerEnabled(enabled);
1499 }
1500 #endif // ENABLE(INSPECTOR)
1501
1502 bool Internals::hasGrammarMarker(Document* document, int from, int length, ExceptionCode&)
1503 {
1504     if (!document || !document->frame())
1505         return 0;
1506
1507     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Grammar, from, length);
1508 }
1509
1510 unsigned Internals::numberOfScrollableAreas(Document* document, ExceptionCode&)
1511 {
1512     unsigned count = 0;
1513     Frame* frame = document->frame();
1514     if (frame->view()->scrollableAreas())
1515         count += frame->view()->scrollableAreas()->size();
1516
1517     for (Frame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
1518         if (child->view() && child->view()->scrollableAreas())
1519             count += child->view()->scrollableAreas()->size();
1520     }
1521
1522     return count;
1523 }
1524     
1525 bool Internals::isPageBoxVisible(Document* document, int pageNumber, ExceptionCode& ec)
1526 {
1527     if (!document) {
1528         ec = INVALID_ACCESS_ERR;
1529         return false;
1530     }
1531
1532     return document->isPageBoxVisible(pageNumber);
1533 }
1534
1535 String Internals::layerTreeAsText(Document* document, ExceptionCode& ec) const
1536 {
1537     return layerTreeAsText(document, 0, ec);
1538 }
1539
1540 String Internals::layerTreeAsText(Document* document, unsigned flags, ExceptionCode& ec) const
1541 {
1542     if (!document || !document->frame()) {
1543         ec = INVALID_ACCESS_ERR;
1544         return String();
1545     }
1546
1547     LayerTreeFlags layerTreeFlags = 0;
1548     if (flags & LAYER_TREE_INCLUDES_VISIBLE_RECTS)
1549         layerTreeFlags |= LayerTreeFlagsIncludeVisibleRects;
1550     if (flags & LAYER_TREE_INCLUDES_TILE_CACHES)
1551         layerTreeFlags |= LayerTreeFlagsIncludeTileCaches;
1552     if (flags & LAYER_TREE_INCLUDES_REPAINT_RECTS)
1553         layerTreeFlags |= LayerTreeFlagsIncludeRepaintRects;
1554     if (flags & LAYER_TREE_INCLUDES_PAINTING_PHASES)
1555         layerTreeFlags |= LayerTreeFlagsIncludePaintingPhases;
1556     if (flags & LAYER_TREE_INCLUDES_CONTENT_LAYERS)
1557         layerTreeFlags |= LayerTreeFlagsIncludeContentLayers;
1558
1559     return document->frame()->layerTreeAsText(layerTreeFlags);
1560 }
1561
1562 String Internals::repaintRectsAsText(Document* document, ExceptionCode& ec) const
1563 {
1564     if (!document || !document->frame()) {
1565         ec = INVALID_ACCESS_ERR;
1566         return String();
1567     }
1568
1569     return document->frame()->trackedRepaintRectsAsText();
1570 }
1571
1572 String Internals::scrollingStateTreeAsText(Document* document, ExceptionCode& ec) const
1573 {
1574     if (!document || !document->frame()) {
1575         ec = INVALID_ACCESS_ERR;
1576         return String();
1577     }
1578
1579     Page* page = document->page();
1580     if (!page)
1581         return String();
1582
1583     return page->scrollingStateTreeAsText();
1584 }
1585
1586 String Internals::mainThreadScrollingReasons(Document* document, ExceptionCode& ec) const
1587 {
1588     if (!document || !document->frame()) {
1589         ec = INVALID_ACCESS_ERR;
1590         return String();
1591     }
1592
1593     Page* page = document->page();
1594     if (!page)
1595         return String();
1596
1597     return page->mainThreadScrollingReasonsAsText();
1598 }
1599
1600 PassRefPtr<ClientRectList> Internals::nonFastScrollableRects(Document* document, ExceptionCode& ec) const
1601 {
1602     if (!document || !document->frame()) {
1603         ec = INVALID_ACCESS_ERR;
1604         return 0;
1605     }
1606
1607     Page* page = document->page();
1608     if (!page)
1609         return 0;
1610
1611     return page->nonFastScrollableRects(document->frame());
1612 }
1613
1614 void Internals::garbageCollectDocumentResources(Document* document, ExceptionCode& ec) const
1615 {
1616     if (!document) {
1617         ec = INVALID_ACCESS_ERR;
1618         return;
1619     }
1620
1621     CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader();
1622     if (!cachedResourceLoader)
1623         return;
1624     cachedResourceLoader->garbageCollectDocumentResources();
1625 }
1626
1627 void Internals::allowRoundingHacks() const
1628 {
1629     TextRun::setAllowsRoundingHacks(true);
1630 }
1631
1632 void Internals::insertAuthorCSS(Document* document, const String& css, ExceptionCode& ec) const
1633 {
1634     if (!document) {
1635         ec = INVALID_ACCESS_ERR;
1636         return;
1637     }
1638
1639     RefPtr<StyleSheetContents> parsedSheet = StyleSheetContents::create(*document);
1640     parsedSheet->setIsUserStyleSheet(false);
1641     parsedSheet->parseString(css);
1642     document->styleSheetCollection()->addAuthorSheet(parsedSheet);
1643 }
1644
1645 void Internals::insertUserCSS(Document* document, const String& css, ExceptionCode& ec) const
1646 {
1647     if (!document) {
1648         ec = INVALID_ACCESS_ERR;
1649         return;
1650     }
1651
1652     RefPtr<StyleSheetContents> parsedSheet = StyleSheetContents::create(*document);
1653     parsedSheet->setIsUserStyleSheet(true);
1654     parsedSheet->parseString(css);
1655     document->styleSheetCollection()->addUserSheet(parsedSheet);
1656 }
1657
1658 String Internals::counterValue(Element* element)
1659 {
1660     if (!element)
1661         return String();
1662
1663     return counterValueForElement(element);
1664 }
1665
1666 int Internals::pageNumber(Element* element, float pageWidth, float pageHeight)
1667 {
1668     if (!element)
1669         return 0;
1670
1671     return PrintContext::pageNumberForElement(element, FloatSize(pageWidth, pageHeight));
1672 }
1673
1674 Vector<String> Internals::iconURLs(Document* document, int iconTypesMask) const
1675 {
1676     Vector<IconURL> iconURLs = document->iconURLs(iconTypesMask);
1677     Vector<String> array;
1678
1679     Vector<IconURL>::const_iterator iter(iconURLs.begin());
1680     for (; iter != iconURLs.end(); ++iter)
1681         array.append(iter->m_iconURL.string());
1682
1683     return array;
1684 }
1685
1686 Vector<String> Internals::shortcutIconURLs(Document* document) const
1687 {
1688     return iconURLs(document, Favicon);
1689 }
1690
1691 Vector<String> Internals::allIconURLs(Document* document) const
1692 {
1693     return iconURLs(document, Favicon | TouchIcon | TouchPrecomposedIcon);
1694 }
1695
1696 int Internals::numberOfPages(float pageWidth, float pageHeight)
1697 {
1698     if (!frame())
1699         return -1;
1700
1701     return PrintContext::numberOfPages(frame(), FloatSize(pageWidth, pageHeight));
1702 }
1703
1704 String Internals::pageProperty(String propertyName, int pageNumber, ExceptionCode& ec) const
1705 {
1706     if (!frame()) {
1707         ec = INVALID_ACCESS_ERR;
1708         return String();
1709     }
1710
1711     return PrintContext::pageProperty(frame(), propertyName.utf8().data(), pageNumber);
1712 }
1713
1714 String Internals::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft, ExceptionCode& ec) const
1715 {
1716     if (!frame()) {
1717         ec = INVALID_ACCESS_ERR;
1718         return String();
1719     }
1720
1721     return PrintContext::pageSizeAndMarginsInPixels(frame(), pageNumber, width, height, marginTop, marginRight, marginBottom, marginLeft);
1722 }
1723
1724 void Internals::setPageScaleFactor(float scaleFactor, int x, int y, ExceptionCode& ec)
1725 {
1726     Document* document = contextDocument();
1727     if (!document || !document->page()) {
1728         ec = INVALID_ACCESS_ERR;
1729         return;
1730     }
1731     Page* page = document->page();
1732     page->setPageScaleFactor(scaleFactor, IntPoint(x, y));
1733 }
1734
1735 void Internals::setHeaderHeight(Document* document, float height)
1736 {
1737     if (!document || !document->view())
1738         return;
1739 #if USE(ACCELERATED_COMPOSITING)
1740     FrameView* frameView = document->view();
1741     frameView->setHeaderHeight(height);
1742 #endif
1743 }
1744
1745 void Internals::setFooterHeight(Document* document, float height)
1746 {
1747     if (!document || !document->view())
1748         return;
1749 #if USE(ACCELERATED_COMPOSITING)
1750     FrameView* frameView = document->view();
1751     frameView->setFooterHeight(height);
1752 #endif
1753 }
1754
1755 #if ENABLE(FULLSCREEN_API)
1756 void Internals::webkitWillEnterFullScreenForElement(Document* document, Element* element)
1757 {
1758     if (!document)
1759         return;
1760     document->webkitWillEnterFullScreenForElement(element);
1761 }
1762
1763 void Internals::webkitDidEnterFullScreenForElement(Document* document, Element* element)
1764 {
1765     if (!document)
1766         return;
1767     document->webkitDidEnterFullScreenForElement(element);
1768 }
1769
1770 void Internals::webkitWillExitFullScreenForElement(Document* document, Element* element)
1771 {
1772     if (!document)
1773         return;
1774     document->webkitWillExitFullScreenForElement(element);
1775 }
1776
1777 void Internals::webkitDidExitFullScreenForElement(Document* document, Element* element)
1778 {
1779     if (!document)
1780         return;
1781     document->webkitDidExitFullScreenForElement(element);
1782 }
1783 #endif
1784
1785 void Internals::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme)
1786 {
1787     SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
1788 }
1789
1790 void Internals::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(const String& scheme)
1791 {
1792     SchemeRegistry::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(scheme);
1793 }
1794
1795 PassRefPtr<MallocStatistics> Internals::mallocStatistics() const
1796 {
1797     return MallocStatistics::create();
1798 }
1799
1800 PassRefPtr<TypeConversions> Internals::typeConversions() const
1801 {
1802     return TypeConversions::create();
1803 }
1804
1805 PassRefPtr<MemoryInfo> Internals::memoryInfo() const
1806 {
1807     return MemoryInfo::create();
1808 }
1809
1810 Vector<String> Internals::getReferencedFilePaths() const
1811 {
1812     frame()->loader().history().saveDocumentAndScrollState();
1813     return FormController::getReferencedFilePaths(frame()->loader().history().currentItem()->documentState());
1814 }
1815
1816 void Internals::startTrackingRepaints(Document* document, ExceptionCode& ec)
1817 {
1818     if (!document || !document->view()) {
1819         ec = INVALID_ACCESS_ERR;
1820         return;
1821     }
1822
1823     FrameView* frameView = document->view();
1824     frameView->setTracksRepaints(true);
1825 }
1826
1827 void Internals::stopTrackingRepaints(Document* document, ExceptionCode& ec)
1828 {
1829     if (!document || !document->view()) {
1830         ec = INVALID_ACCESS_ERR;
1831         return;
1832     }
1833
1834     FrameView* frameView = document->view();
1835     frameView->setTracksRepaints(false);
1836 }
1837
1838 #if USE(LAZY_NATIVE_CURSOR)
1839 static const char* cursorTypeToString(Cursor::Type cursorType)
1840 {
1841     switch (cursorType) {
1842     case Cursor::Pointer: return "Pointer";
1843     case Cursor::Cross: return "Cross";
1844     case Cursor::Hand: return "Hand";
1845     case Cursor::IBeam: return "IBeam";
1846     case Cursor::Wait: return "Wait";
1847     case Cursor::Help: return "Help";
1848     case Cursor::EastResize: return "EastResize";
1849     case Cursor::NorthResize: return "NorthResize";
1850     case Cursor::NorthEastResize: return "NorthEastResize";
1851     case Cursor::NorthWestResize: return "NorthWestResize";
1852     case Cursor::SouthResize: return "SouthResize";
1853     case Cursor::SouthEastResize: return "SouthEastResize";
1854     case Cursor::SouthWestResize: return "SouthWestResize";
1855     case Cursor::WestResize: return "WestResize";
1856     case Cursor::NorthSouthResize: return "NorthSouthResize";
1857     case Cursor::EastWestResize: return "EastWestResize";
1858     case Cursor::NorthEastSouthWestResize: return "NorthEastSouthWestResize";
1859     case Cursor::NorthWestSouthEastResize: return "NorthWestSouthEastResize";
1860     case Cursor::ColumnResize: return "ColumnResize";
1861     case Cursor::RowResize: return "RowResize";
1862     case Cursor::MiddlePanning: return "MiddlePanning";
1863     case Cursor::EastPanning: return "EastPanning";
1864     case Cursor::NorthPanning: return "NorthPanning";
1865     case Cursor::NorthEastPanning: return "NorthEastPanning";
1866     case Cursor::NorthWestPanning: return "NorthWestPanning";
1867     case Cursor::SouthPanning: return "SouthPanning";
1868     case Cursor::SouthEastPanning: return "SouthEastPanning";
1869     case Cursor::SouthWestPanning: return "SouthWestPanning";
1870     case Cursor::WestPanning: return "WestPanning";
1871     case Cursor::Move: return "Move";
1872     case Cursor::VerticalText: return "VerticalText";
1873     case Cursor::Cell: return "Cell";
1874     case Cursor::ContextMenu: return "ContextMenu";
1875     case Cursor::Alias: return "Alias";
1876     case Cursor::Progress: return "Progress";
1877     case Cursor::NoDrop: return "NoDrop";
1878     case Cursor::Copy: return "Copy";
1879     case Cursor::None: return "None";
1880     case Cursor::NotAllowed: return "NotAllowed";
1881     case Cursor::ZoomIn: return "ZoomIn";
1882     case Cursor::ZoomOut: return "ZoomOut";
1883     case Cursor::Grab: return "Grab";
1884     case Cursor::Grabbing: return "Grabbing";
1885     case Cursor::Custom: return "Custom";
1886     }
1887
1888     ASSERT_NOT_REACHED();
1889     return "UNKNOWN";
1890 }
1891 #endif
1892
1893 String Internals::getCurrentCursorInfo(Document* document, ExceptionCode& ec)
1894 {
1895     if (!document || !document->frame()) {
1896         ec = INVALID_ACCESS_ERR;
1897         return String();
1898     }
1899
1900     Cursor cursor = document->frame()->eventHandler().currentMouseCursor();
1901
1902 #if USE(LAZY_NATIVE_CURSOR)
1903     StringBuilder result;
1904     result.append("type=");
1905     result.append(cursorTypeToString(cursor.type()));
1906     result.append(" hotSpot=");
1907     result.appendNumber(cursor.hotSpot().x());
1908     result.append(",");
1909     result.appendNumber(cursor.hotSpot().y());
1910     if (cursor.image()) {
1911         IntSize size = cursor.image()->size();
1912         result.append(" image=");
1913         result.appendNumber(size.width());
1914         result.append("x");
1915         result.appendNumber(size.height());
1916     }
1917 #if ENABLE(MOUSE_CURSOR_SCALE)
1918     if (cursor.imageScaleFactor() != 1) {
1919         result.append(" scale=");
1920         NumberToStringBuffer buffer;
1921         result.append(numberToFixedPrecisionString(cursor.imageScaleFactor(), 8, buffer, true));
1922     }
1923 #endif
1924     return result.toString();
1925 #else
1926     return "FAIL: Cursor details not available on this platform.";
1927 #endif
1928 }
1929
1930 PassRefPtr<ArrayBuffer> Internals::serializeObject(PassRefPtr<SerializedScriptValue> value) const
1931 {
1932     Vector<uint8_t> bytes = value->data();
1933     return ArrayBuffer::create(bytes.data(), bytes.size());
1934 }
1935
1936 PassRefPtr<SerializedScriptValue> Internals::deserializeBuffer(PassRefPtr<ArrayBuffer> buffer) const
1937 {
1938     Vector<uint8_t> bytes;
1939     bytes.append(static_cast<const uint8_t*>(buffer->data()), buffer->byteLength());
1940     return SerializedScriptValue::adopt(bytes);
1941 }
1942
1943 void Internals::setUsesOverlayScrollbars(bool enabled)
1944 {
1945     WebCore::Settings::setUsesOverlayScrollbars(enabled);
1946 }
1947
1948 void Internals::forceReload(bool endToEnd)
1949 {
1950     frame()->loader().reload(endToEnd);
1951 }
1952
1953 #if ENABLE(ENCRYPTED_MEDIA_V2)
1954 void Internals::initializeMockCDM()
1955 {
1956     CDM::registerCDMFactory(MockCDM::create, MockCDM::supportsKeySystem, MockCDM::supportsKeySystemAndMimeType);
1957 }
1958 #endif
1959
1960 String Internals::markerTextForListItem(Element* element, ExceptionCode& ec)
1961 {
1962     if (!element) {
1963         ec = INVALID_ACCESS_ERR;
1964         return String();
1965     }
1966     return WebCore::markerTextForListItem(element);
1967 }
1968
1969 String Internals::getImageSourceURL(Element* element, ExceptionCode& ec)
1970 {
1971     if (!element) {
1972         ec = INVALID_ACCESS_ERR;
1973         return String();
1974     }
1975     return element->imageSourceURL();
1976 }
1977
1978 #if ENABLE(VIDEO)
1979 void Internals::simulateAudioInterruption(Node* node)
1980 {
1981 #if USE(GSTREAMER)
1982     HTMLMediaElement* element = toHTMLMediaElement(node);
1983     element->player()->simulateAudioInterruption();
1984 #else
1985     UNUSED_PARAM(node);
1986 #endif
1987 }
1988 #endif
1989
1990 bool Internals::isSelectPopupVisible(Node* node)
1991 {
1992     if (!isHTMLSelectElement(node))
1993         return false;
1994
1995     HTMLSelectElement* select = toHTMLSelectElement(node);
1996
1997     RenderObject* renderer = select->renderer();
1998     if (!renderer->isMenuList())
1999         return false;
2000
2001     RenderMenuList* menuList = toRenderMenuList(renderer);
2002     return menuList->popupIsVisible();
2003 }
2004
2005 String Internals::captionsStyleSheetOverride(ExceptionCode& ec)
2006 {
2007     Document* document = contextDocument();
2008     if (!document || !document->page()) {
2009         ec = INVALID_ACCESS_ERR;
2010         return emptyString();
2011     }
2012
2013 #if ENABLE(VIDEO_TRACK) && !PLATFORM(WIN)
2014     return document->page()->group().captionPreferences()->captionsStyleSheetOverride();
2015 #else
2016     return emptyString();
2017 #endif
2018 }
2019
2020 void Internals::setCaptionsStyleSheetOverride(const String& override, ExceptionCode& ec)
2021 {
2022     Document* document = contextDocument();
2023     if (!document || !document->page()) {
2024         ec = INVALID_ACCESS_ERR;
2025         return;
2026     }
2027
2028 #if ENABLE(VIDEO_TRACK) && !PLATFORM(WIN)
2029     document->page()->group().captionPreferences()->setCaptionsStyleSheetOverride(override);
2030 #endif
2031 }
2032
2033 void Internals::setPrimaryAudioTrackLanguageOverride(const String& language, ExceptionCode& ec)
2034 {
2035     Document* document = contextDocument();
2036     if (!document || !document->page()) {
2037         ec = INVALID_ACCESS_ERR;
2038         return;
2039     }
2040
2041 #if ENABLE(VIDEO_TRACK) && !PLATFORM(WIN)
2042     document->page()->group().captionPreferences()->setPrimaryAudioTrackLanguageOverride(language);
2043 #else
2044     UNUSED_PARAM(language);
2045 #endif
2046 }
2047
2048 void Internals::setCaptionDisplayMode(const String& mode, ExceptionCode& ec)
2049 {
2050     Document* document = contextDocument();
2051     if (!document || !document->page()) {
2052         ec = INVALID_ACCESS_ERR;
2053         return;
2054     }
2055     
2056 #if ENABLE(VIDEO_TRACK) && !PLATFORM(WIN)
2057     CaptionUserPreferences* captionPreferences = document->page()->group().captionPreferences();
2058     
2059     if (equalIgnoringCase(mode, "Automatic"))
2060         captionPreferences->setCaptionDisplayMode(CaptionUserPreferences::Automatic);
2061     else if (equalIgnoringCase(mode, "ForcedOnly"))
2062         captionPreferences->setCaptionDisplayMode(CaptionUserPreferences::ForcedOnly);
2063     else if (equalIgnoringCase(mode, "AlwaysOn"))
2064         captionPreferences->setCaptionDisplayMode(CaptionUserPreferences::AlwaysOn);
2065     else
2066         ec = SYNTAX_ERR;
2067 #else
2068     UNUSED_PARAM(mode);
2069 #endif
2070 }
2071
2072 #if ENABLE(VIDEO)
2073 PassRefPtr<TimeRanges> Internals::createTimeRanges(Float32Array* startTimes, Float32Array* endTimes)
2074 {
2075     ASSERT(startTimes && endTimes);
2076     ASSERT(startTimes->length() == endTimes->length());
2077     RefPtr<TimeRanges> ranges = TimeRanges::create();
2078
2079     unsigned count = std::min(startTimes->length(), endTimes->length());
2080     for (unsigned i = 0; i < count; ++i)
2081         ranges->add(startTimes->item(i), endTimes->item(i));
2082     return ranges;
2083 }
2084
2085 double Internals::closestTimeToTimeRanges(double time, TimeRanges* ranges)
2086 {
2087     return ranges->nearest(time);
2088 }
2089 #endif
2090
2091 PassRefPtr<ClientRect> Internals::selectionBounds(ExceptionCode& ec)
2092 {
2093     Document* document = contextDocument();
2094     if (!document || !document->frame()) {
2095         ec = INVALID_ACCESS_ERR;
2096         return ClientRect::create();
2097     }
2098
2099     return ClientRect::create(document->frame()->selection().bounds());
2100 }
2101
2102 #if ENABLE(VIBRATION)
2103 bool Internals::isVibrating()
2104 {
2105     Page* page = contextDocument()->page();
2106     ASSERT(page);
2107
2108     return Vibration::from(page)->isVibrating();
2109 }
2110 #endif
2111
2112 bool Internals::isPluginUnavailabilityIndicatorObscured(Element* element, ExceptionCode& ec)
2113 {
2114     if (!element) {
2115         ec = INVALID_ACCESS_ERR;
2116         return false;
2117     }
2118
2119     RenderObject* renderer = element->renderer();
2120     if (!renderer || !renderer->isEmbeddedObject()) {
2121         ec = INVALID_ACCESS_ERR;
2122         return false;
2123     }
2124
2125     RenderEmbeddedObject* embed = toRenderEmbeddedObject(renderer);
2126     return embed->isReplacementObscured();
2127 }
2128
2129 }