Add pencil buttons to initiate header override editing
Add a small button with a pencil icon next to each response header on
hover. Clicking this button does all of the following if necessary:
- Prompt the user for a folder to store overrides in
- Turn on the overrides setting
- Create a '.headers' file to store header overrides in
The user ends up in the same panel which shows the response headers,
only that they are now editable to create header overrides.
Video: https://i.imgur.com/nSqcwLj.mp4
Bug: 1297533
Change-Id: I974b3314b504ef69d041495f291dcdee39c4db4d
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/4003964
Auto-Submit: Wolfgang Beyer <[email protected]>
Reviewed-by: Danil Somsikov <[email protected]>
Commit-Queue: Wolfgang Beyer <[email protected]>
diff --git a/front_end/core/i18n/locales/en-US.json b/front_end/core/i18n/locales/en-US.json
index 8a66737..ca77a25 100644
--- a/front_end/core/i18n/locales/en-US.json
+++ b/front_end/core/i18n/locales/en-US.json
@@ -6872,6 +6872,9 @@
"panels/network/components/HeaderSectionRow.ts | decoded": {
"message": "Decoded:"
},
+ "panels/network/components/HeaderSectionRow.ts | editHeader": {
+ "message": "Override header"
+ },
"panels/network/components/HeaderSectionRow.ts | learnMore": {
"message": "Learn more"
},
diff --git a/front_end/core/i18n/locales/en-XL.json b/front_end/core/i18n/locales/en-XL.json
index 42292f5..3246626 100644
--- a/front_end/core/i18n/locales/en-XL.json
+++ b/front_end/core/i18n/locales/en-XL.json
@@ -6872,6 +6872,9 @@
"panels/network/components/HeaderSectionRow.ts | decoded": {
"message": "D̂éĉód̂éd̂:"
},
+ "panels/network/components/HeaderSectionRow.ts | editHeader": {
+ "message": "Ôv́êŕr̂íd̂é ĥéâd́êŕ"
+ },
"panels/network/components/HeaderSectionRow.ts | learnMore": {
"message": "L̂éâŕn̂ ḿôŕê"
},
diff --git a/front_end/panels/network/NetworkLogView.ts b/front_end/panels/network/NetworkLogView.ts
index 8d3bf75..29ca825 100644
--- a/front_end/panels/network/NetworkLogView.ts
+++ b/front_end/panels/network/NetworkLogView.ts
@@ -1719,6 +1719,7 @@
NetworkForward.UIRequestLocation.UIRequestLocation.responseHeaderMatch(request, {name: '', value: ''});
const networkPersistanceManager = Persistence.NetworkPersistenceManager.NetworkPersistenceManager.instance();
if (networkPersistanceManager.project()) {
+ Common.Settings.Settings.instance().moduleSetting('persistenceNetworkOverridesEnabled').set(true);
await networkPersistanceManager.getOrCreateHeadersUISourceCodeFromUrl(request.url());
await Common.Revealer.reveal(requestLocation);
} else { // If folder for local overrides has not been provided yet
diff --git a/front_end/panels/network/components/HeaderSectionRow.css b/front_end/panels/network/components/HeaderSectionRow.css
index b0feaeb..29143ee 100644
--- a/front_end/panels/network/components/HeaderSectionRow.css
+++ b/front_end/panels/network/components/HeaderSectionRow.css
@@ -169,3 +169,8 @@
opacity: 100%;
visibility: visible;
}
+
+.row:hover .inline-button.enable-editing {
+ opacity: 100%;
+ visibility: visible;
+}
diff --git a/front_end/panels/network/components/HeaderSectionRow.ts b/front_end/panels/network/components/HeaderSectionRow.ts
index 1f7aed2..fe8f0aa 100644
--- a/front_end/panels/network/components/HeaderSectionRow.ts
+++ b/front_end/panels/network/components/HeaderSectionRow.ts
@@ -32,6 +32,10 @@
*/
decoded: 'Decoded:',
/**
+ *@description The title of a button to enable overriding a HTTP header.
+ */
+ editHeader: 'Override header',
+ /**
*@description Text that is usually a hyperlink to more documentation
*/
learnMore: 'Learn more',
@@ -49,6 +53,7 @@
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
const trashIconUrl = new URL('../../../Images/trash_bin_material_icon.svg', import.meta.url).toString();
+const editIconUrl = new URL('../../../Images/edit-icon.svg', import.meta.url).toString();
export class HeaderEditedEvent extends Event {
static readonly eventName = 'headeredited';
@@ -74,6 +79,14 @@
}
}
+export class EnableHeaderEditingEvent extends Event {
+ static readonly eventName = 'enableheaderediting';
+
+ constructor() {
+ super(EnableHeaderEditingEvent.eventName, {});
+ }
+}
+
export interface HeaderSectionRowData {
header: HeaderDescriptor;
}
@@ -146,9 +159,24 @@
return LitHtml.nothing;
}
if (!this.#header.valueEditable) {
+ // clang-format off
return html`
${this.#header.value || ''}
${this.#maybeRenderHeaderValueSuffix(this.#header)}
+ ${this.#header.isResponseHeader ? html`
+ <${Buttons.Button.Button.litTagName}
+ title=${i18nString(UIStrings.editHeader)}
+ .size=${Buttons.Button.Size.TINY}
+ .iconUrl=${editIconUrl}
+ .variant=${Buttons.Button.Variant.ROUND}
+ .iconWidth=${'13px'}
+ .iconHeight=${'13px'}
+ @click=${(): void => {
+ this.dispatchEvent(new EnableHeaderEditingEvent());
+ }}
+ class="enable-editing inline-button"
+ ></${Buttons.Button.Button.litTagName}>
+ ` : LitHtml.nothing}
`;
}
return html`
@@ -165,6 +193,7 @@
@click=${this.#onRemoveOverrideClick}
></${Buttons.Button.Button.litTagName}>
`;
+ // clang-format on
}
focus(): void {
@@ -433,6 +462,7 @@
headerNotSet?: boolean;
setCookieBlockedReasons?: Protocol.Network.SetCookieBlockedReason[];
highlight?: boolean;
+ isResponseHeader?: boolean;
}
export interface HeaderEditorDescriptor {
diff --git a/front_end/panels/network/components/RequestHeadersView.ts b/front_end/panels/network/components/RequestHeadersView.ts
index 862683c..098c61f 100644
--- a/front_end/panels/network/components/RequestHeadersView.ts
+++ b/front_end/panels/network/components/RequestHeadersView.ts
@@ -185,6 +185,9 @@
Workspace.Workspace.Events.UISourceCodeAdded, this.#uiSourceCodeAddedOrRemoved, this);
this.#workspace.addEventListener(
Workspace.Workspace.Events.UISourceCodeRemoved, this.#uiSourceCodeAddedOrRemoved, this);
+ Common.Settings.Settings.instance()
+ .moduleSetting('persistenceNetworkOverridesEnabled')
+ .addChangeListener(this.#render, this);
}
disconnectedCallback(): void {
@@ -192,6 +195,9 @@
Workspace.Workspace.Events.UISourceCodeAdded, this.#uiSourceCodeAddedOrRemoved, this);
this.#workspace.removeEventListener(
Workspace.Workspace.Events.UISourceCodeRemoved, this.#uiSourceCodeAddedOrRemoved, this);
+ Common.Settings.Settings.instance()
+ .moduleSetting('persistenceNetworkOverridesEnabled')
+ .removeChangeListener(this.#render, this);
}
#uiSourceCodeAddedOrRemoved(event: Common.EventTarget.EventTargetEvent<Workspace.UISourceCode.UISourceCode>): void {
diff --git a/front_end/panels/network/components/ResponseHeaderSection.ts b/front_end/panels/network/components/ResponseHeaderSection.ts
index 9a9b87d..10067b5 100644
--- a/front_end/panels/network/components/ResponseHeaderSection.ts
+++ b/front_end/panels/network/components/ResponseHeaderSection.ts
@@ -10,6 +10,8 @@
import * as NetworkForward from '../../../panels/network/forward/forward.js';
import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
import * as LitHtml from '../../../ui/lit-html/lit-html.js';
+import * as Sources from '../../../panels/sources/sources.js';
+import * as UI from '../../../ui/legacy/legacy.js';
import {
type HeaderDescriptor,
@@ -491,8 +493,8 @@
return;
}
- const headerDescriptors: HeaderDescriptor[] =
- this.#headerEditors.map((headerEditor, index) => ({...this.#headerDetails[index], ...headerEditor}));
+ const headerDescriptors: HeaderDescriptor[] = this.#headerEditors.map(
+ (headerEditor, index) => ({...this.#headerDetails[index], ...headerEditor, isResponseHeader: true}));
// Disabled until https://crbug.com/1079231 is fixed.
// clang-format off
@@ -500,7 +502,7 @@
${headerDescriptors.map((header, index) => html`
<${HeaderSectionRow.litTagName} .data=${{
header: header,
- } as HeaderSectionRowData} @headeredited=${this.#onHeaderEdited} @headerremoved=${this.#onHeaderRemoved} data-index=${index}></${HeaderSectionRow.litTagName}>
+ } as HeaderSectionRowData} @headeredited=${this.#onHeaderEdited} @headerremoved=${this.#onHeaderRemoved} @enableheaderediting=${this.#onEnableHeaderEditingClick} data-index=${index}></${HeaderSectionRow.litTagName}>
`)}
${this.#headersAreOverrideable ? html`
<${Buttons.Button.Button.litTagName}
@@ -516,6 +518,23 @@
`, this.#shadow, {host: this});
// clang-format on
}
+
+ async #onEnableHeaderEditingClick(): Promise<void> {
+ if (!this.#request) {
+ return;
+ }
+ const requestUrl = this.#request.url();
+ const networkPersistanceManager = Persistence.NetworkPersistenceManager.NetworkPersistenceManager.instance();
+ if (networkPersistanceManager.project()) {
+ Common.Settings.Settings.instance().moduleSetting('persistenceNetworkOverridesEnabled').set(true);
+ await networkPersistanceManager.getOrCreateHeadersUISourceCodeFromUrl(requestUrl);
+ } else { // If folder for local overrides has not been provided yet
+ UI.InspectorView.InspectorView.instance().displaySelectOverrideFolderInfobar(async(): Promise<void> => {
+ await Sources.SourcesNavigator.OverridesNavigatorView.instance().setupNewWorkspace();
+ await networkPersistanceManager.getOrCreateHeadersUISourceCodeFromUrl(requestUrl);
+ });
+ }
+ }
}
ComponentHelpers.CustomElements.defineComponent('devtools-response-header-section', ResponseHeaderSection);