/*
 * Copyright (C) 2012 Google Inc. All rights reserved.
 * Copyright (C) 2013 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

[
    DoNotCheckConstants
] interface Internals {
    DOMString address(Node node);

    GCObservation observeGC(any observed);

    [RaisesException] DOMString elementRenderTreeAsText(Element element);
    boolean isPreloaded(DOMString url);
    boolean isLoadingFromMemoryCache(DOMString url);

    void crash();

    [RaisesException] unsigned long numberOfScopedHTMLStyleChildren(Node scope);
    [RaisesException] CSSStyleDeclaration computedStyleIncludingVisitedInfo(Node node);

    [RaisesException] ShadowRoot ensureShadowRoot(Element host);
    [RaisesException] ShadowRoot shadowRoot(Element host);
    [RaisesException] ShadowRoot youngestShadowRoot(Element host);
    [RaisesException] ShadowRoot oldestShadowRoot(Element host);
    [RaisesException] ShadowRoot youngerShadowRoot(Node root);
    [RaisesException] ShadowRoot olderShadowRoot(Node root);

    [RaisesException] DOMString shadowRootType(Node root);
    [RaisesException] boolean hasShadowInsertionPoint(Node root);
    [RaisesException] boolean hasContentElement(Node root);
    [RaisesException] unsigned long countElementShadow(Node Root);
    [RaisesException] Element includerFor(Node node);
    [RaisesException] DOMString shadowPseudoId(Element element);
    [RaisesException] void setShadowPseudoId(Element element, DOMString id);
    [RaisesException] Element createContentElement();
    [RaisesException] boolean isValidContentSelect(Element contentElement);
    [RaisesException] Node treeScopeRootNode(Node node);
    [RaisesException] Node parentTreeScope(Node node);
    [RaisesException] boolean hasSelectorForIdInShadow(Element host, DOMString id);
    [RaisesException] boolean hasSelectorForClassInShadow(Element host, DOMString className);
    [RaisesException] boolean hasSelectorForAttributeInShadow(Element host, DOMString attributeName);
    [RaisesException] boolean hasSelectorForPseudoClassInShadow(Element host, DOMString pseudoClass);
    [RaisesException] unsigned short compareTreeScopePosition(Node treeScope1, Node treeScope2);

    // CSS Animation and Transition testing.
    unsigned long numberOfActiveAnimations();
    [RaisesException] void suspendAnimations(Document document);
    [RaisesException] void resumeAnimations(Document document);
    [RaisesException] void pauseAnimations(double pauseTime);

    [RaisesException] Node nextSiblingByWalker(Node node);
    [RaisesException] Node firstChildByWalker(Node node);
    [RaisesException] Node lastChildByWalker(Node node);
    [RaisesException] Node nextNodeByWalker(Node node);
    [RaisesException] Node previousNodeByWalker(Node node);

    [RaisesException] boolean attached(Node node);

    DOMString visiblePlaceholder(Element element);

    void selectColorInColorChooser(Element element, DOMString colorValue);

    [RaisesException] DOMString[] formControlStateOfPreviousHistoryItem();
    [RaisesException] void setFormControlStateOfPreviousHistoryItem(sequence<DOMString> values);
    [RaisesException] void setEnableMockPagePopup(boolean enabled);
    readonly attribute PagePopupController pagePopupController;

    [RaisesException] ClientRect unscaledViewportRect();

    [RaisesException] ClientRect absoluteCaretBounds();

    [RaisesException] ClientRect boundingBox(Element element);

    [RaisesException] ClientRectList inspectorHighlightRects(Document document);

    [RaisesException] unsigned long markerCountForNode(Node node, DOMString markerType);
    [RaisesException] unsigned long activeMarkerCountForNode(Node node);
    [RaisesException] Range markerRangeForNode(Node node, DOMString markerType, unsigned long index);
    [RaisesException] DOMString markerDescriptionForNode(Node node, DOMString markerType, unsigned long index);
    void addTextMatchMarker(Range range, boolean isActive);
    [RaisesException] void setMarkersActive(Node node, unsigned long startOffset, unsigned long endOffset, boolean active);

    [RaisesException] void setScrollViewPosition(Document document, long x, long y);

    [RaisesException] void setPagination(Document document, DOMString mode, long gap, optional long pageLength);

    [RaisesException] DOMString viewportAsText(Document document,
                                               float devicePixelRatio,
                                               long availableWidth,
                                               long availableHeight);

    [RaisesException] boolean wasLastChangeUserEdit(Element textField);
    [RaisesException] boolean elementShouldAutoComplete(Element inputElement);
    [RaisesException] DOMString suggestedValue(Element inputElement);
    [RaisesException] void setSuggestedValue(Element inputElement, DOMString value);
    [RaisesException] void setEditingValue(Element inputElement, DOMString value);
    [RaisesException] void setAutofilled(Element inputElement, boolean enabled);

    [RaisesException] void paintControlTints(Document document);

    [RaisesException] void scrollElementToRect(Element element, long x, long y, long w, long h);

    [RaisesException] Range rangeFromLocationAndLength(Element scope, long rangeLocation, long rangeLength);
    [RaisesException] unsigned long locationFromRange(Element scope, Range range);
    [RaisesException] unsigned long lengthFromRange(Element scope, Range range);
    [RaisesException] DOMString rangeAsText(Range range);

    [RaisesException] WebKitPoint touchPositionAdjustedToBestClickableNode(long x, long y, long width, long height, Document document);
    [RaisesException] Node touchNodeAdjustedToBestClickableNode(long x, long y, long width, long height, Document document);
    [RaisesException] WebKitPoint touchPositionAdjustedToBestContextMenuNode(long x, long y, long width, long height, Document document);
    [RaisesException] Node touchNodeAdjustedToBestContextMenuNode(long x, long y, long width, long height, Document document);
    [RaisesException] ClientRect bestZoomableAreaForTouchPoint(long x, long y, long width, long height, Document document);

    [RaisesException] long lastSpellCheckRequestSequence(Document document);
    [RaisesException] long lastSpellCheckProcessedSequence(Document document);

    sequence<DOMString> userPreferredLanguages();
    void setUserPreferredLanguages(sequence<DOMString> languages);

    [RaisesException] unsigned long wheelEventHandlerCount(Document document);
    [RaisesException] unsigned long touchEventHandlerCount(Document document);
    [RaisesException] LayerRectList touchEventTargetLayerRects(Document document);


    [RaisesException] NodeList nodesFromRect(Document document, long x, long y,
        unsigned long topPadding, unsigned long rightPadding, unsigned long bottomPadding, unsigned long leftPadding,
        boolean ignoreClipping, boolean allowShadowContent, boolean allowChildFrameContent);

    void emitInspectorDidBeginFrame();
    void emitInspectorDidCancelFrame();

    [RaisesException] boolean hasSpellingMarker(Document document, long from, long length);
    [RaisesException] boolean hasGrammarMarker(Document document, long from, long length);
    [RaisesException] void setContinuousSpellCheckingEnabled(boolean enabled);

    [RaisesException] boolean isOverwriteModeEnabled(Document document);
    [RaisesException] void toggleOverwriteModeEnabled(Document document);

    [RaisesException] unsigned long numberOfScrollableAreas(Document document);

    [RaisesException] boolean isPageBoxVisible(Document document, long pageNumber);

    readonly attribute InternalSettings settings;
    readonly attribute InternalProfilers profilers;
    readonly attribute InternalRuntimeFlags runtimeFlags;
    readonly attribute unsigned long workerThreadCount;

    // Flags for layerTreeAsText.
    // The values of these constants must be kept in sync with the values of LayerTreeAsTextBehaviorFlags in GraphicsLayerClient.h.
    const unsigned short LAYER_TREE_INCLUDES_REPAINT_RECTS = 2;
    const unsigned short LAYER_TREE_INCLUDES_PAINTING_PHASES = 4;
    const unsigned short LAYER_TREE_INCLUDES_ROOT_LAYER = 8;
    [RaisesException] DOMString layerTreeAsText(Document document, optional unsigned short flags);
    [RaisesException] DOMString elementLayerTreeAsText(Element element, optional unsigned short flags);

    [RaisesException] NodeList paintOrderListBeforePromote(Element element);
    [RaisesException] NodeList paintOrderListAfterPromote(Element element);

    [RaisesException] boolean scrollsWithRespectTo(Element element1, Element element2);

    // The values of these constants must be kept in sync with those in RenderLayer.
    const unsigned short DO_NOT_FORCE_COMPOSITED_SCROLLING = 0;
    const unsigned short COMPOSITED_SCROLLING_ALWAYS_ON = 1;
    const unsigned short COMPOSITED_SCROLLING_ALWAYS_OFF = 2;
    [RaisesException] void setNeedsCompositedScrolling(Element element, unsigned short value);

    [RaisesException] DOMString scrollingStateTreeAsText(Document document);
    [RaisesException] DOMString mainThreadScrollingReasons(Document document);
    [RaisesException] ClientRectList nonFastScrollableRects(Document document);

    [RaisesException] DOMString repaintRectsAsText(Document document);

    [RaisesException] void garbageCollectDocumentResources(Document document);
    void evictAllResources();

    void allowRoundingHacks();

    void insertAuthorCSS(Document document, DOMString css);
    void insertUserCSS(Document document, DOMString css);

    unsigned long numberOfLiveNodes();
    unsigned long numberOfLiveDocuments();
    sequence<DOMString> consoleMessageArgumentCounts(Document document);
    Window openDummyInspectorFrontend(DOMString url);
    void closeDummyInspectorFrontend();
    unsigned long[] setMemoryCacheCapacities(unsigned long minDeadBytes, unsigned long maxDeadBytes, unsigned long totalBytes);
    [RaisesException] void setInspectorResourcesDataSizeLimits(long maximumResourcesContentSize, long maximumSingleResourceContentSize);

    DOMString counterValue(Element element);
    long pageNumber(Element element, optional float pageWidth, optional float pageHeight);
    DOMString[] shortcutIconURLs(Document document);
    DOMString[] allIconURLs(Document document);
    long numberOfPages(optional double pageWidthInPixels, optional double pageHeightInPixels);
    [RaisesException] DOMString pageProperty(DOMString propertyName, long pageNumber);
    [RaisesException] DOMString pageSizeAndMarginsInPixels(long pageIndex, long width, long height, long marginTop, long marginRight, long marginBottom, long marginLeft);

    [RaisesException] void setDeviceScaleFactor(float scaleFactor);

    [RaisesException] void setIsCursorVisible(Document document, boolean isVisible);

    void webkitWillEnterFullScreenForElement(Document document, Element element);
    void webkitDidEnterFullScreenForElement(Document document, Element element);
    void webkitWillExitFullScreenForElement(Document document, Element element);
    void webkitDidExitFullScreenForElement(Document document, Element element);

    void registerURLSchemeAsBypassingContentSecurityPolicy(DOMString scheme);
    void removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(DOMString scheme);

    MallocStatistics mallocStatistics();
    TypeConversions typeConversions();

    DOMString[] getReferencedFilePaths();

    // These functions both reset the tracked repaint rects. They are inteded to be used in the following order:
    //  startTrackingRepaints, repaintRectsAsText, stopTrackingRepaints.
    [RaisesException] void startTrackingRepaints(Document document);
    [RaisesException] void stopTrackingRepaints(Document document);

    // Returns a string with information about the mouse cursor used at the specified client location.
    [RaisesException] DOMString getCurrentCursorInfo(Document document);

    [RaisesException] DOMString markerTextForListItem(Element element);

    [RaisesException] DOMString baseURL(Document document);

    SerializedScriptValue deserializeBuffer(ArrayBuffer buffer);
    ArrayBuffer serializeObject(SerializedScriptValue obj);

    void setUsesOverlayScrollbars(boolean enabled);

    void forceReload(boolean endToEnd);

    void enableMockSpeechSynthesizer();

    [RaisesException] DOMString getImageSourceURL(Element element);

    boolean isSelectPopupVisible(Node node);

    [RaisesException] ClientRect selectionBounds();

    boolean loseSharedGraphicsContext3D();
};
