Repository: microsoft/vscode (TypeScript)
Task type: Bug Fix

Issue:
Debug Console Linker automatically decodes link

Issue Type: <b>Bug</b>

When debugging code and a link has a URI encode clinking the link in the debug console will auto decode the URL. This causes issues as some APIs expect the paramaters to be URI encoded. When just logging links to the terminal it doesn't do that.

Try the following code:
```
const url = "https://www.test.com/?params=CountryCode%3DUSA%26Name%3Dlramos15";
console.log(url);
```
Steps to reproduce
1. Set a breakpoint on `console.log(url);`
2. Start debugging
3. Type url into the debug console
4. Ctrl+click and navigate to the URL. It will automatically decode to `https://www.test.com/?params=CountryCode=USA&Name=lramos15`, with no way to disable this. Runnig the code normally and following the url in the terminal doesn't do this.


VS Code version: Code - Insiders 1.52.0-insider (5e350b1b79675cecdff224eb00f7bf62ae8789fc, 2020-12-04T10:15:27.849Z)
OS version: Windows_NT x64 10.0.18363

<details>
<summary>System Info</summary>

|Item|Value|
|---|---|
|CPUs|Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz (8 x 2808)|
|GPU Status|2d_canvas: enabled<br>flash_3d: enabled<br>flash_stage3d: enabled<br>flash_stage3d_baseline: enabled<br>gpu_compositing: enabled<br>multiple_raster_threads: enabled_on<br>oop_rasterization: disabled_off<br>opengl: enabled_on<br>protected_video_decode: unavailable_off<br>rasterization: enabled<br>skia_renderer: disabled_off_ok<br>video_decode: enabled<br>vulkan: disabled_off<br>webgl: enabled<br>webgl2: enabled|
|Load (avg)|undefined|
|Memory (System)|15.86GB (6.42GB free)|
|Process Argv|C:\\Users\\ramosl\\Desktop\\Fall 2020 - Hw 8 --crash-reporter-id 6835f0a3-d9c6-4053-812a-2c4e35492724|
|Screen Reader|no|
|VM|0%|
</details><details>
<summary>A/B Experiments</summary>

```
vsliv695:30137379
vsins829:30139715
vsliv368cf:30146710
vsreu685:30147344
openlogontheside:30221882
python763:30178808
python383:30185418
vspor879:30202332
vspor708:30202333
vspor363:30204092
python504:30227505
vswsl492:30208929
wsl2prompt:30219162
vstry244:30230484
pythonvsdeb440:30224570
unusedpromptcf:30219165
folderexplorer:30219166
openfilemenu:30219168
pythonvsded773:30223139

```

</details>

<!-- generated by issue reporter -->


Discussion:
This is a fair request.
Code pointer https://github.com/microsoft/vscode/blob/cf8ed37206e161a30151defa4fc9ea58c32335bc/src/vs/workbench/contrib/debug/browser/linkDetector.ts#L36

PR's to fix this are welcome.
I put a code pointer...
@isidorn Do you think terminal's behavior is correct or debug's behavior is correct. 
I think the reason is uri.parse

![image](https://user-images.githubusercontent.com/14784326/101527499-0c26a100-39c9-11eb-8ab1-9c3a572b4fb5.png)

The correct behavior to me would be not to decode the URI. If I wanted the URI decoded I could do `URI.Parse` within my code or the equivalent of that in whatever language I choose. 
I agree with you @lramos15
I think we can just get rid of URI.parse. I tried it locally, and it work.  But what are the potential problems without URI.parse
Even if we don't use uri.parse here, when we call this.openerService.open(url), the url inside openerService will also be uri.parse, which means that the url shown in the pop-up box is actually decode

![image](https://user-images.githubusercontent.com/14784326/101530331-bb18ac00-39cc-11eb-83ac-b6d61f59bfd1.png)

> Even if we don't use uri.parse here, when we call this.openerService.open(url), the url inside openerService will also be uri.parse, which means that the url shown in the pop-up box is actually decode
> 
> ![image](https://user-images.githubusercontent.com/14784326/101530331-bb18ac00-39cc-11eb-83ac-b6d61f59bfd1.png)

You would definitely want to make sure the URL inside the opener matches the URL the user is being served. So I assume you would want to update it in both places @chenjigeng. I can't think of any consequences of not parsing the URI unless they're using the parsed URI for something besides serving it to the user.
@chenjigeng once you have something feel free to provide a PR and @lramos15 and me can review. Thanks!
I think there are a couple of issues here

1.  Ctrl+click and navigate to the URL. And the Url should not  be decode
2. OpenerService should not decode the Url
3. debug console can't open local file, try the following code
```
const url = "file://Users/something/Desktop/whitelist.png";
console.log(url);
```

This PR is mainly to fix 1 and 3 

The first problem is actually very easy to solve, just need to pass in the original link 

The third question I did was to refer to terminal's current solution: https://github.com/microsoft/vscode/blob/master/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts#L191



Adding bug label so we get this verified.
It looks like the url opener service still decodes the url, so Logan's initial issue is still present.
> It looks like the url opener service still decodes the url, so Logan's initial issue is still present.

So the url you see in the browser is decoded? The reason we didn't touch the opener service is we felt it touched too much code. Although I thought that would only affect the modal shown
Oh, I was hitting the "copy" button to verify the url, but open works. In this scenario, hitting the copy button would result in a broken (decoded) url, we should probably adjust that as well.
@lramos15 can you please look into this if you have time? If not feel free to push to next milestone and assign back to me. Thanks
@connor4312 thanks for cathcing that case. After discussion with @lramos15 we decided to push this part of the fix out of the endgame since it would require a riskier change.
@lramos15 thanks a lot for fixing this. Assingin to February milestone so we get this verified..
[This](https://github.com/microsoft/vscode/issues/112032#issuecomment-768609178) still seems to be happening
Will not fix it last game of endgame, pushing out to backlog
I'll investigate this for debt week.  I just tested it with my fix commit and it worked so I'll have to bisect and see what broke it nothing pops out to me at the moment.

Solution patch:
diff --git a/src/vs/editor/browser/services/openerService.ts b/src/vs/editor/browser/services/openerService.ts
--- a/src/vs/editor/browser/services/openerService.ts
+++ b/src/vs/editor/browser/services/openerService.ts
@@ -166,7 +166,7 @@ export class OpenerService implements IOpenerService {
 		// check with contributed validators
 		const targetURI = typeof target === 'string' ? URI.parse(target) : target;
 		// validate against the original URI that this URI resolves to, if one exists
-		const validationTarget = this._resolvedUriTargets.get(targetURI) ?? targetURI;
+		const validationTarget = this._resolvedUriTargets.get(targetURI) ?? target;
 		for (const validator of this._validators) {
 			if (!(await validator.shouldOpen(validationTarget))) {
 				return false;


Test patch:
diff --git a/src/vs/editor/test/browser/services/openerService.test.ts b/src/vs/editor/test/browser/services/openerService.test.ts
--- a/src/vs/editor/test/browser/services/openerService.test.ts
+++ b/src/vs/editor/test/browser/services/openerService.test.ts
@@ -127,6 +127,20 @@ suite('OpenerService', function () {
 		assert.equal(openCount, 2);
 	});
 
+	test('links aren\'t manipulated before being passed to validator: PR #118226', async function () {
+		const openerService = new OpenerService(editorService, commandService);
+
+		openerService.registerValidator({
+			shouldOpen: (resource) => {
+				// We don't want it to convert strings into URIs
+				assert.strictEqual(resource instanceof URI, false);
+				return Promise.resolve(false);
+			}
+		});
+		await openerService.open('https://wwww.microsoft.com');
+		await openerService.open('https://www.microsoft.com??params=CountryCode%3DUSA%26Name%3Dvscode"');
+	});
+
 	test('links validated by multiple validators', async function () {
 		const openerService = new OpenerService(editorService, commandService);