/*
 * 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.
 */

enum EffectiveConnectionType {
    "slow-2g",
    "2g",
    "3g",
    "4g"
};

[
    DoNotCheckConstants
] interface Internals {
    GCObservation observeGC(any observed);

    [RaisesException] DOMString elementLayoutTreeAsText(Element element);
    boolean isPreloaded(DOMString url);
    boolean isPreloadedBy(DOMString url, Document document);
    boolean isLoading(DOMString url);
    boolean isLoadingFromMemoryCache(DOMString url);
    unsigned long getResourcePriority (DOMString url, Document document);
    DOMString getResourceHeader (DOMString url, DOMString header, Document document);

    bool doesWindowHaveUrlFragment(Window window);

    CSSStyleDeclaration computedStyleIncludingVisitedInfo(Node node);

    ShadowRoot createUserAgentShadowRoot(Element host);

    ShadowRoot shadowRoot(Element host);

    void setBrowserControlsState(float top_height, float bottom_height, boolean shrinksLayout);
    void setBrowserControlsShownRatio(float ratio);

    Node effectiveRootScroller(Document document);

    [RaisesException] DOMString shadowRootType(Node root);
    [RaisesException] boolean hasShadowInsertionPoint(Node root);
    [RaisesException] boolean hasContentElement(Node root);
    [RaisesException] unsigned long countElementShadow(Node Root);
    DOMString shadowPseudoId(Element element);
    [RaisesException] boolean isValidContentSelect(Element contentElement);
    Node treeScopeRootNode(Node node);
    Node parentTreeScope(Node node);
    [RaisesException] unsigned short compareTreeScopePosition(Node treeScope1, Node treeScope2);
    [RaisesException] unsigned long updateStyleAndReturnAffectedElementCount();
    [RaisesException] unsigned long needsLayoutCount();
    [RaisesException] unsigned long hitTestCount(Document document);
    [RaisesException] unsigned long hitTestCacheHits(Document document);
    [RaisesException] Element? elementFromPoint(Document document, double x, double y, boolean ignoreClipping, boolean allowChildFrameContent);
    [RaisesException] void clearHitTestCache(Document document);

    // Allows inspection of the inner editor node.
    [RaisesException] Element? innerEditorElement(Element container);

    // Animation testing.
    [RaisesException] void pauseAnimations(double pauseTime);
    boolean isCompositedAnimation(Animation animation);
    void disableCompositedAnimation(Animation animation);
    void disableCSSAdditiveAnimations();

    // Advances an animated image. For BitmapImage (e.g., animated gifs) this
    // will advance to the next frame. For SVGImage, this will trigger an
    // animation update for CSS and advance the SMIL timeline by one frame.
    [RaisesException] void advanceImageAnimation(Element image);

    [RaisesException] Node nextSiblingInFlatTree(Node node);
    [RaisesException] Node firstChildInFlatTree(Node node);
    [RaisesException] Node lastChildInFlatTree(Node node);
    [RaisesException] Node nextInFlatTree(Node node);
    [RaisesException] Node previousInFlatTree(Node node);

    DOMString visiblePlaceholder(Element element);
    boolean isValidationMessageVisible(Element element);
    void selectColorInColorChooser(Element element, DOMString colorValue);
    void endColorChooser(Element element);

    // If the argument is omitted, the top-level document is used.
    boolean hasAutofocusRequest(optional Document document);
    [RaisesException] sequence<DOMString> formControlStateOfHistoryItem();
    [RaisesException] void setFormControlStateOfHistoryItem(sequence<DOMString> values);
    readonly attribute Window pagePopupWindow;

    [RaisesException] DOMRectReadOnly absoluteCaretBounds();

    DOMRectReadOnly boundingBox(Element element);

    [RaisesException] void setMarker(Document document, Range range, DOMString markerType);
    [RaisesException] unsigned long markerCountForNode(Node node, DOMString markerType);
    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);
    [RaisesException] unsigned long markerBackgroundColorForNode(Node node, DOMString markerType, unsigned long index);
    [RaisesException] unsigned long markerUnderlineColorForNode(Node node, DOMString markerType, unsigned long index);
    [RaisesException] void addTextMatchMarker(Range range, DOMString matchStatus);
    [RaisesException] void addCompositionMarker(Range range, DOMString underlineColorValue, DOMString thicknessValue, DOMString backgroundColorValue);
    [RaisesException] void addActiveSuggestionMarker(Range range, DOMString underlineColorValue, DOMString thicknessValue, DOMString backgroundColorValue);
    [RaisesException] void addSuggestionMarker(Range range, sequence<DOMString> suggestions, DOMString suggestionHighlightColorValue, DOMString underlineColorValue, DOMString thicknessValue, DOMString backgroundColorValue);
    void setTextMatchMarkersActive(Node node, unsigned long startOffset, unsigned long endOffset, boolean active);
    void setMarkedTextMatchesAreHighlighted(Document document, boolean highlight);

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

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

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

    [RaisesException] DOMPoint 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] DOMPoint 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] long lastSpellCheckRequestSequence(Document document);
    [RaisesException] long lastSpellCheckProcessedSequence(Document document);
    [RaisesException] void cancelCurrentSpellCheckRequest(Document document);
    [RaisesException] DOMString idleTimeSpellCheckerState(Document document);
    [RaisesException] void runIdleTimeSpellChecker(Document document);

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

    unsigned long mediaKeysCount();
    unsigned long mediaKeySessionCount();
    unsigned long pausableObjectCount(Document document);
    unsigned long wheelEventHandlerCount(Document document);
    unsigned long scrollEventHandlerCount(Document document);
    unsigned long touchStartOrMoveEventHandlerCount(Document document);
    unsigned long touchEndOrCancelEventHandlerCount(Document document);
    unsigned long pointerEventHandlerCount(Document document);
    [RaisesException] HitTestLayerRectList touchEventTargetLayerRects(Document document);

    [RaisesException] boolean executeCommand(Document document, DOMString name, DOMString value);

    DOMString htmlNamespace();
    sequence<DOMString> htmlTags();
    DOMString svgNamespace();
    sequence<DOMString> svgTags();

    [RaisesException] NodeList nodesFromRect(Document document, long x, long y,
        unsigned long width, unsigned long height, boolean ignoreClipping,
        boolean allowChildFrameContent);

    [RaisesException] boolean hasSpellingMarker(Document document, long from, long length);
    [RaisesException] boolean hasGrammarMarker(Document document, long from, long length);
    [RaisesException] void replaceMisspelled(Document document, DOMString replacement);

    boolean canHyphenate(DOMString locale);
    void setMockHyphenation(DOMString locale);

    boolean isOverwriteModeEnabled(Document document);
    void toggleOverwriteModeEnabled(Document document);

    unsigned long numberOfScrollableAreas(Document document);

    boolean isPageBoxVisible(Document document, long pageNumber);

    readonly attribute InternalSettings settings;
    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 LayerTreeFlags in GraphicsLayerClient.h.
    const unsigned short LAYER_TREE_INCLUDES_DEBUG_INFO = 1;
    const unsigned short LAYER_TREE_INCLUDES_PAINT_INVALIDATIONS = 2;
    const unsigned short LAYER_TREE_INCLUDES_PAINTING_PHASES = 4;
    const unsigned short LAYER_TREE_INCLUDES_ROOT_LAYER = 8;
    const unsigned short LAYER_TREE_INCLUDES_CLIP_AND_SCROLL_PARENTS = 16;
    const unsigned short LAYER_TREE_INCLUDES_COMPOSITING_REASONS = 32;
    const unsigned short LAYER_TREE_INCLUDES_PAINT_RECORDS = 64;
    const unsigned short OUTPUT_AS_LAYER_TREE = 0x4000;

    [RaisesException] DOMString layerTreeAsText(Document document, optional unsigned short flags);
    [RaisesException] DOMString elementLayerTreeAsText(Element element, optional unsigned short flags);

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

    DOMString scrollingStateTreeAsText(Document document);
    [RaisesException] DOMString mainThreadScrollingReasons(Document document);
    [RaisesException] DOMRectList nonFastScrollableRects(Document document);
    [RaisesException] void markGestureScrollRegionDirty(Document document);

    void evictAllResources();

    unsigned long numberOfLiveNodes();
    unsigned long numberOfLiveDocuments();

    DOMString counterValue(Element element);
    [RaisesException] long pageNumber(Element element, optional float pageWidth = 800, optional float pageHeight = 600);
    sequence<DOMString> shortcutIconURLs(Document document);
    sequence<DOMString> allIconURLs(Document document);
    [RaisesException] long numberOfPages(optional double pageWidthInPixels = 800, optional double pageHeightInPixels = 600);
    [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] float pageScaleFactor();
    [RaisesException] void setPageScaleFactor(float scaleFactor);
    [RaisesException] void setPageScaleFactorLimits(float minScaleFactor, float maxScaleFactor);

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

    // HTMLMediaElement, HTMLAudioElement and HTMLVideoElement.
    DOMString effectivePreload(HTMLMediaElement mediaElement);
    void mediaPlayerRemoteRouteAvailabilityChanged(HTMLMediaElement mediaElement, boolean available);
    void mediaPlayerPlayingRemotelyChanged(HTMLMediaElement mediaElement, boolean remote);
    void setPersistent(HTMLVideoElement video, boolean persistent);
    void forceStaleStateForMediaElement(HTMLMediaElement mediaElement, long state);
    boolean isMediaElementSuspended(HTMLMediaElement mediaElement);
    void setMediaControlsTestMode(HTMLMediaElement mediaElement, boolean enable);

    void registerURLSchemeAsBypassingContentSecurityPolicy(DOMString scheme);
    void registerURLSchemeAsBypassingContentSecurityPolicy(DOMString scheme, sequence<DOMString> policyAreas);
    void removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(DOMString scheme);

    TypeConversions typeConversions();

    sequence<DOMString> getReferencedFilePaths();

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

    // |node| should be Document, HTMLIFrameElement, or unspecified.
    // If |node| is an HTMLIFrameElement, it assumes node.contentDocument is
    // specified without security checks. Unspecified means this document.
    [RaisesException] void updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(optional Node? node = null);

    [RaisesException] void forceFullRepaint(Document document);

    // Returns a list of draggable/non-draggable regions in the document.
    [RaisesException] DOMRectList draggableRegions(Document document);
    [RaisesException] DOMRectList nonDraggableRegions(Document document);

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

    readonly attribute boolean cursorUpdatePending;
    readonly attribute boolean fakeMouseMovePending;

    DOMString markerTextForListItem(Element element);

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

    [CallWith=ScriptState] any deserializeBufferContainingWasm(ArrayBuffer buffer);
    ArrayBuffer serializeWithInlineWasm(any obj);


    void forceReload(boolean endToEnd);

    DOMString getImageSourceURL(Element element);
    [RaisesException] void forceImageReload(Element element);

    DOMString selectMenuListText(HTMLSelectElement select);
    boolean isSelectPopupVisible(Node node);
    boolean selectPopupItemStyleIsRtl(Node select, long itemIndex);
    long selectPopupItemStyleFontHeight(Node select, long itemIndex);
    void resetTypeAheadSession(HTMLSelectElement select);

    [RaisesException] StaticSelection getSelectionInFlatTree(Window window);
    // TODO(editing-dev): We should change |visibleSelection*| to
    // |StaticSelection|.
    readonly attribute Node? visibleSelectionAnchorNode;
    readonly attribute unsigned long visibleSelectionAnchorOffset;
    readonly attribute Node? visibleSelectionFocusNode;
    readonly attribute unsigned long visibleSelectionFocusOffset;
    [RaisesException] DOMRect selectionBounds();
    readonly attribute DOMString textAffinity;

    boolean loseSharedGraphicsContext3D();

    [RaisesException] void forceCompositingUpdate(Document document);

    void setZoomFactor(float factor);

    [RaisesException] void setShouldRevealPassword(Element element, boolean reveal);

    [CallWith=ScriptState] Promise<any> createResolvedPromise(any value);
    [CallWith=ScriptState] Promise<any> createRejectedPromise(any reason);
    [CallWith=ScriptState] Promise<any> addOneToPromise(Promise<any> promise);
    [CallWith=ScriptState, RaisesException] Promise<any> promiseCheck(long arg1, boolean arg2, object arg3, DOMString arg4, sequence<DOMString> arg5);
    [CallWith=ScriptState] Promise<any> promiseCheckWithoutExceptionState(object arg1, DOMString arg2, DOMString... variadic);
    [CallWith=ScriptState] Promise<any> promiseCheckRange([EnforceRange] octet arg1);
    [CallWith=ScriptState] Promise<any> promiseCheckOverload(Location arg1);
    [CallWith=ScriptState] Promise<any> promiseCheckOverload(Document arg1);
    [CallWith=ScriptState] Promise<any> promiseCheckOverload(Location arg1, long arg2, long arg3);

    void setValueForUser(HTMLInputElement element, DOMString value);

    void setFocused(boolean focused);
    void setInitialFocus(boolean reverse);

    boolean ignoreLayoutWithPendingStylesheets(Document document);

    // These functions are for testing NetInfo. You must call clearNetworkConnectionInfoOverride() at the end.
    [RaisesException] void setNetworkConnectionInfoOverride(boolean onLine, DOMString type, EffectiveConnectionType effective_type, unsigned long http_rtt_msec, double downlink_max_mbps);
    void setSaveDataEnabled(boolean enabled);
    void clearNetworkConnectionInfoOverride();

    // This function is for testing HitRegions on Canvas2D.
    unsigned long countHitRegions(CanvasRenderingContext2D context);

    boolean isInCanvasFontCache(Document document, DOMString fontString);
    unsigned long canvasFontCacheMaxFonts();

    DictionaryTest dictionaryTest();
    RecordTest recordTest();
    SequenceTest sequenceTest();
    UnionTypesTest unionTypesTest();
    CallbackFunctionTest callbackFunctionTest();
    [RaisesException] void setScrollChain(ScrollState scrollState, sequence<Element> elements);
    void forceBlinkGCWithoutV8GC();

    DOMString selectedHTMLForClipboard();
    DOMString selectedTextForClipboard();

    void setVisualViewportOffset(long x, long y);

    boolean magnifyScaleAroundAnchor(float offset, float x, float y);

    boolean isUseCounted(Document document, unsigned long feature);
    boolean isCSSPropertyUseCounted(Document document, DOMString propertyName);
    boolean isAnimatedCSSPropertyUseCounted(Document document, DOMString propertyName);
    void clearUseCounter(Document document, unsigned long feature);

    sequence<DOMString> getCSSPropertyLonghands();
    sequence<DOMString> getCSSPropertyShorthands();
    sequence<DOMString> getCSSPropertyAliases();

    // Returns a promise that is resolved when |feature| is counted on
    // |document|'s UseCounter. When |feature| was already counted, it's
    // immediately resolved.
    [CallWith=ScriptState] Promise<boolean> observeUseCounter(Document document, unsigned long feature);

    readonly attribute unsigned long length;
    getter long (unsigned long index);
    iterable<long>;

    [Unscopable] readonly attribute DOMString unscopableAttribute;
    [Unscopable] DOMString unscopableMethod();

    void setCapsLockState(boolean enabled);

    // Returns whether the scrollbar was able to be shown or hidden; not all platforms
    // support overlay scrollbars.
    boolean setScrollbarVisibilityInScrollableArea(Node node, boolean visible);

    [RaisesException] double monotonicTimeToZeroBasedDocumentTime(double platformTime);

    DOMString getScrollAnimationState(Node node);

    DOMString getProgrammaticScrollAnimationState(Node node);

    DOMRect visualRect(Node node);

    OriginTrialsTest originTrialsTest();

    void crash();

    DOMString evaluateInInspectorOverlay(DOMString script);

    void setIsLowEndDevice(boolean isLowEndDevice);
    boolean isLowEndDevice();

    sequence<DOMString> supportedTextEncodingLabels();

    // When RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() and
    // simulateRasterUnderInvalidation(true) is called, all changed pixels will
    // be reported as raster under-invalidations.
    void simulateRasterUnderInvalidations(boolean enable);

    // Bypass the threshold of 'script-compile' of long-task attribution in
    // PerformanceMonitor for testing. "PerformanceObserver should be observing
    // 'longtask' while calling BypassLongCompileThresholdOnce.
    [RaisesException] void BypassLongCompileThresholdOnce();

    // The number of calls to update the blink lifecycle (see:
    // LocalFrameView::UpdateLifecyclePhasesInternal).
    unsigned long LifecycleUpdateCount();

    // Disable the 'delay' option for IntersectionObserver, so that observations
    // are recomputed on every frame.  This eliminates the need to add
    // setTimeout(..., delay_ms) calls to web tests to wait for notifications
    // to be generated.
    void DisableIntersectionObserverThrottleDelay();

    // Declare that the given |name| is in use by the embedder via the custom
    // element mechanism.
    [RaisesException] void addEmbedderCustomElementName(DOMString name);
};
