/*
 * Copyright (C) 2010 Apple Inc. All rights reserved.
 * Copyright (C) 2011 Google 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER OR 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.
 */

module core {
    interface [Conditional=INSPECTOR] Inspector {
        void addScriptToEvaluateOnLoad(in String scriptSource);
        void removeAllScriptsToEvaluateOnLoad();
        void reloadPage(in boolean ignoreCache);
        void populateScriptObjects();

        void openInInspectedWindow(in String url);
        void setSearchingForNode(in boolean enabled, out boolean newState);
        [notify] void frontendReused();
        [notify] void addNodesToSearchResult(out Array nodeIds);
        [notify] void bringToFront();
        [notify] void disconnectFromBackend();
        [notify] void inspectedURLChanged(out String url);
        [notify] void domContentEventFired(out double time);
        [notify] void loadEventFired(out double time);
        [notify] void reset();
        [notify] void showPanel(out String panel);

        [notify] void evaluateForTestInFrontend(out long testCallId, out String script);
        void didEvaluateForTestInFrontend(in long testCallId, in String jsonResult);

        void highlightDOMNode(in long nodeId);
        void hideDOMNodeHighlight();
        void highlightFrame(in unsigned long frameId);
        void hideFrameHighlight();
        [notify] void updateFocusedNode(out long nodeId);

        void setUserAgentOverride(in String userAgent);

        void getCookies(out Array cookies, out String cookiesString);
        void deleteCookie(in String cookieName, in String domain);

        // FIXME: dispatch on agents.
        void startTimelineProfiler();
        void stopTimelineProfiler();

#if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER
        void enableDebugger();
        void disableDebugger();
        void enableProfiler();
        void disableProfiler();
        void startProfiling();
        void stopProfiling();
#endif // ENABLE_JAVASCRIPT_DEBUGGER
    };

    interface [Conditional=INSPECTOR] Runtime {
        void evaluate(in String expression, in String objectGroup, in boolean includeCommandLineAPI, out Value result);
        void getCompletions(in String expression, in boolean includeCommandLineAPI, out Value result);
        void getProperties(in Object objectId, in boolean ignoreHasOwnProperty, in boolean abbreviate, out Value result);
        void setPropertyValue(in Object objectId, in String propertyName, in String expression, out Value result);
        void releaseWrapperObjectGroup(in long injectedScriptId, in String objectGroup);
    };

    interface [Conditional=INSPECTOR] InjectedScript {
        void evaluateOnSelf(in String functionBody, in Array argumentsArray, out Value result);
    };

    interface [Conditional=INSPECTOR] Console {
        void setConsoleMessagesEnabled(in boolean enabled, out boolean newState);
        [notify] void addConsoleMessage(out Object messageObj);
        [notify] void updateConsoleMessageExpiredCount(out unsigned long count);
        [notify] void updateConsoleMessageRepeatCount(out unsigned long count);
        void clearConsoleMessages();
        [notify] void consoleMessagesCleared();
        void setMonitoringXHREnabled(in boolean enabled);
    };

    interface [Conditional=INSPECTOR] Network {
        void cachedResources(out Object resources);
        void resourceContent(in unsigned long frameId, in String url, in boolean base64Encode, out boolean success, out String content);
        void setExtraHeaders(in Object headers);

        [notify] void frameDetachedFromParent(out unsigned long frameId);
        [notify] void identifierForInitialRequest(out long identifier, out String url, out Object loader, out Value callStack);
        [notify] void willSendRequest(out long identifier, out double time, out Object request, out Object redirectResponse);
        [notify] void markResourceAsCached(out long identifier);
        [notify] void didReceiveResponse(out long identifier, out double time, out String resourceType, out Object response);
        [notify] void didReceiveContentLength(out long identifier, out double time, out long lengthReceived);
        [notify] void didFinishLoading(out long identifier, out double finishTime);
        [notify] void didFailLoading(out long identifier, out double time, out String localizedDescription);
        [notify] void didLoadResourceFromMemoryCache(out double time, out Object resource);
        [notify] void setInitialContent(out long identifier, out String sourceString, out String type);
        [notify] void didCommitLoadForFrame(out Object frame, out Object loader);
        [notify] void didCreateWebSocket(out unsigned long identifier, out String requestURL);
        [notify] void willSendWebSocketHandshakeRequest(out unsigned long identifier, out double time, out Object request);
        [notify] void didReceiveWebSocketHandshakeResponse(out unsigned long identifier, out double time, out Object response);
        [notify] void didCloseWebSocket(out unsigned long identifier, out double time);
    };

#if defined(ENABLE_DATABASE) && ENABLE_DATABASE
    interface [Conditional=INSPECTOR] Database {
        void getDatabaseTableNames(in long databaseId, out Array tableNames);
        void executeSQL(in long databaseId, in String query, out boolean success, out long transactionId);

        [notify] void addDatabase(out Object database);
        [notify] void selectDatabase(out int databaseId);
        [notify] void sqlTransactionSucceeded(out long transactionId, out Value columnNames, out Value values);
        [notify] void sqlTransactionFailed(out long transactionId, out Value sqlError);
    };
#endif

#if defined(ENABLE_DOM_STORAGE) && ENABLE_DOM_STORAGE
    interface [Conditional=INSPECTOR] DOMStorage {
        void getDOMStorageEntries(in long storageId, out Array entries);
        void setDOMStorageItem(in long storageId, in String key, in String value, out boolean success);
        void removeDOMStorageItem(in long storageId, in String key, out boolean success);
        [notify] void addDOMStorage(out Object storage);
        [notify] void updateDOMStorage(out int storageId);
        [notify] void selectDOMStorage(out int storageId);
    };
#endif

#if defined(ENABLE_OFFLINE_WEB_APPLICATIONS) && ENABLE_OFFLINE_WEB_APPLICATIONS
    interface [Conditional=INSPECTOR] ApplicationCache {
        void getApplicationCaches(out Value applicationCaches);
        [notify] void updateApplicationCacheStatus(out int status);
        [notify] void updateNetworkState(out boolean isNowOnline);
    };
#endif

    interface [Conditional=INSPECTOR] DOM {
        void getChildNodes(in long nodeId);
        void setAttribute(in long elementId, in String name, in String value, out boolean success);
        void removeAttribute(in long elementId, in String name, out boolean success);
        void setTextNodeValue(in long nodeId, in String value, out boolean success);
        void getEventListenersForNode(in long nodeId, out long outNodeId, out Array listenersArray);
        void copyNode(in long nodeId);
        void removeNode(in long nodeId, out long outNodeId);
        void changeTagName(in long nodeId, in String newTagName, out long outNodeId);
        void getOuterHTML(in long nodeId, out String outerHTML);
        void setOuterHTML(in long nodeId, in String outerHTML, out long outNodeId);
        void addInspectedNode(in long nodeId);
        void performSearch(in String query, in boolean runSynchronously);
        void searchCanceled();
        void pushNodeByPathToFrontend(in String path, out long nodeId);
        void resolveNode(in long nodeId, out Value result);
        void getNodeProperties(in long nodeId, in Array propertiesArray, out Value result);
        void getNodePrototypes(in long nodeId, out Value result);
        void pushNodeToFrontend(in Object objectId, out Value result);

        [notify] void setDocument(out Value root); // FIXME: should be requested from the front-end as getDocument.
        [notify] void attributesUpdated(out long id, out Array attributes);
        [notify] void characterDataModified(out long id, out String newValue);
        [notify] void setChildNodes(out long parentId, out Array nodes);
        [notify] void setDetachedRoot(out Object root);
        [notify] void childNodeCountUpdated(out long id, out int newValue);
        [notify] void childNodeInserted(out long parentId, out long prevId, out Object node);
        [notify] void childNodeRemoved(out long parentId, out long id);
    };

    interface [Conditional=INSPECTOR] CSS {
        void getStylesForNode(in long nodeId, out Value styles);
        void getComputedStyleForNode(in long nodeId, out Value style);
        void getInlineStyleForNode(in long nodeId, out Value style);
        void getAllStyles(out Array styleSheetIds);
        void getStyleSheet(in String styleSheetId, out Value styleSheet);
        void getStyleSheetText(in String styleSheetId, out String url, out String text);
        void setStyleSheetText(in String styleSheetId, in String text, out boolean success);
        void setPropertyText(in Object styleId, in long propertyIndex, in String text, in boolean overwrite, out Value style);
        void toggleProperty(in Object styleId, in long propertyIndex, in boolean disable, out Value style);
        void setRuleSelector(in Object ruleId, in String selector, out Value rule);
        void addRule(in long contextNodeId, in String selector, out Value rule);
        void getSupportedCSSProperties(out Array cssProperties);
        void querySelectorAll(in long documentId, in String selector, out Array result);
    };

    interface [Conditional=INSPECTOR] Timeline {
        [notify] void timelineProfilerWasStarted();
        [notify] void timelineProfilerWasStopped();
        [notify] void addRecordToTimeline(out Object record);
    };

#if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER
    interface [Conditional=INSPECTOR] Debugger {
        [notify] void debuggerWasEnabled();
        [notify] void debuggerWasDisabled();

        [notify] void parsedScriptSource(out String sourceID, out String url, out int lineOffset, out int columnOffset, out int length, out int scriptWorldType);
        [notify] void failedToParseScriptSource(out String url, out String data, out int firstLine, out int errorLine, out String errorMessage);

        void activateBreakpoints();
        void deactivateBreakpoints();

        void setJavaScriptBreakpoint(in String url, in int lineNumber, in int columnNumber, in String condition, in boolean enabled, out String breakpointId, out Array locations);
        void setJavaScriptBreakpointBySourceId(in String sourceId, in int lineNumber, in int columnNumber, in String condition, in boolean enabled, out String breakpointId, out int actualLineNumber, out int actualColumnNumber);
        void removeJavaScriptBreakpoint(in String breakpointId);
        [notify] void breakpointResolved(out String breakpointId, out String sourceId, out int lineNumber, out int columnNumber);
        void continueToLocation(in String sourceId, in int lineNumber, in int columnNumber);

        void stepOver();
        void stepInto();
        void stepOut();
        void pause();
        [notify] void pausedScript(out Object details);
        void resume();
        [notify] void resumedScript(); // FIXME: Make this out parameter of resume if possible.

        void editScriptSource(in String sourceID, in String newContent, out boolean success, out String result, out Value newCallFrames);
        void getScriptSource(in String sourceID, out String scriptSource);

        void setPauseOnExceptionsState(in long pauseOnExceptionsState, out long newState);

        void evaluateOnCallFrame(in Object callFrameId, in String expression, in String objectGroup, in boolean includeCommandLineAPI, out Value result);
        void getCompletionsOnCallFrame(in Object callFrameId, in String expression, in boolean includeCommandLineAPI, out Value result);

#if defined(ENABLE_WORKERS) && ENABLE_WORKERS
        [notify] void didCreateWorker(out long id, out String url, out boolean isShared);
        [notify] void didDestroyWorker(out long id);
#endif // ENABLE_WORKERS

    };
#endif // ENABLE_JAVASCRIPT_DEBUGGER

#if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER
    interface [Conditional=INSPECTOR] BrowserDebugger {
        void setAllBrowserBreakpoints(in Object breakpoints);
        void setDOMBreakpoint(in long nodeId, in long type);
        void removeDOMBreakpoint(in long nodeId, in long type);
        void setEventListenerBreakpoint(in String eventName);
        void removeEventListenerBreakpoint(in String eventName);
        void setXHRBreakpoint(in String url);
        void removeXHRBreakpoint(in String url);
    };
#endif // ENABLE_JAVASCRIPT_DEBUGGER

#if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER
    interface [Conditional=INSPECTOR] Profiler {
        [notify] void profilerWasEnabled();
        [notify] void profilerWasDisabled();

        void getProfileHeaders(out Array headers);
        void getProfile(in String type, in unsigned long uid, out Object profile);
        void removeProfile(in String type, in unsigned long uid);
        void clearProfiles();

        // FIXME: split into Profiler and HeapProfiler.
        void takeHeapSnapshot(in boolean detailed);
        [notify] void addProfileHeader(out Object header);
        [notify] void addHeapSnapshotChunk(out unsigned long uid, out String chunk);
        [notify] void finishHeapSnapshot(out unsigned long uid);
        [notify] void setRecordingProfile(out boolean isProfiling);
        [notify] void resetProfiles();
        [notify] void reportHeapSnapshotProgress(out int done, out int total);
    };
#endif // ENABLE_JAVASCRIPT_DEBUGGER
}
