diff --git a/src/core.js b/src/core.js
index 0e6f13e97..ed16e1a42 100644
--- a/src/core.js
+++ b/src/core.js
@@ -7,7 +7,6 @@ var globalScope = (typeof window === 'undefined') ? this : window;
 
 var ERRORS = 0, WARNINGS = 1, TODOS = 5;
 var verbosity = WARNINGS;
-var useWorker = false;
 
 // The global PDFJS object exposes the API
 // In production, it will be declared outside a global wrapper
@@ -470,8 +469,14 @@ var PDFDoc = (function pdfDoc() {
     this.objs = new PDFObjects();
 
     this.pageCache = [];
+    this.workerReadyPromise = new Promise('workerReady');
 
-    if (useWorker) {
+    // If worker support isn't disabled explicit and the browser has worker
+    // support, create a new web worker and test if it/the browser fullfills
+    // all requirements to run parts of pdf.js in a web worker.
+    // Right now, the requirement is, that an Uint8Array is still an Uint8Array
+    // as it arrives on the worker. Chrome added this with version 15.
+    if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') {
       var workerSrc = PDFJS.workerSrc;
       if (typeof workerSrc === 'undefined') {
         throw 'No PDFJS.workerSrc specified';
@@ -479,105 +484,121 @@ var PDFDoc = (function pdfDoc() {
 
       var worker = new Worker(workerSrc);
 
+      var messageHandler = new MessageHandler('main', worker);
+
       // Tell the worker the file it was created from.
-      worker.postMessage({
-        action: 'workerSrc',
-        data: workerSrc
-      });
+      messageHandler.send('workerSrc', workerSrc);
+
+      messageHandler.on('test', function pdfDocTest(supportTypedArray) {
+        if (supportTypedArray) {
+          this.worker = worker;
+          this.setupMessageHandler(messageHandler);
+        } else {
+          this.setupFakeWorker();
+        }
+      }.bind(this));
+
+      var testObj = new Uint8Array(1);
+      messageHandler.send('test', testObj);
     } else {
-      // If we don't use a worker, just post/sendMessage to the main thread.
-      var worker = {
-        postMessage: function pdfDocPostMessage(obj) {
-          worker.onmessage({data: obj});
-        },
-        terminate: function pdfDocTerminate() {}
-      };
+      this.setupFakeWorker();
     }
-    this.worker = worker;
 
     this.fontsLoading = {};
-
-    var processorHandler = this.processorHandler =
-                                        new MessageHandler('main', worker);
-
-    processorHandler.on('page', function pdfDocPage(data) {
-      var pageNum = data.pageNum;
-      var page = this.pageCache[pageNum];
-      var depFonts = data.depFonts;
-
-      page.startRenderingFromIRQueue(data.IRQueue, depFonts);
-    }, this);
-
-    processorHandler.on('obj', function pdfDocObj(data) {
-      var id = data[0];
-      var type = data[1];
-
-      switch (type) {
-        case 'JpegStream':
-          var IR = data[2];
-          new JpegImage(id, IR, this.objs);
-        break;
-        case 'Font':
-          var name = data[2];
-          var file = data[3];
-          var properties = data[4];
-
-          if (file) {
-            var fontFileDict = new Dict();
-            fontFileDict.map = file.dict.map;
-
-            var fontFile = new Stream(file.bytes, file.start,
-                                      file.end - file.start, fontFileDict);
-
-            // Check if this is a FlateStream. Otherwise just use the created
-            // Stream one. This makes complex_ttf_font.pdf work.
-            var cmf = file.bytes[0];
-            if ((cmf & 0x0f) == 0x08) {
-              file = new FlateStream(fontFile);
-            } else {
-              file = fontFile;
-            }
-          }
-
-          // For now, resolve the font object here direclty. The real font
-          // object is then created in FontLoader.bind().
-          this.objs.resolve(id, {
-            name: name,
-            file: file,
-            properties: properties
-          });
-        break;
-        default:
-          throw 'Got unkown object type ' + type;
-      }
-    }, this);
-
-    processorHandler.on('font_ready', function pdfDocFontReady(data) {
-      var id = data[0];
-      var font = new FontShape(data[1]);
-
-      // If there is no string, then there is nothing to attach to the DOM.
-      if (!font.str) {
-        this.objs.resolve(id, font);
-      } else {
-        this.objs.setData(id, font);
-      }
-    }.bind(this));
-
-    if (!useWorker) {
-      // If the main thread is our worker, setup the handling for the messages
-      // the main thread sends to it self.
-      WorkerProcessorHandler.setup(processorHandler);
-    }
-
-    this.workerReadyPromise = new Promise('workerReady');
-    setTimeout(function pdfDocFontReadySetTimeout() {
-      processorHandler.send('doc', this.data);
-      this.workerReadyPromise.resolve(true);
-    }.bind(this));
   }
 
   constructor.prototype = {
+    setupFakeWorker: function() {
+      // If we don't use a worker, just post/sendMessage to the main thread.
+      var fakeWorker = {
+        postMessage: function pdfDocPostMessage(obj) {
+          fakeWorker.onmessage({data: obj});
+        },
+        terminate: function pdfDocTerminate() {}
+      };
+
+      var messageHandler = new MessageHandler('main', fakeWorker);
+      this.setupMessageHandler(messageHandler);
+
+      // If the main thread is our worker, setup the handling for the messages
+      // the main thread sends to it self.
+      WorkerMessageHandler.setup(messageHandler);
+    },
+
+
+    setupMessageHandler: function(messageHandler) {
+      this.messageHandler = messageHandler;
+
+      messageHandler.on('page', function pdfDocPage(data) {
+        var pageNum = data.pageNum;
+        var page = this.pageCache[pageNum];
+        var depFonts = data.depFonts;
+
+        page.startRenderingFromIRQueue(data.IRQueue, depFonts);
+      }, this);
+
+      messageHandler.on('obj', function pdfDocObj(data) {
+        var id = data[0];
+        var type = data[1];
+
+        switch (type) {
+          case 'JpegStream':
+            var IR = data[2];
+            new JpegImage(id, IR, this.objs);
+            break;
+          case 'Font':
+            var name = data[2];
+            var file = data[3];
+            var properties = data[4];
+
+            if (file) {
+              var fontFileDict = new Dict();
+              fontFileDict.map = file.dict.map;
+
+              var fontFile = new Stream(file.bytes, file.start,
+                                        file.end - file.start, fontFileDict);
+
+              // Check if this is a FlateStream. Otherwise just use the created
+              // Stream one. This makes complex_ttf_font.pdf work.
+              var cmf = file.bytes[0];
+              if ((cmf & 0x0f) == 0x08) {
+                file = new FlateStream(fontFile);
+              } else {
+                file = fontFile;
+              }
+            }
+
+            // For now, resolve the font object here direclty. The real font
+            // object is then created in FontLoader.bind().
+            this.objs.resolve(id, {
+              name: name,
+              file: file,
+              properties: properties
+            });
+            break;
+          default:
+            throw 'Got unkown object type ' + type;
+        }
+      }, this);
+
+      messageHandler.on('font_ready', function pdfDocFontReady(data) {
+        var id = data[0];
+        var font = new FontShape(data[1]);
+
+        // If there is no string, then there is nothing to attach to the DOM.
+        if (!font.str) {
+          this.objs.resolve(id, font);
+        } else {
+          this.objs.setData(id, font);
+        }
+      }.bind(this));
+
+      setTimeout(function pdfDocFontReadySetTimeout() {
+        messageHandler.send('doc', this.data);
+        this.workerReadyPromise.resolve(true);
+      }.bind(this));
+    },
+
     get numPages() {
       return this.pdf.numPages;
     },
@@ -585,7 +606,7 @@ var PDFDoc = (function pdfDoc() {
     startRendering: function pdfDocStartRendering(page) {
       // The worker might not be ready to receive the page request yet.
       this.workerReadyPromise.then(function pdfDocStartRenderingThen() {
-        this.processorHandler.send('page_request', page.pageNumber + 1);
+        this.messageHandler.send('page_request', page.pageNumber + 1);
       }.bind(this));
     },
 
diff --git a/src/worker.js b/src/worker.js
index 74a880cae..b6ea68741 100644
--- a/src/worker.js
+++ b/src/worker.js
@@ -43,10 +43,14 @@ MessageHandler.prototype = {
   }
 };
 
-var WorkerProcessorHandler = {
+var WorkerMessageHandler = {
   setup: function wphSetup(handler) {
     var pdfDoc = null;
 
+    handler.on('test', function wphSetupTest(data) {
+      handler.send('test', data instanceof Uint8Array);
+    });
+
     handler.on('workerSrc', function wphSetupWorkerSrc(data) {
       // In development, the `workerSrc` message is handled in the
       // `worker_loader.js` file. In production the workerProcessHandler is
@@ -184,6 +188,6 @@ if (typeof window === 'undefined') {
   globalScope.console = workerConsole;
 
   var handler = new MessageHandler('worker_processor', this);
-  WorkerProcessorHandler.setup(handler);
+  WorkerMessageHandler.setup(handler);
 }