diff options
Diffstat (limited to 'devtools/client/aboutdebugging/src/reducers')
5 files changed, 482 insertions, 0 deletions
diff --git a/devtools/client/aboutdebugging/src/reducers/debug-targets-state.js b/devtools/client/aboutdebugging/src/reducers/debug-targets-state.js new file mode 100644 index 0000000000..8ee0473e3c --- /dev/null +++ b/devtools/client/aboutdebugging/src/reducers/debug-targets-state.js @@ -0,0 +1,155 @@ +/* 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 { + EXTENSION_BGSCRIPT_STATUS_UPDATED, + REQUEST_EXTENSIONS_SUCCESS, + REQUEST_PROCESSES_SUCCESS, + REQUEST_TABS_SUCCESS, + REQUEST_WORKERS_SUCCESS, + TEMPORARY_EXTENSION_RELOAD_FAILURE, + TEMPORARY_EXTENSION_RELOAD_START, + TERMINATE_EXTENSION_BGSCRIPT_FAILURE, + TERMINATE_EXTENSION_BGSCRIPT_START, + UNWATCH_RUNTIME_SUCCESS, +} = require("resource://devtools/client/aboutdebugging/src/constants.js"); + +function DebugTargetsState() { + return { + installedExtensions: [], + otherWorkers: [], + processes: [], + serviceWorkers: [], + sharedWorkers: [], + tabs: [], + temporaryExtensions: [], + }; +} + +function updateExtensionDetails(extensions, id, updatedDetails) { + // extensions is meant to be either state.installExtensions or state.temporaryExtensions. + return extensions.map(extension => { + if (extension.id === id) { + extension = Object.assign({}, extension); + + extension.details = Object.assign({}, extension.details, updatedDetails); + } + return extension; + }); +} + +function updateTemporaryExtension(state, id, updatedDetails) { + return updateExtensionDetails(state.temporaryExtensions, id, updatedDetails); +} + +function updateInstalledExtension(state, id, updatedDetails) { + return updateExtensionDetails(state.installedExtensions, id, updatedDetails); +} + +function updateExtension(state, id, updatedDetails) { + return { + installedExtensions: updateInstalledExtension(state, id, updatedDetails), + temporaryExtensions: updateTemporaryExtension(state, id, updatedDetails), + }; +} + +function debugTargetsReducer(state = DebugTargetsState(), action) { + switch (action.type) { + case UNWATCH_RUNTIME_SUCCESS: { + return DebugTargetsState(); + } + case REQUEST_EXTENSIONS_SUCCESS: { + const { installedExtensions, temporaryExtensions } = action; + return Object.assign({}, state, { + installedExtensions, + temporaryExtensions, + }); + } + case REQUEST_PROCESSES_SUCCESS: { + const { processes } = action; + return Object.assign({}, state, { processes }); + } + case REQUEST_TABS_SUCCESS: { + const { tabs } = action; + return Object.assign({}, state, { tabs }); + } + case REQUEST_WORKERS_SUCCESS: { + const { otherWorkers, serviceWorkers, sharedWorkers } = action; + return Object.assign({}, state, { + otherWorkers, + serviceWorkers, + sharedWorkers, + }); + } + case TEMPORARY_EXTENSION_RELOAD_FAILURE: { + const { id, error } = action; + const temporaryExtensions = updateTemporaryExtension(state, id, { + reloadError: error.message, + }); + return Object.assign({}, state, { temporaryExtensions }); + } + case TEMPORARY_EXTENSION_RELOAD_START: { + const { id } = action; + const temporaryExtensions = updateTemporaryExtension(state, id, { + reloadError: null, + }); + return Object.assign({}, state, { temporaryExtensions }); + } + case TERMINATE_EXTENSION_BGSCRIPT_START: { + const { id } = action; + const { installedExtensions, temporaryExtensions } = updateExtension( + state, + id, + { + // Clear the last error if one was still set. + lastTerminateBackgroundScriptError: null, + } + ); + return Object.assign({}, state, { + installedExtensions, + temporaryExtensions, + }); + } + case TERMINATE_EXTENSION_BGSCRIPT_FAILURE: { + const { id, error } = action; + const { installedExtensions, temporaryExtensions } = updateExtension( + state, + id, + { + lastTerminateBackgroundScriptError: error.message, + } + ); + return Object.assign({}, state, { + installedExtensions, + temporaryExtensions, + }); + } + case EXTENSION_BGSCRIPT_STATUS_UPDATED: { + const { id, backgroundScriptStatus } = action; + const { installedExtensions, temporaryExtensions } = updateExtension( + state, + id, + { + backgroundScriptStatus, + // Clear the last error if one was still set. + lastTerminateBackgroundScriptError: null, + } + ); + return Object.assign({}, state, { + installedExtensions, + temporaryExtensions, + }); + } + + default: + return state; + } +} + +module.exports = { + DebugTargetsState, + debugTargetsReducer, +}; diff --git a/devtools/client/aboutdebugging/src/reducers/index.js b/devtools/client/aboutdebugging/src/reducers/index.js new file mode 100644 index 0000000000..8f104a4ff7 --- /dev/null +++ b/devtools/client/aboutdebugging/src/reducers/index.js @@ -0,0 +1,24 @@ +/* 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 { + combineReducers, +} = require("resource://devtools/client/shared/vendor/redux.js"); +const { + debugTargetsReducer, +} = require("resource://devtools/client/aboutdebugging/src/reducers/debug-targets-state.js"); +const { + runtimesReducer, +} = require("resource://devtools/client/aboutdebugging/src/reducers/runtimes-state.js"); +const { + uiReducer, +} = require("resource://devtools/client/aboutdebugging/src/reducers/ui-state.js"); + +module.exports = combineReducers({ + debugTargets: debugTargetsReducer, + runtimes: runtimesReducer, + ui: uiReducer, +}); diff --git a/devtools/client/aboutdebugging/src/reducers/moz.build b/devtools/client/aboutdebugging/src/reducers/moz.build new file mode 100644 index 0000000000..24d3382f5b --- /dev/null +++ b/devtools/client/aboutdebugging/src/reducers/moz.build @@ -0,0 +1,10 @@ +# 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( + "debug-targets-state.js", + "index.js", + "runtimes-state.js", + "ui-state.js", +) diff --git a/devtools/client/aboutdebugging/src/reducers/runtimes-state.js b/devtools/client/aboutdebugging/src/reducers/runtimes-state.js new file mode 100644 index 0000000000..5acf35390a --- /dev/null +++ b/devtools/client/aboutdebugging/src/reducers/runtimes-state.js @@ -0,0 +1,178 @@ +/* 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 { + CONNECT_RUNTIME_CANCEL, + CONNECT_RUNTIME_FAILURE, + CONNECT_RUNTIME_NOT_RESPONDING, + CONNECT_RUNTIME_START, + CONNECT_RUNTIME_SUCCESS, + DISCONNECT_RUNTIME_SUCCESS, + RUNTIMES, + UPDATE_CONNECTION_PROMPT_SETTING_SUCCESS, + REMOTE_RUNTIMES_UPDATED, + SELECTED_RUNTIME_ID_UPDATED, + THIS_FIREFOX_RUNTIME_CREATED, +} = require("resource://devtools/client/aboutdebugging/src/constants.js"); + +const { + findRuntimeById, +} = require("resource://devtools/client/aboutdebugging/src/modules/runtimes-state-helper.js"); + +const { + remoteClientManager, +} = require("resource://devtools/client/shared/remote-debugging/remote-client-manager.js"); + +// Map between known runtime types and nodes in the runtimes state. +const TYPE_TO_RUNTIMES_KEY = { + [RUNTIMES.THIS_FIREFOX]: "thisFirefoxRuntimes", + [RUNTIMES.NETWORK]: "networkRuntimes", + [RUNTIMES.USB]: "usbRuntimes", +}; + +function RuntimesState() { + return { + networkRuntimes: [], + selectedRuntimeId: null, + // "This Firefox" runtimes is an array for consistency, but it should only contain one + // runtime. This runtime will be added after initializing the application via + // THIS_FIREFOX_RUNTIME_CREATED. + thisFirefoxRuntimes: [], + usbRuntimes: [], + }; +} + +/** + * Update the runtime matching the provided runtimeId with the content of updatedRuntime, + * and return the new state. + * + * @param {String} runtimeId + * The id of the runtime to update + * @param {Object} updatedRuntime + * Object used to update the runtime matching the idea using Object.assign. + * @param {Object} state + * Current runtimes state. + * @return {Object} The updated state + */ +function _updateRuntimeById(runtimeId, updatedRuntime, state) { + // Find the array of runtimes that contains the updated runtime. + const runtime = findRuntimeById(runtimeId, state); + const key = TYPE_TO_RUNTIMES_KEY[runtime.type]; + const runtimesToUpdate = state[key]; + + // Update the runtime with the provided updatedRuntime. + const updatedRuntimes = runtimesToUpdate.map(r => { + if (r.id === runtimeId) { + return Object.assign({}, r, updatedRuntime); + } + return r; + }); + return Object.assign({}, state, { [key]: updatedRuntimes }); +} + +function runtimesReducer(state = RuntimesState(), action) { + switch (action.type) { + case CONNECT_RUNTIME_START: { + const { id } = action; + const updatedState = { + isConnecting: true, + isConnectionFailed: false, + isConnectionNotResponding: false, + isConnectionTimeout: false, + }; + return _updateRuntimeById(id, updatedState, state); + } + + case CONNECT_RUNTIME_NOT_RESPONDING: { + const { id } = action; + return _updateRuntimeById(id, { isConnectionNotResponding: true }, state); + } + + case CONNECT_RUNTIME_CANCEL: { + const { id } = action; + const updatedState = { + isConnecting: false, + isConnectionFailed: false, + isConnectionNotResponding: false, + isConnectionTimeout: true, + }; + return _updateRuntimeById(id, updatedState, state); + } + + case CONNECT_RUNTIME_SUCCESS: { + const { id, runtimeDetails, type } = action.runtime; + + // Update the remoteClientManager with the connected runtime. + const client = runtimeDetails.clientWrapper.client; + const runtimeInfo = runtimeDetails.info; + remoteClientManager.setClient(id, type, client, runtimeInfo); + + const updatedState = { + isConnecting: false, + isConnectionFailed: false, + isConnectionNotResponding: false, + isConnectionTimeout: false, + runtimeDetails, + }; + return _updateRuntimeById(id, updatedState, state); + } + + case CONNECT_RUNTIME_FAILURE: { + const { id } = action; + const updatedState = { + isConnecting: false, + isConnectionFailed: true, + isConnectionNotResponding: false, + isConnectionTimeout: false, + }; + return _updateRuntimeById(id, updatedState, state); + } + + case DISCONNECT_RUNTIME_SUCCESS: { + const { id, type } = action.runtime; + remoteClientManager.removeClient(id, type); + return _updateRuntimeById(id, { runtimeDetails: null }, state); + } + + case SELECTED_RUNTIME_ID_UPDATED: { + const selectedRuntimeId = action.runtimeId || null; + return Object.assign({}, state, { selectedRuntimeId }); + } + + case UPDATE_CONNECTION_PROMPT_SETTING_SUCCESS: { + const { connectionPromptEnabled } = action; + const { id: runtimeId } = action.runtime; + const runtime = findRuntimeById(runtimeId, state); + const runtimeDetails = Object.assign({}, runtime.runtimeDetails, { + connectionPromptEnabled, + }); + return _updateRuntimeById(runtimeId, { runtimeDetails }, state); + } + + case REMOTE_RUNTIMES_UPDATED: { + const { runtimes, runtimeType } = action; + const key = TYPE_TO_RUNTIMES_KEY[runtimeType]; + return Object.assign({}, state, { + [key]: runtimes, + }); + } + + case THIS_FIREFOX_RUNTIME_CREATED: { + const { runtime } = action; + return Object.assign({}, state, { + thisFirefoxRuntimes: [runtime], + }); + } + + default: + return state; + } +} + +module.exports = { + RuntimesState, + runtimesReducer, +}; diff --git a/devtools/client/aboutdebugging/src/reducers/ui-state.js b/devtools/client/aboutdebugging/src/reducers/ui-state.js new file mode 100644 index 0000000000..771358eaac --- /dev/null +++ b/devtools/client/aboutdebugging/src/reducers/ui-state.js @@ -0,0 +1,115 @@ +/* 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 { + ADB_ADDON_STATUS_UPDATED, + ADB_READY_UPDATED, + DEBUG_TARGET_COLLAPSIBILITY_UPDATED, + HIDE_PROFILER_DIALOG, + NETWORK_LOCATIONS_UPDATE_SUCCESS, + PROFILER_PAGE_CONTEXT, + SELECT_PAGE_SUCCESS, + SHOW_PROFILER_DIALOG, + SWITCH_PROFILER_CONTEXT, + TEMPORARY_EXTENSION_INSTALL_FAILURE, + TEMPORARY_EXTENSION_INSTALL_SUCCESS, + USB_RUNTIMES_SCAN_START, + USB_RUNTIMES_SCAN_SUCCESS, +} = require("resource://devtools/client/aboutdebugging/src/constants.js"); + +function UiState( + locations = [], + debugTargetCollapsibilities = {}, + showHiddenAddons = false +) { + return { + adbAddonStatus: null, + debugTargetCollapsibilities, + isAdbReady: false, + isScanningUsb: false, + networkLocations: locations, + profilerContext: PROFILER_PAGE_CONTEXT.DEVTOOLS_REMOTE, + selectedPage: null, + showProfilerDialog: false, + showHiddenAddons, + temporaryInstallError: null, + }; +} + +function uiReducer(state = UiState(), action) { + switch (action.type) { + case ADB_ADDON_STATUS_UPDATED: { + const { adbAddonStatus } = action; + return Object.assign({}, state, { adbAddonStatus }); + } + + case ADB_READY_UPDATED: { + const { isAdbReady } = action; + return Object.assign({}, state, { isAdbReady }); + } + + case DEBUG_TARGET_COLLAPSIBILITY_UPDATED: { + const { isCollapsed, key } = action; + const debugTargetCollapsibilities = new Map( + state.debugTargetCollapsibilities + ); + debugTargetCollapsibilities.set(key, isCollapsed); + return Object.assign({}, state, { debugTargetCollapsibilities }); + } + + case NETWORK_LOCATIONS_UPDATE_SUCCESS: { + const { locations } = action; + return Object.assign({}, state, { networkLocations: locations }); + } + + case SELECT_PAGE_SUCCESS: { + const { page } = action; + return Object.assign({}, state, { selectedPage: page }); + } + + case SHOW_PROFILER_DIALOG: { + return Object.assign({}, state, { + showProfilerDialog: true, + // Always start in the devtools-remote view. + profilerContext: "devtools-remote", + }); + } + + case HIDE_PROFILER_DIALOG: { + return Object.assign({}, state, { showProfilerDialog: false }); + } + + case SWITCH_PROFILER_CONTEXT: { + const { profilerContext } = action; + return Object.assign({}, state, { profilerContext }); + } + + case USB_RUNTIMES_SCAN_START: { + return Object.assign({}, state, { isScanningUsb: true }); + } + + case USB_RUNTIMES_SCAN_SUCCESS: { + return Object.assign({}, state, { isScanningUsb: false }); + } + + case TEMPORARY_EXTENSION_INSTALL_SUCCESS: { + return Object.assign({}, state, { temporaryInstallError: null }); + } + + case TEMPORARY_EXTENSION_INSTALL_FAILURE: { + const { error } = action; + return Object.assign({}, state, { temporaryInstallError: error }); + } + + default: + return state; + } +} + +module.exports = { + UiState, + uiReducer, +}; |