mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
0dd3f803d8
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/51963 Changelog: [Internal] - Update `react-native/debugger-frontend` from 41bf86b...68cfd0a Resyncs `react-native/debugger-frontend` from GitHub - see `rn-chrome-devtools-frontend` [changelog](https://github.com/facebook/react-native-devtools-frontend/compare/41bf86bdbb3e59e7711f11527efac67c050bca75...68cfd0ae84acb0ed8e47b421afd64ae3b0b5b727). ### Changelog | Commit | Author | Date/Time | Subject | | ------ | ------ | --------- | ------- | | [68cfd0ae8](https://github.com/facebook/react-native-devtools-frontend/commit/68cfd0ae8) | Ruslan Lesiutin (rdlesyutin@gmail.com) | 2025-06-11T19:20:10+01:00 | [feat: restore Performance landing page (#179)](https://github.com/facebook/react-native-devtools-frontend/commit/68cfd0ae8) | | [bc3bd7f55](https://github.com/facebook/react-native-devtools-frontend/commit/bc3bd7f55) | Ruslan Lesiutin (rdlesyutin@gmail.com) | 2025-06-11T12:19:18+01:00 | [chore: hide unsupported Detached elements memory profiling option (#178)](https://github.com/facebook/react-native-devtools-frontend/commit/bc3bd7f55) | | [1f9eb6528](https://github.com/facebook/react-native-devtools-frontend/commit/1f9eb6528) | Ruslan Lesiutin (rdlesyutin@gmail.com) | 2025-06-11T10:05:12+01:00 | [ci: minor naming and formatting fixes (#177)](https://github.com/facebook/react-native-devtools-frontend/commit/1f9eb6528) | | [42526665c](https://github.com/facebook/react-native-devtools-frontend/commit/42526665c) | Ruslan Lesiutin (rdlesyutin@gmail.com) | 2025-06-11T10:02:00+01:00 | [ci: split build workflow (#176)](https://github.com/facebook/react-native-devtools-frontend/commit/42526665c) | | [7307e9532](https://github.com/facebook/react-native-devtools-frontend/commit/7307e9532) | Ruslan Lesiutin (rdlesyutin@gmail.com) | 2025-06-10T19:43:08+01:00 | [chore: added lint GitHub workflow (#174)](https://github.com/facebook/react-native-devtools-frontend/commit/7307e9532) | | [8d613dd1c](https://github.com/facebook/react-native-devtools-frontend/commit/8d613dd1c) | Ruslan Lesiutin (rdlesyutin@gmail.com) | 2025-06-10T19:42:53+01:00 | [chore: more instructions on repository syncing (#173)](https://github.com/facebook/react-native-devtools-frontend/commit/8d613dd1c) | | [d449be9e2](https://github.com/facebook/react-native-devtools-frontend/commit/d449be9e2) | Ruslan Lesiutin (rdlesyutin@gmail.com) | 2025-06-10T18:48:14+01:00 | [Merge pull request #172 from facebook/repo-sync-7103](https://github.com/facebook/react-native-devtools-frontend/commit/d449be9e2) | Reviewed By: huntie Differential Revision: D76455694 fbshipit-source-id: e44a016afe25ae62d72cf4b02e620ba166a9eeb9
1742 lines
46 KiB
JavaScript
1742 lines
46 KiB
JavaScript
// Copyright 2014 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
(function(window) {
|
|
|
|
// DevToolsAPI ----------------------------------------------------------------
|
|
|
|
/**
|
|
* @typedef {{runtimeAllowedHosts: !Array<string>, runtimeBlockedHosts: !Array<string>}} ExtensionHostsPolicy
|
|
*/
|
|
/**
|
|
* @typedef {{startPage: string, name: string, exposeExperimentalAPIs: boolean, hostsPolicy?: ExtensionHostsPolicy}} ExtensionDescriptor
|
|
*/
|
|
const DevToolsAPIImpl = class {
|
|
constructor() {
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
this._lastCallId = 0;
|
|
|
|
/**
|
|
* @type {!Object.<number, function(?Object)>}
|
|
*/
|
|
this._callbacks = {};
|
|
|
|
/**
|
|
* @type {!Array.<!ExtensionDescriptor>}
|
|
*/
|
|
this._pendingExtensionDescriptors = [];
|
|
|
|
/**
|
|
* @type {?function(!ExtensionDescriptor): void}
|
|
*/
|
|
this._addExtensionCallback = null;
|
|
|
|
/**
|
|
* @type {!Array<string>}
|
|
*/
|
|
this._originsForbiddenForExtensions = [];
|
|
|
|
/**
|
|
* @type {!Promise<string>}
|
|
*/
|
|
this._initialTargetIdPromise = new Promise(resolve => {
|
|
this._setInitialTargetId = resolve;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @param {number} id
|
|
* @param {?Object} arg
|
|
*/
|
|
embedderMessageAck(id, arg) {
|
|
const callback = this._callbacks[id];
|
|
delete this._callbacks[id];
|
|
if (callback) {
|
|
callback(arg);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {string} method
|
|
* @param {!Array.<*>} args
|
|
* @param {?function(?Object)} callback
|
|
*/
|
|
sendMessageToEmbedder(method, args, callback) {
|
|
const callId = ++this._lastCallId;
|
|
if (callback) {
|
|
this._callbacks[callId] = callback;
|
|
}
|
|
const message = {id: callId, method};
|
|
if (args.length) {
|
|
message.params = args;
|
|
}
|
|
DevToolsHost.sendMessageToEmbedder(JSON.stringify(message));
|
|
}
|
|
|
|
/**
|
|
* @param {string} method
|
|
* @param {!Array<*>} args
|
|
*/
|
|
_dispatchOnInspectorFrontendAPI(method, args) {
|
|
const inspectorFrontendAPI = /** @type {!Object<string, function()>} */ (window['InspectorFrontendAPI']);
|
|
if (!inspectorFrontendAPI) {
|
|
// This is the case for device_mode_emulation_frame entrypoint. It's created via `window.open` from
|
|
// the DevTools window, so it shares a context with DevTools but has a separate DevToolsUIBinding and `window` object.
|
|
// We can safely ignore the events since they also arrive on the DevTools `window` object.
|
|
return;
|
|
}
|
|
inspectorFrontendAPI[method].apply(inspectorFrontendAPI, args);
|
|
}
|
|
|
|
// API methods below this line --------------------------------------------
|
|
|
|
/**
|
|
* @param {!Array.<!ExtensionDescriptor>} extensions
|
|
*/
|
|
addExtensions(extensions) {
|
|
// Support for legacy front-ends (<M41).
|
|
if (window['WebInspector'] && window['WebInspector']['addExtensions']) {
|
|
window['WebInspector']['addExtensions'](extensions);
|
|
// The addExtensions command is sent as the onload event happens for
|
|
// DevTools front-end. We should buffer this command until the frontend
|
|
// is ready for it.
|
|
} else if (this._addExtensionCallback) {
|
|
extensions.forEach(this._addExtensionCallback);
|
|
} else {
|
|
this._pendingExtensionDescriptors.push(...extensions);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {!Array<string>} forbiddenOrigins
|
|
*/
|
|
setOriginsForbiddenForExtensions(forbiddenOrigins) {
|
|
this._originsForbiddenForExtensions = forbiddenOrigins;
|
|
}
|
|
|
|
/**
|
|
* @return {!Array<string>}
|
|
*/
|
|
getOriginsForbiddenForExtensions() {
|
|
return this._originsForbiddenForExtensions;
|
|
}
|
|
|
|
/**
|
|
* @param {string} url
|
|
*/
|
|
appendedToURL(url) {
|
|
this._dispatchOnInspectorFrontendAPI('appendedToURL', [url]);
|
|
}
|
|
|
|
/**
|
|
* @param {string} url
|
|
*/
|
|
canceledSaveURL(url) {
|
|
this._dispatchOnInspectorFrontendAPI('canceledSaveURL', [url]);
|
|
}
|
|
|
|
contextMenuCleared() {
|
|
this._dispatchOnInspectorFrontendAPI('contextMenuCleared', []);
|
|
}
|
|
|
|
/**
|
|
* @param {string} id
|
|
*/
|
|
contextMenuItemSelected(id) {
|
|
this._dispatchOnInspectorFrontendAPI('contextMenuItemSelected', [id]);
|
|
}
|
|
|
|
/**
|
|
* @param {number} count
|
|
*/
|
|
deviceCountUpdated(count) {
|
|
this._dispatchOnInspectorFrontendAPI('deviceCountUpdated', [count]);
|
|
}
|
|
|
|
/**
|
|
* @param {!Adb.Config} config
|
|
*/
|
|
devicesDiscoveryConfigChanged(config) {
|
|
this._dispatchOnInspectorFrontendAPI('devicesDiscoveryConfigChanged', [config]);
|
|
}
|
|
|
|
/**
|
|
* @param {!Adb.PortForwardingStatus} status
|
|
*/
|
|
devicesPortForwardingStatusChanged(status) {
|
|
this._dispatchOnInspectorFrontendAPI('devicesPortForwardingStatusChanged', [status]);
|
|
}
|
|
|
|
/**
|
|
* @param {!Array.<!Adb.Device>} devices
|
|
*/
|
|
devicesUpdated(devices) {
|
|
this._dispatchOnInspectorFrontendAPI('devicesUpdated', [devices]);
|
|
}
|
|
|
|
/**
|
|
* @param {string} message
|
|
*/
|
|
dispatchMessage(message) {
|
|
this._dispatchOnInspectorFrontendAPI('dispatchMessage', [message]);
|
|
}
|
|
|
|
/**
|
|
* @param {string} messageChunk
|
|
* @param {number} messageSize
|
|
*/
|
|
dispatchMessageChunk(messageChunk, messageSize) {
|
|
this._dispatchOnInspectorFrontendAPI('dispatchMessageChunk', [messageChunk, messageSize]);
|
|
}
|
|
|
|
enterInspectElementMode() {
|
|
this._dispatchOnInspectorFrontendAPI('enterInspectElementMode', []);
|
|
}
|
|
|
|
/**
|
|
* @param {!{r: number, g: number, b: number, a: number}} color
|
|
*/
|
|
eyeDropperPickedColor(color) {
|
|
this._dispatchOnInspectorFrontendAPI('eyeDropperPickedColor', [color]);
|
|
}
|
|
|
|
/**
|
|
* @param {!Array.<!{fileSystemName: string, rootURL: string, fileSystemPath: string}>} fileSystems
|
|
*/
|
|
fileSystemsLoaded(fileSystems) {
|
|
this._dispatchOnInspectorFrontendAPI('fileSystemsLoaded', [fileSystems]);
|
|
}
|
|
|
|
/**
|
|
* @param {string} fileSystemPath
|
|
*/
|
|
fileSystemRemoved(fileSystemPath) {
|
|
this._dispatchOnInspectorFrontendAPI('fileSystemRemoved', [fileSystemPath]);
|
|
}
|
|
|
|
/**
|
|
* @param {?string} error
|
|
* @param {?{type: string, fileSystemName: string, rootURL: string, fileSystemPath: string}} fileSystem
|
|
*/
|
|
fileSystemAdded(error, fileSystem) {
|
|
this._dispatchOnInspectorFrontendAPI('fileSystemAdded', [error, fileSystem]);
|
|
}
|
|
|
|
/**
|
|
* @param {!Array<string>} changedPaths
|
|
* @param {!Array<string>} addedPaths
|
|
* @param {!Array<string>} removedPaths
|
|
*/
|
|
fileSystemFilesChangedAddedRemoved(changedPaths, addedPaths, removedPaths) {
|
|
// Support for legacy front-ends (<M58)
|
|
if (window['InspectorFrontendAPI'] && window['InspectorFrontendAPI']['fileSystemFilesChanged']) {
|
|
this._dispatchOnInspectorFrontendAPI(
|
|
'fileSystemFilesChanged', [changedPaths.concat(addedPaths).concat(removedPaths)]);
|
|
} else {
|
|
this._dispatchOnInspectorFrontendAPI(
|
|
'fileSystemFilesChangedAddedRemoved', [changedPaths, addedPaths, removedPaths]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {number} requestId
|
|
* @param {string} fileSystemPath
|
|
* @param {number} totalWork
|
|
*/
|
|
indexingTotalWorkCalculated(requestId, fileSystemPath, totalWork) {
|
|
this._dispatchOnInspectorFrontendAPI('indexingTotalWorkCalculated', [requestId, fileSystemPath, totalWork]);
|
|
}
|
|
|
|
/**
|
|
* @param {number} requestId
|
|
* @param {string} fileSystemPath
|
|
* @param {number} worked
|
|
*/
|
|
indexingWorked(requestId, fileSystemPath, worked) {
|
|
this._dispatchOnInspectorFrontendAPI('indexingWorked', [requestId, fileSystemPath, worked]);
|
|
}
|
|
|
|
/**
|
|
* @param {number} requestId
|
|
* @param {string} fileSystemPath
|
|
*/
|
|
indexingDone(requestId, fileSystemPath) {
|
|
this._dispatchOnInspectorFrontendAPI('indexingDone', [requestId, fileSystemPath]);
|
|
}
|
|
|
|
/**
|
|
* @param {{type: string, key: string, code: string, keyCode: number, modifiers: number}} event
|
|
*/
|
|
keyEventUnhandled(event) {
|
|
event.keyIdentifier = keyCodeToKeyIdentifier(event.keyCode);
|
|
this._dispatchOnInspectorFrontendAPI('keyEventUnhandled', [event]);
|
|
}
|
|
|
|
/**
|
|
* @param {function(!ExtensionDescriptor)} callback
|
|
*/
|
|
setAddExtensionCallback(callback) {
|
|
this._addExtensionCallback = callback;
|
|
if (this._pendingExtensionDescriptors.length) {
|
|
this._pendingExtensionDescriptors.forEach(this._addExtensionCallback);
|
|
this._pendingExtensionDescriptors = [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {boolean} hard
|
|
*/
|
|
reloadInspectedPage(hard) {
|
|
this._dispatchOnInspectorFrontendAPI('reloadInspectedPage', [hard]);
|
|
}
|
|
|
|
/**
|
|
* @param {string} url
|
|
* @param {number} lineNumber
|
|
* @param {number} columnNumber
|
|
*/
|
|
revealSourceLine(url, lineNumber, columnNumber) {
|
|
this._dispatchOnInspectorFrontendAPI('revealSourceLine', [url, lineNumber, columnNumber]);
|
|
}
|
|
|
|
/**
|
|
* @param {string} url
|
|
* @param {string=} fileSystemPath
|
|
*/
|
|
savedURL(url, fileSystemPath) {
|
|
this._dispatchOnInspectorFrontendAPI('savedURL', [url, fileSystemPath]);
|
|
}
|
|
|
|
/**
|
|
* @param {number} requestId
|
|
* @param {string} fileSystemPath
|
|
* @param {!Array.<string>} files
|
|
*/
|
|
searchCompleted(requestId, fileSystemPath, files) {
|
|
this._dispatchOnInspectorFrontendAPI('searchCompleted', [requestId, fileSystemPath, files]);
|
|
}
|
|
|
|
colorThemeChanged() {
|
|
this._dispatchOnInspectorFrontendAPI('colorThemeChanged', []);
|
|
}
|
|
|
|
/**
|
|
* @param {string} tabId
|
|
*/
|
|
setInspectedTabId(tabId) {
|
|
this._inspectedTabIdValue = tabId;
|
|
|
|
// Support for legacy front-ends (<M41).
|
|
if (window['WebInspector'] && window['WebInspector']['setInspectedTabId']) {
|
|
window['WebInspector']['setInspectedTabId'](tabId);
|
|
} else {
|
|
this._dispatchOnInspectorFrontendAPI('setInspectedTabId', [tabId]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {string} targetId
|
|
*/
|
|
setInitialTargetId(targetId) {
|
|
this._setInitialTargetId(targetId);
|
|
}
|
|
|
|
/**
|
|
* @return {string|undefined}
|
|
*/
|
|
getInspectedTabId() {
|
|
return this._inspectedTabIdValue;
|
|
}
|
|
|
|
/**
|
|
* @param {boolean} useSoftMenu
|
|
*/
|
|
setUseSoftMenu(useSoftMenu) {
|
|
this._dispatchOnInspectorFrontendAPI('setUseSoftMenu', [useSoftMenu]);
|
|
}
|
|
|
|
/**
|
|
* @param {string} panelName
|
|
*/
|
|
showPanel(panelName) {
|
|
this._dispatchOnInspectorFrontendAPI('showPanel', [panelName]);
|
|
}
|
|
|
|
/**
|
|
* @param {number} id
|
|
* @param {string} chunk
|
|
* @param {boolean} encoded
|
|
*/
|
|
streamWrite(id, chunk, encoded) {
|
|
this._dispatchOnInspectorFrontendAPI('streamWrite', [id, encoded ? this._decodeBase64(chunk) : chunk]);
|
|
}
|
|
|
|
/**
|
|
* @param {string} chunk
|
|
* @return {string}
|
|
*/
|
|
_decodeBase64(chunk) {
|
|
const request = new XMLHttpRequest();
|
|
request.open('GET', 'data:text/plain;base64,' + chunk, false);
|
|
request.send(null);
|
|
if (request.status === 200) {
|
|
return request.responseText;
|
|
}
|
|
console.error('Error while decoding chunk in streamWrite');
|
|
return '';
|
|
}
|
|
};
|
|
|
|
const DevToolsAPI = new DevToolsAPIImpl();
|
|
window.DevToolsAPI = DevToolsAPI;
|
|
|
|
// InspectorFrontendHostImpl --------------------------------------------------
|
|
|
|
/**
|
|
* Enum for recordPerformanceHistogram
|
|
* Warning: There is another definition of this enum in the DevTools code
|
|
* base, keep them in sync:
|
|
* front_end/core/host/InspectorFrontendHostAPI.ts
|
|
* @readonly
|
|
* @enum {string}
|
|
*/
|
|
const EnumeratedHistogram = {
|
|
// LINT.IfChange(EnumeratedHistogram)
|
|
ActionTaken: 'DevTools.ActionTaken',
|
|
CSSHintShown: 'DevTools.CSSHintShown',
|
|
DeveloperResourceLoaded: 'DevTools.DeveloperResourceLoaded',
|
|
DeveloperResourceScheme: 'DevTools.DeveloperResourceScheme',
|
|
ExperimentDisabled: 'DevTools.ExperimentDisabled',
|
|
ExperimentDisabledAtLaunch: 'DevTools.ExperimentDisabledAtLaunch',
|
|
ExperimentEnabled: 'DevTools.ExperimentEnabled',
|
|
ExperimentEnabledAtLaunch: 'DevTools.ExperimentEnabledAtLaunch',
|
|
IssueCreated: 'DevTools.IssueCreated',
|
|
IssuesPanelIssueExpanded: 'DevTools.IssuesPanelIssueExpanded',
|
|
IssuesPanelOpenedFrom: 'DevTools.IssuesPanelOpenedFrom',
|
|
IssuesPanelResourceOpened: 'DevTools.IssuesPanelResourceOpened',
|
|
KeybindSetSettingChanged: 'DevTools.KeybindSetSettingChanged',
|
|
KeyboardShortcutFired: 'DevTools.KeyboardShortcutFired',
|
|
Language: 'DevTools.Language',
|
|
LighthouseModeRun: 'DevTools.LighthouseModeRun',
|
|
LighthouseCategoryUsed: 'DevTools.LighthouseCategoryUsed',
|
|
PanelShown: 'DevTools.PanelShown',
|
|
PanelShownInLocation: 'DevTools.PanelShownInLocation',
|
|
RecordingAssertion: 'DevTools.RecordingAssertion',
|
|
RecordingCodeToggled: 'DevTools.RecordingCodeToggled',
|
|
RecordingCopiedToClipboard: 'DevTools.RecordingCopiedToClipboard',
|
|
RecordingEdited: 'DevTools.RecordingEdited',
|
|
RecordingExported: 'DevTools.RecordingExported',
|
|
RecordingReplayFinished: 'DevTools.RecordingReplayFinished',
|
|
RecordingReplaySpeed: 'DevTools.RecordingReplaySpeed',
|
|
RecordingReplayStarted: 'DevTools.RecordingReplayStarted',
|
|
RecordingToggled: 'DevTools.RecordingToggled',
|
|
SidebarPaneShown: 'DevTools.SidebarPaneShown',
|
|
SourcesPanelFileDebugged: 'DevTools.SourcesPanelFileDebugged',
|
|
SourcesPanelFileOpened: 'DevTools.SourcesPanelFileOpened',
|
|
NetworkPanelResponsePreviewOpened: 'DevTools.NetworkPanelResponsePreviewOpened',
|
|
TimelineNavigationSettingState: 'DevTools.TimelineNavigationSettingState',
|
|
SyncSetting: 'DevTools.SyncSetting',
|
|
SwatchActivated: 'DevTools.SwatchActivated',
|
|
AnimationPlaybackRateChanged: 'DevTools.AnimationPlaybackRateChanged',
|
|
AnimationPointDragged: 'DevTools.AnimationPointDragged',
|
|
// LINT.ThenChange(/front_end/core/host/InspectorFrontendHostAPI.ts:EnumeratedHistogram)
|
|
};
|
|
|
|
/**
|
|
* @implements {InspectorFrontendHostAPI}
|
|
*/
|
|
const InspectorFrontendHostImpl = class {
|
|
/**
|
|
* @return {string}
|
|
*/
|
|
getSelectionBackgroundColor() {
|
|
return '#6e86ff';
|
|
}
|
|
|
|
/**
|
|
* @return {string}
|
|
*/
|
|
getSelectionForegroundColor() {
|
|
return '#ffffff';
|
|
}
|
|
|
|
/**
|
|
* @return {string}
|
|
*/
|
|
getInactiveSelectionBackgroundColor() {
|
|
return '#c9c8c8';
|
|
}
|
|
|
|
/**
|
|
* @return {string}
|
|
*/
|
|
getInactiveSelectionForegroundColor() {
|
|
return '#323232';
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @return {string}
|
|
*/
|
|
platform() {
|
|
return DevToolsHost.platform();
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
loadCompleted() {
|
|
DevToolsAPI.sendMessageToEmbedder('loadCompleted', [], null);
|
|
// Support for legacy (<57) frontends.
|
|
if (window.Runtime && window.Runtime.queryParam) {
|
|
const panelToOpen = window.Runtime.queryParam('panel');
|
|
if (panelToOpen) {
|
|
window.DevToolsAPI.showPanel(panelToOpen);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
bringToFront() {
|
|
DevToolsAPI.sendMessageToEmbedder('bringToFront', [], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
closeWindow() {
|
|
DevToolsAPI.sendMessageToEmbedder('closeWindow', [], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {boolean} isDocked
|
|
* @param {function()} callback
|
|
*/
|
|
setIsDocked(isDocked, callback) {
|
|
DevToolsAPI.sendMessageToEmbedder('setIsDocked', [isDocked], callback);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} trigger
|
|
* @param {function(!InspectorFrontendHostAPI.ShowSurveyResult): void} callback
|
|
*/
|
|
showSurvey(trigger, callback) {
|
|
DevToolsAPI.sendMessageToEmbedder('showSurvey', [trigger], /** @type {function(?Object)} */ (callback));
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} trigger
|
|
* @param {function(!InspectorFrontendHostAPI.CanShowSurveyResult): void} callback
|
|
*/
|
|
canShowSurvey(trigger, callback) {
|
|
DevToolsAPI.sendMessageToEmbedder('canShowSurvey', [trigger], /** @type {function(?Object)} */ (callback));
|
|
}
|
|
|
|
/**
|
|
* Requests inspected page to be placed atop of the inspector frontend with specified bounds.
|
|
* @override
|
|
* @param {{x: number, y: number, width: number, height: number}} bounds
|
|
*/
|
|
setInspectedPageBounds(bounds) {
|
|
DevToolsAPI.sendMessageToEmbedder('setInspectedPageBounds', [bounds], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
inspectElementCompleted() {
|
|
DevToolsAPI.sendMessageToEmbedder('inspectElementCompleted', [], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} url
|
|
* @param {string} headers
|
|
* @param {number} streamId
|
|
* @param {function(!InspectorFrontendHostAPI.LoadNetworkResourceResult): void} callback
|
|
*/
|
|
loadNetworkResource(url, headers, streamId, callback) {
|
|
DevToolsAPI.sendMessageToEmbedder(
|
|
'loadNetworkResource', [url, headers, streamId], /** @type {function(?Object)} */ (callback));
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} name
|
|
* @param {!{synced: (boolean|undefined)}} options
|
|
*/
|
|
registerPreference(name, options) {
|
|
DevToolsAPI.sendMessageToEmbedder('registerPreference', [name, options], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {function(!Object<string, string>)} callback
|
|
*/
|
|
getPreferences(callback) {
|
|
DevToolsAPI.sendMessageToEmbedder('getPreferences', [], /** @type {function(?Object)} */ (callback));
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} name
|
|
* @param {function(string)} callback
|
|
*/
|
|
getPreference(name, callback) {
|
|
DevToolsAPI.sendMessageToEmbedder('getPreference', [name], /** @type {function(string)} */ (callback));
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} name
|
|
* @param {string} value
|
|
*/
|
|
setPreference(name, value) {
|
|
DevToolsAPI.sendMessageToEmbedder('setPreference', [name, value], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} name
|
|
*/
|
|
removePreference(name) {
|
|
DevToolsAPI.sendMessageToEmbedder('removePreference', [name], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
clearPreferences() {
|
|
DevToolsAPI.sendMessageToEmbedder('clearPreferences', [], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {!function(!InspectorFrontendHostAPI.SyncInformation):void} callback
|
|
*/
|
|
getSyncInformation(callback) {
|
|
DevToolsAPI.sendMessageToEmbedder('getSyncInformation', [], callback);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {function(Object<string, Object<string, string|boolean>>):void} callback
|
|
*/
|
|
getHostConfig(callback) {
|
|
DevToolsAPI.sendMessageToEmbedder('getHostConfig', [], hostConfig => {
|
|
const majorVersion = getRemoteMajorVersion();
|
|
if (majorVersion && majorVersion < 129 && hostConfig?.aidaAvailability) {
|
|
return callback(this.hostConfigNewToOld(hostConfig));
|
|
}
|
|
return callback(hostConfig);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @param {Object<string, Object<string, string|boolean>>} newConfig
|
|
*/
|
|
hostConfigNewToOld(newConfig) {
|
|
const devToolsConsoleInsights = {
|
|
enabled: (newConfig.devToolsConsoleInsights?.enabled && newConfig.aidaAvailability?.enabled) ?? false,
|
|
aidaModelId: newConfig.devToolsConsoleInsights?.modelId ?? '',
|
|
aidaTemperature: newConfig.devToolsConsoleInsights?.temperature ?? 0,
|
|
blockedByAge: newConfig.aidaAvailability?.blockedByAge ?? true,
|
|
blockedByEnterprisePolicy: newConfig.aidaAvailability?.blockedByEnterprisePolicy ?? true,
|
|
blockedByFeatureFlag:
|
|
(newConfig.devToolsConsoleInsights?.enabled && newConfig.aidaAvailability?.enabled) ?? false,
|
|
blockedByGeo: newConfig.aidaAvailability?.blockedByGeo ?? true,
|
|
blockedByRollout: false,
|
|
disallowLogging: newConfig.aidaAvailability?.disallowLogging ?? true,
|
|
optIn: false,
|
|
};
|
|
const devToolsFreestylerDogfood = {
|
|
enabled: (newConfig.devToolsFreestyler?.enabled && newConfig.aidaAvailability?.enabled) ?? false,
|
|
aidaModelId: newConfig.devToolsFreestyler?.modelId ?? '',
|
|
aidaTemperature: newConfig.devToolsFreestyler?.temperature ?? 0,
|
|
blockedByAge: newConfig.aidaAvailability?.blockedByAge ?? true,
|
|
blockedByEnterprisePolicy: newConfig.aidaAvailability?.blockedByEnterprisePolicy ?? true,
|
|
blockedByGeo: newConfig.aidaAvailability?.blockedByGeo ?? true,
|
|
};
|
|
return {
|
|
devToolsConsoleInsights,
|
|
devToolsFreestylerDogfood,
|
|
devToolsVeLogging: newConfig.devToolsVeLogging,
|
|
isOffTheRecord: newConfig.isOffTheRecord,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} origin
|
|
* @param {string} script
|
|
*/
|
|
setInjectedScriptForOrigin(origin, script) {
|
|
DevToolsAPI.sendMessageToEmbedder('registerExtensionsAPI', [origin, script], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} url
|
|
*/
|
|
inspectedURLChanged(url) {
|
|
DevToolsAPI.sendMessageToEmbedder('inspectedURLChanged', [url], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} text
|
|
*/
|
|
copyText(text) {
|
|
DevToolsHost.copyText(text);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} url
|
|
*/
|
|
openInNewTab(url) {
|
|
DevToolsAPI.sendMessageToEmbedder('openInNewTab', [url], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} query
|
|
*/
|
|
openSearchResultsInNewTab(query) {
|
|
DevToolsAPI.sendMessageToEmbedder('openSearchResultsInNewTab', [query], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} fileSystemPath
|
|
*/
|
|
showItemInFolder(fileSystemPath) {
|
|
DevToolsAPI.sendMessageToEmbedder('showItemInFolder', [fileSystemPath], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} url
|
|
* @param {string} content
|
|
* @param {boolean} forceSaveAs
|
|
* @param {boolean} isBase64
|
|
*/
|
|
save(url, content, forceSaveAs, isBase64) {
|
|
DevToolsAPI.sendMessageToEmbedder('save', [url, content, forceSaveAs, isBase64], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} url
|
|
* @param {string} content
|
|
*/
|
|
append(url, content) {
|
|
DevToolsAPI.sendMessageToEmbedder('append', [url, content], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} url
|
|
*/
|
|
close(url) {
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} message
|
|
*/
|
|
sendMessageToBackend(message) {
|
|
DevToolsAPI.sendMessageToEmbedder('dispatchProtocolMessage', [message], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} histogramName
|
|
* @param {number} sample
|
|
* @param {number} min
|
|
* @param {number} exclusiveMax
|
|
* @param {number} bucketSize
|
|
*/
|
|
recordCountHistogram(histogramName, sample, min, exclusiveMax, bucketSize) {
|
|
DevToolsAPI.sendMessageToEmbedder(
|
|
'recordCountHistogram', [histogramName, sample, min, exclusiveMax, bucketSize], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {!InspectorFrontendHostAPI.EnumeratedHistogram} actionName
|
|
* @param {number} actionCode
|
|
* @param {number} bucketSize
|
|
*/
|
|
recordEnumeratedHistogram(actionName, actionCode, bucketSize) {
|
|
if (!Object.values(EnumeratedHistogram).includes(actionName)) {
|
|
return;
|
|
}
|
|
DevToolsAPI.sendMessageToEmbedder('recordEnumeratedHistogram', [actionName, actionCode, bucketSize], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} histogramName
|
|
* @param {number} duration
|
|
*/
|
|
recordPerformanceHistogram(histogramName, duration) {
|
|
DevToolsAPI.sendMessageToEmbedder('recordPerformanceHistogram', [histogramName, duration], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} umaName
|
|
*/
|
|
recordUserMetricsAction(umaName) {
|
|
DevToolsAPI.sendMessageToEmbedder('recordUserMetricsAction', [umaName], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
connectAutomaticFileSystem(fileSystemPath, fileSystemUUID, addIfMissing, callback) {
|
|
DevToolsAPI.sendMessageToEmbedder(
|
|
'connectAutomaticFileSystem',
|
|
[fileSystemPath, fileSystemUUID, addIfMissing],
|
|
callback,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
disconnectAutomaticFileSystem(fileSystemPath) {
|
|
DevToolsAPI.sendMessageToEmbedder(
|
|
'disconnectAutomaticFileSystem',
|
|
[fileSystemPath],
|
|
null,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
requestFileSystems() {
|
|
DevToolsAPI.sendMessageToEmbedder('requestFileSystems', [], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string=} type
|
|
*/
|
|
addFileSystem(type) {
|
|
DevToolsAPI.sendMessageToEmbedder('addFileSystem', [type || ''], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} fileSystemPath
|
|
*/
|
|
removeFileSystem(fileSystemPath) {
|
|
DevToolsAPI.sendMessageToEmbedder('removeFileSystem', [fileSystemPath], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} fileSystemId
|
|
* @param {string} registeredName
|
|
* @return {?FileSystem}
|
|
*/
|
|
isolatedFileSystem(fileSystemId, registeredName) {
|
|
return DevToolsHost.isolatedFileSystem(fileSystemId, registeredName);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {!FileSystem} fileSystem
|
|
*/
|
|
upgradeDraggedFileSystemPermissions(fileSystem) {
|
|
DevToolsHost.upgradeDraggedFileSystemPermissions(fileSystem);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {number} requestId
|
|
* @param {string} fileSystemPath
|
|
* @param {string} excludedFolders
|
|
*/
|
|
indexPath(requestId, fileSystemPath, excludedFolders) {
|
|
// |excludedFolders| added in M67. For backward compatibility,
|
|
// pass empty array.
|
|
excludedFolders = excludedFolders || '[]';
|
|
DevToolsAPI.sendMessageToEmbedder('indexPath', [requestId, fileSystemPath, excludedFolders], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {number} requestId
|
|
*/
|
|
stopIndexing(requestId) {
|
|
DevToolsAPI.sendMessageToEmbedder('stopIndexing', [requestId], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {number} requestId
|
|
* @param {string} fileSystemPath
|
|
* @param {string} query
|
|
*/
|
|
searchInPath(requestId, fileSystemPath, query) {
|
|
DevToolsAPI.sendMessageToEmbedder('searchInPath', [requestId, fileSystemPath, query], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @return {number}
|
|
*/
|
|
zoomFactor() {
|
|
return DevToolsHost.zoomFactor();
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
zoomIn() {
|
|
DevToolsAPI.sendMessageToEmbedder('zoomIn', [], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
zoomOut() {
|
|
DevToolsAPI.sendMessageToEmbedder('zoomOut', [], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
resetZoom() {
|
|
DevToolsAPI.sendMessageToEmbedder('resetZoom', [], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} shortcuts
|
|
*/
|
|
setWhitelistedShortcuts(shortcuts) {
|
|
DevToolsAPI.sendMessageToEmbedder('setWhitelistedShortcuts', [shortcuts], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {boolean} active
|
|
*/
|
|
setEyeDropperActive(active) {
|
|
DevToolsAPI.sendMessageToEmbedder('setEyeDropperActive', [active], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {!Array<string>} certChain
|
|
*/
|
|
showCertificateViewer(certChain) {
|
|
DevToolsAPI.sendMessageToEmbedder('showCertificateViewer', [JSON.stringify(certChain)], null);
|
|
}
|
|
|
|
/**
|
|
* Only needed to run Lighthouse on old devtools.
|
|
* @override
|
|
* @param {function()} callback
|
|
*/
|
|
reattach(callback) {
|
|
DevToolsAPI.sendMessageToEmbedder('reattach', [], callback);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
readyForTest() {
|
|
DevToolsAPI.sendMessageToEmbedder('readyForTest', [], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
connectionReady() {
|
|
DevToolsAPI.sendMessageToEmbedder('connectionReady', [], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {boolean} value
|
|
*/
|
|
setOpenNewWindowForPopups(value) {
|
|
DevToolsAPI.sendMessageToEmbedder('setOpenNewWindowForPopups', [value], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {!Adb.Config} config
|
|
*/
|
|
setDevicesDiscoveryConfig(config) {
|
|
DevToolsAPI.sendMessageToEmbedder(
|
|
'setDevicesDiscoveryConfig',
|
|
[
|
|
config.discoverUsbDevices, config.portForwardingEnabled, JSON.stringify(config.portForwardingConfig),
|
|
config.networkDiscoveryEnabled, JSON.stringify(config.networkDiscoveryConfig)
|
|
],
|
|
null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {boolean} enabled
|
|
*/
|
|
setDevicesUpdatesEnabled(enabled) {
|
|
DevToolsAPI.sendMessageToEmbedder('setDevicesUpdatesEnabled', [enabled], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} browserId
|
|
* @param {string} url
|
|
*/
|
|
openRemotePage(browserId, url) {
|
|
DevToolsAPI.sendMessageToEmbedder('openRemotePage', [browserId, url], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
openNodeFrontend() {
|
|
DevToolsAPI.sendMessageToEmbedder('openNodeFrontend', [], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {number} x
|
|
* @param {number} y
|
|
* @param {!Array.<!InspectorFrontendHostAPI.ContextMenuDescriptor>} items
|
|
* @param {!Document} document
|
|
*/
|
|
showContextMenuAtPoint(x, y, items, document) {
|
|
DevToolsHost.showContextMenuAtPoint(x, y, items, document);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @return {boolean}
|
|
*/
|
|
isHostedMode() {
|
|
return DevToolsHost.isHostedMode();
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {function(!ExtensionDescriptor)} callback
|
|
*/
|
|
setAddExtensionCallback(callback) {
|
|
DevToolsAPI.setAddExtensionCallback(callback);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {InspectorFrontendHostAPI.ImpressionEvent} impressionEvent
|
|
*/
|
|
recordImpression(impressionEvent) {
|
|
DevToolsAPI.sendMessageToEmbedder('recordImpression', [impressionEvent], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {InspectorFrontendHostAPI.ResizeEvent} resizeEvent
|
|
*/
|
|
recordResize(resizeEvent) {
|
|
DevToolsAPI.sendMessageToEmbedder('recordResize', [resizeEvent], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {InspectorFrontendHostAPI.ClickEvent} clickEvent
|
|
*/
|
|
recordClick(clickEvent) {
|
|
DevToolsAPI.sendMessageToEmbedder('recordClick', [clickEvent], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {InspectorFrontendHostAPI.HoverEvent} hoverEvent
|
|
*/
|
|
recordHover(hoverEvent) {
|
|
DevToolsAPI.sendMessageToEmbedder('recordHover', [hoverEvent], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {InspectorFrontendHostAPI.DragEvent} dragEvent
|
|
*/
|
|
recordDrag(dragEvent) {
|
|
DevToolsAPI.sendMessageToEmbedder('recordDrag', [dragEvent], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {InspectorFrontendHostAPI.ChangeEvent} changeEvent
|
|
*/
|
|
recordChange(changeEvent) {
|
|
DevToolsAPI.sendMessageToEmbedder('recordChange', [changeEvent], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {InspectorFrontendHostAPI.KeyDownEvent} keyDownEvent
|
|
*/
|
|
recordKeyDown(keyDownEvent) {
|
|
DevToolsAPI.sendMessageToEmbedder('recordKeyDown', [keyDownEvent], null);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {InspectorFrontendHostAPI.SettingAccessEvent} settingAccessEvent
|
|
*/
|
|
recordSettingAccess(settingAccessEvent) {
|
|
DevToolsAPI.sendMessageToEmbedder('recordSettingAccess', [settingAccessEvent], null);
|
|
}
|
|
|
|
// Backward-compatible methods below this line --------------------------------------------
|
|
|
|
/**
|
|
* Support for legacy front-ends (<M65).
|
|
* @return {boolean}
|
|
*/
|
|
isUnderTest() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Support for legacy front-ends (<M50).
|
|
* @param {string} message
|
|
*/
|
|
sendFrontendAPINotification(message) {
|
|
}
|
|
|
|
/**
|
|
* Support for legacy front-ends (<M41).
|
|
* @return {string}
|
|
*/
|
|
port() {
|
|
return 'unknown';
|
|
}
|
|
|
|
/**
|
|
* Support for legacy front-ends (<M38).
|
|
* @param {number} zoomFactor
|
|
*/
|
|
setZoomFactor(zoomFactor) {
|
|
}
|
|
|
|
/**
|
|
* Support for legacy front-ends (<M34).
|
|
*/
|
|
sendMessageToEmbedder() {
|
|
}
|
|
|
|
/**
|
|
* Support for legacy front-ends (<M34).
|
|
* @param {string} dockSide
|
|
*/
|
|
requestSetDockSide(dockSide) {
|
|
DevToolsAPI.sendMessageToEmbedder('setIsDocked', [dockSide !== 'undocked'], null);
|
|
}
|
|
|
|
/**
|
|
* Support for legacy front-ends (<M34).
|
|
* @return {boolean}
|
|
*/
|
|
supportsFileSystems() {
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Support for legacy front-ends (<M44).
|
|
* @param {number} actionCode
|
|
*/
|
|
recordActionTaken(actionCode) {
|
|
// Do not record actions, as that may crash the DevTools renderer.
|
|
}
|
|
|
|
/**
|
|
* Support for legacy front-ends (<M44).
|
|
* @param {number} panelCode
|
|
*/
|
|
recordPanelShown(panelCode) {
|
|
// Do not record actions, as that may crash the DevTools renderer.
|
|
}
|
|
|
|
/**
|
|
* @return {!Promise<string>}
|
|
*/
|
|
initialTargetId() {
|
|
return DevToolsAPI._initialTargetIdPromise;
|
|
}
|
|
|
|
/**
|
|
* @param {string} request
|
|
* @param {number} streamId
|
|
* @param {function(!InspectorFrontendHostAPI.DoAidaConversationResult): void} cb
|
|
*/
|
|
doAidaConversation(request, streamId, cb) {
|
|
DevToolsAPI.sendMessageToEmbedder('doAidaConversation', [request, streamId], cb);
|
|
}
|
|
|
|
/**
|
|
* @param {string} request
|
|
* @param {function(!InspectorFrontendHostAPI.AidaClientResult): void} cb
|
|
*/
|
|
registerAidaClientEvent(request, cb) {
|
|
DevToolsAPI.sendMessageToEmbedder('registerAidaClientEvent', [request], cb);
|
|
}
|
|
};
|
|
|
|
window.InspectorFrontendHost = new InspectorFrontendHostImpl();
|
|
|
|
// DevToolsApp ---------------------------------------------------------------
|
|
|
|
function installObjectObserve() {
|
|
/** @type {!Array<string>} */
|
|
const properties = [
|
|
'advancedSearchConfig',
|
|
'auditsPanelSplitViewState',
|
|
'auditsSidebarWidth',
|
|
'blockedURLs',
|
|
'breakpoints',
|
|
'cacheDisabled',
|
|
'colorFormat',
|
|
'consoleHistory',
|
|
'consoleTimestampsEnabled',
|
|
'cpuProfilerView',
|
|
'cssSourceMapsEnabled',
|
|
'currentDockState',
|
|
'customColorPalette',
|
|
'customDevicePresets',
|
|
'customEmulatedDeviceList',
|
|
'customFormatters',
|
|
'customUserAgent',
|
|
'databaseTableViewVisibleColumns',
|
|
'dataGrid-cookiesTable',
|
|
'dataGrid-DOMStorageItemsView',
|
|
'debuggerSidebarHidden',
|
|
'disablePausedStateOverlay',
|
|
'domBreakpoints',
|
|
'domWordWrap',
|
|
'elementsPanelSplitViewState',
|
|
'elementsSidebarWidth',
|
|
'emulation.deviceHeight',
|
|
'emulation.deviceModeValue',
|
|
'emulation.deviceOrientationOverride',
|
|
'emulation.deviceScale',
|
|
'emulation.deviceScaleFactor',
|
|
'emulation.deviceUA',
|
|
'emulation.deviceWidth',
|
|
'emulation.locationOverride',
|
|
'emulation.showDeviceMode',
|
|
'emulation.showRulers',
|
|
'enableAsyncStackTraces',
|
|
'enableIgnoreListing',
|
|
'eventListenerBreakpoints',
|
|
'fileMappingEntries',
|
|
'fileSystemMapping',
|
|
'FileSystemViewSidebarWidth',
|
|
'fileSystemViewSplitViewState',
|
|
'filterBar-consoleView',
|
|
'filterBar-networkPanel',
|
|
'filterBar-promisePane',
|
|
'filterBar-timelinePanel',
|
|
'frameViewerHideChromeWindow',
|
|
'heapSnapshotRetainersViewSize',
|
|
'heapSnapshotSplitViewState',
|
|
'hideCollectedPromises',
|
|
'hideNetworkMessages',
|
|
'highlightNodeOnHoverInOverlay',
|
|
'inlineVariableValues',
|
|
'Inspector.drawerSplitView',
|
|
'Inspector.drawerSplitViewState',
|
|
'InspectorView.panelOrder',
|
|
'InspectorView.screencastSplitView',
|
|
'InspectorView.screencastSplitViewState',
|
|
'InspectorView.splitView',
|
|
'InspectorView.splitViewState',
|
|
'javaScriptDisabled',
|
|
'jsSourceMapsEnabled',
|
|
'lastActivePanel',
|
|
'lastDockState',
|
|
'lastSelectedSourcesSidebarPaneTab',
|
|
'lastSnippetEvaluationIndex',
|
|
'layerDetailsSplitView',
|
|
'layerDetailsSplitViewState',
|
|
'layersPanelSplitViewState',
|
|
'layersShowInternalLayers',
|
|
'layersSidebarWidth',
|
|
'messageLevelFilters',
|
|
'messageURLFilters',
|
|
'monitoringXHREnabled',
|
|
'navigatorGroupByAuthored',
|
|
'navigatorGroupByFolder',
|
|
'navigatorHidden',
|
|
'networkColorCodeResourceTypes',
|
|
'networkConditions',
|
|
'networkConditionsCustomProfiles',
|
|
'networkHideDataURL',
|
|
'networkLogColumnsVisibility',
|
|
'networkLogLargeRows',
|
|
'networkLogShowOverview',
|
|
'networkPanelSplitViewState',
|
|
'networkRecordFilmStripSetting',
|
|
'networkResourceTypeFilters',
|
|
'networkShowPrimaryLoadWaterfall',
|
|
'networkSidebarWidth',
|
|
'openLinkHandler',
|
|
'pauseOnUncaughtException',
|
|
'pauseOnCaughtException',
|
|
'pauseOnExceptionEnabled',
|
|
'preserveConsoleLog',
|
|
'prettyPrintInfobarDisabled',
|
|
'previouslyViewedFiles',
|
|
'profilesPanelSplitViewState',
|
|
'profilesSidebarWidth',
|
|
'promiseStatusFilters',
|
|
'recordAllocationStacks',
|
|
'requestHeaderFilterSetting',
|
|
'request-info-formData-category-expanded',
|
|
'request-info-general-category-expanded',
|
|
'request-info-queryString-category-expanded',
|
|
'request-info-requestHeaders-category-expanded',
|
|
'request-info-requestPayload-category-expanded',
|
|
'request-info-responseHeaders-category-expanded',
|
|
'resources',
|
|
'resourcesLastSelectedItem',
|
|
'resourcesPanelSplitViewState',
|
|
'resourcesSidebarWidth',
|
|
'resourceViewTab',
|
|
'savedURLs',
|
|
'screencastEnabled',
|
|
'scriptsPanelNavigatorSidebarWidth',
|
|
'searchInContentScripts',
|
|
'selectedAuditCategories',
|
|
'selectedColorPalette',
|
|
'selectedProfileType',
|
|
'shortcutPanelSwitch',
|
|
'showAdvancedHeapSnapshotProperties',
|
|
'showEventListenersForAncestors',
|
|
'showFrameowkrListeners',
|
|
'showHeaSnapshotObjectsHiddenProperties',
|
|
'showInheritedComputedStyleProperties',
|
|
'showMediaQueryInspector',
|
|
'showUAShadowDOM',
|
|
'showWhitespacesInEditor',
|
|
'sidebarPosition',
|
|
'skipContentScripts',
|
|
'automaticallyIgnoreListKnownThirdPartyScripts',
|
|
'skipStackFramesPattern',
|
|
'sourceMapInfobarDisabled',
|
|
'sourceMapSkippedInfobarDisabled',
|
|
'sourcesPanelDebuggerSidebarSplitViewState',
|
|
'sourcesPanelNavigatorSplitViewState',
|
|
'sourcesPanelSplitSidebarRatio',
|
|
'sourcesPanelSplitViewState',
|
|
'sourcesSidebarWidth',
|
|
'standardEmulatedDeviceList',
|
|
'StylesPaneSplitRatio',
|
|
'stylesPaneSplitViewState',
|
|
'textEditorAutocompletion',
|
|
'textEditorAutoDetectIndent',
|
|
'textEditorBracketMatching',
|
|
'textEditorIndent',
|
|
'textEditorTabMovesFocus',
|
|
'timelineCaptureFilmStrip',
|
|
'timelineCaptureLayersAndPictures',
|
|
'timelineCaptureMemory',
|
|
'timelineCaptureNetwork',
|
|
'timeline-details',
|
|
'timelineEnableJSSampling',
|
|
'timelineOverviewMode',
|
|
'timelinePanelDetailsSplitViewState',
|
|
'timelinePanelRecorsSplitViewState',
|
|
'timelinePanelTimelineStackSplitViewState',
|
|
'timelinePerspective',
|
|
'timeline-split',
|
|
'timelineTreeGroupBy',
|
|
'timeline-view',
|
|
'timelineViewMode',
|
|
'uiTheme',
|
|
'watchExpressions',
|
|
'WebInspector.Drawer.lastSelectedView',
|
|
'WebInspector.Drawer.showOnLoad',
|
|
'workspaceExcludedFolders',
|
|
'workspaceFolderExcludePattern',
|
|
'workspaceInfobarDisabled',
|
|
'workspaceMappingInfobarDisabled',
|
|
'xhrBreakpoints'
|
|
];
|
|
|
|
/**
|
|
* @this {!{_storage: Object, _name: string}}
|
|
*/
|
|
function settingRemove() {
|
|
this._storage[this._name] = undefined;
|
|
}
|
|
|
|
/**
|
|
* @param {!Object} object
|
|
* @param {function(!Array<!{name: string}>)} observer
|
|
*/
|
|
function objectObserve(object, observer) {
|
|
if (window['WebInspector']) {
|
|
const settingPrototype = /** @type {!Object} */ (window['WebInspector']['Setting']['prototype']);
|
|
if (typeof settingPrototype['remove'] === 'function') {
|
|
settingPrototype['remove'] = settingRemove;
|
|
}
|
|
}
|
|
/** @type {!Set<string>} */
|
|
const changedProperties = new Set();
|
|
let scheduled = false;
|
|
|
|
function scheduleObserver() {
|
|
if (scheduled) {
|
|
return;
|
|
}
|
|
scheduled = true;
|
|
queueMicrotask(callObserver);
|
|
}
|
|
|
|
function callObserver() {
|
|
scheduled = false;
|
|
const changes = /** @type {!Array<!{name: string}>} */ ([]);
|
|
changedProperties.forEach(function(name) {
|
|
changes.push({name});
|
|
});
|
|
changedProperties.clear();
|
|
observer.call(null, changes);
|
|
}
|
|
|
|
/** @type {!Map<string, *>} */
|
|
const storage = new Map();
|
|
|
|
/**
|
|
* @param {string} property
|
|
*/
|
|
function defineProperty(property) {
|
|
if (property in object) {
|
|
storage.set(property, object[property]);
|
|
delete object[property];
|
|
}
|
|
|
|
Object.defineProperty(object, property, {
|
|
/**
|
|
* @return {*}
|
|
*/
|
|
get: function() {
|
|
return storage.get(property);
|
|
},
|
|
|
|
/**
|
|
* @param {*} value
|
|
*/
|
|
set: function(value) {
|
|
storage.set(property, value);
|
|
changedProperties.add(property);
|
|
scheduleObserver();
|
|
}
|
|
});
|
|
}
|
|
|
|
for (let i = 0; i < properties.length; ++i) {
|
|
defineProperty(properties[i]);
|
|
}
|
|
}
|
|
|
|
window.Object.observe = objectObserve;
|
|
}
|
|
|
|
/** @type {!Map<number, string>} */
|
|
const staticKeyIdentifiers = new Map([
|
|
[0x12, 'Alt'],
|
|
[0x11, 'Control'],
|
|
[0x10, 'Shift'],
|
|
[0x14, 'CapsLock'],
|
|
[0x5b, 'Win'],
|
|
[0x5c, 'Win'],
|
|
[0x0c, 'Clear'],
|
|
[0x28, 'Down'],
|
|
[0x23, 'End'],
|
|
[0x0a, 'Enter'],
|
|
[0x0d, 'Enter'],
|
|
[0x2b, 'Execute'],
|
|
[0x70, 'F1'],
|
|
[0x71, 'F2'],
|
|
[0x72, 'F3'],
|
|
[0x73, 'F4'],
|
|
[0x74, 'F5'],
|
|
[0x75, 'F6'],
|
|
[0x76, 'F7'],
|
|
[0x77, 'F8'],
|
|
[0x78, 'F9'],
|
|
[0x79, 'F10'],
|
|
[0x7a, 'F11'],
|
|
[0x7b, 'F12'],
|
|
[0x7c, 'F13'],
|
|
[0x7d, 'F14'],
|
|
[0x7e, 'F15'],
|
|
[0x7f, 'F16'],
|
|
[0x80, 'F17'],
|
|
[0x81, 'F18'],
|
|
[0x82, 'F19'],
|
|
[0x83, 'F20'],
|
|
[0x84, 'F21'],
|
|
[0x85, 'F22'],
|
|
[0x86, 'F23'],
|
|
[0x87, 'F24'],
|
|
[0x2f, 'Help'],
|
|
[0x24, 'Home'],
|
|
[0x2d, 'Insert'],
|
|
[0x25, 'Left'],
|
|
[0x22, 'PageDown'],
|
|
[0x21, 'PageUp'],
|
|
[0x13, 'Pause'],
|
|
[0x2c, 'PrintScreen'],
|
|
[0x27, 'Right'],
|
|
[0x91, 'Scroll'],
|
|
[0x29, 'Select'],
|
|
[0x26, 'Up'],
|
|
[0x2e, 'U+007F'], // Standard says that DEL becomes U+007F.
|
|
[0xb0, 'MediaNextTrack'],
|
|
[0xb1, 'MediaPreviousTrack'],
|
|
[0xb2, 'MediaStop'],
|
|
[0xb3, 'MediaPlayPause'],
|
|
[0xad, 'VolumeMute'],
|
|
[0xae, 'VolumeDown'],
|
|
[0xaf, 'VolumeUp'],
|
|
]);
|
|
|
|
/**
|
|
* @param {number} keyCode
|
|
* @return {string}
|
|
*/
|
|
function keyCodeToKeyIdentifier(keyCode) {
|
|
let result = staticKeyIdentifiers.get(keyCode);
|
|
if (result !== undefined) {
|
|
return result;
|
|
}
|
|
result = 'U+';
|
|
const hexString = keyCode.toString(16).toUpperCase();
|
|
for (let i = hexString.length; i < 4; ++i) {
|
|
result += '0';
|
|
}
|
|
result += hexString;
|
|
return result;
|
|
}
|
|
|
|
function installBackwardsCompatibility() {
|
|
const majorVersion = getRemoteMajorVersion();
|
|
if (!majorVersion) {
|
|
return;
|
|
}
|
|
|
|
/** @type {!Array<string>} */
|
|
const styleRules = [];
|
|
// Shadow DOM V0 polyfill
|
|
if (majorVersion <= 73 && !Element.prototype.createShadowRoot) {
|
|
Element.prototype.createShadowRoot = function() {
|
|
try {
|
|
return this.attachShadow({mode: 'open'});
|
|
} catch {
|
|
// some elements we use to add shadow roots can no
|
|
// longer have shadow roots.
|
|
const fakeShadowHost = document.createElement('span');
|
|
this.appendChild(fakeShadowHost);
|
|
fakeShadowHost.className = 'fake-shadow-host';
|
|
return fakeShadowHost.createShadowRoot();
|
|
}
|
|
};
|
|
|
|
const origAdd = DOMTokenList.prototype.add;
|
|
DOMTokenList.prototype.add = function(...tokens) {
|
|
if (tokens[0].startsWith('insertion-point') || tokens[0].startsWith('tabbed-pane-header')) {
|
|
this._myElement.slot = '.' + tokens[0];
|
|
}
|
|
return origAdd.apply(this, tokens);
|
|
};
|
|
|
|
const origCreateElement = Document.prototype.createElement;
|
|
Document.prototype.createElement = function(tagName, ...rest) {
|
|
if (tagName === 'content') {
|
|
tagName = 'slot';
|
|
}
|
|
const element = origCreateElement.call(this, tagName, ...rest);
|
|
element.classList._myElement = element;
|
|
return element;
|
|
};
|
|
|
|
Object.defineProperty(HTMLSlotElement.prototype, 'select', {
|
|
set(selector) {
|
|
this.name = selector;
|
|
}
|
|
});
|
|
}
|
|
|
|
// Custom Elements V0 polyfill
|
|
if (majorVersion <= 73 && !Document.prototype.hasOwnProperty('registerElement')) {
|
|
const fakeRegistry = new Map();
|
|
Document.prototype.registerElement = function(typeExtension, options) {
|
|
const {prototype, extends: localName} = options;
|
|
const document = this;
|
|
const callback = function() {
|
|
const element = document.createElement(localName || typeExtension);
|
|
const skip = new Set(['constructor', '__proto__']);
|
|
for (const key of Object.keys(Object.getOwnPropertyDescriptors(prototype.__proto__ || {}))) {
|
|
if (skip.has(key)) {
|
|
continue;
|
|
}
|
|
element[key] = prototype[key];
|
|
}
|
|
element.setAttribute('is', typeExtension);
|
|
if (element['createdCallback']) {
|
|
element['createdCallback']();
|
|
}
|
|
return element;
|
|
};
|
|
fakeRegistry.set(typeExtension, callback);
|
|
return callback;
|
|
};
|
|
|
|
const origCreateElement = Document.prototype.createElement;
|
|
Document.prototype.createElement = function(tagName, fakeCustomElementType) {
|
|
const fakeConstructor = fakeRegistry.get(fakeCustomElementType);
|
|
if (fakeConstructor) {
|
|
return fakeConstructor();
|
|
}
|
|
return origCreateElement.call(this, tagName, fakeCustomElementType);
|
|
};
|
|
|
|
// DevTools front-ends mistakenly assume that
|
|
// classList.toggle('a', undefined) works as
|
|
// classList.toggle('a', false) rather than as
|
|
// classList.toggle('a');
|
|
const originalDOMTokenListToggle = DOMTokenList.prototype.toggle;
|
|
DOMTokenList.prototype.toggle = function(token, force) {
|
|
if (arguments.length === 1) {
|
|
force = !this.contains(token);
|
|
}
|
|
return originalDOMTokenListToggle.call(this, token, Boolean(force));
|
|
};
|
|
}
|
|
|
|
if (majorVersion <= 66) {
|
|
/** @type {(!function(number, number):Element|undefined)} */
|
|
ShadowRoot.prototype.__originalShadowRootElementFromPoint;
|
|
|
|
if (!ShadowRoot.prototype.__originalShadowRootElementFromPoint) {
|
|
ShadowRoot.prototype.__originalShadowRootElementFromPoint = ShadowRoot.prototype.elementFromPoint;
|
|
/**
|
|
* @param {number} x
|
|
* @param {number} y
|
|
* @return {Element}
|
|
*/
|
|
ShadowRoot.prototype.elementFromPoint = function(x, y) {
|
|
const originalResult = ShadowRoot.prototype.__originalShadowRootElementFromPoint.apply(this, arguments);
|
|
if (this.host && originalResult === this.host) {
|
|
return null;
|
|
}
|
|
return originalResult;
|
|
};
|
|
}
|
|
}
|
|
|
|
if (majorVersion <= 53) {
|
|
Object.defineProperty(window.KeyboardEvent.prototype, 'keyIdentifier', {
|
|
/**
|
|
* @return {string}
|
|
* @this {KeyboardEvent}
|
|
*/
|
|
get: function() {
|
|
return keyCodeToKeyIdentifier(this.keyCode);
|
|
}
|
|
});
|
|
}
|
|
|
|
if (majorVersion <= 50) {
|
|
installObjectObserve();
|
|
}
|
|
|
|
if (majorVersion <= 71) {
|
|
styleRules.push(
|
|
'.coverage-toolbar-container, .animation-timeline-toolbar-container, .computed-properties { flex-basis: auto; }');
|
|
}
|
|
|
|
if (majorVersion <= 50) {
|
|
Event.prototype.deepPath = undefined;
|
|
}
|
|
|
|
if (majorVersion <= 54) {
|
|
window.FileError = /** @type {!function (new: FileError) : ?} */ ({
|
|
NOT_FOUND_ERR: DOMException.NOT_FOUND_ERR,
|
|
ABORT_ERR: DOMException.ABORT_ERR,
|
|
INVALID_MODIFICATION_ERR: DOMException.INVALID_MODIFICATION_ERR,
|
|
NOT_READABLE_ERR: 0 // No matching DOMException, so code will be 0.
|
|
});
|
|
}
|
|
|
|
installExtraStyleRules(styleRules);
|
|
}
|
|
|
|
/**
|
|
* @return {?number}
|
|
*/
|
|
function getRemoteMajorVersion() {
|
|
try {
|
|
const remoteVersion = new URLSearchParams(window.location.search).get('remoteVersion');
|
|
if (!remoteVersion) {
|
|
return null;
|
|
}
|
|
const majorVersion = parseInt(remoteVersion.split('.')[0], 10);
|
|
return majorVersion;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {!Array<string>} styleRules
|
|
*/
|
|
function installExtraStyleRules(styleRules) {
|
|
if (!styleRules.length) {
|
|
return;
|
|
}
|
|
const styleText = styleRules.join('\n');
|
|
document.head.appendChild(createStyleElement(styleText));
|
|
|
|
const origCreateShadowRoot = HTMLElement.prototype.createShadowRoot;
|
|
HTMLElement.prototype.createShadowRoot = function(...args) {
|
|
const shadowRoot = origCreateShadowRoot.call(this, ...args);
|
|
shadowRoot.appendChild(createStyleElement(styleText));
|
|
return shadowRoot;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @param {string} styleText
|
|
* @return {!Element}
|
|
*/
|
|
function createStyleElement(styleText) {
|
|
const style = document.createElement('style');
|
|
style.textContent = styleText;
|
|
return style;
|
|
}
|
|
|
|
installBackwardsCompatibility();
|
|
})(window);
|