Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
9cec31a8e1
@ -14,6 +14,7 @@ const MOZ_CENTRAL = PDFJSSCRIPT_MOZ_CENTRAL;
|
|||||||
const PDFJS_EVENT_ID = 'pdf.js.message';
|
const PDFJS_EVENT_ID = 'pdf.js.message';
|
||||||
const PDF_CONTENT_TYPE = 'application/pdf';
|
const PDF_CONTENT_TYPE = 'application/pdf';
|
||||||
const PREF_PREFIX = 'PDFJSSCRIPT_PREF_PREFIX';
|
const PREF_PREFIX = 'PDFJSSCRIPT_PREF_PREFIX';
|
||||||
|
const PDF_VIEWER_WEB_PAGE = 'resource://pdf.js/web/viewer.html';
|
||||||
const MAX_DATABASE_LENGTH = 4096;
|
const MAX_DATABASE_LENGTH = 4096;
|
||||||
const FIREFOX_ID = '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}';
|
const FIREFOX_ID = '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}';
|
||||||
const SEAMONKEY_ID = '{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}';
|
const SEAMONKEY_ID = '{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}';
|
||||||
@ -122,9 +123,68 @@ function getLocalizedString(strings, id, property) {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PDF data storage
|
||||||
|
function PdfDataListener(length) {
|
||||||
|
this.length = length; // less than 0, if length is unknown
|
||||||
|
this.data = new Uint8Array(length >= 0 ? length : 0x10000);
|
||||||
|
this.loaded = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PdfDataListener.prototype = {
|
||||||
|
set: function PdfDataListener_set(chunk, offset) {
|
||||||
|
if (this.length < 0) {
|
||||||
|
var willBeLoaded = this.loaded + chunk.length;
|
||||||
|
// data length is unknown and new chunk will not fit in the existing
|
||||||
|
// buffer, resizing the buffer by doubling the its last length
|
||||||
|
if (this.data.length < willBeLoaded) {
|
||||||
|
var newLength = this.data.length;
|
||||||
|
for (; newLength < willBeLoaded; newLength *= 2) {}
|
||||||
|
var newData = new Uint8Array(newLength);
|
||||||
|
newData.set(this.data);
|
||||||
|
this.data = newData;
|
||||||
|
}
|
||||||
|
this.data.set(chunk, this.loaded);
|
||||||
|
this.loaded = willBeLoaded;
|
||||||
|
} else {
|
||||||
|
this.data.set(chunk, offset);
|
||||||
|
this.loaded = offset + chunk.length;
|
||||||
|
this.onprogress(this.loaded, this.length);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getData: function PdfDataListener_getData() {
|
||||||
|
var data = this.length >= 0 ? this.data :
|
||||||
|
this.data.subarray(0, this.loaded);
|
||||||
|
delete this.data; // releasing temporary storage
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
finish: function PdfDataListener_finish() {
|
||||||
|
this.isDataReady = true;
|
||||||
|
if (this.oncompleteCallback) {
|
||||||
|
this.oncompleteCallback(this.getData());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function PdfDataListener_error(errorCode) {
|
||||||
|
this.errorCode = errorCode;
|
||||||
|
if (this.oncompleteCallback) {
|
||||||
|
this.oncompleteCallback(null, errorCode);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onprogress: function() {},
|
||||||
|
set oncomplete(value) {
|
||||||
|
this.oncompleteCallback = value;
|
||||||
|
if (this.isDataReady) {
|
||||||
|
value(this.getData());
|
||||||
|
}
|
||||||
|
if (this.errorCode) {
|
||||||
|
value(null, this.errorCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// All the priviledged actions.
|
// All the priviledged actions.
|
||||||
function ChromeActions(domWindow) {
|
function ChromeActions(domWindow, dataListener) {
|
||||||
this.domWindow = domWindow;
|
this.domWindow = domWindow;
|
||||||
|
this.dataListener = dataListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChromeActions.prototype = {
|
ChromeActions.prototype = {
|
||||||
@ -194,6 +254,38 @@ ChromeActions.prototype = {
|
|||||||
getLocale: function() {
|
getLocale: function() {
|
||||||
return getStringPref('general.useragent.locale', 'en-US');
|
return getStringPref('general.useragent.locale', 'en-US');
|
||||||
},
|
},
|
||||||
|
getLoadingType: function() {
|
||||||
|
return this.dataListener ? 'passive' : 'active';
|
||||||
|
},
|
||||||
|
initPassiveLoading: function() {
|
||||||
|
if (!this.dataListener)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var domWindow = this.domWindow;
|
||||||
|
this.dataListener.onprogress =
|
||||||
|
function ChromeActions_dataListenerProgress(loaded, total) {
|
||||||
|
|
||||||
|
domWindow.postMessage({
|
||||||
|
pdfjsLoadAction: 'progress',
|
||||||
|
loaded: loaded,
|
||||||
|
total: total
|
||||||
|
}, '*');
|
||||||
|
};
|
||||||
|
|
||||||
|
this.dataListener.oncomplete =
|
||||||
|
function ChromeActions_dataListenerComplete(data, errorCode) {
|
||||||
|
|
||||||
|
domWindow.postMessage({
|
||||||
|
pdfjsLoadAction: 'complete',
|
||||||
|
data: data,
|
||||||
|
errorCode: errorCode
|
||||||
|
}, '*');
|
||||||
|
|
||||||
|
delete this.dataListener;
|
||||||
|
};
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
getStrings: function(data) {
|
getStrings: function(data) {
|
||||||
try {
|
try {
|
||||||
// Lazy initialization of localizedStrings
|
// Lazy initialization of localizedStrings
|
||||||
@ -341,17 +433,21 @@ PdfStreamConverter.prototype = {
|
|||||||
asyncConvertData: function(aFromType, aToType, aListener, aCtxt) {
|
asyncConvertData: function(aFromType, aToType, aListener, aCtxt) {
|
||||||
if (!isEnabled())
|
if (!isEnabled())
|
||||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||||
// Ignoring HTTP POST requests -- pdf.js has to repeat the request.
|
|
||||||
var skipConversion = false;
|
var useFetchByChrome = getBoolPref(PREF_PREFIX + '.fetchByChrome', true);
|
||||||
try {
|
if (!useFetchByChrome) {
|
||||||
var request = aCtxt;
|
// Ignoring HTTP POST requests -- pdf.js has to repeat the request.
|
||||||
request.QueryInterface(Ci.nsIHttpChannel);
|
var skipConversion = false;
|
||||||
skipConversion = (request.requestMethod !== 'GET');
|
try {
|
||||||
} catch (e) {
|
var request = aCtxt;
|
||||||
// Non-HTTP request... continue normally.
|
request.QueryInterface(Ci.nsIHttpChannel);
|
||||||
|
skipConversion = (request.requestMethod !== 'GET');
|
||||||
|
} catch (e) {
|
||||||
|
// Non-HTTP request... continue normally.
|
||||||
|
}
|
||||||
|
if (skipConversion)
|
||||||
|
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
if (skipConversion)
|
|
||||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
|
||||||
|
|
||||||
// Store the listener passed to us
|
// Store the listener passed to us
|
||||||
this.listener = aListener;
|
this.listener = aListener;
|
||||||
@ -359,8 +455,14 @@ PdfStreamConverter.prototype = {
|
|||||||
|
|
||||||
// nsIStreamListener::onDataAvailable
|
// nsIStreamListener::onDataAvailable
|
||||||
onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
|
onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
|
||||||
// Do nothing since all the data loading is handled by the viewer.
|
if (!this.dataListener) {
|
||||||
log('SANITY CHECK: onDataAvailable SHOULD NOT BE CALLED!');
|
// Do nothing since all the data loading is handled by the viewer.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var binaryStream = this.binaryStream;
|
||||||
|
binaryStream.setInputStream(aInputStream);
|
||||||
|
this.dataListener.set(binaryStream.readByteArray(aCount), aOffset);
|
||||||
},
|
},
|
||||||
|
|
||||||
// nsIRequestObserver::onStartRequest
|
// nsIRequestObserver::onStartRequest
|
||||||
@ -368,15 +470,27 @@ PdfStreamConverter.prototype = {
|
|||||||
|
|
||||||
// Setup the request so we can use it below.
|
// Setup the request so we can use it below.
|
||||||
aRequest.QueryInterface(Ci.nsIChannel);
|
aRequest.QueryInterface(Ci.nsIChannel);
|
||||||
// Cancel the request so the viewer can handle it.
|
var useFetchByChrome = getBoolPref(PREF_PREFIX + '.fetchByChrome', true);
|
||||||
aRequest.cancel(Cr.NS_BINDING_ABORTED);
|
var dataListener;
|
||||||
|
if (useFetchByChrome) {
|
||||||
|
// Creating storage for PDF data
|
||||||
|
var contentLength = aRequest.contentLength;
|
||||||
|
dataListener = new PdfDataListener(contentLength);
|
||||||
|
this.dataListener = dataListener;
|
||||||
|
this.binaryStream = Cc['@mozilla.org/binaryinputstream;1']
|
||||||
|
.createInstance(Ci.nsIBinaryInputStream);
|
||||||
|
} else {
|
||||||
|
// Cancel the request so the viewer can handle it.
|
||||||
|
aRequest.cancel(Cr.NS_BINDING_ABORTED);
|
||||||
|
}
|
||||||
|
|
||||||
// Create a new channel that is viewer loaded as a resource.
|
// Create a new channel that is viewer loaded as a resource.
|
||||||
var ioService = Services.io;
|
var ioService = Services.io;
|
||||||
var channel = ioService.newChannel(
|
var channel = ioService.newChannel(
|
||||||
'resource://pdf.js/web/viewer.html', null, null);
|
PDF_VIEWER_WEB_PAGE, null, null);
|
||||||
|
|
||||||
var listener = this.listener;
|
var listener = this.listener;
|
||||||
|
var self = this;
|
||||||
// Proxy all the request observer calls, when it gets to onStopRequest
|
// Proxy all the request observer calls, when it gets to onStopRequest
|
||||||
// we can get the dom window.
|
// we can get the dom window.
|
||||||
var proxy = {
|
var proxy = {
|
||||||
@ -390,8 +504,8 @@ PdfStreamConverter.prototype = {
|
|||||||
var domWindow = getDOMWindow(channel);
|
var domWindow = getDOMWindow(channel);
|
||||||
// Double check the url is still the correct one.
|
// Double check the url is still the correct one.
|
||||||
if (domWindow.document.documentURIObject.equals(aRequest.URI)) {
|
if (domWindow.document.documentURIObject.equals(aRequest.URI)) {
|
||||||
let requestListener = new RequestListener(
|
let actions = new ChromeActions(domWindow, dataListener);
|
||||||
new ChromeActions(domWindow));
|
let requestListener = new RequestListener(actions);
|
||||||
domWindow.addEventListener(PDFJS_EVENT_ID, function(event) {
|
domWindow.addEventListener(PDFJS_EVENT_ID, function(event) {
|
||||||
requestListener.receive(event);
|
requestListener.receive(event);
|
||||||
}, false, true);
|
}, false, true);
|
||||||
@ -403,11 +517,33 @@ PdfStreamConverter.prototype = {
|
|||||||
// Keep the URL the same so the browser sees it as the same.
|
// Keep the URL the same so the browser sees it as the same.
|
||||||
channel.originalURI = aRequest.URI;
|
channel.originalURI = aRequest.URI;
|
||||||
channel.asyncOpen(proxy, aContext);
|
channel.asyncOpen(proxy, aContext);
|
||||||
|
if (useFetchByChrome) {
|
||||||
|
// We can use resource principal when data is fetched by the chrome
|
||||||
|
// e.g. useful for NoScript
|
||||||
|
var securityManager = Cc['@mozilla.org/scriptsecuritymanager;1']
|
||||||
|
.getService(Ci.nsIScriptSecurityManager);
|
||||||
|
var uri = ioService.newURI(PDF_VIEWER_WEB_PAGE, null, null);
|
||||||
|
// FF16 and below had getCodebasePrincipal (bug 774585)
|
||||||
|
var resourcePrincipal = 'getSimpleCodebasePrincipal' in securityManager ?
|
||||||
|
securityManager.getSimpleCodebasePrincipal(uri) :
|
||||||
|
securityManager.getCodebasePrincipal(uri);
|
||||||
|
channel.owner = resourcePrincipal;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// nsIRequestObserver::onStopRequest
|
// nsIRequestObserver::onStopRequest
|
||||||
onStopRequest: function(aRequest, aContext, aStatusCode) {
|
onStopRequest: function(aRequest, aContext, aStatusCode) {
|
||||||
// Do nothing.
|
if (!this.dataListener) {
|
||||||
|
// Do nothing
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Components.isSuccessCode(aStatusCode))
|
||||||
|
this.dataListener.finish();
|
||||||
|
else
|
||||||
|
this.dataListener.error(aStatusCode);
|
||||||
|
delete this.dataListener;
|
||||||
|
delete this.binaryStream;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -347,6 +347,10 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
var rowBytes = (originalWidth * numComps * bpc + 7) >> 3;
|
var rowBytes = (originalWidth * numComps * bpc + 7) >> 3;
|
||||||
var imgArray = this.getImageBytes(originalHeight * rowBytes);
|
var imgArray = this.getImageBytes(originalHeight * rowBytes);
|
||||||
|
|
||||||
|
// imgArray can be incomplete (e.g. after CCITT fax encoding)
|
||||||
|
var actualHeight = 0 | (imgArray.length / rowBytes *
|
||||||
|
height / originalHeight);
|
||||||
|
|
||||||
var comps = this.colorSpace.getRgbBuffer(
|
var comps = this.colorSpace.getRgbBuffer(
|
||||||
this.getComponents(imgArray), bpc);
|
this.getComponents(imgArray), bpc);
|
||||||
if (originalWidth != width || originalHeight != height)
|
if (originalWidth != width || originalHeight != height)
|
||||||
@ -355,7 +359,7 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
var compsPos = 0;
|
var compsPos = 0;
|
||||||
var opacity = this.getOpacity(width, height);
|
var opacity = this.getOpacity(width, height);
|
||||||
var opacityPos = 0;
|
var opacityPos = 0;
|
||||||
var length = width * height * 4;
|
var length = width * actualHeight * 4;
|
||||||
|
|
||||||
for (var i = 0; i < length; i += 4) {
|
for (var i = 0; i < length; i += 4) {
|
||||||
buffer[i] = comps[compsPos++];
|
buffer[i] = comps[compsPos++];
|
||||||
|
1
test/pdfs/issue1658.pdf.link
Normal file
1
test/pdfs/issue1658.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://www.ads.tuwien.ac.at/teaching/archiv/praktika/CherkasskyGoldberg-1995-MaxFlow.pdf
|
@ -539,6 +539,15 @@
|
|||||||
"link": true,
|
"link": true,
|
||||||
"type": "eq"
|
"type": "eq"
|
||||||
},
|
},
|
||||||
|
{ "id": "issue1658",
|
||||||
|
"file": "pdfs/issue1658.pdf",
|
||||||
|
"md5": "b71a0f641e83ad427b8bcfc180899a05",
|
||||||
|
"rounds": 1,
|
||||||
|
"skipPages": [1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||||||
|
"pageLimit": 10,
|
||||||
|
"link": true,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
{ "id": "issue1049",
|
{ "id": "issue1049",
|
||||||
"file": "pdfs/issue1049.pdf",
|
"file": "pdfs/issue1049.pdf",
|
||||||
"md5": "15473fffcdde9fb8f3756a4cf1aab347",
|
"md5": "15473fffcdde9fb8f3756a4cf1aab347",
|
||||||
|
@ -348,11 +348,42 @@ var PDFView = {
|
|||||||
return support;
|
return support;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
initPassiveLoading: function pdfViewInitPassiveLoading() {
|
||||||
|
if (!PDFView.loadingBar) {
|
||||||
|
PDFView.loadingBar = new ProgressBar('#loadingBar', {});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('message', function window_message(e) {
|
||||||
|
var args = e.data;
|
||||||
|
|
||||||
|
if (typeof args !== 'object' || !('pdfjsLoadAction' in args))
|
||||||
|
return;
|
||||||
|
switch (args.pdfjsLoadAction) {
|
||||||
|
case 'progress':
|
||||||
|
PDFView.progress(args.loaded / args.total);
|
||||||
|
break;
|
||||||
|
case 'complete':
|
||||||
|
if (!args.data) {
|
||||||
|
PDFView.error(mozL10n.get('loading_error', null,
|
||||||
|
'An error occurred while loading the PDF.'), e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
PDFView.open(args.data, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
FirefoxCom.requestSync('initPassiveLoading', null);
|
||||||
|
},
|
||||||
|
|
||||||
|
setTitleUsingUrl: function pdfViewSetTitleUsingUrl(url) {
|
||||||
|
this.url = url;
|
||||||
|
document.title = decodeURIComponent(getFileName(url)) || url;
|
||||||
|
},
|
||||||
|
|
||||||
open: function pdfViewOpen(url, scale, password) {
|
open: function pdfViewOpen(url, scale, password) {
|
||||||
var parameters = {password: password};
|
var parameters = {password: password};
|
||||||
if (typeof url === 'string') { // URL
|
if (typeof url === 'string') { // URL
|
||||||
this.url = url;
|
this.setTitleUsingUrl(url);
|
||||||
document.title = decodeURIComponent(getFileName(url)) || url;
|
|
||||||
parameters.url = url;
|
parameters.url = url;
|
||||||
} else if (url && 'byteLength' in url) { // ArrayBuffer
|
} else if (url && 'byteLength' in url) { // ArrayBuffer
|
||||||
parameters.data = url;
|
parameters.data = url;
|
||||||
@ -1768,7 +1799,7 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv) {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener('load', function webViewerLoad(evt) {
|
document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) {
|
||||||
PDFView.initialize();
|
PDFView.initialize();
|
||||||
var params = PDFView.parseQueryString(document.location.search.substring(1));
|
var params = PDFView.parseQueryString(document.location.search.substring(1));
|
||||||
|
|
||||||
@ -1870,6 +1901,15 @@ window.addEventListener('load', function webViewerLoad(evt) {
|
|||||||
PDFView.sidebarOpen = outerContainer.classList.contains('sidebarOpen');
|
PDFView.sidebarOpen = outerContainer.classList.contains('sidebarOpen');
|
||||||
PDFView.renderHighestPriority();
|
PDFView.renderHighestPriority();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//#if (FIREFOX || MOZCENTRAL)
|
||||||
|
//if (FirefoxCom.requestSync('getLoadingType') == 'passive') {
|
||||||
|
// PDFView.setTitleUsingUrl(file);
|
||||||
|
// PDFView.initPassiveLoading();
|
||||||
|
// return;
|
||||||
|
//}
|
||||||
|
//#endif
|
||||||
|
|
||||||
//#if !B2G
|
//#if !B2G
|
||||||
PDFView.open(file, 0);
|
PDFView.open(file, 0);
|
||||||
//#endif
|
//#endif
|
||||||
@ -1961,7 +2001,7 @@ window.addEventListener('change', function webViewerChange(evt) {
|
|||||||
|
|
||||||
var file = files[0];
|
var file = files[0];
|
||||||
fileReader.readAsArrayBuffer(file);
|
fileReader.readAsArrayBuffer(file);
|
||||||
document.title = file.name;
|
PDFView.setTitleUsingUrl(file.name);
|
||||||
|
|
||||||
// URL does not reflect proper document location - hiding some icons.
|
// URL does not reflect proper document location - hiding some icons.
|
||||||
document.getElementById('viewBookmark').setAttribute('hidden', 'true');
|
document.getElementById('viewBookmark').setAttribute('hidden', 'true');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user