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

"...document's frame is sandboxed and the 'allow-scripts' permission is not set" #117

Open
hugolpz opened this issue Dec 29, 2015 · 12 comments

Comments

@hugolpz
Copy link

hugolpz commented Dec 29, 2015

Report

Using CSScritics, I get the error :

Blocked script execution in 'http://solar-druid.codio.io/tests/csscritic.html' because the document's
frame is sandboxed and the 'allow-scripts' permission is not set.
. h.1.e.calculateDocumentContentSize @ rasterizeHTML.allinone.js:12
. h.1.f.drawDocumentAsSvg @ rasterizeHTML.allinone.js:12
. h.1.k @ rasterizeHTML.allinone.js:12
. (anonymous function) @ rasterizeHTML.allinone.js:12
. (anonymous function) @ rasterizeHTML.allinone.js:12

2015 12 29_csscritic_sanboxed_frame

Resolution hints

Fortunately, Stackoverflow helps. See Why am I getting a blocked script execution error?

This error message (introduced
here) is displayed
when an <iframe> element with sandbox
attribute

is attempting to run JavaScript (only allowed when allow-scripts is
specified in that attribute). A look at the rasterizeHTML source code
shows that the function
createHiddenSandboxedIFrame()
creates such a frame. It is used for calculateDocumentContentSize(),
the contents of the document are being copied into the temporary
sandboxed frame in order to measure their size. Apparently, that
document also contains some <script> tags and these cause the error
(not because of the script origin but because scripts are generally
disallowed).

Reproduce bug

I got this bug using Chromium 45.0.2454.101 Ubuntu 15.04 (64-bit), upon ./test/csscritic.html.

The tested page is ./index.html. There is what you should see if all right (on first connexion) :
2015-12-29_mathador_ui_home

(+ Hi Christopher, long time not seen !)

@edouard-lopez
Copy link

I get screenshots on Firefox and no error.

cc @cburgmer

@cburgmer
Copy link
Owner

Hey sorry for being silent on this. At some point it must have slipped just right under the other issues.

Disabling the script execution is done on purpose. When we are measuring the dimensions, the script content has already been executed and it's effects on the DOM have already been recorded. As the script tags are still there however, we want to avoid that they are executed yet again. Sadly Chrome and Safari complain loudly.

I'd like to clean this up, be don't see a way. Removing the sandboxing as described is not an option :(

inuyashamx added a commit to inuyashamx/rasterizeHTML.js that referenced this issue Feb 22, 2017
@inuyashamx
Copy link

Change
iframe.sandbox = 'allow-same-origin';

for

iframe.sandbox = 'allow-same-origin allow-scripts allow-popups allow-forms';

in src/browser.js

change

@cburgmer
Copy link
Owner

Hey, could you let me know what problem you are facing? As mentioned above, this sandbox setting is intentional, so that JavaScript is not executed twice.

@richardsonvix
Copy link

I'm getting the same error message, but my page is simple, just with table tags and divs.

@cburgmer
Copy link
Owner

@richardsonvix If there's no JS involved, and you are seeing this, please consider posting an example (jsfiddle or something similar maybe). As mentioned above, rasterizeHTML.js is using the sandboxing property by design, which sadly triggers this (unwanted) log.

@richardsonvix
Copy link

Hi @cburgmer, I can´t create a case in jsfiddle, it´s a dynamic generated page (ASP.NET MVC), but using simple tags (tables, divs, ...) loading .js and .css by bundles (css using classes).
Some contents like table rows are created dynamically, also some css classes change for tds.

I can save HTML to evaluate and a screenshot, would it be possible to check only with this?

@cburgmer
Copy link
Owner

Have a try and see whether this still triggers the behaviour.

@richardsonvix
Copy link

I´ll try again when back to this task in my work.

Thank you.

@devellopah
Copy link

same error here, i am on win10, rasterizehtml version is 1.3.0
seems like the error occures in webkit based browsers(chrome, opera, et cetera)
works perfectly fine in firefox

dunno how to hadle it, please help.

rasterizehtml_error

@cburgmer
Copy link
Owner

Hey Islam, can I assume that the HTML you are trying to render includes references to external scripts?

The way this library works with scripts is to inline them before injecting them into the sandboxed iframe. So while this enables scripts to run, it will likely fail for your script, as it is sourced from a foreign origin and rasterizeHTML.js' approach with loading the script via AJAX then fails.

But happy to have a look at an example (maybe on jsfiddle or a similar site).

@devellopah
Copy link

I cannot provide full example, but i can share relevant parts

<template>
...
    <div class="col-sm-6">
      <div class="pdf-container">
      <div class="pdf-loader-container">
          <img src="../../img/loader.gif" alt="loader" class="pdf-loader">
      </div>
        <object
          id="pdf_viewer"
          :data="[pdf ? pdf : intro]"
          width="100%"
          height="100%"
        ></object>
      </div>
    </div>
...
</template>
<script>
import * as rasterizeHTML from 'rasterizehtml'
import jsPDF from 'jspdf'
import _ from 'lodash'
import proximanova from '../fonts'

export default {
  name: 'Generator',
  components: {},

  data: () => ({
    text: 'Сообщение для учеников',
    pdf: null,
  }),
  computed: {
    textComputed: {
      get() { return this.text },
      set: _.debounce(newValue => this.text = newValue, 3000)
    },
    intro() {
        const pdf = new jsPDF()
        pdf.addFileToVFS(proximanova.regular.ttf, proximanova.regular.base64)
        pdf.addFont(proximanova.regular.ttf, proximanova.name, proximanova.regular.weight)
        pdf.setFont(proximanova.name)
        pdf.setFontSize(16)
        pdf.text(this.textComputed, 10, 10)
        return pdf.output('datauristring')
    },
  },

  methods: {
    run() {
      Promise.resolve(true)
        .then(() => this.generateTasks())
        .then(tasks => this.drawHTML(tasks))
    },
    generateTasks() {
      const { quantity } = this.options
      const tasks = []

      for (let i = 0; i < quantity; i++) {
        tasks.push(this.getTask())
      }

      console.log('tasks', tasks)
      return tasks
    },
    createTaskHtml(list) {
      return `
        <div style="max-width: 435px; margin: auto;">
            <div style="display: flex; justify-content: center; flex-wrap: wrap">
                ${list
                  .map(task => {
                    return `
                        <div style="width: 20%; text-align: center; margin-bottom: 25px;">
                            <div style=" border: 1px solid #333; width: 60px; color: #333; font-size: 18px; line-height: 25px; font-weight: 400; display: inline-block;">
                            ${task
                              .map(num => {
                                return `
                                    <div style="border-bottom: 1px solid #333;">${num}</div>
                                `.trim()
                              })
                              .join('')}
                            <div style="font-size: 0 !important;">:)</div>
                            </div
                            >
                        </div>`.trim()
                  })
                  .join('')}
            </div>
        </div>
            `
    },

    async createCanvas(html) {
      const canvas = document.createElement('canvas')

      canvas.width = 435
      canvas.height = 900

      await rasterizeHTML.drawHTML(html, canvas)

      return canvas
    },

    drawHTML(tasks) {

      const { nums } = this.options
      let k

      if ([6, 7, 8].indexOf(nums) !== -1) {
        k = 15
      } else if ([9, 10].indexOf(nums) !== -1) {
        k = 10
      } else {
        k = 20
      }

      console.log('k', k)

      const promises = _.chunk(tasks, k)
        .map(this.createTaskHtml)
        .map(this.createCanvas)

      Promise.all(promises).then(canvas => this.generatePDF(canvas))
    },
    generatePDF(canvas) {
      const pdf = new jsPDF('p', 'pt', 'a4')

      pdf.addFileToVFS(proximanova.regular.ttf, proximanova.regular.base64)
      pdf.addFont(proximanova.regular.ttf, proximanova.name, proximanova.regular.weight)
      pdf.setFont(proximanova.name)
      pdf.setFontSize(16)

      pdf.text(this.textComputed, 30, 30)

      canvas.forEach((image, i) => {
        !!i && pdf.addPage() // если не первый элемент, добавляем новую страницу в документ
        pdf.addImage(image.toDataURL(), 'PNG', 80, 80, image.width, image.height) // добавляем изображение на страницу
      })
      this.pdf = pdf.output('datauristring')
    },
  }
}
</script>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants