diff --git a/make.js b/make.js
index cc6274fac..bb9896391 100755
--- a/make.js
+++ b/make.js
@@ -1,6 +1,7 @@
#!/usr/bin/env node
require('./external/shelljs/make');
var fs = require('fs');
+var path = require('path');
var vm = require('vm');
var ROOT_DIR = __dirname + '/', // absolute path to project's root
@@ -10,6 +11,7 @@ var ROOT_DIR = __dirname + '/', // absolute path to project's root
EXTENSION_SRC_DIR = 'extensions/',
LOCALE_SRC_DIR = 'l10n/',
GH_PAGES_DIR = BUILD_DIR + 'gh-pages/',
+ GENERIC_DIR = BUILD_DIR + 'generic/',
REPO = 'git@github.com:mozilla/pdf.js.git',
PYTHON_BIN = 'python2.7',
MOZCENTRAL_PREF_PREFIX = 'pdfjs',
@@ -17,48 +19,147 @@ 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 DEFINES = {
+ PRODUCTION: true,
+ // The main build targets:
+ GENERIC: false,
+ FIREFOX: false,
+ MOZCENTRAL: false,
+ B2G: false,
+ CHROME: false
+};
- 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;
+function extendDefines(obj) {
+ var ret = {};
+ for (var key in DEFINES)
+ ret[key] = DEFINES[key];
+ for (key in obj)
+ ret[key] = obj[key];
+ return ret;
+}
+
+var BuildHelper = {
+ /**
+ * A simple preprocessor that is based on the firefox preprocessor
+ * see (https://developer.mozilla.org/en/Build/Text_Preprocessor). The main
+ * difference is that this supports a subset of the commands and it supports
+ * preproccesor commands in html style comments.
+ * Currently Supported commands:
+ * - if
+ * - else
+ * - endif
+ * - include
+ * - expand
+ */
+ preprocess: function preprocess(inFilename, outFilename, defines) {
+ // 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;
+ }
+ var writeLine = typeof outFilename === 'function' ? outFilename : function(line) {
+ out += line + '\n';
+ }
+ function include(file) {
+ var realPath = fs.realpathSync(inFilename);
+ var dir = path.dirname(realPath);
+ preprocess(path.join(dir, file), writeLine, defines);
+ }
+ function expand(line) {
+ line = line.replace(/__[\w]+__/g, function(variable) {
+ variable = variable.substring(2, variable.length - 2);
+ if (variable in defines) {
+ return defines[variable];
+ }
+ return '';
+ });
+ writeLine(line);
+ }
+
+ var s, state = 0, stack = [];
+ var control = /^(?:\/\/|)?$)?/;
+ var lineNumber = 0;
+ while ((s = readLine()) !== null) {
+ ++lineNumber;
+ var m = control.exec(s);
+ if (m) {
+ switch (m[1]) {
+ case 'if':
+ stack.push(state);
+ try {
+ state = vm.runInNewContext(m[2], defines) ? 3 : 1;
+ } catch (e) {
+ console.error('Could not evalute line \'' + m[2] + '\' at ' +
+ fs.realpathSync(inFilename) + ':' + lineNumber);
+ throw e;
+ }
+ break;
+ case 'else':
+ state = state === 1 ? 3 : 2;
+ break;
+ case 'endif':
+ state = stack.pop();
+ break;
+ case 'expand':
+ if (state === 0 || state === 3)
+ expand(m[2]);
+ break;
+ case 'include':
+ if (state === 0 || state === 3)
+ include(m[2]);
+ break;
+ }
} else {
- state = stack.pop();
- }
- } else {
- if (state === 0) {
- writeLine(s);
- } else if(state === 3) {
- writeLine(s.replace(/^\/\//g, " "));
+ if (state === 0) {
+ writeLine(s);
+ } else if(state === 3) {
+ writeLine(s.replace(/^\/\/|^/g, " "));
+ }
}
}
- }
- fs.writeFileSync(outFilename, out);
-}
+ if (state !== 0 || stack.length !== 0)
+ throw new Error('Missing endif in preprocessor.');
+ if (typeof outFilename !== 'function')
+ fs.writeFileSync(outFilename, out);
+ },
+ /**
+ * Simplifies common build steps.
+ * @param setup
+ * .defines defines for preprocessors
+ * .copy array of arrays of source and destination pairs of files to copy
+ * .preprocess array of arrays of source and destination pairs of files
+ * run through preprocessor
+ */
+ build: function build(setup) {
+ var defines = setup.defines;
-target.pre = function() {
- preprocess('in.txt', 'out.txt', {B2G: true});
-}
+ setup.copy.forEach(function(option) {
+ var source = option[0];
+ var destination = option[1];
+ cp('-R', source, destination);
+ });
+
+ setup.preprocess.forEach(function(option) {
+ var sources = option[0];
+ var destination = option[1];
+
+ sources = ls('-R', sources);
+ sources.forEach(function(source) {
+ // ??? Warn if the source is wildcard and dest is file?
+ var destWithFolder = destination;
+ if (test('-d', destination))
+ destWithFolder += '/' + path.basename(source);
+ BuildHelper.preprocess(source, destWithFolder, defines);
+ });
+ });
+ }
+};
//
// make all
@@ -76,14 +177,59 @@ target.all = function() {
// Production stuff
//
+// Files that need to be included in every build.
+var COMMON_WEB_FILES =
+ ['web/viewer.css',
+ 'web/images',
+ 'web/debugger.js'],
+ COMMON_WEB_FILES_PREPROCESS =
+ ['web/viewer.js',
+ 'web/viewer.html'];
+
+//
+// make generic
+// Builds the generic production viewer that should be compatible with most
+// modern HTML5 browsers.
+//
+target.generic = function() {
+ target.bundle();
+ target.locale();
+
+ cd(ROOT_DIR);
+ echo();
+ echo('### Creating generic viewer');
+
+ rm('-rf', GENERIC_DIR);
+ mkdir('-p', GENERIC_DIR);
+ mkdir('-p', GENERIC_DIR + BUILD_DIR);
+ mkdir('-p', GENERIC_DIR + '/web');
+
+ var defines = extendDefines({GENERIC: true});
+
+ var setup = {
+ defines: defines,
+ copy: [
+ [COMMON_WEB_FILES, GENERIC_DIR + '/web'],
+ ['external/webL10n/l10n.js', GENERIC_DIR + '/web'],
+ ['web/compatibility.js', GENERIC_DIR + '/web'],
+ ['web/compressed.tracemonkey-pldi-09.pdf', GENERIC_DIR + '/web'],
+ ['web/locale.properties', GENERIC_DIR + '/web']
+ ],
+ preprocess: [
+ [BUILD_TARGET, GENERIC_DIR + BUILD_TARGET],
+ [COMMON_WEB_FILES_PREPROCESS, GENERIC_DIR + '/web']
+ ]
+ };
+ BuildHelper.build(setup);
+};
+
//
// make web
// Generates the website for the project, by checking out the gh-pages branch underneath
// the build directory, and then moving the various viewer files into place.
//
target.web = function() {
- target.production();
- target.locale();
+ target.generic();
target.extension();
target.pagesrepo();
@@ -91,25 +237,18 @@ target.web = function() {
echo();
echo('### Creating web site');
- var GH_PAGES_SRC_FILES = [
- 'web/*',
- 'external/webL10n/l10n.js'
- ];
-
- cp(BUILD_TARGET, GH_PAGES_DIR + BUILD_TARGET);
- cp('-R', GH_PAGES_SRC_FILES, GH_PAGES_DIR + '/web');
+ cp('-R', GENERIC_DIR + '/*', GH_PAGES_DIR);
cp(FIREFOX_BUILD_DIR + '/*.xpi', FIREFOX_BUILD_DIR + '/*.rdf',
- GH_PAGES_DIR + EXTENSION_SRC_DIR + 'firefox/');
- cp(GH_PAGES_DIR + '/web/index.html.template', GH_PAGES_DIR + '/index.html');
- mv('-f', GH_PAGES_DIR + '/web/viewer-production.html',
- GH_PAGES_DIR + '/web/viewer.html');
+ GH_PAGES_DIR + EXTENSION_SRC_DIR + 'firefox/');
+ cp('web/index.html.template', GH_PAGES_DIR + '/index.html');
+
cd(GH_PAGES_DIR);
exec('git add -A');
echo();
echo("Website built in " + GH_PAGES_DIR);
echo("Don't forget to cd into " + GH_PAGES_DIR +
- " and issue 'git commit' to push changes.");
+ " and issue 'git commit' to push changes.");
};
//
@@ -169,20 +308,10 @@ target.locale = function() {
chromeManifestContent.to(CHROME_MANIFEST_OUTPUT);
};
-//
-// make production
-// Creates production output (pdf.js, and corresponding changes to web/ files)
-//
-target.production = function() {
- target.bundle();
- target.viewer();
-};
-
//
// make bundle
// Bundles all source files into one wrapper 'pdf.js' file, in the given order.
//
-
target.bundle = function() {
cd(ROOT_DIR);
echo();
@@ -223,29 +352,12 @@ target.bundle = function() {
bundleVersion = exec('git log --format="%h" -n 1',
{silent: true}).output.replace('\n', '');
- sed(/.*PDFJSSCRIPT_INCLUDE_ALL.*\n/, bundle, 'pdf.js')
- .to(ROOT_DIR + BUILD_TARGET);
- sed('-i', 'PDFJSSCRIPT_BUNDLE_VER', bundleVersion, ROOT_DIR + BUILD_TARGET);
+ // This just preprocesses the empty pdf.js file, we don't actually want to
+ // preprocess everything yet since other build targets use this file.
+ BuildHelper.preprocess('pdf.js', ROOT_DIR + BUILD_TARGET,
+ {BUNDLE: bundle, BUNDLE_VERSION: bundleVersion});
};
-//
-// make viewer
-// Changes development
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/web/viewer.js b/web/viewer.js
index f6874f9a9..e2b2e1260 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -90,6 +90,7 @@ var ProgressBar = (function ProgressBarClosure() {
return ProgressBar;
})();
+//#if FIREFOX || MOZCENTRAL
var FirefoxCom = (function FirefoxComClosure() {
return {
/**
@@ -150,6 +151,7 @@ var FirefoxCom = (function FirefoxComClosure() {
}
};
})();
+//#endif
// Settings Manager - This is a utility for saving settings
// First we see if localStorage is available
@@ -167,17 +169,17 @@ var Settings = (function SettingsClosure() {
}
})();
- var isFirefoxExtension = PDFJS.isFirefoxExtension;
-
function Settings(fingerprint) {
var database = null;
var index;
- if (isFirefoxExtension)
- database = FirefoxCom.requestSync('getDatabase', null) || '{}';
- else if (isLocalStorageEnabled)
+//#if !(FIREFOX || MOZCENTRAL)
+ if (isLocalStorageEnabled)
database = localStorage.getItem('database') || '{}';
else
return false;
+//#else
+// database = FirefoxCom.requestSync('getDatabase', null) || '{}';
+//#endif
database = JSON.parse(database);
if (!('files' in database))
@@ -205,10 +207,12 @@ var Settings = (function SettingsClosure() {
var file = this.file;
file[name] = val;
var database = JSON.stringify(this.database);
- if (isFirefoxExtension)
- FirefoxCom.requestSync('setDatabase', database);
- else if (isLocalStorageEnabled)
+//#if !(FIREFOX || MOZCENTRAL)
+ if (isLocalStorageEnabled)
localStorage.setItem('database', database);
+//#else
+// FirefoxCom.requestSync('setDatabase', database);
+//#endif
},
get: function settingsGet(name, defaultValue) {
@@ -460,52 +464,54 @@ var PDFView = {
}
var url = this.url.split('#')[0];
- if (PDFJS.isFirefoxExtension) {
- // Document isn't ready just try to download with the url.
- if (!this.pdfDocument) {
- noData();
- return;
- }
- this.pdfDocument.getData().then(
- function getDataSuccess(data) {
- var bb = new MozBlobBuilder();
- bb.append(data.buffer);
- var blobUrl = window.URL.createObjectURL(
- bb.getBlob('application/pdf'));
-
- FirefoxCom.request('download', { blobUrl: blobUrl, originalUrl: url },
- function response(err) {
- if (err) {
- // This error won't really be helpful because it's likely the
- // fallback won't work either (or is already open).
- PDFView.error('PDF failed to download.');
- }
- window.URL.revokeObjectURL(blobUrl);
- }
- );
- },
- noData // Error ocurred try downloading with just the url.
- );
- } else {
- url += '#pdfjs.action=download', '_parent';
- window.open(url, '_parent');
- }
+//#if !(FIREFOX || MOZCENTRAL)
+ url += '#pdfjs.action=download', '_parent';
+ window.open(url, '_parent');
+//#else
+// // Document isn't ready just try to download with the url.
+// if (!this.pdfDocument) {
+// noData();
+// return;
+// }
+// this.pdfDocument.getData().then(
+// function getDataSuccess(data) {
+// var bb = new MozBlobBuilder();
+// bb.append(data.buffer);
+// var blobUrl = window.URL.createObjectURL(
+// bb.getBlob('application/pdf'));
+//
+// FirefoxCom.request('download', { blobUrl: blobUrl, originalUrl: url },
+// function response(err) {
+// if (err) {
+// // This error won't really be helpful because it's likely the
+// // fallback won't work either (or is already open).
+// PDFView.error('PDF failed to download.');
+// }
+// window.URL.revokeObjectURL(blobUrl);
+// }
+// );
+// },
+// noData // Error ocurred try downloading with just the url.
+// );
+//#endif
},
fallback: function pdfViewFallback() {
- if (!PDFJS.isFirefoxExtension)
+//#if !(FIREFOX || MOZCENTRAL)
return;
- // Only trigger the fallback once so we don't spam the user with messages
- // for one PDF.
- if (this.fellback)
- return;
- this.fellback = true;
- var url = this.url.split('#')[0];
- FirefoxCom.request('fallback', url, function response(download) {
- if (!download)
- return;
- PDFView.download();
- });
+//#else
+// // Only trigger the fallback once so we don't spam the user with messages
+// // for one PDF.
+// if (this.fellback)
+// return;
+// this.fellback = true;
+// var url = this.url.split('#')[0];
+// FirefoxCom.request('fallback', url, function response(download) {
+// if (!download)
+// return;
+// PDFView.download();
+// });
+//#endif
},
navigateTo: function pdfViewNavigateTo(dest) {
@@ -557,9 +563,11 @@ var PDFView = {
* @param {String} anchor The anchor hash include the #.
*/
getAnchorUrl: function getAnchorUrl(anchor) {
- if (PDFJS.isFirefoxExtension)
- return this.url.split('#')[0] + anchor;
+//#if !(FIREFOX || MOZCENTRAL)
return anchor;
+//#else
+// return this.url.split('#')[0] + anchor;
+//#endif
},
/**
@@ -593,11 +601,7 @@ var PDFView = {
}
}
}
- if (PDFJS.isFirefoxExtension) {
- console.error(message + '\n' + moreInfoText);
- this.fallback();
- return;
- }
+//#if !(FIREFOX || MOZCENTRAL)
var errorWrapper = document.getElementById('errorWrapper');
errorWrapper.removeAttribute('hidden');
@@ -627,6 +631,10 @@ var PDFView = {
errorMoreInfo.value = moreInfoText;
errorMoreInfo.rows = moreInfoText.split('\n').length - 1;
+//#else
+// console.error(message + '\n' + moreInfoText);
+// this.fallback();
+//#endif
},
progress: function pdfViewProgress(level) {
@@ -1804,15 +1812,21 @@ window.addEventListener('load', function webViewerLoad(evt) {
PDFView.initialize();
var params = PDFView.parseQueryString(document.location.search.substring(1));
- var file = PDFJS.isFirefoxExtension ?
- window.location.toString() : params.file || kDefaultURL;
+//#if !(FIREFOX || MOZCENTRAL)
+ var file = params.file || kDefaultURL;
+//#else
+//var file = window.location.toString()
+//#endif
- if (PDFJS.isFirefoxExtension || !window.File || !window.FileReader ||
- !window.FileList || !window.Blob) {
+//#if !(FIREFOX || MOZCENTRAL)
+ if (!window.File || !window.FileReader || !window.FileList || !window.Blob) {
document.getElementById('openFile').setAttribute('hidden', 'true');
} else {
document.getElementById('fileInput').value = null;
}
+//#else
+//document.getElementById('openFile').setAttribute('hidden', 'true');
+//#endif
// Special debugging flags in the hash section of the URL.
var hash = document.location.hash.substring(1);
@@ -1821,18 +1835,21 @@ window.addEventListener('load', function webViewerLoad(evt) {
if ('disableWorker' in hashParams)
PDFJS.disableWorker = (hashParams['disableWorker'] === 'true');
- if (!PDFJS.isFirefoxExtension) {
- var locale = navigator.language;
- if ('locale' in hashParams)
- locale = hashParams['locale'];
- mozL10n.language.code = locale;
- }
+//#if !(FIREFOX || MOZCENTRAL)
+ var locale = navigator.language;
+ if ('locale' in hashParams)
+ locale = hashParams['locale'];
+ mozL10n.language.code = locale;
+//#endif
if ('disableTextLayer' in hashParams)
PDFJS.disableTextLayer = (hashParams['disableTextLayer'] === 'true');
- if ('pdfBug' in hashParams &&
- (!PDFJS.isFirefoxExtension || FirefoxCom.requestSync('pdfBugEnabled'))) {
+//#if !(FIREFOX || MOZCENTRAL)
+ if ('pdfBug' in hashParams) {
+//#else
+//if ('pdfBug' in hashParams && FirefoxCom.requestSync('pdfBugEnabled')) {
+//#endif
PDFJS.pdfBug = true;
var pdfBug = hashParams['pdfBug'];
var enabled = pdfBug.split(',');
@@ -1840,10 +1857,12 @@ window.addEventListener('load', function webViewerLoad(evt) {
PDFBug.init();
}
- if (!PDFJS.isFirefoxExtension ||
- (PDFJS.isFirefoxExtension && FirefoxCom.requestSync('searchEnabled'))) {
- document.querySelector('#viewSearch').classList.remove('hidden');
- }
+//#if !(FIREFOX || MOZCENTRAL)
+//#else
+//if (FirefoxCom.requestSync('searchEnabled')) {
+// document.querySelector('#viewSearch').classList.remove('hidden');
+//}
+//#endif
if (!PDFView.supportsPrinting) {
document.getElementById('print').classList.add('hidden');
@@ -2143,19 +2162,19 @@ window.addEventListener('afterprint', function afterPrint(evt) {
})();
//#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);
-// });
-// });
+//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