@samitouri / QOS-React-2 / commits / 78721bde4c

Backend notifies the frontend of Storage API support. Frontend disables e.g. reload-and-profile based on this.

Brian Vaughn committed Jun 7, 2019 at 13:08 UTC 78721bde4cd5a277b168df4673d38cf78d40a5f0
3 files changed +49 -3
src/backend/agent.js
+9
@@ -127,6 +127,15 @@ export default class Agent extends EventEmitter {
127 if (this._isProfiling) {
128 bridge.send('profilingStatus', true);
129 }
130 +
131 + // Notify the frontend if the backend supports the Storage API (e.g. localStorage).
132 + // If not, features like reload-and-profile will not work correctly and must be disabled.
133 + let isBackendStorageAPISupported = false;
134 + try {
135 + localStorage.getItem('test');
136 + isBackendStorageAPISupported = true;
137 + } catch (error) {}
138 + bridge.send('isBackendStorageAPISupported', isBackendStorageAPISupported);
139 }
140
141 captureScreenshot = ({
src/devtools/store.js
+22 -1
@@ -73,6 +73,10 @@ export default class Store extends EventEmitter {
73 // The InspectedElementContext also relies on this mutability for its WeakMap usage.
74 _idToElement: Map<number, Element> = new Map();
75
76 + // Can the backend use the Storage API (e.g. localStorage)?
77 + // If not, features like reload-and-profile will not work correctly and must be disabled.
78 + _isBackendStorageAPISupported: boolean = false;
79 +
80 // Map of element (id) to the set of elements (ids) it owns.
81 // This map enables getOwnersListForElement() to avoid traversing the entire tree.
82 _ownersMap: Map<number, Set<number>> = new Map();
@@ -141,6 +145,10 @@ export default class Store extends EventEmitter {
145 this._bridge = bridge;
146 bridge.addListener('operations', this.onBridgeOperations);
147 bridge.addListener('shutdown', this.onBridgeShutdown);
148 + bridge.addListener(
149 + 'isBackendStorageAPISupported',
150 + this.onBridgeStorageSupported
151 + );
152
153 this._profilerStore = new ProfilerStore(bridge, this, isProfiling);
154 }
@@ -261,7 +269,10 @@ export default class Store extends EventEmitter {
269 }
270
271 get supportsReloadAndProfile(): boolean {
264 - return this._supportsReloadAndProfile;
272 + // Does the DevTools shell support reloading and eagerly injecting the renderer interface?
273 + // And if so, can the backend use the localStorage API?
274 + // Both of these are required for the reload-and-profile feature to work.
275 + return this._supportsReloadAndProfile && this._isBackendStorageAPISupported;
276 }
277
278 containsElement(id: number): boolean {
@@ -904,5 +915,15 @@ export default class Store extends EventEmitter {
915
916 this._bridge.removeListener('operations', this.onBridgeOperations);
917 this._bridge.removeListener('shutdown', this.onBridgeShutdown);
918 + this._bridge.removeListener(
919 + 'isBackendStorageAPISupported',
920 + this.onBridgeStorageSupported
921 + );
922 + };
923 +
924 + onBridgeStorageSupported = (isBackendStorageAPISupported: boolean) => {
925 + this._isBackendStorageAPISupported = isBackendStorageAPISupported;
926 +
927 + this.emit('supportsReloadAndProfile');
928 };
929 }
src/devtools/views/Profiler/ReloadAndProfileButton.js
+18 -2
@@ -1,19 +1,35 @@
1 // @flow
2
3 -import React, { useCallback, useContext } from 'react';
3 +import React, { useCallback, useContext, useMemo } from 'react';
4 import Button from '../Button';
5 import ButtonIcon from '../ButtonIcon';
6 import { BridgeContext, StoreContext } from '../context';
7 +import { useSubscription } from '../hooks';
8 +import Store from 'src/devtools/store';
9
10 export default function ReloadAndProfileButton() {
11 const bridge = useContext(BridgeContext);
12 const store = useContext(StoreContext);
13
14 + const supportsReloadAndProfileSubscription = useMemo(
15 + () => ({
16 + getCurrentValue: () => store.supportsReloadAndProfile,
17 + subscribe: (callback: Function) => {
18 + store.addListener('supportsReloadAndProfile', callback);
19 + return () => store.removeListener('supportsReloadAndProfile', callback);
20 + },
21 + }),
22 + [store]
23 + );
24 + const supportsReloadAndProfile = useSubscription<boolean, Store>(
25 + supportsReloadAndProfileSubscription
26 + );
27 +
28 const reloadAndProfile = useCallback(() => bridge.send('reloadAndProfile'), [
29 bridge,
30 ]);
31
16 - if (!store.supportsReloadAndProfile) {
32 + if (!supportsReloadAndProfile) {
33 return null;
34 }
35