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