Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
All notable changes to `dash` will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Fixed
- [#1080](https://github.com/plotly/dash/pull/1080) Handle case where dash fails to load when used inside an iframe with a sandbox attribute that only has allow-scripts


## [1.8.0] - 2020-01-14
### Added
- [#1073](https://github.com/plotly/dash/pull/1073) Two new functions to simplify usage handling URLs and pathnames: `app.get_relative_path` & `app.trim_relative_path`.
Expand Down
16 changes: 12 additions & 4 deletions dash-renderer/src/AccessDenied.react.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
/* global window:true, document:true */
import React from 'react';
import {mergeRight} from 'ramda';
import {mergeRight, once} from 'ramda';
import PropTypes from 'prop-types';
import * as styles from './styles/styles.js';
import * as constants from './constants/constants.js';

/* eslint-disable-next-line no-console */
const logWarningOnce = once(console.warn);

function AccessDenied(props) {
const {config} = props;
const fid = config.fid;
Expand All @@ -28,9 +31,14 @@ function AccessDenied(props) {
<a
style={styles.base.a}
onClick={() => {
document.cookie =
`${constants.OAUTH_COOKIE_NAME}=; ` +
'expires=Thu, 01 Jan 1970 00:00:01 GMT;';
/* eslint no-empty: ["error", { "allowEmptyCatch": true }] */
try {
document.cookie =
`${constants.OAUTH_COOKIE_NAME}=; ` +
'expires=Thu, 01 Jan 1970 00:00:01 GMT;';
} catch (e) {
logWarningOnce(e);
}
window.location.reload(true);
}}
>
Expand Down
15 changes: 12 additions & 3 deletions dash-renderer/src/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
lensPath,
mergeLeft,
mergeDeepRight,
once,
path,
pluck,
propEq,
Expand Down Expand Up @@ -54,10 +55,18 @@ export function hydrateInitialOutputs() {
};
}

/* eslint-disable-next-line no-console */
const logWarningOnce = once(console.warn);

export function getCSRFHeader() {
return {
'X-CSRFToken': cookie.parse(document.cookie)._csrf_token,
};
try {
return {
'X-CSRFToken': cookie.parse(document.cookie)._csrf_token,
};
} catch (e) {
logWarningOnce(e);
return {};
}
}

function triggerDefaultState(dispatch, getState) {
Expand Down
57 changes: 57 additions & 0 deletions tests/integration/renderer/test_iframe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from multiprocessing import Value

import dash
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate

import dash_html_components as html


def test_rdif001_sandbox_allow_scripts(dash_duo):
app = dash.Dash(__name__)
call_count = Value("i")

N_OUTPUTS = 50

app.layout = html.Div([
html.Button("click me", id="btn"),
] + [html.Div(id="output-{}".format(i)) for i in range(N_OUTPUTS)])

@app.callback(
[Output("output-{}".format(i), "children") for i in range(N_OUTPUTS)],
[Input("btn", "n_clicks")]
)
def update_output(n_clicks):
if n_clicks is None:
raise PreventUpdate

call_count.value += 1
return ["{}={}".format(i, i + n_clicks) for i in range(N_OUTPUTS)]

@app.server.after_request
def apply_cors(response):
response.headers["Access-Control-Allow-Origin"] = "*"
response.headers["Access-Control-Allow-Headers"] = "Origin, X-Requested-With, Content-Type, Accept, Authorization"
return response

dash_duo.start_server(app)

iframe = """
<!DOCTYPE html>
<html>
<iframe src="{0}" sandbox="allow-scripts">
</iframe>
</html>
"""

html_content = iframe.format(dash_duo.server_url)

dash_duo.driver.get("data:text/html;charset=utf-8," + html_content)

dash_duo.driver.switch_to.frame(0)

dash_duo.wait_for_element('#output-0')
dash_duo.wait_for_element_by_id('btn').click()
dash_duo.wait_for_element('#output-0').text == '0=1'

assert len(dash_duo.get_logs()) != 0