diff --git a/make.js b/make.js
index 727e740ca..cc6274fac 100755
--- a/make.js
+++ b/make.js
@@ -1,5 +1,7 @@
 #!/usr/bin/env node
 require('./external/shelljs/make');
+var fs = require('fs');
+var vm = require('vm');
 
 var ROOT_DIR = __dirname + '/', // absolute path to project's root
     BUILD_DIR = 'build/',
@@ -15,6 +17,49 @@ var ROOT_DIR = __dirname + '/', // absolute path to project's root
     MOZCENTRAL_STREAM_CONVERTER_ID = 'd0c5195d-e798-49d4-b1d3-9324328b2291',
     FIREFOX_STREAM_CONVERTER_ID = '6457a96b-2d68-439a-bcfa-44465fbcdbb1';
 
+function preprocess(inFilename, outFilename, flags) {
+  // TODO make this really read line by line.
+  var lines = fs.readFileSync(inFilename).toString().split("\n");
+  var totalLines = lines.length;
+  var out = '';
+  var i = 0;
+  function readLine() {
+    if (i < totalLines) {
+      return lines[i++];
+    }
+    return null;
+  }
+  function writeLine(line) {
+    out += line + '\n';
+  }
+
+  var s, state = 0, stack = [];
+  while ((s = readLine()) !== null) {
+    var m = new RegExp(/^\/\/\s*#(if|else|endif)\b(?:\s+(.*))?/).exec(s);
+    if (m) {
+      if (m[1] === "if") {
+        stack.push(state);
+        state = vm.runInNewContext(m[2], flags) ? 3 : 1;
+      } else if (m[1] === "else") {
+        state = state === 1 ? 3 : 2;
+      } else {
+        state = stack.pop();
+      }
+    } else {
+      if (state === 0) {
+        writeLine(s);
+      } else if(state === 3) {
+        writeLine(s.replace(/^\/\//g, "  "));
+      }
+    }
+  }
+  fs.writeFileSync(outFilename, out);
+}
+
+target.pre = function() {
+  preprocess('in.txt', 'out.txt', {B2G: true});
+}
+
 //
 // make all
 //
@@ -482,6 +527,49 @@ target.mozcentral = function() {
   cp('-Rf', 'test/mozcentral/*', MOZCENTRAL_TEST_DIR);
 };
 
+target.b2g = function() {
+  echo();
+  echo('### Building B2G (Firefox OS App)');
+  var B2G_BUILD_DIR = BUILD_DIR + '/b2g/',
+      B2G_BUILD_CONTENT_DIR = B2G_BUILD_DIR + '/content/';
+  target.production();
+  target.buildnumber();
+  
+    // Clear out everything in the b2g build directory
+  cd(ROOT_DIR);
+  rm('-Rf', B2G_BUILD_DIR);
+  mkdir('-p', B2G_BUILD_CONTENT_DIR);
+  mkdir('-p', B2G_BUILD_CONTENT_DIR + BUILD_DIR);
+  mkdir('-p', B2G_BUILD_CONTENT_DIR + '/web');
+
+  // Copy a standalone version of pdf.js inside the content directory
+  cp(BUILD_TARGET, B2G_BUILD_CONTENT_DIR + BUILD_DIR);
+  cp('-R', EXTENSION_WEB_FILES, B2G_BUILD_CONTENT_DIR + '/web');
+  cp('web/viewer-snippet-b2g.html', B2G_BUILD_CONTENT_DIR + '/web/');
+  // Replacing the l10n.js file with regular gh-pages one
+  rm(B2G_BUILD_CONTENT_DIR + '/web/l10n.js');
+  cp('external/webL10n/l10n.js', B2G_BUILD_CONTENT_DIR + '/web');
+  cp('web/locale.properties', B2G_BUILD_CONTENT_DIR + '/web');
+
+  mv('-f', B2G_BUILD_CONTENT_DIR + '/web/viewer-production.html',
+     B2G_BUILD_CONTENT_DIR + '/web/viewer.html');
+  cd(B2G_BUILD_CONTENT_DIR + '/web');
+  sed('-i', /.*PDFJSSCRIPT_INCLUDE_B2G.*\n/, cat('viewer-snippet-b2g.html'),  'viewer.html');
+  rm('viewer-snippet-b2g.html');
+  cd(ROOT_DIR);
+
+  var flags = {
+    B2G: true
+  };
+  var prep = [
+    B2G_BUILD_CONTENT_DIR + '/web/viewer.js',
+    B2G_BUILD_CONTENT_DIR + '/build/pdf.js'
+  ];
+  for (var i in prep) {
+    preprocess(prep[i], prep[i], flags);
+  }
+};
+
 //
 // make chrome
 //
diff --git a/src/core.js b/src/core.js
index e8d008074..6d051b152 100644
--- a/src/core.js
+++ b/src/core.js
@@ -29,9 +29,11 @@ function getPdf(arg, callback) {
   var params = arg;
   if (typeof arg === 'string')
     params = { url: arg };
-
+//#if !B2G
   var xhr = new XMLHttpRequest();
-
+//#else
+//var xhr = new XMLHttpRequest({mozSystem: true});
+//#endif
   xhr.open('GET', params.url);
 
   var headers = params.headers;
diff --git a/web/viewer.html b/web/viewer.html
index 58b35464f..d7a57fee4 100644
--- a/web/viewer.html
+++ b/web/viewer.html
@@ -38,6 +38,7 @@
       
       
      
+    
     
     
   
diff --git a/web/viewer.js b/web/viewer.js
index 4de66b5af..f6874f9a9 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -1880,8 +1880,9 @@ window.addEventListener('load', function webViewerLoad(evt) {
       PDFView.sidebarOpen = outerContainer.classList.contains('sidebarOpen');
       PDFView.renderHighestPriority();
     });
-
+//#if !B2G
   PDFView.open(file, 0);
+//#endif
 }, true);
 
 function updateViewarea() {
@@ -2140,3 +2141,21 @@ window.addEventListener('afterprint', function afterPrint(evt) {
   window.addEventListener('mozfullscreenchange', fullscreenChange, false);
   window.addEventListener('webkitfullscreenchange', fullscreenChange, false);
 })();
+
+//#if B2G
+// window.navigator.mozSetMessageHandler('activity', function(activity) {
+//   var url = activity.source.data.url;
+//   // Temporarily get the data here since the cross domain xhr is broken in
+//   // the worker currently, see bug 761227.
+//   var params = {
+//     url: url,
+//     error: function(e) {
+//       PDFView.error(mozL10n.get('loading_error', null,
+//                     'An error occurred while loading the PDF.'), e);
+//     }
+//   };
+//   PDFJS.getPdf(params, function successCallback(data) {
+//     PDFView.open(data, 0);
+//   });
+// });
+//#endif