rasterizeHTML.js icon indicating copy to clipboard operation
rasterizeHTML.js copied to clipboard

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

Open hugolpz opened this issue 10 years ago • 12 comments

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 !)

hugolpz avatar Dec 29 '15 15:12 hugolpz

I get screenshots on Firefox and no error.

cc @cburgmer

edouard-lopez avatar Dec 29 '15 16:12 edouard-lopez

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 :(

cburgmer avatar Oct 31 '16 14:10 cburgmer

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

for

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

in src/browser.js

change

inuyashamx avatar Feb 22 '17 20:02 inuyashamx

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.

cburgmer avatar Feb 25 '17 06:02 cburgmer

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

richardsonvix avatar May 15 '17 13:05 richardsonvix

@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.

cburgmer avatar May 23 '17 19:05 cburgmer

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?

richardsonvix avatar May 24 '17 12:05 richardsonvix

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

cburgmer avatar May 25 '17 20:05 cburgmer

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

Thank you.

richardsonvix avatar May 26 '17 13:05 richardsonvix

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

devellopah avatar Mar 22 '19 13:03 devellopah

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).

cburgmer avatar Mar 23 '19 18:03 cburgmer

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>

devellopah avatar Mar 24 '19 00:03 devellopah