ui.js (5976B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 "use strict"; 6 7 const { 8 ADB_ADDON_INSTALL_START, 9 ADB_ADDON_INSTALL_SUCCESS, 10 ADB_ADDON_INSTALL_FAILURE, 11 ADB_ADDON_UNINSTALL_START, 12 ADB_ADDON_UNINSTALL_SUCCESS, 13 ADB_ADDON_UNINSTALL_FAILURE, 14 ADB_ADDON_STATUS_UPDATED, 15 ADB_READY_UPDATED, 16 DEBUG_TARGET_COLLAPSIBILITY_UPDATED, 17 HIDE_PROFILER_DIALOG, 18 NETWORK_LOCATIONS_UPDATE_FAILURE, 19 NETWORK_LOCATIONS_UPDATE_START, 20 NETWORK_LOCATIONS_UPDATE_SUCCESS, 21 PAGE_TYPES, 22 SELECT_PAGE_FAILURE, 23 SELECT_PAGE_START, 24 SELECT_PAGE_SUCCESS, 25 SELECTED_RUNTIME_ID_UPDATED, 26 SHOW_PROFILER_DIALOG, 27 SWITCH_PROFILER_CONTEXT, 28 USB_RUNTIMES_SCAN_START, 29 USB_RUNTIMES_SCAN_SUCCESS, 30 } = require("resource://devtools/client/aboutdebugging/src/constants.js"); 31 32 const NetworkLocationsModule = require("resource://devtools/client/aboutdebugging/src/modules/network-locations.js"); 33 const { 34 adbAddon, 35 } = require("resource://devtools/client/shared/remote-debugging/adb/adb-addon.js"); 36 const { 37 refreshUSBRuntimes, 38 } = require("resource://devtools/client/aboutdebugging/src/modules/usb-runtimes.js"); 39 40 const Actions = require("resource://devtools/client/aboutdebugging/src/actions/index.js"); 41 42 function selectPage(page, runtimeId) { 43 return async ({ dispatch, getState }) => { 44 dispatch({ type: SELECT_PAGE_START }); 45 46 try { 47 const isSamePage = (oldPage, newPage) => { 48 if (newPage === PAGE_TYPES.RUNTIME && oldPage === PAGE_TYPES.RUNTIME) { 49 return runtimeId === getState().runtimes.selectedRuntimeId; 50 } 51 return newPage === oldPage; 52 }; 53 54 if (!page) { 55 throw new Error("No page provided."); 56 } 57 58 const currentPage = getState().ui.selectedPage; 59 // Nothing to dispatch if the page is the same as the current page 60 if (isSamePage(currentPage, page)) { 61 return; 62 } 63 64 // Stop showing the profiler dialog if we are navigating to another page. 65 if (getState().ui.showProfilerDialog) { 66 await dispatch({ type: HIDE_PROFILER_DIALOG }); 67 } 68 69 // Stop watching current runtime, if currently on a RUNTIME page. 70 if (currentPage === PAGE_TYPES.RUNTIME) { 71 const currentRuntimeId = getState().runtimes.selectedRuntimeId; 72 await dispatch(Actions.unwatchRuntime(currentRuntimeId)); 73 } 74 75 // Always update the selected runtime id. 76 // If we are navigating to a non-runtime page, the Runtime page components are no 77 // longer rendered so it is safe to nullify the runtimeId. 78 // If we are navigating to a runtime page, the runtime corresponding to runtimeId 79 // is already connected, so components can safely get runtimeDetails on this new 80 // runtime. 81 dispatch({ type: SELECTED_RUNTIME_ID_UPDATED, runtimeId }); 82 83 // Start watching current runtime, if moving to a RUNTIME page. 84 if (page === PAGE_TYPES.RUNTIME) { 85 await dispatch(Actions.watchRuntime(runtimeId)); 86 } 87 88 dispatch({ type: SELECT_PAGE_SUCCESS, page }); 89 } catch (e) { 90 dispatch({ type: SELECT_PAGE_FAILURE, error: e }); 91 } 92 }; 93 } 94 95 function updateDebugTargetCollapsibility(key, isCollapsed) { 96 return { type: DEBUG_TARGET_COLLAPSIBILITY_UPDATED, key, isCollapsed }; 97 } 98 99 function addNetworkLocation(location) { 100 return () => { 101 NetworkLocationsModule.addNetworkLocation(location); 102 }; 103 } 104 105 function removeNetworkLocation(location) { 106 return () => { 107 NetworkLocationsModule.removeNetworkLocation(location); 108 }; 109 } 110 111 function showProfilerDialog() { 112 return { type: SHOW_PROFILER_DIALOG }; 113 } 114 115 /** 116 * The profiler can switch between "devtools-remote" and "aboutprofiling-remote" 117 * page contexts. 118 */ 119 function switchProfilerContext(profilerContext) { 120 return { type: SWITCH_PROFILER_CONTEXT, profilerContext }; 121 } 122 123 function hideProfilerDialog() { 124 return { type: HIDE_PROFILER_DIALOG }; 125 } 126 127 function updateAdbAddonStatus(adbAddonStatus) { 128 return { type: ADB_ADDON_STATUS_UPDATED, adbAddonStatus }; 129 } 130 131 function updateAdbReady(isAdbReady) { 132 return { type: ADB_READY_UPDATED, isAdbReady }; 133 } 134 135 function updateNetworkLocations(locations) { 136 return async ({ dispatch }) => { 137 dispatch({ type: NETWORK_LOCATIONS_UPDATE_START }); 138 try { 139 await dispatch(Actions.updateNetworkRuntimes(locations)); 140 dispatch({ type: NETWORK_LOCATIONS_UPDATE_SUCCESS, locations }); 141 } catch (e) { 142 dispatch({ type: NETWORK_LOCATIONS_UPDATE_FAILURE, error: e }); 143 } 144 }; 145 } 146 147 function installAdbAddon() { 148 return async ({ dispatch }) => { 149 dispatch({ type: ADB_ADDON_INSTALL_START }); 150 151 try { 152 // "aboutdebugging" will be forwarded to telemetry as the installation source 153 // for the addon. 154 await adbAddon.install("about:debugging"); 155 dispatch({ type: ADB_ADDON_INSTALL_SUCCESS }); 156 } catch (e) { 157 dispatch({ type: ADB_ADDON_INSTALL_FAILURE, error: e }); 158 } 159 }; 160 } 161 162 function uninstallAdbAddon() { 163 return async ({ dispatch }) => { 164 dispatch({ type: ADB_ADDON_UNINSTALL_START }); 165 166 try { 167 await adbAddon.uninstall(); 168 dispatch({ type: ADB_ADDON_UNINSTALL_SUCCESS }); 169 } catch (e) { 170 dispatch({ type: ADB_ADDON_UNINSTALL_FAILURE, error: e }); 171 } 172 }; 173 } 174 175 function scanUSBRuntimes() { 176 return async ({ dispatch, getState }) => { 177 // do not re-scan if we are already doing it 178 if (getState().ui.isScanningUsb) { 179 return; 180 } 181 182 dispatch({ type: USB_RUNTIMES_SCAN_START }); 183 await refreshUSBRuntimes(); 184 dispatch({ type: USB_RUNTIMES_SCAN_SUCCESS }); 185 }; 186 } 187 188 module.exports = { 189 addNetworkLocation, 190 hideProfilerDialog, 191 installAdbAddon, 192 removeNetworkLocation, 193 scanUSBRuntimes, 194 selectPage, 195 showProfilerDialog, 196 switchProfilerContext, 197 uninstallAdbAddon, 198 updateAdbAddonStatus, 199 updateAdbReady, 200 updateDebugTargetCollapsibility, 201 updateNetworkLocations, 202 };