diff options
Diffstat (limited to 'devtools/shared/specs')
43 files changed, 3533 insertions, 0 deletions
diff --git a/devtools/shared/specs/actor-registry.js b/devtools/shared/specs/actor-registry.js new file mode 100644 index 000000000..0f57dc8d2 --- /dev/null +++ b/devtools/shared/specs/actor-registry.js @@ -0,0 +1,43 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { + Arg, + RetVal, + generateActorSpec, +} = require("devtools/shared/protocol"); + +const actorActorSpec = generateActorSpec({ + typeName: "actorActor", + + methods: { + unregister: { + request: {}, + response: {} + } + }, +}); + +exports.actorActorSpec = actorActorSpec; + +const actorRegistrySpec = generateActorSpec({ + typeName: "actorRegistry", + + methods: { + registerActor: { + request: { + sourceText: Arg(0, "string"), + filename: Arg(1, "string"), + options: Arg(2, "json") + }, + + response: { + actorActor: RetVal("actorActor") + } + } + } +}); + +exports.actorRegistrySpec = actorRegistrySpec; diff --git a/devtools/shared/specs/addons.js b/devtools/shared/specs/addons.js new file mode 100644 index 000000000..6246b9d1f --- /dev/null +++ b/devtools/shared/specs/addons.js @@ -0,0 +1,19 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const {Arg, RetVal, generateActorSpec} = require("devtools/shared/protocol"); + +const addonsSpec = generateActorSpec({ + typeName: "addons", + + methods: { + installTemporaryAddon: { + request: { addonPath: Arg(0, "string") }, + response: { addon: RetVal("json") }, + }, + }, +}); + +exports.addonsSpec = addonsSpec; diff --git a/devtools/shared/specs/animation.js b/devtools/shared/specs/animation.js new file mode 100644 index 000000000..20af12c23 --- /dev/null +++ b/devtools/shared/specs/animation.js @@ -0,0 +1,151 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { + Arg, + RetVal, + generateActorSpec, + types +} = require("devtools/shared/protocol"); +require("devtools/shared/specs/inspector"); + +/** + * Sent with the 'mutations' event as part of an array of changes, used to + * inform fronts of the type of change that occured. + */ +types.addDictType("animationMutationChange", { + // The type of change ("added" or "removed"). + type: "string", + // The changed AnimationPlayerActor. + player: "animationplayer" +}); + +const animationPlayerSpec = generateActorSpec({ + typeName: "animationplayer", + + events: { + "changed": { + type: "changed", + state: Arg(0, "json") + } + }, + + methods: { + release: { release: true }, + getCurrentState: { + request: {}, + response: { + data: RetVal("json") + } + }, + pause: { + request: {}, + response: {} + }, + play: { + request: {}, + response: {} + }, + ready: { + request: {}, + response: {} + }, + setCurrentTime: { + request: { + currentTime: Arg(0, "number") + }, + response: {} + }, + setPlaybackRate: { + request: { + currentTime: Arg(0, "number") + }, + response: {} + }, + getFrames: { + request: {}, + response: { + frames: RetVal("json") + } + }, + getProperties: { + request: {}, + response: { + properties: RetVal("array:json") + } + } + } +}); + +exports.animationPlayerSpec = animationPlayerSpec; + +const animationsSpec = generateActorSpec({ + typeName: "animations", + + events: { + "mutations": { + type: "mutations", + changes: Arg(0, "array:animationMutationChange") + } + }, + + methods: { + setWalkerActor: { + request: { + walker: Arg(0, "domwalker") + }, + response: {} + }, + getAnimationPlayersForNode: { + request: { + actorID: Arg(0, "domnode") + }, + response: { + players: RetVal("array:animationplayer") + } + }, + stopAnimationPlayerUpdates: { + request: {}, + response: {} + }, + pauseAll: { + request: {}, + response: {} + }, + playAll: { + request: {}, + response: {} + }, + toggleAll: { + request: {}, + response: {} + }, + toggleSeveral: { + request: { + players: Arg(0, "array:animationplayer"), + shouldPause: Arg(1, "boolean") + }, + response: {} + }, + setCurrentTimes: { + request: { + players: Arg(0, "array:animationplayer"), + time: Arg(1, "number"), + shouldPause: Arg(2, "boolean") + }, + response: {} + }, + setPlaybackRates: { + request: { + players: Arg(0, "array:animationplayer"), + rate: Arg(1, "number") + }, + response: {} + } + } +}); + +exports.animationsSpec = animationsSpec; + diff --git a/devtools/shared/specs/breakpoint.js b/devtools/shared/specs/breakpoint.js new file mode 100644 index 000000000..e30c03ce8 --- /dev/null +++ b/devtools/shared/specs/breakpoint.js @@ -0,0 +1,16 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const {generateActorSpec} = require("devtools/shared/protocol"); + +const breakpointSpec = generateActorSpec({ + typeName: "breakpoint", + + methods: { + delete: {} + }, +}); + +exports.breakpointSpec = breakpointSpec; diff --git a/devtools/shared/specs/call-watcher.js b/devtools/shared/specs/call-watcher.js new file mode 100644 index 000000000..34d63111a --- /dev/null +++ b/devtools/shared/specs/call-watcher.js @@ -0,0 +1,79 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const protocol = require("devtools/shared/protocol"); +const { Arg, RetVal, Option, generateActorSpec } = protocol; + +/** + * Type describing a single function call in a stack trace. + */ +protocol.types.addDictType("call-stack-item", { + name: "string", + file: "string", + line: "number" +}); + +/** + * Type describing an overview of a function call. + */ +protocol.types.addDictType("call-details", { + type: "number", + name: "string", + stack: "array:call-stack-item" +}); + +const functionCallSpec = generateActorSpec({ + typeName: "function-call", + + methods: { + getDetails: { + response: { info: RetVal("call-details") } + }, + }, +}); + +exports.functionCallSpec = functionCallSpec; + +const callWatcherSpec = generateActorSpec({ + typeName: "call-watcher", + + events: { + /** + * Events emitted when the `onCall` function isn't provided. + */ + "call": { + type: "call", + function: Arg(0, "function-call") + } + }, + + methods: { + setup: { + request: { + tracedGlobals: Option(0, "nullable:array:string"), + tracedFunctions: Option(0, "nullable:array:string"), + startRecording: Option(0, "boolean"), + performReload: Option(0, "boolean"), + holdWeak: Option(0, "boolean"), + storeCalls: Option(0, "boolean") + }, + oneway: true + }, + finalize: { + oneway: true + }, + isRecording: { + response: RetVal("boolean") + }, + initTimestampEpoch: {}, + resumeRecording: {}, + pauseRecording: { + response: { calls: RetVal("array:function-call") } + }, + eraseRecording: {}, + } +}); + +exports.callWatcherSpec = callWatcherSpec; diff --git a/devtools/shared/specs/canvas.js b/devtools/shared/specs/canvas.js new file mode 100644 index 000000000..dcb26f9a9 --- /dev/null +++ b/devtools/shared/specs/canvas.js @@ -0,0 +1,131 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const protocol = require("devtools/shared/protocol"); +const {Arg, Option, RetVal, generateActorSpec} = protocol; + +/** + * Type representing an ArrayBufferView, serialized fast(er). + * + * Don't create a new array buffer view from the parsed array on the frontend. + * Consumers may copy the data into an existing buffer, or create a new one if + * necesasry. For example, this avoids the need for a redundant copy when + * populating ImageData objects, at the expense of transferring char views + * of a pixel buffer over the protocol instead of a packed int view. + * + * XXX: It would be nice if on local connections (only), we could just *give* + * the buffer directly to the front, instead of going through all this + * serialization redundancy. + */ +protocol.types.addType("array-buffer-view", { + write: (v) => "[" + Array.join(v, ",") + "]", + read: (v) => JSON.parse(v) +}); + +/** + * Type describing a thumbnail or screenshot in a recorded animation frame. + */ +protocol.types.addDictType("snapshot-image", { + index: "number", + width: "number", + height: "number", + scaling: "number", + flipped: "boolean", + pixels: "array-buffer-view" +}); + +/** + * Type describing an overview of a recorded animation frame. + */ +protocol.types.addDictType("snapshot-overview", { + calls: "array:function-call", + thumbnails: "array:snapshot-image", + screenshot: "snapshot-image" +}); + +exports.CANVAS_CONTEXTS = [ + "CanvasRenderingContext2D", + "WebGLRenderingContext" +]; + +exports.ANIMATION_GENERATORS = [ + "requestAnimationFrame" +]; + +exports.LOOP_GENERATORS = [ + "setTimeout" +]; + +exports.DRAW_CALLS = [ + // 2D canvas + "fill", + "stroke", + "clearRect", + "fillRect", + "strokeRect", + "fillText", + "strokeText", + "drawImage", + + // WebGL + "clear", + "drawArrays", + "drawElements", + "finish", + "flush" +]; + +exports.INTERESTING_CALLS = [ + // 2D canvas + "save", + "restore", + + // WebGL + "useProgram" +]; + +const frameSnapshotSpec = generateActorSpec({ + typeName: "frame-snapshot", + + methods: { + getOverview: { + response: { overview: RetVal("snapshot-overview") } + }, + generateScreenshotFor: { + request: { call: Arg(0, "function-call") }, + response: { screenshot: RetVal("snapshot-image") } + }, + }, +}); + +exports.frameSnapshotSpec = frameSnapshotSpec; + +const canvasSpec = generateActorSpec({ + typeName: "canvas", + + methods: { + setup: { + request: { reload: Option(0, "boolean") }, + oneway: true + }, + finalize: { + oneway: true + }, + isInitialized: { + response: { initialized: RetVal("boolean") } + }, + isRecording: { + response: { recording: RetVal("boolean") } + }, + recordAnimationFrame: { + response: { snapshot: RetVal("nullable:frame-snapshot") } + }, + stopRecordingAnimationFrame: { + oneway: true + }, + } +}); + +exports.canvasSpec = canvasSpec; diff --git a/devtools/shared/specs/css-properties.js b/devtools/shared/specs/css-properties.js new file mode 100644 index 000000000..76c85bd74 --- /dev/null +++ b/devtools/shared/specs/css-properties.js @@ -0,0 +1,20 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { RetVal, generateActorSpec } = require("devtools/shared/protocol"); + +const cssPropertiesSpec = generateActorSpec({ + typeName: "cssProperties", + + methods: { + getCSSDatabase: { + request: {}, + + response: RetVal("json"), + } + } +}); + +exports.cssPropertiesSpec = cssPropertiesSpec; diff --git a/devtools/shared/specs/csscoverage.js b/devtools/shared/specs/csscoverage.js new file mode 100644 index 000000000..4c58b09a9 --- /dev/null +++ b/devtools/shared/specs/csscoverage.js @@ -0,0 +1,44 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const {Arg, RetVal, generateActorSpec} = require("devtools/shared/protocol"); + +require("devtools/shared/specs/stylesheets"); + +const cssUsageSpec = generateActorSpec({ + typeName: "cssUsage", + + events: { + "state-change": { + type: "stateChange", + stateChange: Arg(0, "json") + } + }, + + methods: { + start: { + request: { url: Arg(0, "boolean") } + }, + stop: {}, + toggle: {}, + oneshot: {}, + createEditorReport: { + request: { url: Arg(0, "string") }, + response: { reports: RetVal("array:json") } + }, + createEditorReportForSheet: { + request: { url: Arg(0, "stylesheet") }, + response: { reports: RetVal("array:json") } + }, + createPageReport: { + response: RetVal("json") + }, + _testOnlyVisitedPages: { + response: { value: RetVal("array:string") } + }, + }, +}); + +exports.cssUsageSpec = cssUsageSpec; diff --git a/devtools/shared/specs/device.js b/devtools/shared/specs/device.js new file mode 100644 index 000000000..3237d1593 --- /dev/null +++ b/devtools/shared/specs/device.js @@ -0,0 +1,19 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const {RetVal, generateActorSpec} = require("devtools/shared/protocol"); + +const deviceSpec = generateActorSpec({ + typeName: "device", + + methods: { + getDescription: {request: {}, response: { value: RetVal("json")}}, + getWallpaper: {request: {}, response: { value: RetVal("longstring")}}, + screenshotToDataURL: {request: {}, response: { value: RetVal("longstring")}}, + getRawPermissionsTable: {request: {}, response: { value: RetVal("json")}}, + }, +}); + +exports.deviceSpec = deviceSpec; diff --git a/devtools/shared/specs/director-manager.js b/devtools/shared/specs/director-manager.js new file mode 100644 index 000000000..8a9bf77ee --- /dev/null +++ b/devtools/shared/specs/director-manager.js @@ -0,0 +1,190 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { + types, + Arg, + Option, + RetVal, + generateActorSpec, +} = require("devtools/shared/protocol"); + +/** + * Type describing a messageport event + */ +types.addDictType("messageportevent", { + isTrusted: "boolean", + data: "nullable:primitive", + origin: "nullable:string", + lastEventId: "nullable:string", + source: "messageport", + ports: "nullable:array:messageport" +}); + +const messagePortSpec = generateActorSpec({ + typeName: "messageport", + + /** + * Events emitted by this actor. + */ + events: { + message: { + type: "message", + msg: Arg(0, "nullable:messageportevent") + } + }, + + methods: { + postMessage: { + oneway: true, + request: { + msg: Arg(0, "nullable:json") + } + }, + start: { + oneway: true, + request: {} + }, + close: { + oneway: true, + request: {} + }, + finalize: { + oneway: true + }, + }, +}); + +exports.messagePortSpec = messagePortSpec; + +/** + * Type describing a director-script error + */ +types.addDictType("director-script-error", { + directorScriptId: "string", + message: "nullable:string", + stack: "nullable:string", + fileName: "nullable:string", + lineNumber: "nullable:number", + columnNumber: "nullable:number" +}); + +/** + * Type describing a director-script attach event + */ +types.addDictType("director-script-attach", { + directorScriptId: "string", + url: "string", + innerId: "number", + port: "nullable:messageport" +}); + +/** + * Type describing a director-script detach event + */ +types.addDictType("director-script-detach", { + directorScriptId: "string", + innerId: "number" +}); + +const directorScriptSpec = generateActorSpec({ + typeName: "director-script", + + /** + * Events emitted by this actor. + */ + events: { + error: { + type: "error", + data: Arg(0, "director-script-error") + }, + attach: { + type: "attach", + data: Arg(0, "director-script-attach") + }, + detach: { + type: "detach", + data: Arg(0, "director-script-detach") + } + }, + + methods: { + setup: { + request: { + reload: Option(0, "boolean"), + skipAttach: Option(0, "boolean") + }, + oneway: true + }, + getMessagePort: { + request: { }, + response: { + port: RetVal("nullable:messageport") + } + }, + finalize: { + oneway: true + }, + }, +}); + +exports.directorScriptSpec = directorScriptSpec; + +const directorManagerSpec = generateActorSpec({ + typeName: "director-manager", + + /** + * Events emitted by this actor. + */ + events: { + "director-script-error": { + type: "error", + data: Arg(0, "director-script-error") + }, + "director-script-attach": { + type: "attach", + data: Arg(0, "director-script-attach") + }, + "director-script-detach": { + type: "detach", + data: Arg(0, "director-script-detach") + } + }, + + methods: { + list: { + response: { + directorScripts: RetVal("json") + } + }, + enableByScriptIds: { + oneway: true, + request: { + selectedIds: Arg(0, "array:string"), + reload: Option(1, "boolean") + } + }, + disableByScriptIds: { + oneway: true, + request: { + selectedIds: Arg(0, "array:string"), + reload: Option(1, "boolean") + } + }, + getByScriptId: { + request: { + scriptId: Arg(0, "string") + }, + response: { + directorScript: RetVal("director-script") + } + }, + finalize: { + oneway: true + }, + }, +}); + +exports.directorManagerSpec = directorManagerSpec; diff --git a/devtools/shared/specs/director-registry.js b/devtools/shared/specs/director-registry.js new file mode 100644 index 000000000..8ebb08eea --- /dev/null +++ b/devtools/shared/specs/director-registry.js @@ -0,0 +1,41 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const {Arg, Option, RetVal, generateActorSpec} = require("devtools/shared/protocol"); + +const directorRegistrySpec = generateActorSpec({ + typeName: "director-registry", + + methods: { + finalize: { + oneway: true + }, + install: { + request: { + scriptId: Arg(0, "string"), + scriptCode: Option(1, "string"), + scriptOptions: Option(1, "nullable:json") + }, + response: { + success: RetVal("boolean") + } + }, + uninstall: { + request: { + scritpId: Arg(0, "string") + }, + response: { + success: RetVal("boolean") + } + }, + list: { + response: { + directorScripts: RetVal("array:string") + } + }, + }, +}); + +exports.directorRegistrySpec = directorRegistrySpec; diff --git a/devtools/shared/specs/emulation.js b/devtools/shared/specs/emulation.js new file mode 100644 index 000000000..1267feaf9 --- /dev/null +++ b/devtools/shared/specs/emulation.js @@ -0,0 +1,106 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { Arg, RetVal, generateActorSpec } = require("devtools/shared/protocol"); + +const emulationSpec = generateActorSpec({ + typeName: "emulation", + + methods: { + setDPPXOverride: { + request: { + dppx: Arg(0, "number") + }, + response: { + valueChanged: RetVal("boolean") + } + }, + + getDPPXOverride: { + request: {}, + response: { + dppx: RetVal("number") + } + }, + + clearDPPXOverride: { + request: {}, + response: { + valueChanged: RetVal("boolean") + } + }, + + setNetworkThrottling: { + request: { + options: Arg(0, "json") + }, + response: { + valueChanged: RetVal("boolean") + } + }, + + getNetworkThrottling: { + request: {}, + response: { + state: RetVal("json") + } + }, + + clearNetworkThrottling: { + request: {}, + response: { + valueChanged: RetVal("boolean") + } + }, + + setTouchEventsOverride: { + request: { + flag: Arg(0, "number") + }, + response: { + valueChanged: RetVal("boolean") + } + }, + + getTouchEventsOverride: { + request: {}, + response: { + flag: RetVal("number") + } + }, + + clearTouchEventsOverride: { + request: {}, + response: { + valueChanged: RetVal("boolean") + } + }, + + setUserAgentOverride: { + request: { + flag: Arg(0, "string") + }, + response: { + valueChanged: RetVal("boolean") + } + }, + + getUserAgentOverride: { + request: {}, + response: { + userAgent: RetVal("string") + } + }, + + clearUserAgentOverride: { + request: {}, + response: { + valueChanged: RetVal("boolean") + } + }, + } +}); + +exports.emulationSpec = emulationSpec; diff --git a/devtools/shared/specs/environment.js b/devtools/shared/specs/environment.js new file mode 100644 index 000000000..d320d98a4 --- /dev/null +++ b/devtools/shared/specs/environment.js @@ -0,0 +1,27 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const {Arg, RetVal, generateActorSpec} = require("devtools/shared/protocol"); + +const environmentSpec = generateActorSpec({ + typeName: "environment", + + methods: { + assign: { + request: { + name: Arg(1), + value: Arg(2) + } + }, + bindings: { + request: {}, + response: { + bindings: RetVal("json") + } + }, + }, +}); + +exports.environmentSpec = environmentSpec; diff --git a/devtools/shared/specs/eventlooplag.js b/devtools/shared/specs/eventlooplag.js new file mode 100644 index 000000000..1498d5f63 --- /dev/null +++ b/devtools/shared/specs/eventlooplag.js @@ -0,0 +1,31 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { Arg, RetVal, generateActorSpec } = require("devtools/shared/protocol"); + +const eventLoopLagSpec = generateActorSpec({ + typeName: "eventLoopLag", + + events: { + "event-loop-lag": { + type: "event-loop-lag", + // duration of the lag in milliseconds. + time: Arg(0, "number") + } + }, + + methods: { + start: { + request: {}, + response: {success: RetVal("number")} + }, + stop: { + request: {}, + response: {} + } + } +}); + +exports.eventLoopLagSpec = eventLoopLagSpec; diff --git a/devtools/shared/specs/frame.js b/devtools/shared/specs/frame.js new file mode 100644 index 000000000..6365d6e90 --- /dev/null +++ b/devtools/shared/specs/frame.js @@ -0,0 +1,14 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const {generateActorSpec} = require("devtools/shared/protocol"); + +const frameSpec = generateActorSpec({ + typeName: "frame", + + methods: {}, +}); + +exports.frameSpec = frameSpec; diff --git a/devtools/shared/specs/framerate.js b/devtools/shared/specs/framerate.js new file mode 100644 index 000000000..9fb2dff5d --- /dev/null +++ b/devtools/shared/specs/framerate.js @@ -0,0 +1,34 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { Arg, RetVal, generateActorSpec } = require("devtools/shared/protocol"); + +const framerateSpec = generateActorSpec({ + typeName: "framerate", + + methods: { + startRecording: {}, + stopRecording: { + request: { + beginAt: Arg(0, "nullable:number"), + endAt: Arg(1, "nullable:number") + }, + response: { ticks: RetVal("array:number") } + }, + cancelRecording: {}, + isRecording: { + response: { recording: RetVal("boolean") } + }, + getPendingTicks: { + request: { + beginAt: Arg(0, "nullable:number"), + endAt: Arg(1, "nullable:number") + }, + response: { ticks: RetVal("array:number") } + } + } +}); + +exports.framerateSpec = framerateSpec; diff --git a/devtools/shared/specs/gcli.js b/devtools/shared/specs/gcli.js new file mode 100644 index 000000000..2e0768bc8 --- /dev/null +++ b/devtools/shared/specs/gcli.js @@ -0,0 +1,86 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { Arg, RetVal, generateActorSpec } = require("devtools/shared/protocol"); + +const gcliSpec = generateActorSpec({ + typeName: "gcli", + + events: { + "commands-changed": { + type: "commandsChanged" + } + }, + + methods: { + _testOnlyAddItemsByModule: { + request: { + customProps: Arg(0, "array:string") + } + }, + _testOnlyRemoveItemsByModule: { + request: { + customProps: Arg(0, "array:string") + } + }, + specs: { + request: { + customProps: Arg(0, "nullable:array:string") + }, + response: { + value: RetVal("array:json") + } + }, + execute: { + request: { + // The command string + typed: Arg(0, "string") + }, + response: RetVal("json") + }, + state: { + request: { + // The command string + typed: Arg(0, "string"), + // Cursor start position + start: Arg(1, "number"), + // The prediction offset (# times UP/DOWN pressed) + rank: Arg(2, "number") + }, + response: RetVal("json") + }, + parseType: { + request: { + // The command string + typed: Arg(0, "string"), + // The name of the parameter to parse + paramName: Arg(1, "string") + }, + response: RetVal("json") + }, + nudgeType: { + request: { + // The command string + typed: Arg(0, "string"), + // +1/-1 for increment / decrement + by: Arg(1, "number"), + // The name of the parameter to parse + paramName: Arg(2, "string") + }, + response: RetVal("string") + }, + getSelectionLookup: { + request: { + // The command containing the parameter in question + commandName: Arg(0, "string"), + // The name of the parameter + paramName: Arg(1, "string"), + }, + response: RetVal("json") + } + } +}); + +exports.gcliSpec = gcliSpec; diff --git a/devtools/shared/specs/heap-snapshot-file.js b/devtools/shared/specs/heap-snapshot-file.js new file mode 100644 index 000000000..dfd03e1fa --- /dev/null +++ b/devtools/shared/specs/heap-snapshot-file.js @@ -0,0 +1,20 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { Arg, generateActorSpec } = require("devtools/shared/protocol"); + +const heapSnapshotFileSpec = generateActorSpec({ + typeName: "heapSnapshotFile", + + methods: { + transferHeapSnapshot: { + request: { + snapshotId: Arg(0, "string") + } + } + }, +}); + +exports.heapSnapshotFileSpec = heapSnapshotFileSpec; diff --git a/devtools/shared/specs/highlighters.js b/devtools/shared/specs/highlighters.js new file mode 100644 index 000000000..8335b22d9 --- /dev/null +++ b/devtools/shared/specs/highlighters.js @@ -0,0 +1,63 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { + Arg, + Option, + RetVal, + generateActorSpec +} = require("devtools/shared/protocol"); + +const highlighterSpec = generateActorSpec({ + typeName: "highlighter", + + methods: { + showBoxModel: { + request: { + node: Arg(0, "domnode"), + region: Option(1), + hideInfoBar: Option(1), + hideGuides: Option(1), + showOnly: Option(1), + onlyRegionArea: Option(1) + } + }, + hideBoxModel: { + request: {} + }, + pick: {}, + pickAndFocus: {}, + cancelPick: {} + } +}); + +exports.highlighterSpec = highlighterSpec; + +const customHighlighterSpec = generateActorSpec({ + typeName: "customhighlighter", + + methods: { + release: { + release: true + }, + show: { + request: { + node: Arg(0, "domnode"), + options: Arg(1, "nullable:json") + }, + response: { + value: RetVal("nullable:boolean") + } + }, + hide: { + request: {} + }, + finalize: { + oneway: true + } + } +}); + +exports.customHighlighterSpec = customHighlighterSpec; diff --git a/devtools/shared/specs/inspector.js b/devtools/shared/specs/inspector.js new file mode 100644 index 000000000..28736ed34 --- /dev/null +++ b/devtools/shared/specs/inspector.js @@ -0,0 +1,445 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { + Arg, + Option, + RetVal, + generateActorSpec, + types +} = require("devtools/shared/protocol"); +const { nodeSpec } = require("devtools/shared/specs/node"); +require("devtools/shared/specs/styles"); +require("devtools/shared/specs/highlighters"); +require("devtools/shared/specs/layout"); + +exports.nodeSpec = nodeSpec; + +/** + * Returned from any call that might return a node that isn't connected to root + * by nodes the child has seen, such as querySelector. + */ +types.addDictType("disconnectedNode", { + // The actual node to return + node: "domnode", + + // Nodes that are needed to connect the node to a node the client has already + // seen + newParents: "array:domnode" +}); + +types.addDictType("disconnectedNodeArray", { + // The actual node list to return + nodes: "array:domnode", + + // Nodes that are needed to connect those nodes to the root. + newParents: "array:domnode" +}); + +types.addDictType("dommutation", {}); + +types.addDictType("searchresult", { + list: "domnodelist", + // Right now there is isn't anything required for metadata, + // but it's json so it can be extended with extra data. + metadata: "array:json" +}); + +const nodeListSpec = generateActorSpec({ + typeName: "domnodelist", + + methods: { + item: { + request: { item: Arg(0) }, + response: RetVal("disconnectedNode") + }, + items: { + request: { + start: Arg(0, "nullable:number"), + end: Arg(1, "nullable:number") + }, + response: RetVal("disconnectedNodeArray") + }, + release: { + release: true + } + } +}); + +exports.nodeListSpec = nodeListSpec; + +// Some common request/response templates for the dom walker + +var nodeArrayMethod = { + request: { + node: Arg(0, "domnode"), + maxNodes: Option(1), + center: Option(1, "domnode"), + start: Option(1, "domnode"), + whatToShow: Option(1) + }, + response: RetVal(types.addDictType("domtraversalarray", { + nodes: "array:domnode" + })) +}; + +var traversalMethod = { + request: { + node: Arg(0, "domnode"), + whatToShow: Option(1) + }, + response: { + node: RetVal("nullable:domnode") + } +}; + +const walkerSpec = generateActorSpec({ + typeName: "domwalker", + + events: { + "new-mutations": { + type: "newMutations" + }, + "picker-node-picked": { + type: "pickerNodePicked", + node: Arg(0, "disconnectedNode") + }, + "picker-node-previewed": { + type: "pickerNodePreviewed", + node: Arg(0, "disconnectedNode") + }, + "picker-node-hovered": { + type: "pickerNodeHovered", + node: Arg(0, "disconnectedNode") + }, + "picker-node-canceled": { + type: "pickerNodeCanceled" + }, + "highlighter-ready": { + type: "highlighter-ready" + }, + "highlighter-hide": { + type: "highlighter-hide" + }, + "display-change": { + type: "display-change", + nodes: Arg(0, "array:domnode") + }, + // The walker actor emits a useful "resize" event to its front to let + // clients know when the browser window gets resized. This may be useful + // for refreshing a DOM node's styles for example, since those may depend on + // media-queries. + "resize": { + type: "resize" + } + }, + + methods: { + release: { + release: true + }, + pick: { + request: {}, + response: RetVal("disconnectedNode") + }, + cancelPick: {}, + highlight: { + request: {node: Arg(0, "nullable:domnode")} + }, + document: { + request: { node: Arg(0, "nullable:domnode") }, + response: { node: RetVal("domnode") }, + }, + documentElement: { + request: { node: Arg(0, "nullable:domnode") }, + response: { node: RetVal("domnode") }, + }, + parents: { + request: { + node: Arg(0, "domnode"), + sameDocument: Option(1), + sameTypeRootTreeItem: Option(1) + }, + response: { + nodes: RetVal("array:domnode") + }, + }, + retainNode: { + request: { node: Arg(0, "domnode") }, + response: {} + }, + unretainNode: { + request: { node: Arg(0, "domnode") }, + response: {}, + }, + releaseNode: { + request: { + node: Arg(0, "domnode"), + force: Option(1) + } + }, + children: nodeArrayMethod, + siblings: nodeArrayMethod, + nextSibling: traversalMethod, + previousSibling: traversalMethod, + findInspectingNode: { + request: {}, + response: RetVal("disconnectedNode") + }, + querySelector: { + request: { + node: Arg(0, "domnode"), + selector: Arg(1) + }, + response: RetVal("disconnectedNode") + }, + querySelectorAll: { + request: { + node: Arg(0, "domnode"), + selector: Arg(1) + }, + response: { + list: RetVal("domnodelist") + } + }, + multiFrameQuerySelectorAll: { + request: { + selector: Arg(0) + }, + response: { + list: RetVal("domnodelist") + } + }, + search: { + request: { + query: Arg(0), + }, + response: { + list: RetVal("searchresult"), + } + }, + getSuggestionsForQuery: { + request: { + query: Arg(0), + completing: Arg(1), + selectorState: Arg(2) + }, + response: { + list: RetVal("array:array:string") + } + }, + addPseudoClassLock: { + request: { + node: Arg(0, "domnode"), + pseudoClass: Arg(1), + parents: Option(2) + }, + response: {} + }, + hideNode: { + request: { node: Arg(0, "domnode") } + }, + unhideNode: { + request: { node: Arg(0, "domnode") } + }, + removePseudoClassLock: { + request: { + node: Arg(0, "domnode"), + pseudoClass: Arg(1), + parents: Option(2) + }, + response: {} + }, + clearPseudoClassLocks: { + request: { + node: Arg(0, "nullable:domnode") + }, + response: {} + }, + innerHTML: { + request: { + node: Arg(0, "domnode") + }, + response: { + value: RetVal("longstring") + } + }, + setInnerHTML: { + request: { + node: Arg(0, "domnode"), + value: Arg(1, "string"), + }, + response: {} + }, + outerHTML: { + request: { + node: Arg(0, "domnode") + }, + response: { + value: RetVal("longstring") + } + }, + setOuterHTML: { + request: { + node: Arg(0, "domnode"), + value: Arg(1, "string"), + }, + response: {} + }, + insertAdjacentHTML: { + request: { + node: Arg(0, "domnode"), + position: Arg(1, "string"), + value: Arg(2, "string") + }, + response: RetVal("disconnectedNodeArray") + }, + duplicateNode: { + request: { + node: Arg(0, "domnode") + }, + response: {} + }, + removeNode: { + request: { + node: Arg(0, "domnode") + }, + response: { + nextSibling: RetVal("nullable:domnode") + } + }, + removeNodes: { + request: { + node: Arg(0, "array:domnode") + }, + response: {} + }, + insertBefore: { + request: { + node: Arg(0, "domnode"), + parent: Arg(1, "domnode"), + sibling: Arg(2, "nullable:domnode") + }, + response: {} + }, + editTagName: { + request: { + node: Arg(0, "domnode"), + tagName: Arg(1, "string") + }, + response: {} + }, + getMutations: { + request: { + cleanup: Option(0) + }, + response: { + mutations: RetVal("array:dommutation") + } + }, + isInDOMTree: { + request: { node: Arg(0, "domnode") }, + response: { attached: RetVal("boolean") } + }, + getNodeActorFromObjectActor: { + request: { + objectActorID: Arg(0, "string") + }, + response: { + nodeFront: RetVal("nullable:disconnectedNode") + } + }, + getStyleSheetOwnerNode: { + request: { + styleSheetActorID: Arg(0, "string") + }, + response: { + ownerNode: RetVal("nullable:disconnectedNode") + } + }, + getNodeFromActor: { + request: { + actorID: Arg(0, "string"), + path: Arg(1, "array:string") + }, + response: { + node: RetVal("nullable:disconnectedNode") + } + }, + getLayoutInspector: { + request: {}, + response: { + actor: RetVal("layout") + } + } + } +}); + +exports.walkerSpec = walkerSpec; + +const inspectorSpec = generateActorSpec({ + typeName: "inspector", + + events: { + "color-picked": { + type: "colorPicked", + color: Arg(0, "string") + }, + "color-pick-canceled": { + type: "colorPickCanceled" + } + }, + + methods: { + getWalker: { + request: { + options: Arg(0, "nullable:json") + }, + response: { + walker: RetVal("domwalker") + } + }, + getPageStyle: { + request: {}, + response: { + pageStyle: RetVal("pagestyle") + } + }, + getHighlighter: { + request: { + autohide: Arg(0, "boolean") + }, + response: { + highligter: RetVal("highlighter") + } + }, + getHighlighterByType: { + request: { + typeName: Arg(0) + }, + response: { + highlighter: RetVal("nullable:customhighlighter") + } + }, + getImageDataFromURL: { + request: {url: Arg(0), maxDim: Arg(1, "nullable:number")}, + response: RetVal("imageData") + }, + resolveRelativeURL: { + request: {url: Arg(0, "string"), node: Arg(1, "nullable:domnode")}, + response: {value: RetVal("string")} + }, + pickColorFromPage: { + request: {options: Arg(0, "nullable:json")}, + response: {} + }, + cancelPickColorFromPage: { + request: {}, + response: {} + } + } +}); + +exports.inspectorSpec = inspectorSpec; diff --git a/devtools/shared/specs/layout.js b/devtools/shared/specs/layout.js new file mode 100644 index 000000000..80a0d5f9b --- /dev/null +++ b/devtools/shared/specs/layout.js @@ -0,0 +1,33 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const { Arg, generateActorSpec, RetVal } = require("devtools/shared/protocol"); +require("devtools/shared/specs/node"); + +const gridSpec = generateActorSpec({ + typeName: "grid", + + methods: {}, +}); + +const layoutSpec = generateActorSpec({ + typeName: "layout", + + methods: { + getAllGrids: { + request: { + rootNode: Arg(0, "domnode"), + traverseFrames: Arg(1, "boolean") + }, + response: { + grids: RetVal("array:grid") + } + } + }, +}); + +exports.gridSpec = gridSpec; +exports.layoutSpec = layoutSpec; diff --git a/devtools/shared/specs/memory.js b/devtools/shared/specs/memory.js new file mode 100644 index 000000000..3bff6dc38 --- /dev/null +++ b/devtools/shared/specs/memory.js @@ -0,0 +1,124 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { + Arg, + RetVal, + types, + generateActorSpec, +} = require("devtools/shared/protocol"); + +types.addDictType("AllocationsRecordingOptions", { + // The probability we sample any given allocation when recording + // allocations. Must be between 0.0 and 1.0. Defaults to 1.0, or sampling + // every allocation. + probability: "number", + + // The maximum number of of allocation events to keep in the allocations + // log. If new allocations arrive, when we are already at capacity, the oldest + // allocation event is lost. This number must fit in a 32 bit signed integer. + maxLogLength: "number" +}); + +const memorySpec = generateActorSpec({ + typeName: "memory", + + /** + * The set of unsolicited events the MemoryActor emits that will be sent over + * the RDP (by protocol.js). + */ + events: { + // Same format as the data passed to the + // `Debugger.Memory.prototype.onGarbageCollection` hook. See + // `js/src/doc/Debugger/Debugger.Memory.md` for documentation. + "garbage-collection": { + type: "garbage-collection", + data: Arg(0, "json"), + }, + + // Same data as the data from `getAllocations` -- only fired if + // `autoDrain` set during `startRecordingAllocations`. + "allocations": { + type: "allocations", + data: Arg(0, "json"), + }, + }, + + methods: { + attach: { + request: {}, + response: { + type: "attached" + } + }, + detach: { + request: {}, + response: { + type: "detached" + } + }, + getState: { + response: { + state: RetVal(0, "string") + } + }, + takeCensus: { + request: {}, + response: RetVal("json") + }, + startRecordingAllocations: { + request: { + options: Arg(0, "nullable:AllocationsRecordingOptions") + }, + response: { + // Accept `nullable` in the case of server Gecko <= 37, handled on the front + value: RetVal(0, "nullable:number") + } + }, + stopRecordingAllocations: { + request: {}, + response: { + // Accept `nullable` in the case of server Gecko <= 37, handled on the front + value: RetVal(0, "nullable:number") + } + }, + getAllocationsSettings: { + request: {}, + response: { + options: RetVal(0, "json") + } + }, + getAllocations: { + request: {}, + response: RetVal("json") + }, + forceGarbageCollection: { + request: {}, + response: {} + }, + forceCycleCollection: { + request: {}, + response: {} + }, + measure: { + request: {}, + response: RetVal("json"), + }, + residentUnique: { + request: {}, + response: { value: RetVal("number") } + }, + saveHeapSnapshot: { + request: { + boundaries: Arg(0, "nullable:json") + }, + response: { + snapshotId: RetVal("string") + } + }, + }, +}); + +exports.memorySpec = memorySpec; diff --git a/devtools/shared/specs/moz.build b/devtools/shared/specs/moz.build new file mode 100644 index 000000000..52a810637 --- /dev/null +++ b/devtools/shared/specs/moz.build @@ -0,0 +1,50 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DevToolsModules( + 'actor-registry.js', + 'addons.js', + 'animation.js', + 'breakpoint.js', + 'call-watcher.js', + 'canvas.js', + 'css-properties.js', + 'csscoverage.js', + 'device.js', + 'director-manager.js', + 'director-registry.js', + 'emulation.js', + 'environment.js', + 'eventlooplag.js', + 'frame.js', + 'framerate.js', + 'gcli.js', + 'heap-snapshot-file.js', + 'highlighters.js', + 'inspector.js', + 'layout.js', + 'memory.js', + 'node.js', + 'performance-entries.js', + 'performance-recording.js', + 'performance.js', + 'preference.js', + 'profiler.js', + 'promises.js', + 'reflow.js', + 'script.js', + 'settings.js', + 'source.js', + 'storage.js', + 'string.js', + 'styleeditor.js', + 'styles.js', + 'stylesheets.js', + 'timeline.js', + 'webaudio.js', + 'webgl.js', + 'worker.js' +) diff --git a/devtools/shared/specs/node.js b/devtools/shared/specs/node.js new file mode 100644 index 000000000..ea3d1b264 --- /dev/null +++ b/devtools/shared/specs/node.js @@ -0,0 +1,67 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { + Arg, + RetVal, + generateActorSpec, + types +} = require("devtools/shared/protocol.js"); + +types.addDictType("imageData", { + // The image data + data: "nullable:longstring", + // The original image dimensions + size: "json" +}); + +const nodeSpec = generateActorSpec({ + typeName: "domnode", + + methods: { + getNodeValue: { + request: {}, + response: { + value: RetVal("longstring") + } + }, + setNodeValue: { + request: { value: Arg(0) }, + response: {} + }, + getUniqueSelector: { + request: {}, + response: { + value: RetVal("string") + } + }, + scrollIntoView: { + request: {}, + response: {} + }, + getImageData: { + request: {maxDim: Arg(0, "nullable:number")}, + response: RetVal("imageData") + }, + getEventListenerInfo: { + request: {}, + response: { + events: RetVal("json") + } + }, + modifyAttributes: { + request: { + modifications: Arg(0, "array:json") + }, + response: {} + }, + getFontFamilyDataURL: { + request: {font: Arg(0, "string"), fillStyle: Arg(1, "nullable:string")}, + response: RetVal("imageData") + } + } +}); + +exports.nodeSpec = nodeSpec; diff --git a/devtools/shared/specs/performance-entries.js b/devtools/shared/specs/performance-entries.js new file mode 100644 index 000000000..107afb779 --- /dev/null +++ b/devtools/shared/specs/performance-entries.js @@ -0,0 +1,25 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { Arg, generateActorSpec } = require("devtools/shared/protocol"); + +const performanceEntriesSpec = generateActorSpec({ + typeName: "performanceEntries", + + events: { + "entry": { + type: "entry", + // object containing performance entry name, type, origin, and epoch. + detail: Arg(0, "json") + } + }, + + methods: { + start: {}, + stop: {} + } +}); + +exports.performanceEntriesSpec = performanceEntriesSpec; diff --git a/devtools/shared/specs/performance-recording.js b/devtools/shared/specs/performance-recording.js new file mode 100644 index 000000000..562abc6f7 --- /dev/null +++ b/devtools/shared/specs/performance-recording.js @@ -0,0 +1,12 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { generateActorSpec } = require("devtools/shared/protocol"); + +const performanceRecordingSpec = generateActorSpec({ + typeName: "performance-recording" +}); + +exports.performanceRecordingSpec = performanceRecordingSpec; diff --git a/devtools/shared/specs/performance.js b/devtools/shared/specs/performance.js new file mode 100644 index 000000000..30a570e9a --- /dev/null +++ b/devtools/shared/specs/performance.js @@ -0,0 +1,88 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { Arg, RetVal, generateActorSpec } = require("devtools/shared/protocol"); +require("devtools/shared/specs/performance-recording"); + +const performanceSpec = generateActorSpec({ + typeName: "performance", + + /** + * The set of events the PerformanceActor emits over RDP. + */ + events: { + "recording-started": { + recording: Arg(0, "performance-recording"), + }, + "recording-stopping": { + recording: Arg(0, "performance-recording"), + }, + "recording-stopped": { + recording: Arg(0, "performance-recording"), + data: Arg(1, "json"), + }, + "profiler-status": { + data: Arg(0, "json"), + }, + "console-profile-start": {}, + "timeline-data": { + name: Arg(0, "string"), + data: Arg(1, "json"), + recordings: Arg(2, "array:performance-recording"), + }, + }, + + methods: { + connect: { + request: { options: Arg(0, "nullable:json") }, + response: RetVal("json") + }, + + canCurrentlyRecord: { + request: {}, + response: { value: RetVal("json") } + }, + + startRecording: { + request: { + options: Arg(0, "nullable:json"), + }, + response: { + recording: RetVal("nullable:performance-recording") + } + }, + + stopRecording: { + request: { + options: Arg(0, "performance-recording"), + }, + response: { + recording: RetVal("performance-recording") + } + }, + + isRecording: { + request: {}, + response: { isRecording: RetVal("boolean") } + }, + + getRecordings: { + request: {}, + response: { recordings: RetVal("array:performance-recording") } + }, + + getConfiguration: { + request: {}, + response: { config: RetVal("json") } + }, + + setProfilerStatusInterval: { + request: { interval: Arg(0, "number") }, + response: { oneway: true } + }, + } +}); + +exports.performanceSpec = performanceSpec; diff --git a/devtools/shared/specs/preference.js b/devtools/shared/specs/preference.js new file mode 100644 index 000000000..54123d813 --- /dev/null +++ b/devtools/shared/specs/preference.js @@ -0,0 +1,47 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const {Arg, RetVal, generateActorSpec} = require("devtools/shared/protocol"); + +const preferenceSpec = generateActorSpec({ + typeName: "preference", + + methods: { + getBoolPref: { + request: { value: Arg(0) }, + response: { value: RetVal("boolean") } + }, + getCharPref: { + request: { value: Arg(0) }, + response: { value: RetVal("string") } + }, + getIntPref: { + request: { value: Arg(0) }, + response: { value: RetVal("number") } + }, + getAllPrefs: { + request: {}, + response: { value: RetVal("json") } + }, + setBoolPref: { + request: { name: Arg(0), value: Arg(1) }, + response: {} + }, + setCharPref: { + request: { name: Arg(0), value: Arg(1) }, + response: {} + }, + setIntPref: { + request: { name: Arg(0), value: Arg(1) }, + response: {} + }, + clearUserPref: { + request: { name: Arg(0) }, + response: {} + } + }, +}); + +exports.preferenceSpec = preferenceSpec; diff --git a/devtools/shared/specs/profiler.js b/devtools/shared/specs/profiler.js new file mode 100644 index 000000000..a4a6f384e --- /dev/null +++ b/devtools/shared/specs/profiler.js @@ -0,0 +1,121 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { + Arg, + Option, + RetVal, + generateActorSpec, + types +} = require("devtools/shared/protocol"); + +types.addType("profiler-data", { + // On Fx42+, the profile is only deserialized on the front; older + // servers will get the profiler data as an object from nsIProfiler, + // causing one parse/stringify cycle, then again implicitly in a packet. + read: (v) => { + if (typeof v.profile === "string") { + // Create a new response object since `profile` is read only. + let newValue = Object.create(null); + newValue.profile = JSON.parse(v.profile); + newValue.currentTime = v.currentTime; + return newValue; + } + return v; + } +}); + +const profilerSpec = generateActorSpec({ + typeName: "profiler", + + /** + * The set of events the ProfilerActor emits over RDP. + */ + events: { + "console-api-profiler": { + data: Arg(0, "json"), + }, + "profiler-started": { + data: Arg(0, "json"), + }, + "profiler-stopped": { + data: Arg(0, "json"), + }, + "profiler-status": { + data: Arg(0, "json"), + }, + + // Only for older geckos, pre-protocol.js ProfilerActor (<Fx42). + // Emitted on other events as a transition from older profiler events + // to newer ones. + "eventNotification": { + subject: Option(0, "json"), + topic: Option(0, "string"), + details: Option(0, "json") + } + }, + + methods: { + startProfiler: { + // Write out every property in the request, since we want all these options to be + // on the packet's top-level for backwards compatibility, when the profiler actor + // was not using protocol.js (<Fx42) + request: { + entries: Option(0, "nullable:number"), + interval: Option(0, "nullable:number"), + features: Option(0, "nullable:array:string"), + threadFilters: Option(0, "nullable:array:string"), + }, + response: RetVal("json"), + }, + stopProfiler: { + response: RetVal("json"), + }, + getProfile: { + request: { + startTime: Option(0, "nullable:number"), + stringify: Option(0, "nullable:boolean") + }, + response: RetVal("profiler-data") + }, + getFeatures: { + response: RetVal("json") + }, + getBufferInfo: { + response: RetVal("json") + }, + getStartOptions: { + response: RetVal("json") + }, + isActive: { + response: RetVal("json") + }, + getSharedLibraryInformation: { + response: RetVal("json") + }, + registerEventNotifications: { + // Explicitly enumerate the arguments + // @see ProfilerActor#startProfiler + request: { + events: Option(0, "nullable:array:string"), + }, + response: RetVal("json") + }, + unregisterEventNotifications: { + // Explicitly enumerate the arguments + // @see ProfilerActor#startProfiler + request: { + events: Option(0, "nullable:array:string"), + }, + response: RetVal("json") + }, + setProfilerStatusInterval: { + request: { interval: Arg(0, "number") }, + oneway: true + } + } +}); + +exports.profilerSpec = profilerSpec; diff --git a/devtools/shared/specs/promises.js b/devtools/shared/specs/promises.js new file mode 100644 index 000000000..ef57c3bae --- /dev/null +++ b/devtools/shared/specs/promises.js @@ -0,0 +1,56 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { + Arg, + RetVal, + generateActorSpec, + types +} = require("devtools/shared/protocol"); + +// Teach protocol.js how to deal with legacy actor types +types.addType("ObjectActor", { + write: actor => actor.grip(), + read: grip => grip +}); + +const promisesSpec = generateActorSpec({ + typeName: "promises", + + events: { + // Event emitted for new promises allocated in debuggee and bufferred by + // sending the list of promise objects in a batch. + "new-promises": { + type: "new-promises", + data: Arg(0, "array:ObjectActor"), + }, + // Event emitted for promise settlements. + "promises-settled": { + type: "promises-settled", + data: Arg(0, "array:ObjectActor") + } + }, + + methods: { + attach: { + request: {}, + response: {}, + }, + + detach: { + request: {}, + response: {}, + }, + + listPromises: { + request: {}, + response: { + promises: RetVal("array:ObjectActor"), + }, + } + } +}); + +exports.promisesSpec = promisesSpec; diff --git a/devtools/shared/specs/reflow.js b/devtools/shared/specs/reflow.js new file mode 100644 index 000000000..a33c7a2cf --- /dev/null +++ b/devtools/shared/specs/reflow.js @@ -0,0 +1,33 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const {Arg, generateActorSpec} = require("devtools/shared/protocol"); + +const reflowSpec = generateActorSpec({ + typeName: "reflow", + + events: { + /** + * The reflows event is emitted when reflows have been detected. The event + * is sent with an array of reflows that occured. Each item has the + * following properties: + * - start {Number} + * - end {Number} + * - isInterruptible {Boolean} + */ + reflows: { + type: "reflows", + reflows: Arg(0, "array:json") + } + }, + + methods: { + start: {oneway: true}, + stop: {oneway: true}, + }, +}); + +exports.reflowSpec = reflowSpec; diff --git a/devtools/shared/specs/script.js b/devtools/shared/specs/script.js new file mode 100644 index 000000000..f24426dee --- /dev/null +++ b/devtools/shared/specs/script.js @@ -0,0 +1,14 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const {generateActorSpec} = require("devtools/shared/protocol"); + +const threadSpec = generateActorSpec({ + typeName: "context", + + methods: {}, +}); + +exports.threadSpec = threadSpec; diff --git a/devtools/shared/specs/settings.js b/devtools/shared/specs/settings.js new file mode 100644 index 000000000..482c8f473 --- /dev/null +++ b/devtools/shared/specs/settings.js @@ -0,0 +1,31 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const {Arg, RetVal, generateActorSpec} = require("devtools/shared/protocol"); + +const settingsSpec = generateActorSpec({ + typeName: "settings", + + methods: { + getSetting: { + request: { value: Arg(0) }, + response: { value: RetVal("json") } + }, + setSetting: { + request: { name: Arg(0), value: Arg(1) }, + response: {} + }, + getAllSettings: { + request: {}, + response: { value: RetVal("json") } + }, + clearUserSetting: { + request: { name: Arg(0) }, + response: {} + } + }, +}); + +exports.settingsSpec = settingsSpec; diff --git a/devtools/shared/specs/source.js b/devtools/shared/specs/source.js new file mode 100644 index 000000000..66bcf89e2 --- /dev/null +++ b/devtools/shared/specs/source.js @@ -0,0 +1,40 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const {Arg, RetVal, generateActorSpec} = require("devtools/shared/protocol"); + +const sourceSpec = generateActorSpec({ + typeName: "source", + + methods: { + getExecutableLines: { response: { lines: RetVal("json") } }, + onSource: { + request: { type: "source" }, + response: RetVal("json") + }, + prettyPrint: { + request: { indent: Arg(0, "number") }, + response: RetVal("json") + }, + disablePrettyPrint: { + response: RetVal("json") + }, + blackbox: { response: { pausedInSource: RetVal("boolean") } }, + unblackbox: {}, + setBreakpoint: { + request: { + location: { + line: Arg(0, "number"), + column: Arg(1, "nullable:number") + }, + condition: Arg(2, "nullable:string"), + noSliding: Arg(3, "nullable:boolean") + }, + response: RetVal("json") + }, + }, +}); + +exports.sourceSpec = sourceSpec; diff --git a/devtools/shared/specs/storage.js b/devtools/shared/specs/storage.js new file mode 100644 index 000000000..d6ddaefe5 --- /dev/null +++ b/devtools/shared/specs/storage.js @@ -0,0 +1,279 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const protocol = require("devtools/shared/protocol"); +const { Arg, RetVal, types } = protocol; + +let childSpecs = {}; + +function createStorageSpec(options) { + // common methods for all storage types + let methods = { + getStoreObjects: { + request: { + host: Arg(0), + names: Arg(1, "nullable:array:string"), + options: Arg(2, "nullable:json") + }, + response: RetVal(options.storeObjectType) + }, + getFields: { + request: { + subType: Arg(0, "nullable:string") + }, + response: { + value: RetVal("json") + } + } + }; + + // extra methods specific for storage type + Object.assign(methods, options.methods); + + childSpecs[options.typeName] = protocol.generateActorSpec({ + typeName: options.typeName, + methods + }); +} + +// Cookies store object +types.addDictType("cookieobject", { + name: "string", + value: "longstring", + path: "nullable:string", + host: "string", + isDomain: "boolean", + isSecure: "boolean", + isHttpOnly: "boolean", + creationTime: "number", + lastAccessed: "number", + expires: "number" +}); + +// Array of cookie store objects +types.addDictType("cookiestoreobject", { + total: "number", + offset: "number", + data: "array:nullable:cookieobject" +}); + +// Common methods for edit/remove +const editRemoveMethods = { + getEditableFields: { + request: {}, + response: { + value: RetVal("json") + } + }, + editItem: { + request: { + data: Arg(0, "json"), + }, + response: {} + }, + removeItem: { + request: { + host: Arg(0, "string"), + name: Arg(1, "string"), + }, + response: {} + }, +}; + +// Cookies actor spec +createStorageSpec({ + typeName: "cookies", + storeObjectType: "cookiestoreobject", + methods: Object.assign({}, + editRemoveMethods, + { + removeAll: { + request: { + host: Arg(0, "string"), + domain: Arg(1, "nullable:string") + }, + response: {} + } + } + ) +}); + +// Local Storage / Session Storage store object +types.addDictType("storageobject", { + name: "string", + value: "longstring" +}); + +// Common methods for local/session storage +const storageMethods = Object.assign({}, + editRemoveMethods, + { + removeAll: { + request: { + host: Arg(0, "string") + }, + response: {} + } + } +); + +// Array of Local Storage / Session Storage store objects +types.addDictType("storagestoreobject", { + total: "number", + offset: "number", + data: "array:nullable:storageobject" +}); + +createStorageSpec({ + typeName: "localStorage", + storeObjectType: "storagestoreobject", + methods: storageMethods +}); + +createStorageSpec({ + typeName: "sessionStorage", + storeObjectType: "storagestoreobject", + methods: storageMethods +}); + +types.addDictType("cacheobject", { + "url": "string", + "status": "string" +}); + +// Array of Cache store objects +types.addDictType("cachestoreobject", { + total: "number", + offset: "number", + data: "array:nullable:cacheobject" +}); + +// Cache storage spec +createStorageSpec({ + typeName: "Cache", + storeObjectType: "cachestoreobject", + methods: { + removeAll: { + request: { + host: Arg(0, "string"), + name: Arg(1, "string"), + }, + response: {} + }, + removeItem: { + request: { + host: Arg(0, "string"), + name: Arg(1, "string"), + }, + response: {} + }, + } +}); + +// Indexed DB store object +// This is a union on idb object, db metadata object and object store metadata +// object +types.addDictType("idbobject", { + name: "nullable:string", + db: "nullable:string", + objectStore: "nullable:string", + origin: "nullable:string", + version: "nullable:number", + objectStores: "nullable:number", + keyPath: "nullable:string", + autoIncrement: "nullable:boolean", + indexes: "nullable:string", + value: "nullable:longstring" +}); + +// Array of Indexed DB store objects +types.addDictType("idbstoreobject", { + total: "number", + offset: "number", + data: "array:nullable:idbobject" +}); + +// Result of Indexed DB delete operation: can block or throw error +types.addDictType("idbdeleteresult", { + blocked: "nullable:boolean", + error: "nullable:string" +}); + +createStorageSpec({ + typeName: "indexedDB", + storeObjectType: "idbstoreobject", + methods: { + removeDatabase: { + request: { + host: Arg(0, "string"), + name: Arg(1, "string"), + }, + response: RetVal("idbdeleteresult") + }, + removeAll: { + request: { + host: Arg(0, "string"), + name: Arg(1, "string"), + }, + response: {} + }, + removeItem: { + request: { + host: Arg(0, "string"), + name: Arg(1, "string"), + }, + response: {} + }, + } +}); + +// Update notification object +types.addDictType("storeUpdateObject", { + changed: "nullable:json", + deleted: "nullable:json", + added: "nullable:json" +}); + +// Generate a type definition for an object with actors for all storage types. +types.addDictType("storelist", Object.keys(childSpecs).reduce((obj, type) => { + obj[type] = type; + return obj; +}, {})); + +exports.childSpecs = childSpecs; + +exports.storageSpec = protocol.generateActorSpec({ + typeName: "storage", + + /** + * List of event notifications that the server can send to the client. + * + * - stores-update : When any store object in any storage type changes. + * - stores-cleared : When all the store objects are removed. + * - stores-reloaded : When all stores are reloaded. This generally mean that + * we should refetch everything again. + */ + events: { + "stores-update": { + type: "storesUpdate", + data: Arg(0, "storeUpdateObject") + }, + "stores-cleared": { + type: "storesCleared", + data: Arg(0, "json") + }, + "stores-reloaded": { + type: "storesReloaded", + data: Arg(0, "json") + } + }, + + methods: { + listStores: { + request: {}, + response: RetVal("storelist") + }, + } +}); diff --git a/devtools/shared/specs/string.js b/devtools/shared/specs/string.js new file mode 100644 index 000000000..f759d4052 --- /dev/null +++ b/devtools/shared/specs/string.js @@ -0,0 +1,87 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const protocol = require("devtools/shared/protocol"); +const {Arg, RetVal, generateActorSpec} = protocol; +const promise = require("promise"); +const {Class} = require("sdk/core/heritage"); + +const longStringSpec = generateActorSpec({ + typeName: "longstractor", + + methods: { + substring: { + request: { + start: Arg(0), + end: Arg(1) + }, + response: { substring: RetVal() }, + }, + release: { release: true }, + }, +}); + +exports.longStringSpec = longStringSpec; + +/** + * When a caller is expecting a LongString actor but the string is already available on + * client, the SimpleStringFront can be used as it shares the same API as a + * LongStringFront but will not make unnecessary trips to the server. + */ +const SimpleStringFront = Class({ + initialize: function (str) { + this.str = str; + }, + + get length() { + return this.str.length; + }, + + get initial() { + return this.str; + }, + + string: function () { + return promise.resolve(this.str); + }, + + substring: function (start, end) { + return promise.resolve(this.str.substring(start, end)); + }, + + release: function () { + this.str = null; + return promise.resolve(undefined); + } +}); + +exports.SimpleStringFront = SimpleStringFront; + +// The long string actor needs some custom marshalling, because it is sometimes +// returned as a primitive rather than a complete form. + +var stringActorType = protocol.types.getType("longstractor"); +protocol.types.addType("longstring", { + _actor: true, + write: (value, context, detail) => { + if (!(context instanceof protocol.Actor)) { + throw Error("Passing a longstring as an argument isn't supported."); + } + + if (value.short) { + return value.str; + } + return stringActorType.write(value, context, detail); + }, + read: (value, context, detail) => { + if (context instanceof protocol.Actor) { + throw Error("Passing a longstring as an argument isn't supported."); + } + if (typeof (value) === "string") { + return new SimpleStringFront(value); + } + return stringActorType.read(value, context, detail); + } +}); diff --git a/devtools/shared/specs/styleeditor.js b/devtools/shared/specs/styleeditor.js new file mode 100644 index 000000000..e93b7e56f --- /dev/null +++ b/devtools/shared/specs/styleeditor.js @@ -0,0 +1,61 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { Arg, RetVal, generateActorSpec } = require("devtools/shared/protocol"); + +const oldStyleSheetSpec = generateActorSpec({ + typeName: "old-stylesheet", + + events: { + "property-change": { + type: "propertyChange", + property: Arg(0, "string"), + value: Arg(1, "json") + }, + "source-load": { + type: "sourceLoad", + source: Arg(0, "string") + }, + "style-applied": { + type: "styleApplied" + } + }, + + methods: { + toggleDisabled: { + response: { disabled: RetVal("boolean")} + }, + fetchSource: {}, + update: { + request: { + text: Arg(0, "string"), + transition: Arg(1, "boolean") + } + } + } +}); + +exports.oldStyleSheetSpec = oldStyleSheetSpec; + +const styleEditorSpec = generateActorSpec({ + typeName: "styleeditor", + + events: { + "document-load": { + type: "documentLoad", + styleSheets: Arg(0, "array:old-stylesheet") + } + }, + + method: { + newDocument: {}, + newStyleSheet: { + request: { text: Arg(0, "string") }, + response: { styleSheet: RetVal("old-stylesheet") } + } + } +}); + +exports.styleEditorSpec = styleEditorSpec; diff --git a/devtools/shared/specs/styles.js b/devtools/shared/specs/styles.js new file mode 100644 index 000000000..225d712a4 --- /dev/null +++ b/devtools/shared/specs/styles.js @@ -0,0 +1,206 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { + Arg, + Option, + RetVal, + generateActorSpec, + types +} = require("devtools/shared/protocol"); +require("devtools/shared/specs/node"); +require("devtools/shared/specs/stylesheets"); + +// Predeclare the domstylerule actor type +types.addActorType("domstylerule"); + +/** + * DOM Nodes returned by the style actor will be owned by the DOM walker + * for the connection. + */ +types.addLifetime("walker", "walker"); + +/** + * When asking for the styles applied to a node, we return a list of + * appliedstyle json objects that lists the rules that apply to the node + * and which element they were inherited from (if any). + * + * Note appliedstyle only sends the list of actorIDs and is not a valid return + * value on its own. appliedstyle should be returned with the actual list of + * StyleRuleActor and StyleSheetActor. See appliedStylesReturn. + */ +types.addDictType("appliedstyle", { + rule: "domstylerule#actorid", + inherited: "nullable:domnode#actorid", + keyframes: "nullable:domstylerule#actorid" +}); + +types.addDictType("matchedselector", { + rule: "domstylerule#actorid", + selector: "string", + value: "string", + status: "number" +}); + +types.addDictType("appliedStylesReturn", { + entries: "array:appliedstyle", + rules: "array:domstylerule", + sheets: "array:stylesheet" +}); + +types.addDictType("modifiedStylesReturn", { + isMatching: RetVal("boolean"), + ruleProps: RetVal("nullable:appliedStylesReturn") +}); + +types.addDictType("fontpreview", { + data: "nullable:longstring", + size: "json" +}); + +types.addDictType("fontface", { + name: "string", + CSSFamilyName: "string", + rule: "nullable:domstylerule", + srcIndex: "number", + URI: "string", + format: "string", + preview: "nullable:fontpreview", + localName: "string", + metadata: "string" +}); + +const pageStyleSpec = generateActorSpec({ + typeName: "pagestyle", + + events: { + "stylesheet-updated": { + type: "styleSheetUpdated", + styleSheet: Arg(0, "stylesheet") + } + }, + + methods: { + getComputed: { + request: { + node: Arg(0, "domnode"), + markMatched: Option(1, "boolean"), + onlyMatched: Option(1, "boolean"), + filter: Option(1, "string"), + }, + response: { + computed: RetVal("json") + } + }, + getAllUsedFontFaces: { + request: { + includePreviews: Option(0, "boolean"), + previewText: Option(0, "string"), + previewFontSize: Option(0, "string"), + previewFillStyle: Option(0, "string") + }, + response: { + fontFaces: RetVal("array:fontface") + } + }, + getUsedFontFaces: { + request: { + node: Arg(0, "domnode"), + includePreviews: Option(1, "boolean"), + previewText: Option(1, "string"), + previewFontSize: Option(1, "string"), + previewFillStyle: Option(1, "string") + }, + response: { + fontFaces: RetVal("array:fontface") + } + }, + getMatchedSelectors: { + request: { + node: Arg(0, "domnode"), + property: Arg(1, "string"), + filter: Option(2, "string") + }, + response: RetVal(types.addDictType("matchedselectorresponse", { + rules: "array:domstylerule", + sheets: "array:stylesheet", + matched: "array:matchedselector" + })) + }, + getApplied: { + request: { + node: Arg(0, "domnode"), + inherited: Option(1, "boolean"), + matchedSelectors: Option(1, "boolean"), + filter: Option(1, "string") + }, + response: RetVal("appliedStylesReturn") + }, + isPositionEditable: { + request: { node: Arg(0, "domnode")}, + response: { value: RetVal("boolean") } + }, + getLayout: { + request: { + node: Arg(0, "domnode"), + autoMargins: Option(1, "boolean") + }, + response: RetVal("json") + }, + addNewRule: { + request: { + node: Arg(0, "domnode"), + pseudoClasses: Arg(1, "nullable:array:string"), + editAuthored: Arg(2, "boolean") + }, + response: RetVal("appliedStylesReturn") + } + } +}); + +exports.pageStyleSpec = pageStyleSpec; + +const styleRuleSpec = generateActorSpec({ + typeName: "domstylerule", + + events: { + "location-changed": { + type: "locationChanged", + line: Arg(0, "number"), + column: Arg(1, "number") + }, + }, + + methods: { + setRuleText: { + request: { modification: Arg(0, "string") }, + response: { rule: RetVal("domstylerule") } + }, + modifyProperties: { + request: { modifications: Arg(0, "array:json") }, + response: { rule: RetVal("domstylerule") } + }, + modifySelector: { + request: { selector: Arg(0, "string") }, + response: { isModified: RetVal("boolean") }, + }, + modifySelector2: { + request: { + node: Arg(0, "domnode"), + value: Arg(1, "string"), + editAuthored: Arg(2, "boolean") + }, + response: RetVal("modifiedStylesReturn") + } + } +}); + +exports.styleRuleSpec = styleRuleSpec; + +// The PageStyle actor flattens the DOM CSS objects a little bit, merging +// Rules and their Styles into one actor. For elements (which have a style +// but no associated rule) we fake a rule with the following style id. +const ELEMENT_STYLE = 100; +exports.ELEMENT_STYLE = ELEMENT_STYLE; diff --git a/devtools/shared/specs/stylesheets.js b/devtools/shared/specs/stylesheets.js new file mode 100644 index 000000000..c89a7c088 --- /dev/null +++ b/devtools/shared/specs/stylesheets.js @@ -0,0 +1,120 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { + Arg, + RetVal, + generateActorSpec, + types +} = require("devtools/shared/protocol"); + +const originalSourceSpec = generateActorSpec({ + typeName: "originalsource", + + methods: { + getText: { + response: { + text: RetVal("longstring") + } + } + } +}); + +exports.originalSourceSpec = originalSourceSpec; + +const mediaRuleSpec = generateActorSpec({ + typeName: "mediarule", + + events: { + "matches-change": { + type: "matchesChange", + matches: Arg(0, "boolean"), + } + } +}); + +exports.mediaRuleSpec = mediaRuleSpec; + +types.addActorType("stylesheet"); + +const styleSheetSpec = generateActorSpec({ + typeName: "stylesheet", + + events: { + "property-change": { + type: "propertyChange", + property: Arg(0, "string"), + value: Arg(1, "json") + }, + "style-applied": { + type: "styleApplied", + kind: Arg(0, "number"), + styleSheet: Arg(1, "stylesheet") + }, + "media-rules-changed": { + type: "mediaRulesChanged", + rules: Arg(0, "array:mediarule") + } + }, + + methods: { + toggleDisabled: { + response: { disabled: RetVal("boolean")} + }, + getText: { + response: { + text: RetVal("longstring") + } + }, + getOriginalSources: { + request: {}, + response: { + originalSources: RetVal("nullable:array:originalsource") + } + }, + getOriginalLocation: { + request: { + line: Arg(0, "number"), + column: Arg(1, "number") + }, + response: RetVal(types.addDictType("originallocationresponse", { + source: "string", + line: "number", + column: "number" + })) + }, + getMediaRules: { + request: {}, + response: { + mediaRules: RetVal("nullable:array:mediarule") + } + }, + update: { + request: { + text: Arg(0, "string"), + transition: Arg(1, "boolean") + } + } + } +}); + +exports.styleSheetSpec = styleSheetSpec; + +const styleSheetsSpec = generateActorSpec({ + typeName: "stylesheets", + + methods: { + getStyleSheets: { + request: {}, + response: { styleSheets: RetVal("array:stylesheet") } + }, + addStyleSheet: { + request: { text: Arg(0, "string") }, + response: { styleSheet: RetVal("stylesheet") } + } + } +}); + +exports.styleSheetsSpec = styleSheetsSpec; diff --git a/devtools/shared/specs/timeline.js b/devtools/shared/specs/timeline.js new file mode 100644 index 000000000..653ebef49 --- /dev/null +++ b/devtools/shared/specs/timeline.js @@ -0,0 +1,118 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { + Arg, + RetVal, + Option, + generateActorSpec, + types +} = require("devtools/shared/protocol"); + +/** + * Type representing an array of numbers as strings, serialized fast(er). + * http://jsperf.com/json-stringify-parse-vs-array-join-split/3 + * + * XXX: It would be nice if on local connections (only), we could just *give* + * the array directly to the front, instead of going through all this + * serialization redundancy. + */ +types.addType("array-of-numbers-as-strings", { + write: (v) => v.join(","), + // In Gecko <= 37, `v` is an array; do not transform in this case. + read: (v) => typeof v === "string" ? v.split(",") : v +}); + +const timelineSpec = generateActorSpec({ + typeName: "timeline", + + events: { + /** + * Events emitted when "DOMContentLoaded" and "Load" markers are received. + */ + "doc-loading": { + type: "doc-loading", + marker: Arg(0, "json"), + endTime: Arg(0, "number") + }, + + /** + * The "markers" events emitted every DEFAULT_TIMELINE_DATA_PULL_TIMEOUT ms + * at most, when profile markers are found. The timestamps on each marker + * are relative to when recording was started. + */ + "markers": { + type: "markers", + markers: Arg(0, "json"), + endTime: Arg(1, "number") + }, + + /** + * The "memory" events emitted in tandem with "markers", if this was enabled + * when the recording started. The `delta` timestamp on this measurement is + * relative to when recording was started. + */ + "memory": { + type: "memory", + delta: Arg(0, "number"), + measurement: Arg(1, "json") + }, + + /** + * The "ticks" events (from the refresh driver) emitted in tandem with + * "markers", if this was enabled when the recording started. All ticks + * are timestamps with a zero epoch. + */ + "ticks": { + type: "ticks", + delta: Arg(0, "number"), + timestamps: Arg(1, "array-of-numbers-as-strings") + }, + + /** + * The "frames" events emitted in tandem with "markers", containing + * JS stack frames. The `delta` timestamp on this frames packet is + * relative to when recording was started. + */ + "frames": { + type: "frames", + delta: Arg(0, "number"), + frames: Arg(1, "json") + } + }, + + methods: { + isRecording: { + request: {}, + response: { + value: RetVal("boolean") + } + }, + + start: { + request: { + withMarkers: Option(0, "boolean"), + withTicks: Option(0, "boolean"), + withMemory: Option(0, "boolean"), + withFrames: Option(0, "boolean"), + withGCEvents: Option(0, "boolean"), + withDocLoadingEvents: Option(0, "boolean") + }, + response: { + value: RetVal("number") + } + }, + + stop: { + response: { + // Set as possibly nullable due to the end time possibly being + // undefined during destruction + value: RetVal("nullable:number") + } + }, + }, +}); + +exports.timelineSpec = timelineSpec; diff --git a/devtools/shared/specs/webaudio.js b/devtools/shared/specs/webaudio.js new file mode 100644 index 000000000..9dfb92467 --- /dev/null +++ b/devtools/shared/specs/webaudio.js @@ -0,0 +1,163 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { + Arg, + Option, + RetVal, + generateActorSpec, + types, +} = require("devtools/shared/protocol"); + +exports.NODE_CREATION_METHODS = [ + "createBufferSource", "createMediaElementSource", "createMediaStreamSource", + "createMediaStreamDestination", "createScriptProcessor", "createAnalyser", + "createGain", "createDelay", "createBiquadFilter", "createWaveShaper", + "createPanner", "createConvolver", "createChannelSplitter", "createChannelMerger", + "createDynamicsCompressor", "createOscillator", "createStereoPanner" +]; + +exports.AUTOMATION_METHODS = [ + "setValueAtTime", "linearRampToValueAtTime", "exponentialRampToValueAtTime", + "setTargetAtTime", "setValueCurveAtTime", "cancelScheduledValues" +]; + +exports.NODE_ROUTING_METHODS = [ + "connect", "disconnect" +]; + +types.addActorType("audionode"); +const audionodeSpec = generateActorSpec({ + typeName: "audionode", + + methods: { + getType: { response: { type: RetVal("string") }}, + isBypassed: { + response: { bypassed: RetVal("boolean") } + }, + bypass: { + request: { enable: Arg(0, "boolean") }, + response: { bypassed: RetVal("boolean") } + }, + setParam: { + request: { + param: Arg(0, "string"), + value: Arg(1, "nullable:primitive") + }, + response: { error: RetVal("nullable:json") } + }, + getParam: { + request: { + param: Arg(0, "string") + }, + response: { text: RetVal("nullable:primitive") } + }, + getParamFlags: { + request: { param: Arg(0, "string") }, + response: { flags: RetVal("nullable:primitive") } + }, + getParams: { + response: { params: RetVal("json") } + }, + connectParam: { + request: { + destActor: Arg(0, "audionode"), + paramName: Arg(1, "string"), + output: Arg(2, "nullable:number") + }, + response: { error: RetVal("nullable:json") } + }, + connectNode: { + request: { + destActor: Arg(0, "audionode"), + output: Arg(1, "nullable:number"), + input: Arg(2, "nullable:number") + }, + response: { error: RetVal("nullable:json") } + }, + disconnect: { + request: { output: Arg(0, "nullable:number") }, + response: { error: RetVal("nullable:json") } + }, + getAutomationData: { + request: { paramName: Arg(0, "string") }, + response: { values: RetVal("nullable:json") } + }, + addAutomationEvent: { + request: { + paramName: Arg(0, "string"), + eventName: Arg(1, "string"), + args: Arg(2, "nullable:json") + }, + response: { error: RetVal("nullable:json") } + }, + } +}); + +exports.audionodeSpec = audionodeSpec; + +const webAudioSpec = generateActorSpec({ + typeName: "webaudio", + + /** + * Events emitted by this actor. + */ + events: { + "start-context": { + type: "startContext" + }, + "connect-node": { + type: "connectNode", + source: Option(0, "audionode"), + dest: Option(0, "audionode") + }, + "disconnect-node": { + type: "disconnectNode", + source: Arg(0, "audionode") + }, + "connect-param": { + type: "connectParam", + source: Option(0, "audionode"), + dest: Option(0, "audionode"), + param: Option(0, "string") + }, + "change-param": { + type: "changeParam", + source: Option(0, "audionode"), + param: Option(0, "string"), + value: Option(0, "string") + }, + "create-node": { + type: "createNode", + source: Arg(0, "audionode") + }, + "destroy-node": { + type: "destroyNode", + source: Arg(0, "audionode") + }, + "automation-event": { + type: "automationEvent", + node: Option(0, "audionode"), + paramName: Option(0, "string"), + eventName: Option(0, "string"), + args: Option(0, "json") + } + }, + + methods: { + getDefinition: { + response: { definition: RetVal("json") } + }, + setup: { + request: { reload: Option(0, "boolean") }, + oneway: true + }, + finalize: { + oneway: true + } + } +}); + +exports.webAudioSpec = webAudioSpec; diff --git a/devtools/shared/specs/webgl.js b/devtools/shared/specs/webgl.js new file mode 100644 index 000000000..f97610f3c --- /dev/null +++ b/devtools/shared/specs/webgl.js @@ -0,0 +1,101 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const {Arg, Option, RetVal, generateActorSpec} = require("devtools/shared/protocol"); + +const shaderSpec = generateActorSpec({ + typeName: "gl-shader", + + methods: { + getText: { + response: { text: RetVal("string") } + }, + compile: { + request: { text: Arg(0, "string") }, + response: { error: RetVal("nullable:json") } + }, + }, +}); + +exports.shaderSpec = shaderSpec; + +const programSpec = generateActorSpec({ + typeName: "gl-program", + + methods: { + getVertexShader: { + response: { shader: RetVal("gl-shader") } + }, + getFragmentShader: { + response: { shader: RetVal("gl-shader") } + }, + highlight: { + request: { tint: Arg(0, "array:number") }, + oneway: true + }, + unhighlight: { + oneway: true + }, + blackbox: { + oneway: true + }, + unblackbox: { + oneway: true + }, + } +}); + +exports.programSpec = programSpec; + +const webGLSpec = generateActorSpec({ + typeName: "webgl", + + /** + * Events emitted by this actor. The "program-linked" event is fired every + * time a WebGL program was linked with its respective two shaders. + */ + events: { + "program-linked": { + type: "programLinked", + program: Arg(0, "gl-program") + }, + "global-destroyed": { + type: "globalDestroyed", + program: Arg(0, "number") + }, + "global-created": { + type: "globalCreated", + program: Arg(0, "number") + } + }, + + methods: { + setup: { + request: { reload: Option(0, "boolean") }, + oneway: true + }, + finalize: { + oneway: true + }, + getPrograms: { + response: { programs: RetVal("array:gl-program") } + }, + waitForFrame: { + response: { success: RetVal("nullable:json") } + }, + getPixel: { + request: { + selector: Option(0, "string"), + position: Option(0, "json") + }, + response: { pixels: RetVal("json") } + }, + _getAllPrograms: { + response: { programs: RetVal("array:gl-program") } + } + } +}); + +exports.webGLSpec = webGLSpec; diff --git a/devtools/shared/specs/worker.js b/devtools/shared/specs/worker.js new file mode 100644 index 000000000..568f55ec0 --- /dev/null +++ b/devtools/shared/specs/worker.js @@ -0,0 +1,78 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const {Arg, RetVal, generateActorSpec} = require("devtools/shared/protocol"); + +const workerSpec = generateActorSpec({ + typeName: "worker", + + methods: { + attach: { + request: {}, + response: RetVal("json") + }, + detach: { + request: {}, + response: RetVal("json") + }, + connect: { + request: { + options: Arg(0, "json"), + }, + response: RetVal("json") + }, + push: { + request: {}, + response: RetVal("json") + }, + }, +}); + +exports.workerSpec = workerSpec; + +const pushSubscriptionSpec = generateActorSpec({ + typeName: "pushSubscription", +}); + +exports.pushSubscriptionSpec = pushSubscriptionSpec; + +const serviceWorkerRegistrationSpec = generateActorSpec({ + typeName: "serviceWorkerRegistration", + + events: { + "push-subscription-modified": { + type: "push-subscription-modified" + }, + "registration-changed": { + type: "registration-changed" + } + }, + + methods: { + start: { + request: {}, + response: RetVal("json") + }, + unregister: { + request: {}, + response: RetVal("json") + }, + getPushSubscription: { + request: {}, + response: { + subscription: RetVal("nullable:pushSubscription") + } + }, + }, +}); + +exports.serviceWorkerRegistrationSpec = serviceWorkerRegistrationSpec; + +const serviceWorkerSpec = generateActorSpec({ + typeName: "serviceWorker", +}); + +exports.serviceWorkerSpec = serviceWorkerSpec; + |