diff --git a/.gitignore b/.gitignore
index a982a42..12151a3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,4 @@ node_modules/
 npm-debug.log
 debug.log
 tests/reftests.js
+*.log
diff --git a/karma.conf.js b/karma.conf.js
index 97a1c6c..811827b 100644
--- a/karma.conf.js
+++ b/karma.conf.js
@@ -10,10 +10,11 @@ module.exports = function(config) {
             platform: 'Windows 10',
             version: 'beta'
         },
-        sl_stable_firefox: {
+        sl_beta_firefox: {
             base: 'SauceLabs',
             browserName: 'firefox',
-            platform: 'Windows 10'
+            platform: 'Windows 8.1',
+            version: 'beta'
         },
         sl_ie9: {
             base: 'SauceLabs',
@@ -90,16 +91,6 @@ module.exports = function(config) {
         }
     });
 
-    /*
-     'sl_opera_12.15': {
-     base: 'SauceLabs',
-     browserName: 'opera',
-     platform: 'Linux',
-     version: '12.15'
-     },
-     */
-
-
     config.set({
 
         // base path that will be used to resolve all patterns (eg. files, exclude)
@@ -173,6 +164,7 @@ module.exports = function(config) {
             '/node_modules': `http://localhost:${port}/base/node_modules`,
             '/tests': `http://localhost:${port}/base/tests`,
             '/assets': `http://localhost:${port}/base/tests/assets`,
+            '/screenshot': `http://localhost:8081/screenshot`,
         },
 
         client: {
diff --git a/package.json b/package.json
index 6ec10be..65b4866 100644
--- a/package.json
+++ b/package.json
@@ -28,12 +28,14 @@
     "babel-preset-es2015": "6.24.1",
     "babel-preset-flow": "6.23.0",
     "base64-arraybuffer": "0.1.5",
+    "body-parser": "1.17.2",
     "chai": "4.1.1",
     "chromeless": "^1.2.0",
     "eslint": "4.2.0",
     "eslint-plugin-flowtype": "2.35.0",
     "eslint-plugin-prettier": "2.1.2",
     "express": "4.15.4",
+    "filenamify-url": "1.0.0",
     "flow-bin": "0.50.0",
     "glob": "7.1.2",
     "jquery": "3.2.1",
@@ -45,6 +47,7 @@
     "karma-mocha": "1.3.0",
     "karma-sauce-launcher": "1.1.0",
     "mocha": "3.5.0",
+    "platform": "1.3.4",
     "prettier": "1.5.3",
     "promise-polyfill": "6.0.2",
     "rimraf": "2.6.1",
@@ -59,7 +62,7 @@
     "flow": "flow",
     "lint": "eslint src/**",
     "test": "npm run flow && npm run lint && npm run karma",
-    "karma": "karma start --single-run",
+    "karma": "karma start",
     "watch": "webpack --progress --colors --watch"
   },
   "homepage": "https://html2canvas.hertzen.com",
diff --git a/scripts/screenshot-server.js b/scripts/screenshot-server.js
new file mode 100644
index 0000000..797c9ad
--- /dev/null
+++ b/scripts/screenshot-server.js
@@ -0,0 +1,69 @@
+const path = require('path');
+const fs = require('fs');
+const express = require('express');
+const bodyParser = require('body-parser');
+const filenamifyUrl = require('filenamify-url');
+
+const app = express();
+app.use(
+    bodyParser.json({
+        limit: '15mb',
+        type: '*/*'
+    })
+);
+
+const prefix = 'data:image/png;base64,';
+
+const writeScreenshot = (buffer, body) => {
+    const filename = `${filenamifyUrl(
+        body.test.replace(/^\/tests\/reftests\//, '').replace(/\.html$/, ''),
+        {replacement: '-'}
+    )}!${body.platform.name}-${body.platform.version}.png`;
+
+    fs.writeFileSync(path.resolve(__dirname, '../tests/results/', filename), buffer);
+};
+
+app.post('/screenshot', (req, res) => {
+    if (!req.body || !req.body.screenshot) {
+        return res.sendStatus(400);
+    }
+
+    const buffer = new Buffer(req.body.screenshot.substring(prefix.length), 'base64');
+    writeScreenshot(buffer, req.body);
+    return res.sendStatus(200);
+});
+
+const chunks = {};
+
+app.post('/screenshot/chunk', (req, res) => {
+    if (!req.body || !req.body.screenshot) {
+        return res.sendStatus(400);
+    }
+
+    const key = `${req.body.platform.name}-${req.body.platform.version}-${req.body.test
+        .replace(/^\/tests\/reftests\//, '')
+        .replace(/\.html$/, '')}`;
+    if (!Array.isArray(chunks[key])) {
+        chunks[key] = Array.from(Array(req.body.totalCount));
+    }
+
+    chunks[key][req.body.part] = req.body.screenshot;
+
+    if (chunks[key].every(s => typeof s === 'string')) {
+        const str = chunks[key].reduce((acc, s) => acc + s, '');
+        const buffer = new Buffer(str.substring(prefix.length), 'base64');
+        delete chunks[key];
+        writeScreenshot(buffer, req.body);
+    }
+
+    return res.sendStatus(200);
+});
+
+app.use((error, req, res, next) => {
+    console.error(error);
+    next();
+});
+
+const listener = app.listen(8081, () => {
+    console.log(listener.address().port);
+});
diff --git a/src/Feature.js b/src/Feature.js
index 91786f3..2e158da 100644
--- a/src/Feature.js
+++ b/src/Feature.js
@@ -75,8 +75,15 @@ const testSVG = document => {
 const testForeignObject = document => {
     const img = new Image();
     const canvas = document.createElement('canvas');
+    canvas.width = 1;
+    canvas.height = 1;
     const ctx = canvas.getContext('2d');
-    img.src = `data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><foreignObject><div></div></foreignObject></svg>`;
+    ctx.fillStyle = 'red';
+    ctx.fillRect(0, 0, 1, 1);
+
+    img.src = `data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><foreignObject><img src="${encodeURIComponent(
+        canvas.toDataURL()
+    )}" /></foreignObject></svg>`;
 
     return new Promise(resolve => {
         const onload = () => {
diff --git a/src/index.js b/src/index.js
index 1faf848..126e9a1 100644
--- a/src/index.js
+++ b/src/index.js
@@ -18,6 +18,7 @@ import Color, {TRANSPARENT} from './Color';
 export type Options = {
     async: ?boolean,
     allowTaint: ?boolean,
+    backgroundColor: string,
     canvas: ?HTMLCanvasElement,
     imageTimeout: number,
     proxy: ?string,
@@ -71,14 +72,18 @@ const html2canvas = (element: HTMLElement, config: Options): Promise<*> => {
     const documentBackgroundColor = ownerDocument.documentElement
         ? new Color(getComputedStyle(ownerDocument.documentElement).backgroundColor)
         : TRANSPARENT;
+    const bodyBackgroundColor = ownerDocument.body
+        ? new Color(getComputedStyle(ownerDocument.body).backgroundColor)
+        : TRANSPARENT;
+
     const backgroundColor =
         element === ownerDocument.documentElement
             ? documentBackgroundColor.isTransparent()
-              ? ownerDocument.body
-                ? new Color(getComputedStyle(ownerDocument.body).backgroundColor)
-                : null
+              ? bodyBackgroundColor.isTransparent()
+                ? options.backgroundColor ? new Color(options.backgroundColor) : null
+                : bodyBackgroundColor
               : documentBackgroundColor
-            : null;
+            : options.backgroundColor ? new Color(options.backgroundColor) : null;
 
     // $FlowFixMe
     const result = Feature.SUPPORT_FOREIGNOBJECT_DRAWING.then(
diff --git a/tests/reftests/ignore.txt b/tests/reftests/ignore.txt
index f037e33..e69de29 100644
--- a/tests/reftests/ignore.txt
+++ b/tests/reftests/ignore.txt
@@ -1,5 +0,0 @@
-/tests/reftests/background/radial-gradient.html
-/tests/reftests/text/chinese.html
-[Edge]/tests/reftests/acid2.html
-[Edge]/tests/reftests/pseudoelements.html
-[Edge]/tests/reftests/text/multiple.html
diff --git a/tests/sauceconnect.js b/tests/sauceconnect.js
index 04b54a4..05e99a2 100644
--- a/tests/sauceconnect.js
+++ b/tests/sauceconnect.js
@@ -4,7 +4,12 @@ sauceConnectLauncher(
     {
         username: process.env.SAUCE_USERNAME,
         accessKey: process.env.SAUCE_ACCESS_KEY,
-        logger: console.log
+        logger: console.log,
+        // Log output from the `sc` process to stdout?
+        verbose: true,
+
+        // Enable verbose debugging (optional)
+        verboseDebugging: true
     },
     err => {
         if (err) {
diff --git a/tests/testrunner.js b/tests/testrunner.js
index 2fa3998..0d3a13e 100644
--- a/tests/testrunner.js
+++ b/tests/testrunner.js
@@ -2,6 +2,8 @@ import {expect} from 'chai';
 import parseRefTest from '../scripts/parse-reftest';
 import reftests from './reftests';
 import querystring from 'querystring';
+import platform from 'platform';
+import Promise from 'promise-polyfill';
 
 const DOWNLOAD_REFTESTS = false;
 const query = querystring.parse(location.search.replace(/^\?/, ''));
@@ -78,7 +80,7 @@ const assertPath = (result, expected, desc) => {
             })
             .forEach(url => {
                 describe(url, function() {
-                    this.timeout(30000);
+                    this.timeout(60000);
                     const windowWidth = 800;
                     const windowHeight = 600;
                     const testContainer = document.createElement('iframe');
@@ -113,7 +115,8 @@ const assertPath = (result, expected, desc) => {
                     it('Should render untainted canvas', () => {
                         return testContainer.contentWindow
                             .html2canvas(testContainer.contentWindow.document.documentElement, {
-                                removeContainer: true
+                                removeContainer: true,
+                                backgroundColor: '#ffffff'
                             })
                             .then(canvas => {
                                 try {
@@ -330,6 +333,80 @@ const assertPath = (result, expected, desc) => {
                                         result
                                     );
                                 }
+
+                                // window.__karma__
+                                if (false) {
+                                    const MAX_CHUNK_SIZE = 75000;
+
+                                    const sendScreenshot = (tries, body, url) => {
+                                        return new Promise((resolve, reject) => {
+                                            const xhr = new XMLHttpRequest();
+
+                                            xhr.onload = () => {
+                                                if (
+                                                    typeof xhr.status !== 'number' ||
+                                                    xhr.status === 200
+                                                ) {
+                                                    resolve();
+                                                } else {
+                                                    reject(
+                                                        `Failed to send screenshot with status ${xhr.status}`
+                                                    );
+                                                }
+                                            };
+                                            //   xhr.onerror = reject;
+
+                                            xhr.open('POST', url, true);
+                                            xhr.send(body);
+                                        }).catch(e => {
+                                            if (tries > 0) {
+                                                // Older edge browsers and some safari browsers have issues sending large xhr through saucetunnel
+                                                const data = canvas.toDataURL();
+                                                const totalCount = Math.ceil(
+                                                    data.length / MAX_CHUNK_SIZE
+                                                );
+                                                return Promise.all(
+                                                    Array.apply(
+                                                        null,
+                                                        Array(totalCount)
+                                                    ).map((x, part) =>
+                                                        sendScreenshot(
+                                                            0,
+                                                            JSON.stringify({
+                                                                screenshot: data.substr(
+                                                                    part * MAX_CHUNK_SIZE,
+                                                                    MAX_CHUNK_SIZE
+                                                                ),
+                                                                part,
+                                                                totalCount,
+                                                                test: url,
+                                                                platform: {
+                                                                    name: platform.name,
+                                                                    version: platform.version
+                                                                }
+                                                            }),
+                                                            '/screenshot/chunk'
+                                                        )
+                                                    )
+                                                );
+                                            }
+
+                                            return Promise.reject(e);
+                                        });
+                                    };
+                                    return sendScreenshot(
+                                        1,
+                                        JSON.stringify({
+                                            screenshot: canvas.toDataURL(),
+                                            test: url,
+                                            platform: {
+                                                name: platform.name,
+                                                version: platform.version
+                                            }
+                                        }),
+                                        '/screenshot'
+                                    );
+                                }
                             });
                     });
                 });