Path: blob/main/src/vs/workbench/contrib/browserView/electron-browser/browserView.contribution.ts
5241 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { localize } from '../../../../nls.js';6import { SyncDescriptor } from '../../../../platform/instantiation/common/descriptors.js';7import { Registry } from '../../../../platform/registry/common/platform.js';8import { EditorPaneDescriptor, IEditorPaneRegistry } from '../../../browser/editor.js';9import { EditorExtensions, IEditorFactoryRegistry } from '../../../common/editor.js';10import { BrowserEditor } from './browserEditor.js';11import { BrowserEditorInput, BrowserEditorSerializer } from './browserEditorInput.js';12import { BrowserViewUri } from '../../../../platform/browserView/common/browserViewUri.js';13import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';14import { registerSingleton, InstantiationType } from '../../../../platform/instantiation/common/extensions.js';15import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from '../../../../platform/configuration/common/configurationRegistry.js';16import { workbenchConfigurationNodeBase } from '../../../common/configuration.js';17import { IEditorResolverService, RegisteredEditorPriority } from '../../../services/editor/common/editorResolverService.js';18import { IWorkbenchContribution, registerWorkbenchContribution2, WorkbenchPhase } from '../../../common/contributions.js';19import { Schemas } from '../../../../base/common/network.js';20import { IBrowserViewWorkbenchService } from '../common/browserView.js';21import { BrowserViewWorkbenchService } from './browserViewWorkbenchService.js';22import { BrowserViewStorageScope } from '../../../../platform/browserView/common/browserView.js';23import { IOpenerService, IOpener, OpenInternalOptions, OpenExternalOptions } from '../../../../platform/opener/common/opener.js';24import { isLocalhostAuthority } from '../../../../platform/url/common/trustedDomains.js';25import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';26import { IEditorService } from '../../../services/editor/common/editorService.js';27import { Disposable } from '../../../../base/common/lifecycle.js';28import { URI } from '../../../../base/common/uri.js';29import { ITelemetryService } from '../../../../platform/telemetry/common/telemetry.js';30import { logBrowserOpen } from './browserViewTelemetry.js';3132// Register actions33import './browserViewActions.js';3435Registry.as<IEditorPaneRegistry>(EditorExtensions.EditorPane).registerEditorPane(36EditorPaneDescriptor.create(37BrowserEditor,38BrowserEditor.ID,39localize('browser.editorLabel', "Browser")40),41[42new SyncDescriptor(BrowserEditorInput)43]44);4546Registry.as<IEditorFactoryRegistry>(EditorExtensions.EditorFactory).registerEditorSerializer(47BrowserEditorInput.ID,48BrowserEditorSerializer49);5051class BrowserEditorResolverContribution implements IWorkbenchContribution {52static readonly ID = 'workbench.contrib.browserEditorResolver';5354constructor(55@IEditorResolverService editorResolverService: IEditorResolverService,56@IInstantiationService instantiationService: IInstantiationService57) {58editorResolverService.registerEditor(59`${Schemas.vscodeBrowser}:/**`,60{61id: BrowserEditorInput.ID,62label: localize('browser.editorLabel', "Browser"),63priority: RegisteredEditorPriority.exclusive64},65{66canSupportResource: resource => resource.scheme === Schemas.vscodeBrowser,67singlePerResource: true68},69{70createEditorInput: ({ resource, options }) => {71const parsed = BrowserViewUri.parse(resource);72if (!parsed) {73throw new Error(`Invalid browser view resource: ${resource.toString()}`);74}7576const browserInput = instantiationService.createInstance(BrowserEditorInput, {77id: parsed.id,78url: parsed.url79});8081// Start resolving the input right away. This will create the browser view.82// This allows browser views to be loaded in the background.83void browserInput.resolve();8485return {86editor: browserInput,87options: {88...options,89pinned: !!parsed.url // pin if navigated90}91};92}93}94);95}96}9798registerWorkbenchContribution2(BrowserEditorResolverContribution.ID, BrowserEditorResolverContribution, WorkbenchPhase.BlockStartup);99100/**101* Opens localhost URLs in the Integrated Browser when the setting is enabled.102*/103class LocalhostLinkOpenerContribution extends Disposable implements IWorkbenchContribution, IOpener {104static readonly ID = 'workbench.contrib.localhostLinkOpener';105106constructor(107@IOpenerService openerService: IOpenerService,108@IConfigurationService private readonly configurationService: IConfigurationService,109@IEditorService private readonly editorService: IEditorService,110@ITelemetryService private readonly telemetryService: ITelemetryService111) {112super();113114this._register(openerService.registerOpener(this));115}116117async open(resource: URI | string, _options?: OpenInternalOptions | OpenExternalOptions): Promise<boolean> {118if (!this.configurationService.getValue<boolean>('workbench.browser.openLocalhostLinks')) {119return false;120}121122const url = typeof resource === 'string' ? resource : resource.toString(true);123try {124const parsed = new URL(url);125if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {126return false;127}128if (!isLocalhostAuthority(parsed.host)) {129return false;130}131} catch {132return false;133}134135logBrowserOpen(this.telemetryService, 'localhostLinkOpener');136137const browserUri = BrowserViewUri.forUrl(url);138await this.editorService.openEditor({ resource: browserUri, options: { pinned: true } });139return true;140}141}142143registerWorkbenchContribution2(LocalhostLinkOpenerContribution.ID, LocalhostLinkOpenerContribution, WorkbenchPhase.BlockStartup);144145registerSingleton(IBrowserViewWorkbenchService, BrowserViewWorkbenchService, InstantiationType.Delayed);146147Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).registerConfiguration({148...workbenchConfigurationNodeBase,149properties: {150'workbench.browser.openLocalhostLinks': {151type: 'boolean',152default: false,153markdownDescription: localize(154{ comment: ['This is the description for a setting.'], key: 'browser.openLocalhostLinks' },155'When enabled, localhost links from the terminal, chat, and other sources will open in the Integrated Browser instead of the system browser.'156)157},158'workbench.browser.dataStorage': {159type: 'string',160enum: [161BrowserViewStorageScope.Global,162BrowserViewStorageScope.Workspace,163BrowserViewStorageScope.Ephemeral164],165markdownEnumDescriptions: [166localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'browser.dataStorage.global' }, 'All browser views share a single persistent session across all workspaces.'),167localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'browser.dataStorage.workspace' }, 'Browser views within the same workspace share a persistent session. If no workspace is opened, `ephemeral` storage is used.'),168localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'browser.dataStorage.ephemeral' }, 'Each browser view has its own session that is cleaned up when closed.')169],170restricted: true,171default: BrowserViewStorageScope.Global,172markdownDescription: localize(173{ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'browser.dataStorage' },174'Controls how browser data (cookies, cache, storage) is shared between browser views.\n\n**Note**: In untrusted workspaces, this setting is ignored and `ephemeral` storage is always used.'175),176scope: ConfigurationScope.WINDOW,177order: 100178}179}180});181182183