Merge "Change check fakes to properly respond to feedback"
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 9ace97d3..139d6f8 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -535,6 +535,13 @@
+
By default, `false`.
+[[auth.cookieHttpOnly]]auth.cookieHttpOnly::
++
+Sets "httpOnly" flag of the authentication cookie. If `true`, cookie
+values can't be accessed by client side scripts.
++
+By default, `false`.
+
[[auth.emailFormat]]auth.emailFormat::
+
Optional format string to construct user email addresses out of
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index c6e5623..4e60a30 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -6985,11 +6985,11 @@
|=================================
|Field Name ||Description
|`patch` |required|
-|`allow_conflicts` |optional|
-If true, tolerate conflicts and add conflict markers where required.
The patch to be applied. Must be compatible with `git diff` output.
For example, link:#get-patch[Get Patch] output.
The patch must be provided as UTF-8 text, either directly or base64-encoded.
+|`allow_conflicts` |optional|
+If true, tolerate conflicts and add conflict markers where required.
|=================================
[[applypatchpatchset-input]]
diff --git a/java/com/google/gerrit/httpd/CacheBasedWebSession.java b/java/com/google/gerrit/httpd/CacheBasedWebSession.java
index 9625039..a92d4f0 100644
--- a/java/com/google/gerrit/httpd/CacheBasedWebSession.java
+++ b/java/com/google/gerrit/httpd/CacheBasedWebSession.java
@@ -265,10 +265,10 @@
outCookie.setDomain(domain);
}
- outCookie.setSecure(isSecure(request));
outCookie.setPath(path);
outCookie.setMaxAge(ageSeconds);
- outCookie.setSecure(authConfig.getCookieSecure());
+ outCookie.setSecure(authConfig.getCookieSecure() && isSecure(request));
+ outCookie.setHttpOnly(authConfig.getCookieHttpOnly());
response.addCookie(outCookie);
}
diff --git a/java/com/google/gerrit/httpd/XsrfCookieFilter.java b/java/com/google/gerrit/httpd/XsrfCookieFilter.java
index 079efa4..1ec2649 100644
--- a/java/com/google/gerrit/httpd/XsrfCookieFilter.java
+++ b/java/com/google/gerrit/httpd/XsrfCookieFilter.java
@@ -65,6 +65,7 @@
Cookie c = new Cookie(XsrfConstants.XSRF_COOKIE_NAME, nullToEmpty(v));
c.setPath("/");
c.setSecure(authConfig.getCookieSecure() && isSecure(req));
+ c.setHttpOnly(authConfig.getCookieHttpOnly());
c.setMaxAge(
v != null
? -1 // Set the cookie for this browser session.
diff --git a/java/com/google/gerrit/server/config/AuthConfig.java b/java/com/google/gerrit/server/config/AuthConfig.java
index b6ffcee..e180428 100644
--- a/java/com/google/gerrit/server/config/AuthConfig.java
+++ b/java/com/google/gerrit/server/config/AuthConfig.java
@@ -62,6 +62,7 @@
private final String cookiePath;
private final String cookieDomain;
private final boolean cookieSecure;
+ private final boolean cookieHttpOnly;
private final SignedToken emailReg;
private final boolean allowRegisterNewEmail;
private final boolean userNameCaseInsensitive;
@@ -91,6 +92,7 @@
cookiePath = cfg.getString("auth", null, "cookiepath");
cookieDomain = cfg.getString("auth", null, "cookiedomain");
cookieSecure = cfg.getBoolean("auth", "cookiesecure", false);
+ cookieHttpOnly = cfg.getBoolean("auth", "cookiehttponly", false);
trustContainerAuth = cfg.getBoolean("auth", "trustContainerAuth", false);
enableRunAs = cfg.getBoolean("auth", null, "enableRunAs", true);
gitBasicAuthPolicy = getBasicAuthPolicy(cfg);
@@ -218,6 +220,10 @@
return cookieSecure;
}
+ public boolean getCookieHttpOnly() {
+ return cookieHttpOnly;
+ }
+
public SignedToken getEmailRegistrationToken() {
return emailReg;
}
diff --git a/plugins/codemirror-editor b/plugins/codemirror-editor
index 06719ab..783adf7 160000
--- a/plugins/codemirror-editor
+++ b/plugins/codemirror-editor
@@ -1 +1 @@
-Subproject commit 06719abee6c38d17008599f074050db5153bffa3
+Subproject commit 783adf7ddf19924d054a1596eec6dd3da9f4aafe
diff --git a/polygerrit-ui/app/elements/checks/gr-checks-fix-preview.ts b/polygerrit-ui/app/elements/checks/gr-checks-fix-preview.ts
index c13ef70..e91d9c9 100644
--- a/polygerrit-ui/app/elements/checks/gr-checks-fix-preview.ts
+++ b/polygerrit-ui/app/elements/checks/gr-checks-fix-preview.ts
@@ -9,6 +9,7 @@
import {getAppContext} from '../../services/app-context';
import {EDIT, BasePatchSetNum, RepoName} from '../../types/common';
import {anyLineTooLong} from '../../utils/diff-util';
+import {Timing} from '../../constants/reporting';
import {
DiffInfo,
DiffLayer,
@@ -89,6 +90,8 @@
hide_line_length_indicator: true,
};
+ private readonly reporting = getAppContext().reportingService;
+
private readonly restApiService = getAppContext().restApiService;
private readonly getChangeModel = resolve(this, changeModelToken);
@@ -265,12 +268,17 @@
if (!changeNum || !basePatchNum || !this.fixSuggestionInfo) return;
this.applyingFix = true;
+ this.reporting.time(Timing.APPLY_FIX_LOAD);
const res = await this.restApiService.applyFixSuggestion(
changeNum,
basePatchNum,
this.fixSuggestionInfo.replacements
);
this.applyingFix = false;
+ this.reporting.timeEnd(Timing.APPLY_FIX_LOAD, {
+ method: '1-click',
+ description: this.fixSuggestionInfo.description,
+ });
if (res?.ok) this.navigateToEditPatchset();
}
diff --git a/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.ts b/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.ts
index b57e4ff..d183211 100644
--- a/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.ts
+++ b/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.ts
@@ -126,7 +126,7 @@
this.repoCommentLinks = repoCommentLinks;
// Always linkify URLs starting with https?://
this.repoCommentLinks['ALWAYS_LINK_HTTP'] = {
- match: '(https?://((?!&(gt|lt|amp|quot|apos);)\\S)+[\\w/~-])',
+ match: '(https?://((?!&(gt|lt|quot|apos);)\\S)+[\\w/~-])',
link: '$1',
enabled: true,
};
diff --git a/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text_test.ts b/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text_test.ts
index 23f1594..c1b38d5 100644
--- a/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text_test.ts
+++ b/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text_test.ts
@@ -235,6 +235,11 @@
await checkLinking('https://www.google.com/');
await checkLinking('https://www.google.com/asdf~');
await checkLinking('https://www.google.com/asdf-');
+ await checkLinking('https://www.google.com/asdf-');
+ // matches & part as well, even we first linkify and then htmlEscape
+ await checkLinking(
+ 'https://google.com/traces/list?project=gerrit&tid=123'
+ );
});
});
@@ -710,6 +715,10 @@
await checkLinking('http://www.google.com');
await checkLinking('https://www.google.com');
await checkLinking('https://www.google.com/');
+ // matches & part as well, even we first linkify and then htmlEscape
+ await checkLinking(
+ 'https://google.com/traces/list?project=gerrit&tid=123'
+ );
});
suite('user suggest fix', () => {
diff --git a/polygerrit-ui/app/embed/gr-textarea.ts b/polygerrit-ui/app/embed/gr-textarea.ts
index 05bef49..27948fd 100644
--- a/polygerrit-ui/app/embed/gr-textarea.ts
+++ b/polygerrit-ui/app/embed/gr-textarea.ts
@@ -173,6 +173,8 @@
private focused = false;
+ private currentCursorPosition = -1;
+
private readonly isPlaintextOnlySupported = supportsPlainTextEditing();
static override get styles() {
@@ -488,6 +490,19 @@
event.preventDefault();
this.fire('saveShortcut');
}
+ // Prevent looping of cursor position when CTRL+ARROW_LEFT/ARROW_RIGHT is
+ // pressed.
+ if (event.ctrlKey || event.metaKey || event.altKey) {
+ if (event.key === 'ArrowLeft' && this.currentCursorPosition === 0) {
+ event.preventDefault();
+ }
+ if (
+ event.key === 'ArrowRight' &&
+ this.currentCursorPosition === (this.value?.length ?? 0)
+ ) {
+ event.preventDefault();
+ }
+ }
await this.toggleHintVisibilityIfAny();
}
@@ -597,7 +612,9 @@
}
private onCursorPositionChange() {
- this.fire('cursorPositionChange', {position: this.getCursorPosition()});
+ const cursorPosition = this.getCursorPosition();
+ this.fire('cursorPositionChange', {position: cursorPosition});
+ this.currentCursorPosition = cursorPosition;
}
private async updateValueInDom() {
diff --git a/polygerrit-ui/app/embed/gr-textarea_test.ts b/polygerrit-ui/app/embed/gr-textarea_test.ts
index b701dcb..d125d2f 100644
--- a/polygerrit-ui/app/embed/gr-textarea_test.ts
+++ b/polygerrit-ui/app/embed/gr-textarea_test.ts
@@ -232,4 +232,56 @@
assert.equal(element.value, oldValue + hint);
});
+
+ test('when cursor is at end, Mod + ArrowRight does not change cursor position', async () => {
+ const CURSOR_POSITION_CHANGE_EVENT = 'cursorPositionChange';
+ let cursorPosition = -1;
+ const value = 'Hola amigos';
+ const editableDiv = element.shadowRoot!.querySelector(
+ '.editableDiv'
+ ) as HTMLDivElement;
+ element.addEventListener(CURSOR_POSITION_CHANGE_EVENT, (event: Event) => {
+ const detail = (event as CustomEvent<CursorPositionChangeEventDetail>)
+ .detail;
+ cursorPosition = detail.position;
+ });
+ await element.updateComplete;
+ element.value = value;
+ await element.putCursorAtEnd();
+ await element.updateComplete;
+
+ editableDiv.dispatchEvent(
+ new KeyboardEvent('keydown', {key: 'ArrowRight', metaKey: true})
+ );
+ await element.updateComplete;
+ await rafPromise();
+
+ assert.equal(cursorPosition, value.length);
+ });
+
+ test('when cursor is at 0, Mod + ArrowLeft does not change cursor position', async () => {
+ const CURSOR_POSITION_CHANGE_EVENT = 'cursorPositionChange';
+ let cursorPosition = -1;
+ const value = 'Hola amigos';
+ const editableDiv = element.shadowRoot!.querySelector(
+ '.editableDiv'
+ ) as HTMLDivElement;
+ element.addEventListener(CURSOR_POSITION_CHANGE_EVENT, (event: Event) => {
+ const detail = (event as CustomEvent<CursorPositionChangeEventDetail>)
+ .detail;
+ cursorPosition = detail.position;
+ });
+ await element.updateComplete;
+ element.value = value;
+ element.setCursorPosition(0);
+ await element.updateComplete;
+
+ editableDiv.dispatchEvent(
+ new KeyboardEvent('keydown', {key: 'ArrowLeft', metaKey: true})
+ );
+ await element.updateComplete;
+ await rafPromise();
+
+ assert.equal(cursorPosition, 0);
+ });
});