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