Browse Source

Leave initial request open until the viewer is ready to switch to range requests.

Brendan Dahl 12 years ago
parent
commit
0385131a9a
  1. 41
      extensions/firefox/components/PdfStreamConverter.js
  2. 31
      src/core/chunked_stream.js
  3. 3
      src/core/pdf_manager.js
  4. 3
      src/display/api.js
  5. 3
      web/viewer.js

41
extensions/firefox/components/PdfStreamConverter.js

@ -439,9 +439,12 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
* This is for range requests * This is for range requests
*/ */
function RangedChromeActions( function RangedChromeActions(
domWindow, contentDispositionFilename, originalRequest) { domWindow, contentDispositionFilename, originalRequest,
dataListener) {
ChromeActions.call(this, domWindow, contentDispositionFilename); ChromeActions.call(this, domWindow, contentDispositionFilename);
this.dataListener = dataListener;
this.originalRequest = originalRequest;
this.pdfUrl = originalRequest.URI.spec; this.pdfUrl = originalRequest.URI.spec;
this.contentLength = originalRequest.contentLength; this.contentLength = originalRequest.contentLength;
@ -487,11 +490,15 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
proto.constructor = RangedChromeActions; proto.constructor = RangedChromeActions;
proto.initPassiveLoading = function RangedChromeActions_initPassiveLoading() { proto.initPassiveLoading = function RangedChromeActions_initPassiveLoading() {
this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
this.originalRequest = null;
this.domWindow.postMessage({ this.domWindow.postMessage({
pdfjsLoadAction: 'supportsRangedLoading', pdfjsLoadAction: 'supportsRangedLoading',
pdfUrl: this.pdfUrl, pdfUrl: this.pdfUrl,
length: this.contentLength length: this.contentLength,
data: this.dataListener.getData()
}, '*'); }, '*');
this.dataListener = null;
return true; return true;
}; };
@ -692,8 +699,8 @@ PdfStreamConverter.prototype = {
* 1. asyncConvertData stores the listener * 1. asyncConvertData stores the listener
* 2. onStartRequest creates a new channel, streams the viewer * 2. onStartRequest creates a new channel, streams the viewer
* 3. If range requests are supported: * 3. If range requests are supported:
* 3.1. Suspends and cancels the request so we can issue range * 3.1. Leave the request open until the viewer is ready to switch to
* requests instead. * range requests.
* *
* If range rquests are not supported: * If range rquests are not supported:
* 3.1. Read the stream as it's loaded in onDataAvailable to send * 3.1. Read the stream as it's loaded in onDataAvailable to send
@ -779,18 +786,12 @@ PdfStreamConverter.prototype = {
PdfJsTelemetry.onViewerIsUsed(); PdfJsTelemetry.onViewerIsUsed();
PdfJsTelemetry.onDocumentSize(aRequest.contentLength); PdfJsTelemetry.onDocumentSize(aRequest.contentLength);
if (!rangeRequest) {
// Creating storage for PDF data // Creating storage for PDF data
var contentLength = aRequest.contentLength; var contentLength = aRequest.contentLength;
this.dataListener = new PdfDataListener(contentLength); this.dataListener = new PdfDataListener(contentLength);
this.binaryStream = Cc['@mozilla.org/binaryinputstream;1'] this.binaryStream = Cc['@mozilla.org/binaryinputstream;1']
.createInstance(Ci.nsIBinaryInputStream); .createInstance(Ci.nsIBinaryInputStream);
} else {
// Suspend the request so we're not consuming any of the stream,
// but we can't cancel the request yet. Otherwise, the original
// listener will think we do not want to go the new PDF url
aRequest.suspend();
}
// 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;
@ -816,12 +817,8 @@ PdfStreamConverter.prototype = {
var domWindow = getDOMWindow(channel); var domWindow = getDOMWindow(channel);
var actions; var actions;
if (rangeRequest) { if (rangeRequest) {
// We are going to be issuing range requests, so cancel the actions = new RangedChromeActions(
// original request domWindow, contentDispositionFilename, aRequest, dataListener);
aRequest.resume();
aRequest.cancel(Cr.NS_BINDING_ABORTED);
actions = new RangedChromeActions(domWindow,
contentDispositionFilename, aRequest);
} else { } else {
actions = new StandardChromeActions( actions = new StandardChromeActions(
domWindow, contentDispositionFilename, dataListener); domWindow, contentDispositionFilename, dataListener);

31
src/core/chunked_stream.js

@ -30,6 +30,7 @@ var ChunkedStream = (function ChunkedStreamClosure() {
this.numChunksLoaded = 0; this.numChunksLoaded = 0;
this.numChunks = Math.ceil(length / chunkSize); this.numChunks = Math.ceil(length / chunkSize);
this.manager = manager; this.manager = manager;
this.initialDataLength = 0;
} }
// required methods for a stream. if a particular stream does not // required methods for a stream. if a particular stream does not
@ -77,11 +78,26 @@ var ChunkedStream = (function ChunkedStreamClosure() {
} }
}, },
onReceiveInitialData: function (data) {
this.bytes.set(data);
this.initialDataLength = data.length;
var endChunk = this.end === data.length ?
this.numChunks : Math.floor(data.length / this.chunkSize);
for (var i = 0; i < endChunk; i++) {
this.loadedChunks[i] = true;
++this.numChunksLoaded;
}
},
ensureRange: function ChunkedStream_ensureRange(begin, end) { ensureRange: function ChunkedStream_ensureRange(begin, end) {
if (begin >= end) { if (begin >= end) {
return; return;
} }
if (end <= this.initialDataLength) {
return;
}
var chunkSize = this.chunkSize; var chunkSize = this.chunkSize;
var beginChunk = Math.floor(begin / chunkSize); var beginChunk = Math.floor(begin / chunkSize);
var endChunk = Math.floor((end - 1) / chunkSize) + 1; var endChunk = Math.floor((end - 1) / chunkSize) + 1;
@ -243,10 +259,25 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
this.callbacksByRequest = {}; this.callbacksByRequest = {};
this.loadedStream = new Promise(); this.loadedStream = new Promise();
if (args.initialData) {
this.setInitialData(args.initialData);
}
} }
ChunkedStreamManager.prototype = { ChunkedStreamManager.prototype = {
setInitialData: function ChunkedStreamManager_setInitialData(data) {
this.stream.onReceiveInitialData(data);
if (this.stream.allChunksLoaded()) {
this.loadedStream.resolve(this.stream);
} else if (this.msgHandler) {
this.msgHandler.send('DocProgress', {
loaded: data.length,
total: this.length
});
}
},
onLoadedStream: function ChunkedStreamManager_getLoadedStream() { onLoadedStream: function ChunkedStreamManager_getLoadedStream() {
return this.loadedStream; return this.loadedStream;
}, },

3
src/core/pdf_manager.js

@ -139,7 +139,8 @@ var NetworkPdfManager = (function NetworkPdfManagerClosure() {
msgHandler: msgHandler, msgHandler: msgHandler,
httpHeaders: args.httpHeaders, httpHeaders: args.httpHeaders,
chunkedViewerLoading: args.chunkedViewerLoading, chunkedViewerLoading: args.chunkedViewerLoading,
disableAutoFetch: args.disableAutoFetch disableAutoFetch: args.disableAutoFetch,
initialData: args.initialData
}; };
this.streamManager = new ChunkedStreamManager(args.length, CHUNK_SIZE, this.streamManager = new ChunkedStreamManager(args.length, CHUNK_SIZE,
args.url, params); args.url, params);

3
src/display/api.js

@ -98,6 +98,9 @@ PDFJS.pdfBug = PDFJS.pdfBug === undefined ? false : PDFJS.pdfBug;
* - data - A typed array with PDF data. * - data - A typed array with PDF data.
* - httpHeaders - Basic authentication headers. * - httpHeaders - Basic authentication headers.
* - password - For decrypting password-protected PDFs. * - password - For decrypting password-protected PDFs.
* - initialData - A typed array with the first portion or all of the pdf data.
* Used by the extension since some data is already loaded
* before the switch to range requests.
* *
* @param {object} pdfDataRangeTransport is optional. It is used if you want * @param {object} pdfDataRangeTransport is optional. It is used if you want
* to manually serve range requests for data in the PDF. See viewer.js for * to manually serve range requests for data in the PDF. See viewer.js for

3
web/viewer.js

@ -445,7 +445,8 @@ var PDFView = {
switch (args.pdfjsLoadAction) { switch (args.pdfjsLoadAction) {
case 'supportsRangedLoading': case 'supportsRangedLoading':
PDFView.open(args.pdfUrl, 0, undefined, pdfDataRangeTransport, { PDFView.open(args.pdfUrl, 0, undefined, pdfDataRangeTransport, {
length: args.length length: args.length,
initialData: args.data
}); });
break; break;
case 'range': case 'range':

Loading…
Cancel
Save