/*
 * 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 {
    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);

    // Call this function with the URL of a resource that has not yet been
    // fetched. It returns a promise that resolves with the priority of the
    // request, once it has been made.
    [CallWith=ScriptState] Promise<unsigned long> getResourcePriority(DOMString url, Document document);

    DOMString getResourceHeader(DOMString url, DOMString header, Document document);

    boolean 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 top_ratio, float bottom_ratio);

    Node effectiveRootScroller(Document document);

    [RaisesException] DOMString shadowRootType(Node root);
    [RaisesException] unsigned long countElementShadow(Node Root);
    DOMString shadowPseudoId(Element element);
    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);

    // 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(Text text, DOMString markerType);
    unsigned long activeMarkerCountForNode(Text text);
    [RaisesException] Range markerRangeForNode(Text text, DOMString markerType, unsigned long index);
    [RaisesException] DOMString markerDescriptionForNode(Text text, DOMString markerType, unsigned long index);
    [RaisesException] unsigned long markerBackgroundColorForNode(Text text, DOMString markerType, unsigned long index);
    [RaisesException] unsigned long markerUnderlineColorForNode(Text text, DOMString markerType, unsigned long index);
    [RaisesException] void addTextMatchMarker(Range range, DOMString matchStatus);
    [RaisesException] void addCompositionMarker(Range range, DOMString underlineColorValue, DOMString thicknessValue, DOMString underlineStyleValue, DOMString textColorValue, 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);
    [RaisesException] void setSelectionRangeForNumberType(Element inputElement, unsigned long start, unsigned long end);

    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);
    void setSystemTimeZone(DOMString timezone);

    unsigned long mediaKeysCount();
    unsigned long mediaKeySessionCount();
    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);

    void triggerTestInspectorIssue(Document document);

    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;
    readonly attribute boolean isFormControlsRefreshEnabled;

    // Flag for layerTreeAsText. The value must be kept in sync with the value
    // of LayerTreeFlags in layers_as_json.h.
    // Other flags in LayerTreeFlags are not supported in internals API.
    const unsigned short LAYER_TREE_INCLUDES_INVALIDATIONS = 2;
    const unsigned short LAYER_TREE_INCLUDES_DETAILED_INVALIDATIONS = 4;

    [RaisesException] DOMString layerTreeAsText(Document document, 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);

    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, unsigned long pageNumber);
    [RaisesException] DOMString pageSizeAndMarginsInPixels(unsigned 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] float pageZoomFactor();

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

    // 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 updateLayoutAndRunPostLayoutTasks(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;

    DOMString markerTextForListItem(Element element);

    [CallWith=Isolate, RaisesException] ArrayBuffer serializeObject(any obj);
    [CallWith=Isolate] any deserializeBuffer(ArrayBuffer buffer);

    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);

    StaticSelection getDragCaret();
    [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 setForcedColorsAndDarkPreferredColorScheme(Document document);

    [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);

    // When the FocuslessSpatialNavigation feature is enabled, spatial
    // navigation moves "interest" around a page, rather than focus. This
    // attribute returns the currently interested element on the page.
    readonly attribute Element? interestedElement;

    // Returns true if page associated with current internals object is
    // active.
    boolean isActivated();

    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);

    DOMString selectedHTMLForClipboard();
    DOMString selectedTextForClipboard();

    void setVisualViewportOffset(long x, long 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);

    // pseudo: One of ":focus", ":focus-within", ":active", and ":hover".
    [RaisesException] void setPseudoClassState(Element element, DOMString pseudo, 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);

    // Translate an event's DOMHighResTimeStamp in seconds into a monotonic time
    // in milliseconds.
    long long zeroBasedDocumentTimeToMonotonicTime(double domHighResTimeStamp);

    long long currentTimeTicks();

    DOMString getScrollAnimationState(Node node);

    DOMString getProgrammaticScrollAnimationState(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);

    // 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();

    // Reports whether an iframe's browsing context runs in a separate process
    boolean isSiteIsolated(HTMLIFrameElement iframe);

    // Reports whether a parent document is propagating occlusion information
    // down to a child frame, for the purpose of servicing IntersectionObserver
    // instances that track visibility.
    boolean isTrackingOcclusionForIFrame(HTMLIFrameElement iframe);

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

    // https://html.spec.whatwg.org/C/#resolve-a-module-specifier
    // Throws TypeError on error.
    // Used for testing Import Maps https://github.com/domenic/import-maps
    [RaisesException] DOMString resolveModuleSpecifier(DOMString specifier, DOMString base_url, Document document);

    // Returns the current serialized import map of the Document.
    // TODO(crbug.com/927181): Currently this returns the "imports" value,
    // because Blink doesn't support scopes yet. Update this once scopes are
    // implemented.
    [RaisesException] DOMString getParsedImportMap(Document document);

    // Sets the scale for devtools device emulation.
    [RaisesException] void setDeviceEmulationScale(float scale);

    // Return a string that identifies |window|'s WindowAgent. You can use it
    // to distinguish different Agent instances (perhaps in a remote process).
    // The returned string is composed of the process ID and the memory address
    // of the Agent object.
    DOMString getAgentId(Window window);

    void useMockOverlayScrollbars();
    readonly attribute boolean overlayScrollbarsEnabled;

    // Request generation of a Reporting report.
    void generateTestReport(DOMString message);

    [RaisesException] void setIsAdSubframe(HTMLIFrameElement iframe);

    [RaisesException, CallWith=ScriptState] ReadableStream createReadableStream(long queueSize, DOMString optimizer);
    // The return value consists of a WritableStream (.stream) and a promise of
    // a sink object (.sink).
    [RaisesException, CallWith=ScriptState] any createWritableStreamAndSink(long queueSize, DOMString optimizer);
};
