Skip to content

Commit a84d403

Browse files
authored
feat: prevent accidentally opening binary file (#3772)
1 parent 2e5e991 commit a84d403

22 files changed

Lines changed: 311 additions & 98 deletions

File tree

packages/ai-native/src/browser/widget/light-bulb/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { asClassNameArrayWrapper } from '@opensumi/ide-core-browser';
2-
import { Sumicon } from '@opensumi/ide-core-common/lib/codicons';
3-
import { Codicon } from '@opensumi/monaco-editor-core/esm/vs/base/common/codicons';
2+
import { Codicon, Sumicon } from '@opensumi/ide-core-common/lib/codicons';
43
import { ThemeIcon } from '@opensumi/monaco-editor-core/esm/vs/base/common/themables';
54
import {
65
LightBulbState,

packages/debug/__tests__/browser/view/configuration/debug-configuration.service.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { PreferenceService } from '@opensumi/ide-core-browser';
22
import { Disposable, EventBusImpl, IEventBus, StorageProvider, URI } from '@opensumi/ide-core-common';
3-
import { IDebugSessionManager } from '@opensumi/ide-debug';
4-
import { DEFAULT_CONFIGURATION_NAME_SEPARATOR } from '@opensumi/ide-debug';
3+
import { DEFAULT_CONFIGURATION_NAME_SEPARATOR, IDebugSessionManager } from '@opensumi/ide-debug';
54
import { DebugConfigurationManager } from '@opensumi/ide-debug/lib/browser/debug-configuration-manager';
65
import { DebugConfigurationService } from '@opensumi/ide-debug/lib/browser/view/configuration/debug-configuration.service';
76
import { DebugConsoleService } from '@opensumi/ide-debug/lib/browser/view/console/debug-console.service';
@@ -64,6 +63,7 @@ describe('Debug Configuration Service', () => {
6463
const mockPreferenceService = {
6564
onPreferenceChanged: jest.fn(),
6665
get: jest.fn(() => true),
66+
getValid: jest.fn(() => true),
6767
};
6868

6969
const mockDebugConsoleService = {

packages/editor/src/browser/component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ export class EditorComponentRegistryImpl implements EditorComponentRegistry {
108108
let results: IEditorOpenType[] = [];
109109
const resolvers = this.getResolvers(resource.uri.scheme).slice(); // 防止异步操作时数组被改变
110110
let shouldBreak = false;
111-
const resolve = (res) => {
111+
const resolve = (res: IEditorOpenType[]) => {
112112
results = res;
113113
shouldBreak = true;
114114
};

packages/editor/src/browser/fs-resource/fs-editor-doc.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,10 @@ export class BaseFileSystemEditorDocumentProvider implements IEditorDocumentMode
110110
uri.toString(),
111111
getLanguageIdFromMonaco(uri)!,
112112
);
113+
114+
// TODO: 应该挪到后端去做
113115
const detected = await detectEncodingFromBuffer(buffer, guessEncoding);
116+
114117
detected.encoding = await this.getReadEncoding(uri, options, detected.encoding);
115118

116119
const content = buffer.toString(detected.encoding);
@@ -132,6 +135,7 @@ export class BaseFileSystemEditorDocumentProvider implements IEditorDocumentMode
132135
// TODO: 这部分要优化成buffer获取(长期来看是stream获取,encoding在哪一层做?)
133136
// 暂时还是使用 resolveContent 内提供的 decode 功能
134137
// 之后 encoding 做了分层之后和其他的需要 decode 的地方一起改
138+
135139
return (await this.read(uri, { encoding })).content;
136140
}
137141

packages/editor/src/browser/fs-resource/fs-resource.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,6 @@ export class FileSystemResourceProvider extends WithEventBus implements IResourc
129129
}
130130

131131
async provideResource(uri: URI): Promise<IResource<any>> {
132-
// 获取文件类型 getFileType: (path: string) => string
133132
await this.ready;
134133
this.involvedFiles.add(uri.codeUri.fsPath);
135134
return Promise.all([

packages/editor/src/browser/preference/schema.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1631,7 +1631,7 @@ const customEditorSchema: PreferenceSchemaProperties = {
16311631
},
16321632
'editor.largeFile': {
16331633
type: 'number',
1634-
default: 4 * 1024 * 1024 * 1024,
1634+
default: 4 * 1024 * 1024 * 1024, // 4096 MB
16351635
description: '%editor.configuration.largeFileSize%',
16361636
},
16371637
'editor.quickSuggestionsDelay': {

packages/editor/src/browser/types.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,10 @@ export class RegisterEditorComponentEvent extends BasicEvent<string> {}
114114
export abstract class EditorComponentRegistry {
115115
abstract registerEditorComponent<T>(component: IEditorComponent<T>, initialProps?: any): IDisposable;
116116

117-
// 等同于 handlesScheme => 10
118-
abstract registerEditorComponentResolver<T>(scheme: string, resolver: IEditorComponentResolver<T>): IDisposable;
119-
120-
// handlesScheme 返回权重, 小于 0 表示不处理
121117
abstract registerEditorComponentResolver<T>(
122-
// eslint-disable-next-line @typescript-eslint/unified-signatures
123-
handlesScheme: (scheme: string) => number,
118+
handlesScheme:
119+
| string // 等同于 handlesScheme => 10
120+
| ((scheme: string) => number), // handlesScheme 返回权重, 小于 0 表示不处理
124121
resolver: IEditorComponentResolver<T>,
125122
): IDisposable;
126123

packages/extension/src/browser/vscode/api/main.thread.doc.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ export class MainThreadExtensionDocumentData extends WithEventBus implements IMa
116116
this.docSyncEnabled.set(
117117
uriString,
118118
docRef.instance.getMonacoModel().getValueLength() <
119-
(this.preference.get<number>('editor.docExtHostSyncMaxSize') || 4 * 1024 * 1024 * 1024),
119+
this.preference.getValid<number>('editor.docExtHostSyncMaxSize', 4 * 1024 * 1024 * 1024),
120120
);
121121
docRef.dispose();
122122
}

packages/file-scheme/__tests__/browser/contribution.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { PreferenceService, URI } from '@opensumi/ide-core-browser';
2+
import { createBrowserInjector } from '@opensumi/ide-dev-tool/src/injector-helper';
3+
import { MockInjector } from '@opensumi/ide-dev-tool/src/mock-injector';
24
import {
35
BrowserEditorContribution,
46
EditorComponentRegistry,
@@ -12,9 +14,6 @@ import { IFileServiceClient } from '@opensumi/ide-file-service';
1214
import { ILanguageService } from '@opensumi/monaco-editor-core/esm/vs/editor/common/languages/language';
1315
import { StandaloneServices } from '@opensumi/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneServices';
1416

15-
import { createBrowserInjector } from '../../../../tools/dev-tool/src/injector-helper';
16-
import { MockInjector } from '../../../../tools/dev-tool/src/mock-injector';
17-
1817
const createMockResource = (uriString: string) => ({ uri: new URI(uriString) } as any as IResource);
1918

2019
const mockFileService = {
@@ -27,6 +26,7 @@ const mockFileService = {
2726
const mockPreferenceService = {
2827
onPreferenceChanged: jest.fn(),
2928
get: jest.fn(() => undefined),
29+
getValid: jest.fn((_, defaultValue) => defaultValue),
3030
ready: Promise.resolve(),
3131
};
3232

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,47 @@
11
import React from 'react';
22

33
import { INJECTOR_TOKEN, Injector } from '@opensumi/di';
4-
import { AppConfig, localize, useInjectable } from '@opensumi/ide-core-browser';
4+
import { AppConfig, IEventBus, localize, useInjectable } from '@opensumi/ide-core-browser';
55
import { IElectronMainUIService } from '@opensumi/ide-core-common/lib/electron';
6-
import { ReactEditorComponent } from '@opensumi/ide-editor/lib/browser';
6+
import {
7+
ReactEditorComponent,
8+
ResourceOpenTypeChangedEvent,
9+
WorkbenchEditorService,
10+
} from '@opensumi/ide-editor/lib/browser';
711

8-
import styles from './style.module.less';
12+
import { PreventComponent } from './prevent.view';
913

1014
export const BinaryEditorComponent: ReactEditorComponent<null> = (props) => {
1115
const srcPath = props.resource.uri.codeUri.fsPath;
1216
const injector: Injector = useInjectable(INJECTOR_TOKEN);
1317
const appConfig: AppConfig = useInjectable(AppConfig);
18+
const editorService = useInjectable<WorkbenchEditorService>(WorkbenchEditorService);
19+
const eventBus = useInjectable<IEventBus>(IEventBus);
1420

15-
return (
16-
<div className={styles.external}>
17-
{localize('editor.cannotOpenBinary')}
18-
{appConfig.isElectronRenderer ? (
19-
<a onClick={() => injector.get(IElectronMainUIService).openPath(srcPath)}>{localize('editor.openExternal')}</a>
20-
) : null}
21-
</div>
22-
);
21+
const handleClick = () => {
22+
const current = editorService.currentResource;
23+
24+
if (!current) {
25+
return;
26+
}
27+
28+
current.metadata = { ...current.metadata, skipPreventBinary: true };
29+
eventBus.fire(new ResourceOpenTypeChangedEvent(current.uri));
30+
};
31+
32+
const actions = [
33+
{
34+
label: localize('editor.file.prevent.stillOpen'),
35+
onClick: () => handleClick(),
36+
},
37+
];
38+
39+
if (appConfig.isElectronRenderer) {
40+
actions.push({
41+
label: localize('editor.openExternal'),
42+
onClick: () => injector.get(IElectronMainUIService).openPath(srcPath),
43+
});
44+
}
45+
46+
return <PreventComponent description={localize('editor.cannotOpenBinary')} actions={actions} />;
2347
};

0 commit comments

Comments
 (0)