Skip to content

Commit

Permalink
DS: Open untrusted notebooks as readonly (#12579)
Browse files Browse the repository at this point in the history
  • Loading branch information
joyceerhl committed Jun 29, 2020
1 parent 2960baf commit 2a1c244
Show file tree
Hide file tree
Showing 12 changed files with 80 additions and 24 deletions.
1 change: 1 addition & 0 deletions src/datascience-ui/history-react/interactiveCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ export class InteractiveCell extends React.Component<IInteractiveCellProps> {
codeVersion={this.props.cellVM.codeVersion ? this.props.cellVM.codeVersion : 0}
focusPending={this.props.focusPending}
language={this.props.language}
isNotebookTrusted={true}
/>
);
}
Expand Down
4 changes: 3 additions & 1 deletion src/datascience-ui/interactive-common/cellInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ interface ICellInputProps {
showLineNumbers?: boolean;
font: IFont;
disableUndoStack: boolean;
isNotebookTrusted: boolean;
/**
* Only used in interactive window.
*/
Expand Down Expand Up @@ -101,7 +102,7 @@ export class CellInput extends React.Component<ICellInputProps> {
code={this.getRenderableInputCode()}
codeTheme={this.props.codeTheme}
testMode={this.props.testMode ? true : false}
readOnly={!this.props.cellVM.editable}
readOnly={!this.props.cellVM.editable || !this.props.isNotebookTrusted}
showWatermark={this.props.showWatermark}
ref={this.codeRef}
onChange={this.props.onCodeChange}
Expand Down Expand Up @@ -157,6 +158,7 @@ export class CellInput extends React.Component<ICellInputProps> {
font={this.props.font}
disableUndoStack={this.props.disableUndoStack}
version={this.props.codeVersion}
isNotebookTrusted={this.props.isNotebookTrusted}
/>
</div>
);
Expand Down
6 changes: 5 additions & 1 deletion src/datascience-ui/interactive-common/jupyterInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,15 @@ export class JupyterInfo extends React.Component<IJupyterInfoProps> {
}

private renderKernelStatus(displayNameTextWidth: React.CSSProperties) {
const ariaDisabled = this.props.isNotebookTrusted === undefined ? false : this.props.isNotebookTrusted;
if (this.isKernelSelectionAllowed) {
return (
<div
className="kernel-status-section kernel-status-section-hoverable kernel-status-status"
style={displayNameTextWidth}
onClick={this.selectKernel}
role="button"
aria-disabled={ariaDisabled}
>
{this.props.kernel.displayName}: {this.props.kernel.jupyterServerStatus}
</div>
Expand Down Expand Up @@ -120,7 +122,9 @@ export class JupyterInfo extends React.Component<IJupyterInfoProps> {
}

private selectKernel() {
this.props.selectKernel();
if (this.props.isNotebookTrusted) {
this.props.selectKernel();
}
}
private getIcon(): ImageName {
return this.props.kernel.jupyterServerStatus === ServerStatus.NotStarted
Expand Down
3 changes: 2 additions & 1 deletion src/datascience-ui/interactive-common/markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export interface IMarkdownProps {
hasFocus: boolean;
cursorPos: CursorPos | monacoEditor.IPosition;
disableUndoStack: boolean;
isNotebookTrusted: boolean;
onCreated(code: string, modelId: string): void;
onChange(e: IMonacoModelContentChangeEvent): void;
focused?(): void;
Expand All @@ -46,7 +47,7 @@ export class Markdown extends React.Component<IMarkdownProps> {
<div className={classes}>
<Editor
codeTheme={this.props.codeTheme}
readOnly={false}
readOnly={!this.props.isNotebookTrusted}
history={undefined}
onCreated={this.props.onCreated}
onChange={this.props.onChange}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,10 @@ export namespace Transfer {
postActionToExtension(arg, InteractiveWindowMessages.LoadAllCellsComplete, {
cells: arg.prevState.cellVMs.map((c) => c.cell)
});
if (!arg.prevState.isNotebookTrusted) {
// As soon as an untrusted notebook is loaded, prompt the user to trust it
postActionToExtension(arg, InteractiveWindowMessages.LaunchNotebookTrustPrompt);
}
return arg.prevState;
}
}
2 changes: 1 addition & 1 deletion src/datascience-ui/interactive-common/redux/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ function generateDefaultState(
},
settings: testMode ? getDefaultSettings() : undefined, // When testing, we don't send (or wait) for the real settings.
editorOptions: testMode ? computeEditorOptions(getDefaultSettings()) : undefined,
isNotebookTrusted: false
isNotebookTrusted: true
};
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/datascience-ui/native-editor/addCellLine.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ interface IAddCellLineProps {
baseTheme: string;
includePlus: boolean;
className: string;
isNotebookTrusted: boolean;
click(): void;
}

Expand All @@ -30,6 +31,7 @@ export class AddCellLine extends React.Component<IAddCellLineProps> {
role="button"
aria-pressed="false"
title={tooltip}
disabled={!this.props.isNotebookTrusted}
aria-label={tooltip}
className="add-cell-line-button"
onClick={this.props.click}
Expand Down
40 changes: 30 additions & 10 deletions src/datascience-ui/native-editor/nativeCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ export class NativeCell extends React.Component<INativeCellProps> {
return this.props.cellVM.selected;
};

private isNotebookTrusted = () => {
return this.props.isNotebookTrusted;
};

private isFocused = () => {
return this.props.cellVM.focused;
};
Expand All @@ -142,8 +146,12 @@ export class NativeCell extends React.Component<INativeCellProps> {
};

private renderNormalCell() {
const cellOuterClass = this.props.cellVM.editable ? 'cell-outer-editable' : 'cell-outer';
let cellWrapperClass = this.props.cellVM.editable ? 'cell-wrapper' : 'cell-wrapper cell-wrapper-noneditable';
const cellOuterClass =
this.props.cellVM.editable && this.props.isNotebookTrusted ? 'cell-outer-editable' : 'cell-outer';
let cellWrapperClass =
this.props.cellVM.editable && this.props.isNotebookTrusted
? 'cell-wrapper'
: 'cell-wrapper cell-wrapper-noneditable';
if (this.isSelected() && !this.isFocused()) {
cellWrapperClass += ' cell-wrapper-selected';
}
Expand All @@ -152,7 +160,6 @@ export class NativeCell extends React.Component<INativeCellProps> {
}

// Content changes based on if a markdown cell or not.
// Make renderOutput() conditional on whether notebook is in trusted state
const content =
this.isMarkdownCell() && !this.isShowingMarkdownEditor() ? (
<div className="cell-result-container">
Expand Down Expand Up @@ -258,7 +265,7 @@ export class NativeCell extends React.Component<INativeCellProps> {
};

private shouldRenderOutput(): boolean {
if (this.isCodeCell()) {
if (this.isCodeCell() && this.props.isNotebookTrusted) {
const cell = this.getCodeCell();
return (
this.hasOutput() &&
Expand All @@ -268,13 +275,16 @@ export class NativeCell extends React.Component<INativeCellProps> {
cell.outputs.length !== 0
);
} else if (this.isMarkdownCell()) {
return !this.isShowingMarkdownEditor();
return !this.isShowingMarkdownEditor() && this.isNotebookTrusted();
}
return false;
}

// tslint:disable-next-line: cyclomatic-complexity max-func-body-length
private keyDownInput = (cellId: string, e: IKeyboardEvent) => {
if (!this.isNotebookTrusted()) {
return; // Disable keyboard interaction with untrusted notebooks
}
const isFocusedWhenNotSuggesting = this.isFocused() && e.editorInfo && !e.editorInfo.isSuggesting;
switch (e.code) {
case 'ArrowUp':
Expand Down Expand Up @@ -500,6 +510,7 @@ export class NativeCell extends React.Component<INativeCellProps> {
<ImageButton
baseTheme={this.props.baseTheme}
onClick={this.addNewCellBelow}
disabled={!this.props.isNotebookTrusted}
tooltip={getLocString('DataScience.insertBelow', 'Insert cell below')}
>
<Image baseTheme={this.props.baseTheme} class="image-button-image" image={ImageName.InsertBelow} />
Expand All @@ -513,7 +524,7 @@ export class NativeCell extends React.Component<INativeCellProps> {
<ImageButton
baseTheme={this.props.baseTheme}
onClick={moveUp}
disabled={this.props.firstCell}
disabled={this.props.firstCell || !this.props.isNotebookTrusted}
tooltip={getLocString('DataScience.moveCellUp', 'Move cell up')}
>
<Image baseTheme={this.props.baseTheme} class="image-button-image" image={ImageName.Up} />
Expand All @@ -523,7 +534,7 @@ export class NativeCell extends React.Component<INativeCellProps> {
<ImageButton
baseTheme={this.props.baseTheme}
onClick={moveDown}
disabled={this.props.lastCell}
disabled={this.props.lastCell || !this.props.isNotebookTrusted}
tooltip={getLocString('DataScience.moveCellDown', 'Move cell down')}
>
<Image baseTheme={this.props.baseTheme} class="image-button-image" image={ImageName.Down} />
Expand All @@ -544,6 +555,7 @@ export class NativeCell extends React.Component<INativeCellProps> {
className="add-divider"
baseTheme={this.props.baseTheme}
includePlus={false}
isNotebookTrusted={this.props.isNotebookTrusted}
click={this.addNewCell}
/>
);
Expand Down Expand Up @@ -663,7 +675,7 @@ export class NativeCell extends React.Component<INativeCellProps> {
onClick={runCell}
tooltip={getLocString('DataScience.runCell', 'Run cell')}
hidden={this.isMarkdownCell()}
disabled={this.props.busy}
disabled={this.props.busy || !this.props.isNotebookTrusted}
>
<Image baseTheme={this.props.baseTheme} class="image-button-image" image={ImageName.Run} />
</ImageButton>
Expand All @@ -672,15 +684,20 @@ export class NativeCell extends React.Component<INativeCellProps> {
onClick={runbyline}
tooltip={getLocString('DataScience.runByLine', 'Run by line')}
hidden={this.isMarkdownCell() || !this.props.supportsRunByLine}
disabled={this.props.busy}
disabled={this.props.busy || !this.props.isNotebookTrusted}
>
<Image
baseTheme={this.props.baseTheme}
class="image-button-image"
image={ImageName.RunByLine}
/>
</ImageButton>
<ImageButton baseTheme={this.props.baseTheme} onMouseDown={switchCellType} tooltip={switchTooltip}>
<ImageButton
baseTheme={this.props.baseTheme}
onMouseDown={switchCellType}
tooltip={switchTooltip}
disabled={!this.props.isNotebookTrusted}
>
<Image baseTheme={this.props.baseTheme} class="image-button-image" image={otherCellImage} />
</ImageButton>
<ImageButton
Expand All @@ -691,6 +708,7 @@ export class NativeCell extends React.Component<INativeCellProps> {
'Gather the code required to generate this cell into a new notebook'
)}
hidden={gatherDisabled}
disabled={!this.props.isNotebookTrusted}
>
<Image
baseTheme={this.props.baseTheme}
Expand All @@ -703,6 +721,7 @@ export class NativeCell extends React.Component<INativeCellProps> {
onClick={deleteCell}
tooltip={getLocString('DataScience.deleteCell', 'Delete cell')}
className="delete-cell-button hover-cell-button"
disabled={!this.props.isNotebookTrusted}
>
<Image baseTheme={this.props.baseTheme} class="image-button-image" image={ImageName.Delete} />
</ImageButton>
Expand Down Expand Up @@ -763,6 +782,7 @@ export class NativeCell extends React.Component<INativeCellProps> {
codeVersion={this.props.cellVM.codeVersion ? this.props.cellVM.codeVersion : 1}
focusPending={this.props.focusPending}
language={this.props.language}
isNotebookTrusted={this.props.isNotebookTrusted}
/>
</div>
);
Expand Down
9 changes: 9 additions & 0 deletions src/datascience-ui/native-editor/nativeEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ export class NativeEditor extends React.Component<INativeEditorProps> {
className="add-cell-line-top"
click={this.insertAboveFirst}
baseTheme={this.props.baseTheme}
isNotebookTrusted={this.props.isNotebookTrusted}
/>
);

Expand Down Expand Up @@ -197,8 +198,15 @@ ${buildSettingsCss(this.props.settings)}`}</style>
this.props.getVariableData(this.props.currentExecutionCount, startIndex, pageSize);
};

private isNotebookTrusted = () => {
return this.props.isNotebookTrusted;
};

// tslint:disable-next-line: cyclomatic-complexity
private mainKeyDown = (event: KeyboardEvent) => {
if (!this.isNotebookTrusted()) {
return; // Disable keyboard interaction with untrusted notebooks
}
// Handler for key down presses in the main panel
switch (event.key) {
// tslint:disable-next-line: no-suspicious-comment
Expand Down Expand Up @@ -309,6 +317,7 @@ ${buildSettingsCss(this.props.settings)}`}</style>
baseTheme={this.props.baseTheme}
className="add-cell-line-cell"
click={addNewCell}
isNotebookTrusted={this.props.isNotebookTrusted}
/>
) : null;

Expand Down
18 changes: 10 additions & 8 deletions src/datascience-ui/native-editor/toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ export class Toolbar extends React.PureComponent<INativeEditorToolbarProps> {
<ImageButton
baseTheme={this.props.baseTheme}
onClick={runAll}
disabled={this.props.busy}
disabled={this.props.busy || !this.props.isNotebookTrusted}
className="native-button"
tooltip={getLocString('DataScience.runAll', 'Run All Cells')}
>
Expand All @@ -142,7 +142,7 @@ export class Toolbar extends React.PureComponent<INativeEditorToolbarProps> {
<ImageButton
baseTheme={this.props.baseTheme}
onClick={runAbove}
disabled={!canRunAbove || this.props.busy}
disabled={!canRunAbove || this.props.busy || !this.props.isNotebookTrusted}
className="native-button"
tooltip={getLocString('DataScience.runAbove', 'Run cells above')}
>
Expand All @@ -155,7 +155,7 @@ export class Toolbar extends React.PureComponent<INativeEditorToolbarProps> {
<ImageButton
baseTheme={this.props.baseTheme}
onClick={runBelow}
disabled={!canRunBelow || this.props.busy}
disabled={!canRunBelow || this.props.busy || !this.props.isNotebookTrusted}
className="native-button"
tooltip={getLocString('DataScience.runBelow', 'Run cell and below')}
>
Expand All @@ -168,7 +168,7 @@ export class Toolbar extends React.PureComponent<INativeEditorToolbarProps> {
<ImageButton
baseTheme={this.props.baseTheme}
onClick={this.props.restartKernel}
disabled={!canRestartAndInterruptKernel}
disabled={!canRestartAndInterruptKernel || !this.props.isNotebookTrusted}
className="native-button"
tooltip={getLocString('DataScience.restartServer', 'Restart IPython kernel')}
>
Expand All @@ -181,7 +181,7 @@ export class Toolbar extends React.PureComponent<INativeEditorToolbarProps> {
<ImageButton
baseTheme={this.props.baseTheme}
onClick={this.props.interruptKernel}
disabled={!canRestartAndInterruptKernel}
disabled={!canRestartAndInterruptKernel || !this.props.isNotebookTrusted}
className="native-button"
tooltip={getLocString('DataScience.interruptKernel', 'Interrupt IPython kernel')}
>
Expand All @@ -194,6 +194,7 @@ export class Toolbar extends React.PureComponent<INativeEditorToolbarProps> {
<ImageButton
baseTheme={this.props.baseTheme}
onClick={addCell}
disabled={!this.props.isNotebookTrusted}
className="native-button"
tooltip={getLocString('DataScience.addNewCell', 'Insert cell')}
>
Expand All @@ -206,7 +207,7 @@ export class Toolbar extends React.PureComponent<INativeEditorToolbarProps> {
<ImageButton
baseTheme={this.props.baseTheme}
onClick={this.props.clearAllOutputs}
disabled={!this.props.cellCount}
disabled={!this.props.cellCount || !this.props.isNotebookTrusted}
className="native-button"
tooltip={getLocString('DataScience.clearAllOutput', 'Clear All Output')}
>
Expand All @@ -219,6 +220,7 @@ export class Toolbar extends React.PureComponent<INativeEditorToolbarProps> {
<ImageButton
baseTheme={this.props.baseTheme}
onClick={toggleVariableExplorer}
disabled={!this.props.isNotebookTrusted}
className="native-button"
tooltip={variableExplorerTooltip}
>
Expand All @@ -231,7 +233,7 @@ export class Toolbar extends React.PureComponent<INativeEditorToolbarProps> {
<ImageButton
baseTheme={this.props.baseTheme}
onClick={save}
disabled={!this.props.dirty}
disabled={!this.props.dirty || !this.props.isNotebookTrusted}
className="native-button"
tooltip={getLocString('DataScience.save', 'Save File')}
>
Expand All @@ -244,7 +246,7 @@ export class Toolbar extends React.PureComponent<INativeEditorToolbarProps> {
<ImageButton
baseTheme={this.props.baseTheme}
onClick={this.props.exportAs}
disabled={!this.props.cellCount || this.props.busy}
disabled={!this.props.cellCount || this.props.busy || !this.props.isNotebookTrusted}
className="native-button"
tooltip={getLocString('DataScience.notebookExportAs', 'Export as')}
>
Expand Down
Loading

0 comments on commit 2a1c244

Please sign in to comment.