Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add allow automatic tasks setting #154171

Merged
merged 13 commits into from
Jul 7, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -1084,7 +1084,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
}).then((value) => {
if (runSource === TaskRunSource.User) {
this.getWorkspaceTasks().then(workspaceTasks => {
RunAutomaticTasks.promptForPermission(this, this._storageService, this._notificationService, this._workspaceTrustManagementService, this._openerService, workspaceTasks);
RunAutomaticTasks.promptForPermission(this, this._storageService, this._notificationService, this._workspaceTrustManagementService, this._openerService, this._configurationService, workspaceTasks);
});
}
return value;
Expand Down
48 changes: 26 additions & 22 deletions src/vs/workbench/contrib/tasks/browser/runAutomaticTasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,19 @@ import { IQuickPickItem, IQuickInputService } from 'vs/platform/quickinput/commo
import { Action2 } from 'vs/platform/actions/common/actions';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IWorkspaceTrustManagementService } from 'vs/platform/workspace/common/workspaceTrust';
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { URI } from 'vs/base/common/uri';
import { Event } from 'vs/base/common/event';
import { ILogService } from 'vs/platform/log/common/log';

const ARE_AUTOMATIC_TASKS_ALLOWED_IN_WORKSPACE = 'tasks.run.allowAutomatic';
const HAS_PROMPTED_FOR_AUTOMATIC_TASKS = 'task.hasPromptedForAutomaticTasks';
const ALLOW_AUTOMATIC_TASKS = 'task.allowAutomaticTasks';

export class RunAutomaticTasks extends Disposable implements IWorkbenchContribution {
constructor(
@ITaskService private readonly _taskService: ITaskService,
@IStorageService private readonly _storageService: IStorageService,
@IConfigurationService private readonly _configurationService: IConfigurationService,
@IWorkspaceTrustManagementService private readonly _workspaceTrustManagementService: IWorkspaceTrustManagementService,
@ILogService private readonly _logService: ILogService) {
super();
Expand All @@ -42,7 +43,7 @@ export class RunAutomaticTasks extends Disposable implements IWorkbenchContribut
}

this._logService.trace('RunAutomaticTasks: Checking if automatic tasks should run.');
const isFolderAutomaticAllowed = this._storageService.getBoolean(ARE_AUTOMATIC_TASKS_ALLOWED_IN_WORKSPACE, StorageScope.WORKSPACE, undefined);
const isFolderAutomaticAllowed = this._configurationService.getValue(ALLOW_AUTOMATIC_TASKS) !== 'off';
await this._workspaceTrustManagementService.workspaceTrustInitialized;
const isWorkspaceTrusted = this._workspaceTrustManagementService.isWorkspaceTrusted();
// Only run if allowed. Prompting for permission occurs when a user first tries to run a task.
Expand Down Expand Up @@ -128,30 +129,33 @@ export class RunAutomaticTasks extends Disposable implements IWorkbenchContribut
}

public static async promptForPermission(taskService: ITaskService, storageService: IStorageService, notificationService: INotificationService, workspaceTrustManagementService: IWorkspaceTrustManagementService,
openerService: IOpenerService, workspaceTaskResult: Map<string, IWorkspaceFolderTaskResult>) {
openerService: IOpenerService, configurationService: IConfigurationService, workspaceTaskResult: Map<string, IWorkspaceFolderTaskResult>) {
const isWorkspaceTrusted = workspaceTrustManagementService.isWorkspaceTrusted;
if (!isWorkspaceTrusted) {
return;
}

const isFolderAutomaticAllowed = storageService.getBoolean(ARE_AUTOMATIC_TASKS_ALLOWED_IN_WORKSPACE, StorageScope.WORKSPACE, undefined);
if (isFolderAutomaticAllowed !== undefined) {
if (configurationService.getValue(ALLOW_AUTOMATIC_TASKS) === 'off') {
return;
}

const hasShownPromptForAutomaticTasks = storageService.getBoolean(HAS_PROMPTED_FOR_AUTOMATIC_TASKS, StorageScope.WORKSPACE, undefined);
const { tasks, taskNames, locations } = RunAutomaticTasks._findAutoTasks(taskService, workspaceTaskResult);
if (taskNames.length > 0) {
// We have automatic tasks, prompt to allow.
this._showPrompt(notificationService, storageService, taskService, openerService, taskNames, locations).then(allow => {
if (allow) {
RunAutomaticTasks._runTasks(taskService, tasks);
}
});
if (configurationService.getValue(ALLOW_AUTOMATIC_TASKS) === 'on') {
RunAutomaticTasks._runTasks(taskService, tasks);
} else if (!hasShownPromptForAutomaticTasks) {
// We have automatic tasks, prompt to allow.
this._showPrompt(notificationService, storageService, openerService, configurationService, taskNames, locations).then(allow => {
if (allow) {
RunAutomaticTasks._runTasks(taskService, tasks);
}
});
}
}
}

private static _showPrompt(notificationService: INotificationService, storageService: IStorageService, taskService: ITaskService,
openerService: IOpenerService, taskNames: Array<string>, locations: Map<string, URI>): Promise<boolean> {
private static _showPrompt(notificationService: INotificationService, storageService: IStorageService,
openerService: IOpenerService, configurationService: IConfigurationService, taskNames: Array<string>, locations: Map<string, URI>): Promise<boolean> {
return new Promise<boolean>(resolve => {
notificationService.prompt(Severity.Info, nls.localize('tasks.run.allowAutomatic',
"This workspace has tasks ({0}) defined ({1}) that run automatically when you open this workspace. Do you allow automatic tasks to run when you open this workspace?",
Expand All @@ -162,14 +166,15 @@ export class RunAutomaticTasks extends Disposable implements IWorkbenchContribut
label: nls.localize('allow', "Allow and run"),
run: () => {
resolve(true);
storageService.store(ARE_AUTOMATIC_TASKS_ALLOWED_IN_WORKSPACE, true, StorageScope.WORKSPACE, StorageTarget.MACHINE);
configurationService.updateValue(ALLOW_AUTOMATIC_TASKS, true, ConfigurationTarget.WORKSPACE);
}
},
{
label: nls.localize('disallow', "Disallow"),
run: () => {
resolve(false);
storageService.store(ARE_AUTOMATIC_TASKS_ALLOWED_IN_WORKSPACE, false, StorageScope.WORKSPACE, StorageTarget.MACHINE);
configurationService.updateValue(ALLOW_AUTOMATIC_TASKS, false, ConfigurationTarget.WORKSPACE);

}
},
{
Expand All @@ -182,9 +187,9 @@ export class RunAutomaticTasks extends Disposable implements IWorkbenchContribut
}
}]
);
storageService.store(HAS_PROMPTED_FOR_AUTOMATIC_TASKS, true, StorageScope.WORKSPACE, StorageTarget.MACHINE);
});
}

}

export class ManageAutomaticTaskRunning extends Action2 {
Expand All @@ -202,14 +207,13 @@ export class ManageAutomaticTaskRunning extends Action2 {

public async run(accessor: ServicesAccessor): Promise<any> {
const quickInputService = accessor.get(IQuickInputService);
const storageService = accessor.get(IStorageService);
const configurationService = accessor.get(IConfigurationService);
const allowItem: IQuickPickItem = { label: nls.localize('workbench.action.tasks.allowAutomaticTasks', "Allow Automatic Tasks in Folder") };
const disallowItem: IQuickPickItem = { label: nls.localize('workbench.action.tasks.disallowAutomaticTasks', "Disallow Automatic Tasks in Folder") };
const value = await quickInputService.pick([allowItem, disallowItem], { canPickMany: false });
if (!value) {
return;
}

storageService.store(ARE_AUTOMATIC_TASKS_ALLOWED_IN_WORKSPACE, value === allowItem, StorageScope.WORKSPACE, StorageTarget.MACHINE);
configurationService.updateValue(ALLOW_AUTOMATIC_TASKS, value === allowItem, ConfigurationTarget.WORKSPACE);
}
}
12 changes: 12 additions & 0 deletions src/vs/workbench/contrib/tasks/browser/task.contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,18 @@ configurationRegistry.registerConfiguration({
description: nls.localize('task.quickOpen.showAll', "Causes the Tasks: Run Task command to use the slower \"show all\" behavior instead of the faster two level picker where tasks are grouped by provider."),
default: false
},
[TaskSettingId.AllowAutomaticTasks]: {
type: 'string',
enum: ['on', 'auto', 'off'],
enumDescriptions: [
nls.localize('ttask.allowAutomaticTasks.on', "Always"),
nls.localize('task.allowAutomaticTasks.auto', "Prompt for permission for each folder"),
nls.localize('task.allowAutomaticTasks.off', "Never"),
],
description: nls.localize('task.allowAutomaticTasks', "Enable automatic tasks in the folder."),
default: 'auto',
restricted: true
},
[TaskSettingId.ShowDecorations]: {
type: 'boolean',
description: nls.localize('task.showDecorations', "Shows decorations at points of interest in the terminal buffer such as the first problem found via a watch task. Note that this will only take effect for future tasks."),
Expand Down
3 changes: 2 additions & 1 deletion src/vs/workbench/contrib/tasks/common/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1199,7 +1199,8 @@ export const enum TaskSettingId {
QuickOpenHistory = 'task.quickOpen.history',
QuickOpenDetail = 'task.quickOpen.detail',
QuickOpenSkip = 'task.quickOpen.skip',
QuickOpenShowAll = 'task.quickOpen.showAll'
QuickOpenShowAll = 'task.quickOpen.showAll',
AllowAutomaticTasks = 'task.allowAutomaticTasks'
}

export const enum TasksSchemaProperties {
Expand Down