Merge m-c to inbound on a CLOSED TREE.

This commit is contained in:
Ryan VanderMeulen 2013-05-17 17:34:54 -04:00
commit 9a0ba8199c
30 changed files with 4379 additions and 2494 deletions

View File

@ -9,8 +9,6 @@ this.EXPORTED_SYMBOLS = [ "DeveloperToolbar", "CommandUtils" ];
const NS_XHTML = "http://www.w3.org/1999/xhtml";
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource:///modules/devtools/Commands.jsm");
@ -26,7 +24,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "gcli",
XPCOMUtils.defineLazyModuleGetter(this, "CmdCommands",
"resource:///modules/devtools/BuiltinCommands.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ConsoleServiceListener",
XPCOMUtils.defineLazyModuleGetter(this, "PageErrorListener",
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
@ -437,8 +435,8 @@ DeveloperToolbar.prototype._initErrorsCount = function DT__initErrorsCount(aTab)
}
let window = aTab.linkedBrowser.contentWindow;
let listener = new ConsoleServiceListener(window, {
onConsoleServiceMessage: this._onPageError.bind(this, tabId),
let listener = new PageErrorListener(window, {
onPageError: this._onPageError.bind(this, tabId),
});
listener.init();
@ -595,8 +593,7 @@ DeveloperToolbar.prototype.handleEvent = function DT_handleEvent(aEvent)
DeveloperToolbar.prototype._onPageError =
function DT__onPageError(aTabId, aPageError)
{
if (!(aPageError instanceof Ci.nsIScriptError) ||
aPageError.category == "CSS Parser" ||
if (aPageError.category == "CSS Parser" ||
aPageError.category == "CSS Loader") {
return;
}

View File

@ -130,7 +130,6 @@ MOCHITEST_BROWSER_FILES = \
browser_bug_862916_console_dir_and_filter_off.js \
browser_console_native_getters.js \
browser_bug_871156_ctrlw_close_tab.js \
browser_console_nsiconsolemessage.js \
head.js \
$(NULL)

View File

@ -1,93 +0,0 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Check that nsIConsoleMessages show in the Browser Console and in the Web
// Console. See bug 859756.
const TEST_URI = "data:text/html;charset=utf8,<title>bug859756</title>\n" +
"<p>hello world\n<p>nsIConsoleMessages ftw!";
let gWebConsole, gJSTerm, gVariablesView;
function test()
{
addTab(TEST_URI);
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
// Test for cached nsIConsoleMessages.
sendMessage("test1 for bug859756", "cat2012");
openConsole(null, consoleOpened);
}, true);
}
function sendMessage(aMessage, aCategory)
{
let windowID = WebConsoleUtils.getInnerWindowId(content);
let consoleMsg = Cc["@mozilla.org/consolemessage;1"]
.createInstance(Ci.nsIConsoleMessage);
consoleMsg.initMessage(aMessage, aCategory, windowID);
Services.console.logMessage(consoleMsg);
}
function consoleOpened(hud)
{
gWebConsole = hud;
gJSTerm = hud.jsterm;
// Send a message with no window ID.
Services.console.logStringMessage("do-not-show-me");
sendMessage("test2 for bug859756", "cat2013");
waitForMessages({
webconsole: hud,
messages: [
{
text: "test1 for bug859756",
category: CATEGORY_JS,
},
{
text: "test2 for bug859756",
category: CATEGORY_JS,
},
],
}).then(onLogMessages);
}
function onLogMessages()
{
let text = gWebConsole.outputNode.textContent;
is(text.indexOf("do-not-show-me"), -1,
"message without window ID is not displayed");
closeConsole(null, onWebConsoleClose);
}
function onWebConsoleClose()
{
HUDConsoleUI.toggleBrowserConsole().then(onBrowserConsoleOpen);
}
function onBrowserConsoleOpen(hud)
{
waitForMessages({
webconsole: hud,
messages: [
{
text: "test1 for bug859756",
category: CATEGORY_JS,
},
{
text: "test2 for bug859756",
category: CATEGORY_JS,
},
{
text: "do-not-show-me",
category: CATEGORY_JS,
},
],
}).then(finishTest);
}

View File

@ -956,14 +956,11 @@ WebConsoleFrame.prototype = {
aRemoteMessages.forEach(function(aMessage) {
switch (aMessage._type) {
case "PageError": {
let category = Utils.categoryForConsoleMessage(aMessage);
let category = Utils.categoryForScriptError(aMessage);
this.outputMessage(category, this.reportPageError,
[category, aMessage]);
break;
}
case "LogMessage":
this.handleLogMessage(aMessage);
break;
case "ConsoleAPI":
this.outputMessage(CATEGORY_WEBDEV, this.logConsoleAPIMessage,
[aMessage]);
@ -1191,26 +1188,10 @@ WebConsoleFrame.prototype = {
*/
handlePageError: function WCF_handlePageError(aPageError)
{
let category = Utils.categoryForConsoleMessage(aPageError);
let category = Utils.categoryForScriptError(aPageError);
this.outputMessage(category, this.reportPageError, [category, aPageError]);
},
/**
* Handle log messages received from the server. This method outputs the given
* message.
*
* @param object aPacket
* The message packet received from the server.
*/
handleLogMessage: function WCF_handleLogMessage(aPacket)
{
let category = Utils.categoryForConsoleMessage(aPacket.category);
this.outputMessage(category, () => {
return this.createMessageNode(category, SEVERITY_LOG, aPacket.message,
null, null, null, null, aPacket.timeStamp);
});
},
/**
* Log network event.
*
@ -4356,17 +4337,17 @@ var Utils = {
},
/**
* Determine the category of a given nsIConsoleMessage.
* Determine the category of a given nsIScriptError.
*
* @param nsIConsoleMessage aMessage
* The message you want to determine the category for.
* @param nsIScriptError aScriptError
* The script error you want to determine the category for.
* @return CATEGORY_JS|CATEGORY_CSS|CATEGORY_SECURITY
* Depending on the message kind CATEGORY_JS, CATEGORY_CSS, or
* Depending on the script error CATEGORY_JS, CATEGORY_CSS, or
* CATEGORY_SECURITY can be returned.
*/
categoryForConsoleMessage: function Utils_categoryForConsoleMessage(aMessage)
categoryForScriptError: function Utils_categoryForScriptError(aScriptError)
{
switch (aMessage.category) {
switch (aScriptError.category) {
case "CSS Parser":
case "CSS Loader":
return CATEGORY_CSS;
@ -4527,7 +4508,6 @@ function WebConsoleConnectionProxy(aWebConsole, aTarget)
this.target = aTarget;
this._onPageError = this._onPageError.bind(this);
this._onLogMessage = this._onLogMessage.bind(this);
this._onConsoleAPICall = this._onConsoleAPICall.bind(this);
this._onNetworkEvent = this._onNetworkEvent.bind(this);
this._onNetworkEventUpdate = this._onNetworkEventUpdate.bind(this);
@ -4631,7 +4611,6 @@ WebConsoleConnectionProxy.prototype = {
let client = this.client = this.target.client;
client.addListener("logMessage", this._onLogMessage);
client.addListener("pageError", this._onPageError);
client.addListener("consoleAPICall", this._onConsoleAPICall);
client.addListener("networkEvent", this._onNetworkEvent);
@ -4752,23 +4731,6 @@ WebConsoleConnectionProxy.prototype = {
}
},
/**
* The "logMessage" message type handler. We redirect any message to the UI
* for displaying.
*
* @private
* @param string aType
* Message type.
* @param object aPacket
* The message received from the server.
*/
_onLogMessage: function WCCP__onLogMessage(aType, aPacket)
{
if (this.owner && aPacket.from == this._consoleActor) {
this.owner.handleLogMessage(aPacket);
}
},
/**
* The "consoleAPICall" message type handler. We redirect any message to
* the UI for displaying.
@ -4896,7 +4858,6 @@ WebConsoleConnectionProxy.prototype = {
}
this.client.removeListener("pageError", this._onPageError);
this.client.removeListener("logMessage", this._onLogMessage);
this.client.removeListener("consoleAPICall", this._onConsoleAPICall);
this.client.removeListener("networkEvent", this._onNetworkEvent);
this.client.removeListener("networkEventUpdate", this._onNetworkEventUpdate);

View File

@ -1,4 +1,4 @@
This is the pdf.js project output, https://github.com/mozilla/pdf.js
Current extension version is: 0.8.47
Current extension version is: 0.8.169

View File

@ -16,7 +16,7 @@
*/
/* jshint esnext:true */
/* globals Components, Services, XPCOMUtils, NetUtil, PrivateBrowsingUtils,
dump */
dump, NetworkManager */
'use strict';
@ -37,6 +37,7 @@ const MAX_DATABASE_LENGTH = 4096;
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/Services.jsm');
Cu.import('resource://gre/modules/NetUtil.jsm');
Cu.import('resource://pdf.js/network.js');
XPCOMUtils.defineLazyModuleGetter(this, 'PrivateBrowsingUtils',
'resource://gre/modules/PrivateBrowsingUtils.jsm');
@ -190,9 +191,8 @@ PdfDataListener.prototype = {
};
// All the priviledged actions.
function ChromeActions(domWindow, dataListener, contentDispositionFilename) {
function ChromeActions(domWindow, contentDispositionFilename) {
this.domWindow = domWindow;
this.dataListener = dataListener;
this.contentDispositionFilename = contentDispositionFilename;
}
@ -305,39 +305,6 @@ ChromeActions.prototype = {
getLocale: function() {
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
}, '*');
};
var self = this;
this.dataListener.oncomplete =
function ChromeActions_dataListenerComplete(data, errorCode) {
domWindow.postMessage({
pdfjsLoadAction: 'complete',
data: data,
errorCode: errorCode
}, '*');
delete self.dataListener;
};
return true;
},
getStrings: function(data) {
try {
// Lazy initialization of localizedStrings
@ -436,6 +403,146 @@ ChromeActions.prototype = {
}
};
var RangedChromeActions = (function RangedChromeActionsClosure() {
/**
* This is for range requests
*/
function RangedChromeActions(
domWindow, contentDispositionFilename, originalRequest) {
ChromeActions.call(this, domWindow, contentDispositionFilename);
this.pdfUrl = originalRequest.URI.resolve('');
this.contentLength = originalRequest.contentLength;
// Pass all the headers from the original request through
var httpHeaderVisitor = {
headers: {},
visitHeader: function(aHeader, aValue) {
if (aHeader === 'Range') {
// When loading the PDF from cache, firefox seems to set the Range
// request header to fetch only the unfetched portions of the file
// (e.g. 'Range: bytes=1024-'). However, we want to set this header
// manually to fetch the PDF in chunks.
return;
}
this.headers[aHeader] = aValue;
}
};
originalRequest.visitRequestHeaders(httpHeaderVisitor);
var getXhr = function getXhr() {
const XMLHttpRequest = Components.Constructor(
'@mozilla.org/xmlextras/xmlhttprequest;1');
return new XMLHttpRequest();
};
this.networkManager = new NetworkManager(this.pdfUrl, {
httpHeaders: httpHeaderVisitor.headers,
getXhr: getXhr
});
var self = this;
// If we are in range request mode, this means we manually issued xhr
// requests, which we need to abort when we leave the page
domWindow.addEventListener('unload', function unload(e) {
self.networkManager.abortAllRequests();
domWindow.removeEventListener(e.type, unload);
});
}
RangedChromeActions.prototype = Object.create(ChromeActions.prototype);
var proto = RangedChromeActions.prototype;
proto.constructor = RangedChromeActions;
proto.initPassiveLoading = function RangedChromeActions_initPassiveLoading() {
this.domWindow.postMessage({
pdfjsLoadAction: 'supportsRangedLoading',
pdfUrl: this.pdfUrl,
length: this.contentLength
}, '*');
return true;
};
proto.requestDataRange = function RangedChromeActions_requestDataRange(args) {
var begin = args.begin;
var end = args.end;
var domWindow = this.domWindow;
// TODO(mack): Support error handler. We're not currently not handling
// errors from chrome code for non-range requests, so this doesn't
// seem high-pri
this.networkManager.requestRange(begin, end, {
onDone: function RangedChromeActions_onDone(args) {
domWindow.postMessage({
pdfjsLoadAction: 'range',
begin: args.begin,
chunk: args.chunk
}, '*');
},
onProgress: function RangedChromeActions_onProgress(evt) {
domWindow.postMessage({
pdfjsLoadAction: 'rangeProgress',
loaded: evt.loaded,
}, '*');
}
});
};
return RangedChromeActions;
})();
var StandardChromeActions = (function StandardChromeActionsClosure() {
/**
* This is for a single network stream
*/
function StandardChromeActions(domWindow, contentDispositionFilename,
dataListener) {
ChromeActions.call(this, domWindow, contentDispositionFilename);
this.dataListener = dataListener;
}
StandardChromeActions.prototype = Object.create(ChromeActions.prototype);
var proto = StandardChromeActions.prototype;
proto.constructor = StandardChromeActions;
proto.initPassiveLoading =
function StandardChromeActions_initPassiveLoading() {
if (!this.dataListener) {
return false;
}
var self = this;
this.dataListener.onprogress = function ChromeActions_dataListenerProgress(
loaded, total) {
self.domWindow.postMessage({
pdfjsLoadAction: 'progress',
loaded: loaded,
total: total
}, '*');
};
this.dataListener.oncomplete = function ChromeActions_dataListenerComplete(
data, errorCode) {
self.domWindow.postMessage({
pdfjsLoadAction: 'complete',
data: data,
errorCode: errorCode
}, '*');
delete self.dataListener;
};
return true;
};
return StandardChromeActions;
})();
// Event listener to trigger chrome privedged code.
function RequestListener(actions) {
this.actions = actions;
@ -552,11 +659,17 @@ PdfStreamConverter.prototype = {
/*
* This component works as such:
* 1. asyncConvertData stores the listener
* 2. onStartRequest creates a new channel, streams the viewer and cancels
* the request so pdf.js can do the request
* Since the request is cancelled onDataAvailable should not be called. The
* onStopRequest does nothing. The convert function just returns the stream,
* it's just the synchronous version of asyncConvertData.
* 2. onStartRequest creates a new channel, streams the viewer
* 3. If range requests are supported:
* 3.1. Suspends and cancels the request so we can issue range
* requests instead.
*
* If range rquests are not supported:
* 3.1. Read the stream as it's loaded in onDataAvailable to send
* to the viewer
*
* The convert function just returns the stream, it's just the synchronous
* version of asyncConvertData.
*/
// nsIStreamConverter::convert
@ -573,41 +686,76 @@ PdfStreamConverter.prototype = {
// nsIStreamListener::onDataAvailable
onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
if (!this.dataListener) {
// Do nothing since all the data loading is handled by the viewer.
return;
}
var binaryStream = this.binaryStream;
binaryStream.setInputStream(aInputStream);
this.dataListener.append(binaryStream.readByteArray(aCount));
var chunk = binaryStream.readByteArray(aCount);
this.dataListener.append(chunk);
},
// nsIRequestObserver::onStartRequest
onStartRequest: function(aRequest, aContext) {
// Setup the request so we can use it below.
var isHttpRequest = false;
try {
aRequest.QueryInterface(Ci.nsIHttpChannel);
isHttpRequest = true;
} catch (e) {}
var rangeRequest = false;
if (isHttpRequest) {
var contentEncoding = 'identity';
try {
contentEncoding = aRequest.getResponseHeader('Content-Encoding');
} catch (e) {}
var acceptRanges;
try {
acceptRanges = aRequest.getResponseHeader('Accept-Ranges');
} catch (e) {}
var hash = aRequest.URI.ref;
rangeRequest = contentEncoding === 'identity' &&
acceptRanges === 'bytes' &&
aRequest.contentLength >= 0 &&
hash.indexOf('disableRange=true') < 0;
}
aRequest.QueryInterface(Ci.nsIChannel);
aRequest.QueryInterface(Ci.nsIWritablePropertyBag);
// Creating storage for PDF data
var contentLength = aRequest.contentLength;
var dataListener = new PdfDataListener(contentLength);
var contentDispositionFilename;
try {
contentDispositionFilename = aRequest.contentDispositionFilename;
} catch (e) {}
this.dataListener = dataListener;
this.binaryStream = Cc['@mozilla.org/binaryinputstream;1']
.createInstance(Ci.nsIBinaryInputStream);
// Change the content type so we don't get stuck in a loop.
aRequest.setProperty('contentType', aRequest.contentType);
aRequest.contentType = 'text/html';
if (!rangeRequest) {
// Creating storage for PDF data
var contentLength = aRequest.contentLength;
this.dataListener = new PdfDataListener(contentLength);
this.binaryStream = Cc['@mozilla.org/binaryinputstream;1']
.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.
var ioService = Services.io;
var channel = ioService.newChannel(
PDF_VIEWER_WEB_PAGE, null, null);
var listener = this.listener;
var dataListener = this.dataListener;
// Proxy all the request observer calls, when it gets to onStopRequest
// we can get the dom window. We also intentionally pass on the original
// request(aRequest) below so we don't overwrite the original channel and
@ -623,23 +771,28 @@ PdfStreamConverter.prototype = {
// We get the DOM window here instead of before the request since it
// may have changed during a redirect.
var domWindow = getDOMWindow(channel);
// Double check the url is still the correct one.
if (domWindow.document.documentURIObject.equals(aRequest.URI)) {
var actions = new ChromeActions(domWindow, dataListener,
contentDispositionFilename);
var requestListener = new RequestListener(actions);
domWindow.addEventListener(PDFJS_EVENT_ID, function(event) {
requestListener.receive(event);
}, false, true);
if (actions.supportsIntegratedFind()) {
var chromeWindow = getChromeWindow(domWindow);
var findEventManager = new FindEventManager(chromeWindow.gFindBar,
domWindow,
chromeWindow);
findEventManager.bind();
}
var actions;
if (rangeRequest) {
// We are going to be issuing range requests, so cancel the
// original request
aRequest.resume();
aRequest.cancel(Cr.NS_BINDING_ABORTED);
actions = new RangedChromeActions(domWindow,
contentDispositionFilename, aRequest);
} else {
log('Dom window url did not match request url.');
actions = new StandardChromeActions(
domWindow, contentDispositionFilename, dataListener);
}
var requestListener = new RequestListener(actions);
domWindow.addEventListener(PDFJS_EVENT_ID, function(event) {
requestListener.receive(event);
}, false, true);
if (actions.supportsIntegratedFind()) {
var chromeWindow = getChromeWindow(domWindow);
var findEventManager = new FindEventManager(chromeWindow.gFindBar,
domWindow,
chromeWindow);
findEventManager.bind();
}
listener.onStopRequest(aRequest, context, statusCode);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,230 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* Copyright 2012 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// NOTE: Be careful what goes in this file, as it is also used from the context
// of the addon. So using warn/error in here will break the addon.
'use strict';
Components.utils.import('resource://gre/modules/Services.jsm');
var EXPORTED_SYMBOLS = ['NetworkManager'];
function log(aMsg) {
var msg = 'network.js: ' + (aMsg.join ? aMsg.join('') : aMsg);
Services.console.logStringMessage(msg);
// TODO(mack): dump() doesn't seem to work here...
dump(msg + '\n');
}
var NetworkManager = (function NetworkManagerClosure() {
var OK_RESPONSE = 200;
var PARTIAL_CONTENT_RESPONSE = 206;
function NetworkManager(url, args) {
this.url = url;
args = args || {};
this.httpHeaders = args.httpHeaders || {};
this.getXhr = args.getXhr ||
function NetworkManager_getXhr() {
return new XMLHttpRequest();
};
this.currXhrId = 0;
this.pendingRequests = {};
this.loadedRequests = {};
}
function getArrayBuffer(xhr) {
var data = (xhr.mozResponseArrayBuffer || xhr.mozResponse ||
xhr.responseArrayBuffer || xhr.response);
if (typeof data !== 'string') {
return data;
}
var length = data.length;
var buffer = new Uint8Array(length);
for (var i = 0; i < length; i++) {
buffer[i] = data.charCodeAt(i) & 0xFF;
}
return buffer;
}
NetworkManager.prototype = {
requestRange: function NetworkManager_requestRange(begin, end, listeners) {
var args = {
begin: begin,
end: end
};
for (var prop in listeners) {
args[prop] = listeners[prop];
}
return this.request(args);
},
requestFull: function NetworkManager_requestRange(listeners) {
return this.request(listeners);
},
request: function NetworkManager_requestRange(args) {
var xhr = this.getXhr();
var xhrId = this.currXhrId++;
var pendingRequest = this.pendingRequests[xhrId] = {
xhr: xhr
};
xhr.open('GET', this.url);
for (var property in this.httpHeaders) {
var value = this.httpHeaders[property];
if (typeof value === 'undefined') {
continue;
}
xhr.setRequestHeader(property, value);
}
if ('begin' in args && 'end' in args) {
var rangeStr = args.begin + '-' + (args.end - 1);
xhr.setRequestHeader('Range', 'bytes=' + rangeStr);
pendingRequest.expectedStatus = 206;
} else {
pendingRequest.expectedStatus = 200;
}
xhr.mozResponseType = xhr.responseType = 'arraybuffer';
if (args.onProgress) {
xhr.onprogress = args.onProgress;
}
if (args.onError) {
xhr.onerror = function(evt) {
args.onError(xhr.status);
};
}
xhr.onreadystatechange = this.onStateChange.bind(this, xhrId);
pendingRequest.onHeadersReceived = args.onHeadersReceived;
pendingRequest.onDone = args.onDone;
pendingRequest.onError = args.onError;
xhr.send(null);
return xhrId;
},
onStateChange: function NetworkManager_onStateChange(xhrId, evt) {
var pendingRequest = this.pendingRequests[xhrId];
if (!pendingRequest) {
// Maybe abortRequest was called...
return;
}
var xhr = pendingRequest.xhr;
if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) {
pendingRequest.onHeadersReceived();
delete pendingRequest.onHeadersReceived;
}
if (xhr.readyState !== 4) {
return;
}
if (!(xhrId in this.pendingRequests)) {
// The XHR request might have been aborted in onHeadersReceived()
// callback, in which case we should abort request
return;
}
delete this.pendingRequests[xhrId];
if (xhr.status === 0) {
if (pendingRequest.onError) {
pendingRequest.onError(xhr.status);
}
return;
}
// From http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.2:
// "A server MAY ignore the Range header". This means it's possible to
// get a 200 rather than a 206 response from a range request.
var ok_response_on_range_request =
xhr.status === OK_RESPONSE &&
pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE;
if (!ok_response_on_range_request &&
xhr.status !== pendingRequest.expectedStatus) {
if (pendingRequest.onError) {
pendingRequest.onError(xhr.status);
}
return;
}
this.loadedRequests[xhrId] = true;
var chunk = getArrayBuffer(xhr);
if (xhr.status === PARTIAL_CONTENT_RESPONSE) {
var rangeHeader = xhr.getResponseHeader('Content-Range');
var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader);
var begin = parseInt(matches[1], 10);
pendingRequest.onDone({
begin: begin,
chunk: chunk
});
} else {
pendingRequest.onDone({
begin: 0,
chunk: chunk
});
}
},
hasPendingRequests: function NetworkManager_hasPendingRequests() {
for (var xhrId in this.pendingRequests) {
return true;
}
return false;
},
getRequestXhr: function NetworkManager_getXhr(xhrId) {
return this.pendingRequests[xhrId].xhr;
},
isPendingRequest: function NetworkManager_isPendingRequest(xhrId) {
return xhrId in this.pendingRequests;
},
isLoadedRequest: function NetworkManager_isLoadedRequest(xhrId) {
return xhrId in this.loadedRequests;
},
abortAllRequests: function NetworkManager_abortAllRequests() {
for (var xhrId in this.pendingRequests) {
this.abortRequest(xhrId | 0);
}
},
abortRequest: function NetworkManager_abortRequest(xhrId) {
var xhr = this.pendingRequests[xhrId].xhr;
delete this.pendingRequests[xhrId];
xhr.abort();
}
};
return NetworkManager;
})();

View File

@ -105,7 +105,10 @@
// Arabic, Hebrew, Farsi, Pashto, Urdu
var rtlList = ['ar', 'he', 'fa', 'ps', 'ur'];
return (rtlList.indexOf(gLanguage) >= 0) ? 'rtl' : 'ltr';
}
},
// translate an element or document fragment
translate: translateFragment
};
})(this);

View File

@ -237,12 +237,14 @@ html[dir='rtl'] #sidebarContent {
bottom: 0;
left: 0;
}
.loadingInProgress #viewerContainer {
top: 39px;
}
.toolbar {
position: absolute;
position: relative;
left: 0;
right: 0;
height: 32px;
z-index: 9999;
cursor: default;
}
@ -254,14 +256,7 @@ html[dir='rtl'] #sidebarContent {
#toolbarSidebar {
width: 200px;
height: 32px;
background-image: url(images/texture.png),
-webkit-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95));
background-image: url(images/texture.png),
-moz-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95));
background-image: url(images/texture.png),
-ms-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95));
background-image: url(images/texture.png),
-o-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95));
background-color: #424242; /* fallback */
background-image: url(images/texture.png),
linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95));
box-shadow: inset -1px 0 0 rgba(0, 0, 0, 0.25),
@ -271,18 +266,10 @@ html[dir='rtl'] #sidebarContent {
0 0 1px hsla(0,0%,0%,.1);
}
#toolbarViewer, .findbar {
#toolbarContainer, .findbar {
position: relative;
height: 32px;
background-color: #474747; /* IE9 */
background-image: url(images/texture.png),
-webkit-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95));
background-image: url(images/texture.png),
-moz-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95));
background-image: url(images/texture.png),
-ms-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95));
background-image: url(images/texture.png),
-o-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95));
background-color: #474747; /* fallback */
background-image: url(images/texture.png),
linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95));
box-shadow: inset 1px 0 0 hsla(0,0%,100%,.08),
@ -292,6 +279,80 @@ html[dir='rtl'] #sidebarContent {
0 1px 1px hsla(0,0%,0%,.1);
}
#toolbarViewer {
height: 32px;
}
#loadingBar {
position: relative;
width: 100%;
height: 6px;
background-color: #333;
border-bottom: 1px solid #333;
}
#loadingBar .progress {
position: absolute;
top: 0;
left: 0;
width: 0%;
height: 100%;
background-color: #ddd;
overflow: hidden;
-moz-transition: width 200ms;
-ms-transition: width 200ms;
-webkit-transition: width 200ms;
transition: width 200ms;
}
@-moz-keyframes progressIndeterminate {
0% { left: 0%; }
50% { left: 100%; }
100% { left: 100%; }
}
@-ms-keyframes progressIndeterminate {
0% { left: 0%; }
50% { left: 100%; }
100% { left: 100%; }
}
@-webkit-keyframes progressIndeterminate {
0% { left: 0%; }
50% { left: 100%; }
100% { left: 100%; }
}
@keyframes progressIndeterminate {
0% { left: 0%; }
50% { left: 100%; }
100% { left: 100%; }
}
#loadingBar .progress.indeterminate {
background-color: #999;
-moz-transition: none;
-ms-transition: none;
-webkit-transition: none;
transition: none;
}
#loadingBar .indeterminate .glimmer {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 50px;
background-image: linear-gradient(to right, #999 0%, #fff 50%, #999 100%);
background-size: 100% 100% no-repeat;
-moz-animation: progressIndeterminate 2s linear infinite;
-ms-animation: progressIndeterminate 2s linear infinite;
-webkit-animation: progressIndeterminate 2s linear infinite;
animation: progressIndeterminate 2s linear infinite;
}
.findbar {
top: 32px;
position: absolute;
@ -462,10 +523,6 @@ html[dir='rtl'] .splitToolbarButton > .toolbarButton {
.splitToolbarButton.toggled > .toolbarButton,
.toolbarButton.textButton {
background-color: hsla(0,0%,0%,.12);
background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-clip: padding-box;
border: 1px solid hsla(0,0%,0%,.35);
@ -600,10 +657,6 @@ html[dir='rtl'] .dropdownToolbarButton {
.toolbarButton:focus,
.dropdownToolbarButton {
background-color: hsla(0,0%,0%,.12);
background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-clip: padding-box;
border: 1px solid hsla(0,0%,0%,.35);
@ -616,10 +669,6 @@ html[dir='rtl'] .dropdownToolbarButton {
.toolbarButton:hover:active,
.dropdownToolbarButton:hover:active {
background-color: hsla(0,0%,0%,.2);
background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
border-color: hsla(0,0%,0%,.35) hsla(0,0%,0%,.4) hsla(0,0%,0%,.45);
box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset,
@ -645,10 +694,6 @@ html[dir='rtl'] .dropdownToolbarButton {
.toolbarButton.toggled,
.splitToolbarButton.toggled > .toolbarButton.toggled {
background-color: hsla(0,0%,0%,.3);
background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
border-color: hsla(0,0%,0%,.4) hsla(0,0%,0%,.45) hsla(0,0%,0%,.5);
box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset,
@ -820,9 +865,9 @@ html[dir='rtl'] .toolbarButton.pageDown::before {
content: url(images/toolbarButton-zoomIn.png);
}
.toolbarButton.fullscreen::before {
.toolbarButton.presentationMode::before {
display: inline-block;
content: url(images/toolbarButton-fullscreen.png);
content: url(images/toolbarButton-presentationMode.png);
}
.toolbarButton.print::before {
@ -880,7 +925,7 @@ html[dir='rtl'] .toolbarButton.pageDown::before {
border: 1px solid transparent;
border-radius: 2px;
background-color: hsla(0,0%,100%,.09);
background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-clip: padding-box;
border: 1px solid hsla(0,0%,0%,.35);
border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42);
@ -977,7 +1022,7 @@ a:focus > .thumbnail > .thumbnailSelectionRing > .thumbnailImage,
a:focus > .thumbnail > .thumbnailSelectionRing,
.thumbnail:hover > .thumbnailSelectionRing {
background-color: hsla(0,0%,100%,.15);
background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-clip: padding-box;
box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
0 0 1px hsla(0,0%,100%,.2) inset,
@ -992,7 +1037,7 @@ a:focus > .thumbnail > .thumbnailSelectionRing,
.thumbnail.selected > .thumbnailSelectionRing {
background-color: hsla(0,0%,100%,.3);
background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-clip: padding-box;
box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
0 0 1px hsla(0,0%,100%,.1) inset,
@ -1043,7 +1088,7 @@ html[dir='rtl'] .outlineItem > a {
.outlineItem > a:hover {
background-color: hsla(0,0%,100%,.02);
background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-clip: padding-box;
box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
0 0 1px hsla(0,0%,100%,.2) inset,
@ -1053,7 +1098,7 @@ html[dir='rtl'] .outlineItem > a {
.outlineItem.selected {
background-color: hsla(0,0%,100%,.08);
background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-clip: padding-box;
box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
0 0 1px hsla(0,0%,100%,.1) inset,
@ -1123,82 +1168,6 @@ canvas {
background: url('images/loading-icon.gif') center no-repeat;
}
#loadingBox {
position: absolute;
top: 50%;
margin-top: -25px;
left: 0;
right: 0;
text-align: center;
color: #ddd;
font-size: 14px;
}
#loadingBar {
display: inline-block;
clear: both;
margin: 0px;
margin-top: 5px;
line-height: 0;
border-radius: 2px;
width: 200px;
height: 25px;
background-color: hsla(0,0%,0%,.3);
background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
border: 1px solid #000;
box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset,
0 0 1px hsla(0,0%,0%,.2) inset,
0 0 1px 1px rgba(255, 255, 255, 0.1);
}
#loadingBar .progress {
display: inline-block;
float: left;
background: #666;
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#b2b2b2), color-stop(100%,#898989));
background: -webkit-linear-gradient(top, #b2b2b2 0%,#898989 100%);
background: -moz-linear-gradient(top, #b2b2b2 0%,#898989 100%);
background: -ms-linear-gradient(top, #b2b2b2 0%,#898989 100%);
background: -o-linear-gradient(top, #b2b2b2 0%,#898989 100%);
background: linear-gradient(top, #b2b2b2 0%,#898989 100%);
border-top-left-radius: 2px;
border-bottom-left-radius: 2px;
width: 0%;
height: 100%;
}
#loadingBar .progress.full {
border-top-right-radius: 2px;
border-bottom-right-radius: 2px;
}
#loadingBar .progress.indeterminate {
width: 100%;
height: 25px;
background-image: -moz-linear-gradient( 30deg, #404040, #404040 15%, #898989, #404040 85%, #404040);
background-image: -webkit-linear-gradient( 30deg, #404040, #404040 15%, #898989, #404040 85%, #404040);
background-image: -ms-linear-gradient( 30deg, #404040, #404040 15%, #898989, #404040 85%, #404040);
background-image: -o-linear-gradient( 30deg, #404040, #404040 15%, #898989, #404040 85%, #404040);
background-size: 75px 25px;
-moz-animation: progressIndeterminate 1s linear infinite;
-webkit-animation: progressIndeterminate 1s linear infinite;
}
@-moz-keyframes progressIndeterminate {
from { background-position: 0px 0px; }
to { background-position: 75px 0px; }
}
@-webkit-keyframes progressIndeterminate {
from { background-position: 0px 0px; }
to { background-position: 75px 0px; }
}
.textLayer {
position: absolute;
left: 0;
@ -1280,7 +1249,6 @@ canvas {
left: 0;
position: absolute;
right: 0;
top: 32px;
z-index: 1000;
padding: 3px;
font-size: 0.8em;
@ -1380,6 +1348,11 @@ canvas {
}
@media print {
/* General rules for printing. */
body {
background: transparent none;
}
/* Rules for browsers that don't support mozPrintCallback. */
#sidebarContainer, .toolbar, #loadingBox, #errorWrapper, .textLayer {
display: none;
@ -1430,9 +1403,12 @@ canvas {
@media all and (max-width: 770px) {
#sidebarContainer {
top: 33px;
top: 32px;
z-index: 100;
}
.loadingInProgress #sidebarContainer {
top: 39px;
}
#sidebarContent {
top: 32px;
background-color: hsla(0,0%,0%,.7);

View File

@ -36,8 +36,8 @@ limitations under the License.
<script type="text/javascript" src="viewer.js"></script>
</head>
<body>
<div id="outerContainer">
<body tabindex="1">
<div id="outerContainer" class="loadingInProgress">
<div id="sidebarContainer">
<div id="toolbarSidebar">
@ -105,7 +105,7 @@ limitations under the License.
<div id="toolbarViewerRight">
<input id="fileInput" class="fileInput" type="file" oncontextmenu="return false;" style="visibility: hidden; position: fixed; right: 0; top: 0" />
<button id="fullscreen" class="toolbarButton fullscreen hiddenSmallView" title="Switch to Presentation Mode" tabindex="12" data-l10n-id="presentation_mode">
<button id="presentationMode" class="toolbarButton presentationMode hiddenSmallView" title="Switch to Presentation Mode" tabindex="12" data-l10n-id="presentation_mode">
<span data-l10n-id="presentation_mode_label">Presentation Mode</span>
</button>
@ -126,11 +126,11 @@ limitations under the License.
<div class="outerCenter">
<div class="innerCenter" id="toolbarViewerMiddle">
<div class="splitToolbarButton">
<button class="toolbarButton zoomOut" id="zoom_out" title="Zoom Out" tabindex="9" data-l10n-id="zoom_out">
<button id="zoomOut" class="toolbarButton zoomOut" title="Zoom Out" tabindex="9" data-l10n-id="zoom_out">
<span data-l10n-id="zoom_out_label">Zoom Out</span>
</button>
<div class="splitToolbarButtonSeparator"></div>
<button class="toolbarButton zoomIn" id="zoom_in" title="Zoom In" tabindex="10" data-l10n-id="zoom_in">
<button id="zoomIn" class="toolbarButton zoomIn" title="Zoom In" tabindex="10" data-l10n-id="zoom_in">
<span data-l10n-id="zoom_in_label">Zoom In</span>
</button>
</div>
@ -152,29 +152,30 @@ limitations under the License.
</div>
</div>
</div>
<div id="loadingBar">
<div class="progress">
<div class="glimmer">
</div>
</div>
</div>
</div>
</div>
<menu type="context" id="viewerContextMenu">
<menuitem label="First Page" id="first_page"
<menuitem id="firstPage" label="First Page"
data-l10n-id="first_page" ></menuitem>
<menuitem label="Last Page" id="last_page"
<menuitem id="lastPage" label="Last Page"
data-l10n-id="last_page" ></menuitem>
<menuitem label="Rotate Counter-Clockwise" id="page_rotate_ccw"
<menuitem id="pageRotateCcw" label="Rotate Counter-Clockwise"
data-l10n-id="page_rotate_ccw" ></menuitem>
<menuitem label="Rotate Clockwise" id="page_rotate_cw"
<menuitem id="pageRotateCw" label="Rotate Clockwise"
data-l10n-id="page_rotate_cw" ></menuitem>
</menu>
<div id="viewerContainer" tabindex="1">
<div id="viewerContainer">
<div id="viewer" contextmenu="viewerContextMenu"></div>
</div>
<div id="loadingBox">
<div id="loading"></div>
<div id="loadingBar"><div class="progress"></div></div>
</div>
<div id="errorWrapper" hidden='true'>
<div id="errorMessageLeft">
<span id="errorMessage"></span>

View File

@ -28,9 +28,7 @@ var SCROLLBAR_PADDING = 40;
var VERTICAL_PADDING = 5;
var MIN_SCALE = 0.25;
var MAX_SCALE = 4.0;
var IMAGE_DIR = './images/';
var SETTINGS_MEMORY = 20;
var ANNOT_MIN_SIZE = 10;
var RenderingStates = {
INITIAL: 0,
RUNNING: 1,
@ -108,6 +106,7 @@ var ProgressBar = (function ProgressBarClosure() {
// Initialize heights
this.div.style.height = this.height + this.units;
this.percent = 0;
}
ProgressBar.prototype = {
@ -115,17 +114,12 @@ var ProgressBar = (function ProgressBarClosure() {
updateBar: function ProgressBar_updateBar() {
if (this._indeterminate) {
this.div.classList.add('indeterminate');
this.div.style.width = this.width + this.units;
return;
}
var progressSize = this.width * this._percent / 100;
if (this._percent > 95)
this.div.classList.add('full');
else
this.div.classList.remove('full');
this.div.classList.remove('indeterminate');
var progressSize = this.width * this._percent / 100;
this.div.style.width = progressSize + this.units;
},
@ -742,7 +736,7 @@ var PDFView = {
sidebarOpen: false,
pageViewScroll: null,
thumbnailViewScroll: null,
isFullscreen: false,
isPresentationMode: false,
previousScale: null,
pageRotation: 0,
mouseScrollTimeStamp: 0,
@ -921,11 +915,12 @@ var PDFView = {
var support = doc.requestFullscreen || doc.mozRequestFullScreen ||
doc.webkitRequestFullScreen;
// Disable fullscreen button if we're in an iframe
if (window.parent !== window)
// Disable presentation mode button if we're in an iframe
if (window.parent !== window) {
support = false;
}
Object.defineProperty(this, 'supportsFullScreen', { value: support,
Object.defineProperty(this, 'supportsFullscreen', { value: support,
enumerable: true,
configurable: true,
writable: false });
@ -972,12 +967,57 @@ var PDFView = {
PDFView.loadingBar = new ProgressBar('#loadingBar', {});
}
window.addEventListener('message', function window_message(e) {
var pdfDataRangeTransport = {
rangeListeners: [],
progressListeners: [],
addRangeListener: function PdfDataRangeTransport_addRangeListener(
listener) {
this.rangeListeners.push(listener);
},
addProgressListener: function PdfDataRangeTransport_addProgressListener(
listener) {
this.progressListeners.push(listener);
},
onDataRange: function PdfDataRangeTransport_onDataRange(begin, chunk) {
var listeners = this.rangeListeners;
for (var i = 0, n = listeners.length; i < n; ++i) {
listeners[i](begin, chunk);
}
},
onDataProgress: function PdfDataRangeTransport_onDataProgress(loaded) {
var listeners = this.progressListeners;
for (var i = 0, n = listeners.length; i < n; ++i) {
listeners[i](loaded);
}
},
requestDataRange: function PdfDataRangeTransport_requestDataRange(
begin, end) {
FirefoxCom.request('requestDataRange', { begin: begin, end: end });
}
};
window.addEventListener('message', function windowMessage(e) {
var args = e.data;
if (typeof args !== 'object' || !('pdfjsLoadAction' in args))
return;
switch (args.pdfjsLoadAction) {
case 'supportsRangedLoading':
PDFView.open(args.pdfUrl, 0, undefined, pdfDataRangeTransport, {
length: args.length
});
break;
case 'range':
pdfDataRangeTransport.onDataRange(args.begin, args.chunk);
break;
case 'rangeProgress':
pdfDataRangeTransport.onDataProgress(args.loaded);
break;
case 'progress':
PDFView.progress(args.loaded / args.total);
break;
@ -1009,7 +1049,9 @@ var PDFView = {
document.title = title;
},
open: function pdfViewOpen(url, scale, password) {
// TODO(mack): This function signature should really be pdfViewOpen(url, args)
open: function pdfViewOpen(url, scale, password,
pdfDataRangeTransport, args) {
var parameters = {password: password};
if (typeof url === 'string') { // URL
this.setTitleUsingUrl(url);
@ -1017,6 +1059,11 @@ var PDFView = {
} else if (url && 'byteLength' in url) { // ArrayBuffer
parameters.data = url;
}
if (args) {
for (var prop in args) {
parameters[prop] = args[prop];
}
}
if (!PDFView.loadingBar) {
PDFView.loadingBar = new ProgressBar('#loadingBar', {});
@ -1025,23 +1072,27 @@ var PDFView = {
this.pdfDocument = null;
var self = this;
self.loading = true;
PDFJS.getDocument(parameters).then(
var passwordNeeded = function passwordNeeded(updatePassword, reason) {
var promptString = mozL10n.get('request_password', null,
'PDF is protected by a password:');
if (reason === PDFJS.PasswordResponses.INCORRECT_PASSWORD) {
promptString += '\n' + mozL10n.get('invalid_password', null,
'Invalid Password.');
}
password = prompt(promptString);
if (password && password.length > 0) {
return updatePassword(password);
}
};
PDFJS.getDocument(parameters, pdfDataRangeTransport, passwordNeeded).then(
function getDocumentCallback(pdfDocument) {
self.load(pdfDocument, scale);
self.loading = false;
},
function getDocumentError(message, exception) {
if (exception && exception.name === 'PasswordException') {
if (exception.code === 'needpassword') {
var promptString = mozL10n.get('request_password', null,
'PDF is protected by a password:');
password = prompt(promptString);
if (password && password.length > 0) {
return PDFView.open(url, scale, password);
}
}
}
var loadingErrorMessage = mozL10n.get('loading_error', null,
'An error occurred while loading the PDF.');
@ -1058,9 +1109,6 @@ var PDFView = {
}
var loadingIndicator = document.getElementById('loading');
loadingIndicator.textContent = mozL10n.get('loading_error_indicator',
null, 'Error');
var moreInfo = {
message: message
};
@ -1118,23 +1166,31 @@ var PDFView = {
},
navigateTo: function pdfViewNavigateTo(dest) {
if (typeof dest === 'string')
dest = this.destinations[dest];
if (!(dest instanceof Array))
return; // invalid destination
// dest array looks like that: <page-ref> </XYZ|FitXXX> <args..>
var destRef = dest[0];
var pageNumber = destRef instanceof Object ?
this.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] : (destRef + 1);
if (pageNumber > this.pages.length)
pageNumber = this.pages.length;
if (pageNumber) {
this.page = pageNumber;
var currentPage = this.pages[pageNumber - 1];
if (!this.isFullscreen) { // Avoid breaking fullscreen mode.
currentPage.scrollIntoView(dest);
var self = this;
PDFJS.Promise.all([this.pagesPromise,
this.destinationsPromise]).then(function() {
if (typeof dest === 'string') {
dest = self.destinations[dest];
}
}
if (!(dest instanceof Array)) {
return; // invalid destination
}
// dest array looks like that: <page-ref> </XYZ|FitXXX> <args..>
var destRef = dest[0];
var pageNumber = destRef instanceof Object ?
self.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] :
(destRef + 1);
if (pageNumber) {
if (pageNumber > self.pages.length) {
pageNumber = self.pages.length;
}
self.page = pageNumber;
if (!self.isPresentationMode) { // Avoid breaking presentation mode.
var currentPage = self.pages[pageNumber - 1];
currentPage.scrollIntoView(dest);
}
}
});
},
getDestinationHash: function pdfViewGetDestinationHash(dest) {
@ -1219,16 +1275,19 @@ var PDFView = {
}
}
var loadingBox = document.getElementById('loadingBox');
loadingBox.setAttribute('hidden', 'true');
console.error(message + '\n' + moreInfoText);
this.fallback();
},
progress: function pdfViewProgress(level) {
var percent = Math.round(level * 100);
PDFView.loadingBar.percent = percent;
// When we transition from full request to range requests, it's possible
// that we discard some of the loaded data. This can cause the loading
// bar to move backwards. So prevent this by only updating the bar if it
// increases.
if (percent > PDFView.loadingBar.percent) {
PDFView.loadingBar.percent = percent;
}
},
load: function pdfViewLoad(pdfDocument, scale) {
@ -1244,10 +1303,12 @@ var PDFView = {
var errorWrapper = document.getElementById('errorWrapper');
errorWrapper.setAttribute('hidden', 'true');
var loadingBox = document.getElementById('loadingBox');
loadingBox.setAttribute('hidden', 'true');
var loadingIndicator = document.getElementById('loading');
loadingIndicator.textContent = '';
pdfDocument.dataLoaded().then(function() {
var loadingBar = document.getElementById('loadingBar');
loadingBar.classList.add('hidden');
var outerContainer = document.getElementById('outerContainer');
outerContainer.classList.remove('loadingInProgress');
});
var thumbsView = document.getElementById('thumbnailView');
thumbsView.parentNode.scrollTop = 0;
@ -1279,7 +1340,7 @@ var PDFView = {
var pagesRefMap = this.pagesRefMap = {};
var thumbnails = this.thumbnails = [];
var pagesPromise = new PDFJS.Promise();
var pagesPromise = this.pagesPromise = new PDFJS.Promise();
var self = this;
var firstPagePromise = pdfDocument.getPage(1);
@ -1345,6 +1406,13 @@ var PDFView = {
left + ',' + top;
}
self.setInitialView(storedHash, scale);
// Make all navigation keys work on document load,
// unless the viewer is embedded in another page.
if (window.parent === window) {
PDFView.container.focus();
PDFView.container.blur();
}
});
pagesPromise.then(function() {
@ -1369,7 +1437,8 @@ var PDFView = {
}
});
var destinationsPromise = pdfDocument.getDestinations();
var destinationsPromise =
this.destinationsPromise = pdfDocument.getDestinations();
destinationsPromise.then(function(destinations) {
self.destinations = destinations;
});
@ -1382,12 +1451,6 @@ var PDFView = {
self.outline = new DocumentOutlineView(outline);
document.getElementById('viewOutline').disabled = !outline;
});
// Make all navigation keys work on document load,
// unless the viewer is embedded in another page.
if (window.parent.location === window.location) {
PDFView.container.focus();
}
});
pdfDocument.getMetadata().then(function(data) {
@ -1616,10 +1679,10 @@ var PDFView = {
},
getVisiblePages: function pdfViewGetVisiblePages() {
if (!this.isFullscreen) {
if (!this.isPresentationMode) {
return this.getVisibleElements(this.container, this.pages, true);
} else {
// The algorithm in getVisibleElements is broken in fullscreen mode.
// The algorithm in getVisibleElements is broken in presentation mode.
var visible = [], page = this.page;
var currentPage = this.pages[page - 1];
visible.push({ id: currentPage.id, view: currentPage });
@ -1687,7 +1750,7 @@ var PDFView = {
var param = parts[i].split('=');
var key = param[0];
var value = param.length > 1 ? param[1] : null;
params[unescape(key)] = unescape(value);
params[decodeURIComponent(key)] = decodeURIComponent(value);
}
return params;
},
@ -1731,11 +1794,12 @@ var PDFView = {
div.removeChild(div.lastChild);
},
fullscreen: function pdfViewFullscreen() {
var isFullscreen = document.fullscreenElement || document.mozFullScreen ||
document.webkitIsFullScreen;
presentationMode: function pdfViewPresentationMode() {
var isPresentationMode = document.fullscreenElement ||
document.mozFullScreen ||
document.webkitIsFullScreen;
if (isFullscreen) {
if (isPresentationMode) {
return false;
}
@ -1750,12 +1814,12 @@ var PDFView = {
return false;
}
this.isFullscreen = true;
this.isPresentationMode = true;
var currentPage = this.pages[this.page - 1];
this.previousScale = this.currentScaleValue;
this.parseScale('page-fit', true);
// Wait for fullscreen to take effect
// Wait for presentation mode to take effect
setTimeout(function() {
currentPage.scrollIntoView();
}, 0);
@ -1764,15 +1828,15 @@ var PDFView = {
return true;
},
exitFullscreen: function pdfViewExitFullscreen() {
this.isFullscreen = false;
exitPresentationMode: function pdfViewExitPresentationMode() {
this.isPresentationMode = false;
this.parseScale(this.previousScale);
this.page = this.page;
this.clearMouseScrollState();
this.hidePresentationControls();
// Ensure that the thumbnail of the current page is visible
// when exiting fullscreen mode.
// when exiting presentation mode.
scrollIntoView(document.getElementById('thumbnailContainer' + this.page));
},
@ -1824,7 +1888,7 @@ var PDFView = {
return;
}
// Wait for fullscreen to take effect
// Wait for presentation mode to take effect
setTimeout(function() {
currentPage.scrollIntoView();
}, 0);
@ -1865,7 +1929,7 @@ var PDFView = {
DOWN: 1
};
// In fullscreen mode scroll one page at a time.
// In presentation mode scroll one page at a time.
var pageFlipDirection = (this.mouseScrollDelta > 0) ?
PageFlipDirection.UP :
PageFlipDirection.DOWN;
@ -1982,7 +2046,8 @@ var PageView = function pageView(container, id, scale,
enumerable: true
});
function setupAnnotations(pdfPage, viewport) {
function setupAnnotations(annotationsDiv, pdfPage, viewport) {
function bindLink(link, dest) {
link.href = PDFView.getDestinationHash(dest);
link.onclick = function pageViewSetupLinksOnclick() {
@ -1992,91 +2057,43 @@ var PageView = function pageView(container, id, scale,
};
link.className = 'internalLink';
}
function createElementWithStyle(tagName, item, rect) {
if (!rect) {
rect = viewport.convertToViewportRectangle(item.rect);
rect = PDFJS.Util.normalizeRect(rect);
}
var element = document.createElement(tagName);
element.style.left = Math.floor(rect[0]) + 'px';
element.style.top = Math.floor(rect[1]) + 'px';
element.style.width = Math.ceil(rect[2] - rect[0]) + 'px';
element.style.height = Math.ceil(rect[3] - rect[1]) + 'px';
return element;
}
function createTextAnnotation(item) {
var container = document.createElement('section');
container.className = 'annotText';
var rect = viewport.convertToViewportRectangle(item.rect);
rect = PDFJS.Util.normalizeRect(rect);
// sanity check because of OOo-generated PDFs
if ((rect[3] - rect[1]) < ANNOT_MIN_SIZE) {
rect[3] = rect[1] + ANNOT_MIN_SIZE;
}
if ((rect[2] - rect[0]) < ANNOT_MIN_SIZE) {
rect[2] = rect[0] + (rect[3] - rect[1]); // make it square
}
var image = createElementWithStyle('img', item, rect);
var iconName = item.name;
image.src = IMAGE_DIR + 'annotation-' +
iconName.toLowerCase() + '.svg';
image.alt = mozL10n.get('text_annotation_type', {type: iconName},
'[{{type}} Annotation]');
var content = document.createElement('div');
content.setAttribute('hidden', true);
var title = document.createElement('h1');
var text = document.createElement('p');
content.style.left = Math.floor(rect[2]) + 'px';
content.style.top = Math.floor(rect[1]) + 'px';
title.textContent = item.title;
if (!item.content && !item.title) {
content.setAttribute('hidden', true);
} else {
var e = document.createElement('span');
var lines = item.content.split(/(?:\r\n?|\n)/);
for (var i = 0, ii = lines.length; i < ii; ++i) {
var line = lines[i];
e.appendChild(document.createTextNode(line));
if (i < (ii - 1))
e.appendChild(document.createElement('br'));
pdfPage.getAnnotations().then(function(annotationsData) {
viewport = viewport.clone({ dontFlip: true });
for (var i = 0; i < annotationsData.length; i++) {
var data = annotationsData[i];
var annotation = PDFJS.Annotation.fromData(data);
if (!annotation || !annotation.hasHtml()) {
continue;
}
text.appendChild(e);
image.addEventListener('mouseover', function annotationImageOver() {
content.removeAttribute('hidden');
}, false);
image.addEventListener('mouseout', function annotationImageOut() {
content.setAttribute('hidden', true);
}, false);
}
var element = annotation.getHtmlElement(pdfPage.commonObjs);
mozL10n.translate(element);
content.appendChild(title);
content.appendChild(text);
container.appendChild(image);
container.appendChild(content);
data = annotation.getData();
var rect = data.rect;
var view = pdfPage.view;
rect = PDFJS.Util.normalizeRect([
rect[0],
view[3] - rect[1] + view[1],
rect[2],
view[3] - rect[3] + view[1]
]);
element.style.left = rect[0] + 'px';
element.style.top = rect[1] + 'px';
element.style.position = 'absolute';
return container;
}
var transform = viewport.transform;
var transformStr = 'matrix(' + transform.join(',') + ')';
CustomStyle.setProp('transform', element, transformStr);
var transformOriginStr = -rect[0] + 'px ' + -rect[1] + 'px';
CustomStyle.setProp('transformOrigin', element, transformOriginStr);
pdfPage.getAnnotations().then(function(items) {
for (var i = 0; i < items.length; i++) {
var item = items[i];
switch (item.type) {
case 'Link':
var link = createElementWithStyle('a', item);
link.href = item.url || '';
if (!item.url)
bindLink(link, ('dest' in item) ? item.dest : null);
div.appendChild(link);
break;
case 'Text':
var textAnnotation = createTextAnnotation(item);
if (textAnnotation)
div.appendChild(textAnnotation);
break;
if (data.subtype === 'Link' && !data.url) {
bindLink(element, ('dest' in data) ? data.dest : null);
}
annotationsDiv.appendChild(element);
}
});
}
@ -2135,10 +2152,16 @@ var PageView = function pageView(container, id, scale,
return;
}
if (scale && scale !== PDFView.currentScale)
if (scale && scale !== PDFView.currentScale) {
PDFView.parseScale(scale, true, true);
else if (PDFView.currentScale === UNKNOWN_SCALE)
} else if (PDFView.currentScale === UNKNOWN_SCALE) {
PDFView.parseScale(DEFAULT_SCALE, true, true);
}
if (scale === 'page-fit' && !dest[4]) {
scrollIntoView(div);
return;
}
var boundingRect = [
this.viewport.convertToViewportPoint(x, y),
@ -2248,8 +2271,10 @@ var PageView = function pageView(container, id, scale,
if (self.textLayer && self.textLayer.textDivs &&
self.textLayer.textDivs.length > 0 &&
!PDFView.supportsDocumentColors) {
console.error(mozL10n.get('web_colors_disabled', null,
'Web colors are disabled.'));
console.error(mozL10n.get('document_colors_disabled', null,
'PDF documents are not allowed to use their own colors: ' +
'\'Allow pages to choose their own colors\' ' +
'is deactivated in the browser.'));
PDFView.fallback();
}
if (error) {
@ -2312,7 +2337,7 @@ var PageView = function pageView(container, id, scale,
);
}
setupAnnotations(this.pdfPage, this.viewport);
setupAnnotations(div, pdfPage, this.viewport);
div.setAttribute('data-loaded', true);
};
@ -2990,8 +3015,17 @@ document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) {
var hash = document.location.hash.substring(1);
var hashParams = PDFView.parseQueryString(hash);
if ('disableWorker' in hashParams)
if ('disableWorker' in hashParams) {
PDFJS.disableWorker = (hashParams['disableWorker'] === 'true');
}
if ('disableRange' in hashParams) {
PDFJS.disableRange = (hashParams['disableRange'] === 'true');
}
if ('disableAutoFetch' in hashParams) {
PDFJS.disableAutoFetch = (hashParams['disableAutoFetch'] === 'true');
}
if ('textLayer' in hashParams) {
@ -3021,11 +3055,11 @@ document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) {
}
if (!PDFView.supportsFullscreen) {
document.getElementById('fullscreen').classList.add('hidden');
document.getElementById('presentationMode').classList.add('hidden');
}
if (PDFView.supportsIntegratedFind) {
document.querySelector('#viewFind').classList.add('hidden');
document.getElementById('viewFind').classList.add('hidden');
}
// Listen for warnings to trigger the fallback UI. Errors should be caught
@ -3076,19 +3110,19 @@ document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) {
PDFView.page++;
});
document.querySelector('.zoomIn').addEventListener('click',
document.getElementById('zoomIn').addEventListener('click',
function() {
PDFView.zoomIn();
});
document.querySelector('.zoomOut').addEventListener('click',
document.getElementById('zoomOut').addEventListener('click',
function() {
PDFView.zoomOut();
});
document.getElementById('fullscreen').addEventListener('click',
document.getElementById('presentationMode').addEventListener('click',
function() {
PDFView.fullscreen();
PDFView.presentationMode();
});
document.getElementById('openFile').addEventListener('click',
@ -3126,31 +3160,29 @@ document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) {
PDFView.parseScale(this.value);
});
document.getElementById('first_page').addEventListener('click',
document.getElementById('firstPage').addEventListener('click',
function() {
PDFView.page = 1;
});
document.getElementById('last_page').addEventListener('click',
document.getElementById('lastPage').addEventListener('click',
function() {
PDFView.page = PDFView.pdfDocument.numPages;
});
document.getElementById('page_rotate_ccw').addEventListener('click',
document.getElementById('pageRotateCcw').addEventListener('click',
function() {
PDFView.rotatePages(-90);
});
document.getElementById('page_rotate_cw').addEventListener('click',
document.getElementById('pageRotateCw').addEventListener('click',
function() {
PDFView.rotatePages(90);
});
if (FirefoxCom.requestSync('getLoadingType') == 'passive') {
PDFView.setTitleUsingUrl(file);
PDFView.initPassiveLoading();
return;
}
PDFView.setTitleUsingUrl(file);
PDFView.initPassiveLoading();
return;
PDFView.open(file, 0);
}, true);
@ -3187,7 +3219,7 @@ function updateViewarea() {
currentId = visiblePages[0].id;
}
if (!PDFView.isFullscreen) {
if (!PDFView.isPresentationMode) {
updateViewarea.inProgress = true; // used in "set page"
PDFView.page = currentId;
updateViewarea.inProgress = false;
@ -3285,6 +3317,9 @@ window.addEventListener('localized', function localized(evt) {
}, true);
window.addEventListener('scalechange', function scalechange(evt) {
document.getElementById('zoomOut').disabled = (evt.scale === MIN_SCALE);
document.getElementById('zoomIn').disabled = (evt.scale === MAX_SCALE);
var customScaleOption = document.getElementById('customScaleOption');
customScaleOption.selected = false;
@ -3301,10 +3336,6 @@ window.addEventListener('scalechange', function scalechange(evt) {
customScaleOption.textContent = Math.round(evt.scale * 10000) / 100 + '%';
customScaleOption.selected = true;
}
document.getElementById('zoom_out').disabled = (evt.scale === MIN_SCALE);
document.getElementById('zoom_in').disabled = (evt.scale === MAX_SCALE);
updateViewarea();
}, true);
@ -3343,27 +3374,28 @@ window.addEventListener('DOMMouseScroll', function(evt) {
var direction = (ticks > 0) ? 'zoomOut' : 'zoomIn';
for (var i = 0, length = Math.abs(ticks); i < length; i++)
PDFView[direction]();
} else if (PDFView.isFullscreen) {
} else if (PDFView.isPresentationMode) {
var FIREFOX_DELTA_FACTOR = -40;
PDFView.mouseScroll(evt.detail * FIREFOX_DELTA_FACTOR);
}
}, false);
window.addEventListener('mousemove', function mousemove(evt) {
if (PDFView.isFullscreen) {
if (PDFView.isPresentationMode) {
PDFView.showPresentationControls();
}
}, false);
window.addEventListener('mousedown', function mousedown(evt) {
if (PDFView.isFullscreen && evt.button === 0) {
// Enable clicking of links in fullscreen mode.
if (PDFView.isPresentationMode && evt.button === 0) {
// Enable clicking of links in presentation mode.
// Note: Only links that point to the currently loaded PDF document works.
var targetHref = evt.target.href;
var internalLink = targetHref && (targetHref.replace(/#.*$/, '') ===
window.location.href.replace(/#.*$/, ''));
if (!internalLink) {
// Unless an internal link was clicked, advance a page in fullscreen mode.
// Unless an internal link was clicked, advance a page in presentation
// mode.
evt.preventDefault();
PDFView.page++;
}
@ -3371,7 +3403,7 @@ window.addEventListener('mousedown', function mousedown(evt) {
}, false);
window.addEventListener('click', function click(evt) {
if (PDFView.isFullscreen && evt.button === 0) {
if (PDFView.isPresentationMode && evt.button === 0) {
// Necessary since preventDefault() in 'mousedown' won't stop
// the event propagation in all circumstances.
evt.preventDefault();
@ -3443,7 +3475,7 @@ window.addEventListener('keydown', function keydown(evt) {
}
var controlsElement = document.getElementById('toolbar');
while (curElement) {
if (curElement === controlsElement && !PDFView.isFullscreen)
if (curElement === controlsElement && !PDFView.isPresentationMode)
return; // ignoring if the 'toolbar' element is focused
curElement = curElement.parentNode;
}
@ -3453,10 +3485,11 @@ window.addEventListener('keydown', function keydown(evt) {
case 38: // up arrow
case 33: // pg up
case 8: // backspace
if (!PDFView.isFullscreen && PDFView.currentScaleValue !== 'page-fit') {
if (!PDFView.isPresentationMode &&
PDFView.currentScaleValue !== 'page-fit') {
break;
}
/* in fullscreen mode */
/* in presentation mode */
/* falls through */
case 37: // left arrow
// horizontal scrolling using arrow keys
@ -3478,7 +3511,8 @@ window.addEventListener('keydown', function keydown(evt) {
case 40: // down arrow
case 34: // pg down
case 32: // spacebar
if (!PDFView.isFullscreen && PDFView.currentScaleValue !== 'page-fit') {
if (!PDFView.isPresentationMode &&
PDFView.currentScaleValue !== 'page-fit') {
break;
}
/* falls through */
@ -3495,13 +3529,13 @@ window.addEventListener('keydown', function keydown(evt) {
break;
case 36: // home
if (PDFView.isFullscreen) {
if (PDFView.isPresentationMode) {
PDFView.page = 1;
handled = true;
}
break;
case 35: // end
if (PDFView.isFullscreen) {
if (PDFView.isPresentationMode) {
PDFView.page = PDFView.pdfDocument.numPages;
handled = true;
}
@ -3535,19 +3569,21 @@ window.addEventListener('afterprint', function afterPrint(evt) {
PDFView.afterPrint();
});
(function fullscreenClosure() {
function fullscreenChange(e) {
var isFullscreen = document.fullscreenElement || document.mozFullScreen ||
document.webkitIsFullScreen;
(function presentationModeClosure() {
function presentationModeChange(e) {
var isPresentationMode = document.fullscreenElement ||
document.mozFullScreen ||
document.webkitIsFullScreen;
if (!isFullscreen) {
PDFView.exitFullscreen();
if (!isPresentationMode) {
PDFView.exitPresentationMode();
}
}
window.addEventListener('fullscreenchange', fullscreenChange, false);
window.addEventListener('mozfullscreenchange', fullscreenChange, false);
window.addEventListener('webkitfullscreenchange', fullscreenChange, false);
window.addEventListener('fullscreenchange', presentationModeChange, false);
window.addEventListener('mozfullscreenchange', presentationModeChange, false);
window.addEventListener('webkitfullscreenchange', presentationModeChange,
false);
})();
(function animationStartedClosure() {

View File

@ -2,6 +2,7 @@ chrome.manifest
components/PdfRedirector.js
components/PdfStreamConverter.js
content/build/pdf.js
content/network.js
content/PdfJs.jsm
content/web/debugger.js
content/web/images/annotation-check.svg
@ -22,13 +23,13 @@ content/web/images/shadow.png
content/web/images/texture.png
content/web/images/toolbarButton-bookmark.png
content/web/images/toolbarButton-download.png
content/web/images/toolbarButton-fullscreen.png
content/web/images/toolbarButton-menuArrows.png
content/web/images/toolbarButton-openFile.png
content/web/images/toolbarButton-pageDown-rtl.png
content/web/images/toolbarButton-pageDown.png
content/web/images/toolbarButton-pageUp-rtl.png
content/web/images/toolbarButton-pageUp.png
content/web/images/toolbarButton-presentationMode.png
content/web/images/toolbarButton-print.png
content/web/images/toolbarButton-search.png
content/web/images/toolbarButton-sidebarToggle.png

View File

@ -110,14 +110,15 @@ loading_error=An error occurred while loading the PDF.
invalid_file_error=Invalid or corrupted PDF file.
missing_file_error=Missing PDF file.
# LOCALIZATION NOTE (text_annotation_type): This is used as a tooltip.
# LOCALIZATION NOTE (text_annotation_type.alt): This is used as a tooltip.
# "{{type}}" will be replaced with an annotation type from a list defined in
# the PDF spec (32000-1:2008 Table 169 Annotation types).
# Some common types are e.g.: "Check", "Text", "Comment", "Note"
text_annotation_type=[{{type}} Annotation]
text_annotation_type.alt=[{{type}} Annotation]
request_password=PDF is protected by a password:
invalid_password=Invalid Password.
printing_not_supported=Warning: Printing is not fully supported by this browser.
printing_not_ready=Warning: The PDF is not fully loaded for printing.
web_fonts_disabled=Web fonts are disabled: unable to use embedded PDF fonts.
web_colors_disabled=Web colors are disabled.
document_colors_disabled=PDF documents are not allowed to use their own colors: \'Allow pages to choose their own colors\' is deactivated in the browser.

View File

@ -11,7 +11,7 @@
#include "nsISupports.idl"
#include "nsIConsoleMessage.idl"
[scriptable, uuid(cac9d8e8-0d53-4fa8-9903-bb367e4fa1fe)]
[scriptable, uuid(ec640482-be5f-49a0-a9cb-c87eacce9291)]
interface nsIScriptError : nsIConsoleMessage
{
/** pseudo-flag for default case */
@ -41,6 +41,33 @@ interface nsIScriptError : nsIConsoleMessage
readonly attribute uint32_t columnNumber;
readonly attribute uint32_t flags;
/**
* Categories I know about -
* XUL javascript
* content javascript (both of these from nsDocShell, currently)
* component javascript (errors in JS components)
*/
readonly attribute string category;
/*
The time (in milliseconds from the Epoch) that the script error instance
was initialised, and thus the time when the error occurred.
Currently used to display date and time of the message in Error console.
The timestamp is initialized as JS_now/1000 so that it can be
compared to Date.now in Javascript.
*/
readonly attribute long long timeStamp;
/* Get the window id this was initialized with. Zero will be
returned if init() was used instead of initWithWindowID(). */
readonly attribute unsigned long long outerWindowID;
/* Get the inner window id this was initialized with. Zero will be
returned if init() was used instead of initWithWindowID(). */
readonly attribute unsigned long long innerWindowID;
readonly attribute boolean isFromPrivateWindow;
void init(in AString message,
in AString sourceName,
in AString sourceLine,
@ -60,11 +87,13 @@ interface nsIScriptError : nsIConsoleMessage
in uint32_t flags,
in string category,
in unsigned long long innerWindowID);
AUTF8String toString();
};
%{ C++
#define NS_SCRIPTERROR_CID \
{ 0x1950539a, 0x90f0, 0x4d22, { 0xb5, 0xaf, 0x71, 0x32, 0x9c, 0x68, 0xfa, 0x35 }}
{ 0xe38e53b9, 0x5bb0, 0x456a, { 0xb5, 0x53, 0x57, 0x93, 0x70, 0xcb, 0x15, 0x67 }}
#define NS_SCRIPTERROR_CONTRACTID "@mozilla.org/scripterror;1"
%}

View File

@ -93,16 +93,6 @@ nsScriptError::GetCategory(char **result) {
return NS_OK;
}
// nsIConsoleMessage method
NS_IMETHODIMP
nsScriptError::InitMessage(const nsAString& message,
const char *category,
uint64_t innerWindowID)
{
return InitWithWindowID(message, EmptyString(), EmptyString(), 0, 0, 0,
category, innerWindowID);
}
NS_IMETHODIMP
nsScriptError::Init(const nsAString& message,
const nsAString& sourceName,

View File

@ -174,7 +174,6 @@ const UnsolicitedNotifications = {
"consoleAPICall": "consoleAPICall",
"eventNotification": "eventNotification",
"fileActivity": "fileActivity",
"logMessage": "logMessage",
"networkEvent": "networkEvent",
"networkEventUpdate": "networkEventUpdate",
"newGlobal": "newGlobal",

View File

@ -39,7 +39,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "VariablesView",
"resource:///modules/devtools/VariablesView.jsm");
this.EXPORTED_SYMBOLS = ["WebConsoleUtils", "JSPropertyProvider", "JSTermHelpers",
"ConsoleServiceListener", "ConsoleAPIListener",
"PageErrorListener", "ConsoleAPIListener",
"NetworkResponseListener", "NetworkMonitor",
"ConsoleProgressListener"];
@ -873,25 +873,25 @@ return JSPropertyProvider;
///////////////////////////////////////////////////////////////////////////////
/**
* The nsIConsoleService listener. This is used to send all of the console
* messages (JavaScript, CSS and more) to the remote Web Console instance.
* The nsIConsoleService listener. This is used to send all the page errors
* (JavaScript, CSS and more) to the remote Web Console instance.
*
* @constructor
* @param nsIDOMWindow [aWindow]
* Optional - the window object for which we are created. This is used
* for filtering out messages that belong to other windows.
* @param object aListener
* The listener object must have one method:
* - onConsoleServiceMessage(). This method is invoked with one argument, the
* nsIConsoleMessage, whenever a relevant message is received.
* The listener object must have a method: onPageError. This method is
* invoked with one argument, the nsIScriptError, whenever a relevant
* page error is received.
*/
this.ConsoleServiceListener = function ConsoleServiceListener(aWindow, aListener)
this.PageErrorListener = function PageErrorListener(aWindow, aListener)
{
this.window = aWindow;
this.listener = aListener;
}
ConsoleServiceListener.prototype =
PageErrorListener.prototype =
{
QueryInterface: XPCOMUtils.generateQI([Ci.nsIConsoleListener]),
@ -902,7 +902,8 @@ ConsoleServiceListener.prototype =
window: null,
/**
* The listener object which is notified of messages from the console service.
* The listener object which is notified of page errors. It must have
* a onPageError method which is invoked with one argument: the nsIScriptError.
* @type object
*/
listener: null,
@ -910,7 +911,7 @@ ConsoleServiceListener.prototype =
/**
* Initialize the nsIConsoleService listener.
*/
init: function CSL_init()
init: function PEL_init()
{
Services.console.registerListener(this);
},
@ -920,47 +921,43 @@ ConsoleServiceListener.prototype =
* messages belonging to the current window and sends them to the remote Web
* Console instance.
*
* @param nsIConsoleMessage aMessage
* The message object coming from the nsIConsoleService.
* @param nsIScriptError aScriptError
* The script error object coming from the nsIConsoleService.
*/
observe: function CSL_observe(aMessage)
observe: function PEL_observe(aScriptError)
{
if (!this.listener) {
if (!this.listener ||
!(aScriptError instanceof Ci.nsIScriptError)) {
return;
}
if (this.window) {
if (!aMessage.outerWindowID ||
!this.isCategoryAllowed(aMessage.category)) {
if (!aScriptError.outerWindowID ||
!this.isCategoryAllowed(aScriptError.category)) {
return;
}
let errorWindow = Services.wm.getOuterWindowWithId(aMessage.outerWindowID);
let errorWindow =
Services.wm.getOuterWindowWithId(aScriptError.outerWindowID);
if (!errorWindow || errorWindow.top != this.window) {
return;
}
}
if (aMessage.message) {
this.listener.onConsoleServiceMessage(aMessage);
}
this.listener.onPageError(aScriptError);
},
/**
* Check if the given message category is allowed to be tracked or not.
* Check if the given script error category is allowed to be tracked or not.
* We ignore chrome-originating errors as we only care about content.
*
* @param string aCategory
* The message category you want to check.
* The nsIScriptError category you want to check.
* @return boolean
* True if the category is allowed to be logged, false otherwise.
*/
isCategoryAllowed: function CSL_isCategoryAllowed(aCategory)
isCategoryAllowed: function PEL_isCategoryAllowed(aCategory)
{
if (!aCategory) {
return false;
}
switch (aCategory) {
case "XPConnect JavaScript":
case "component javascript":
@ -980,26 +977,28 @@ ConsoleServiceListener.prototype =
* Get the cached page errors for the current inner window.
*
* @return array
* The array of cached messages. Each element is an nsIScriptError or
* an nsIConsoleMessage.
* The array of cached messages. Each element is an nsIScriptError
* with an added _type property so the remote Web Console instance can
* tell the difference between various types of cached messages.
*/
getCachedMessages: function CSL_getCachedMessages()
getCachedMessages: function PEL_getCachedMessages()
{
let innerWindowId = this.window ?
WebConsoleUtils.getInnerWindowId(this.window) : null;
let errors = Services.console.getMessageArray() || [];
return errors.filter((aError) => {
return !innerWindowId ||
return errors.filter(function(aError) {
return aError instanceof Ci.nsIScriptError &&
(!innerWindowId ||
(aError.innerWindowID == innerWindowId &&
this.isCategoryAllowed(aError.category));
});
this.isCategoryAllowed(aError.category)));
}, this);
},
/**
* Remove the nsIConsoleService listener.
*/
destroy: function CSL_destroy()
destroy: function PEL_destroy()
{
Services.console.unregisterListener(this);
this.listener = this.window = null;
@ -1092,7 +1091,8 @@ ConsoleAPIListener.prototype =
* Get the cached messages for the current inner window.
*
* @return array
* The array of cached messages.
* The array of cached messages. Each element is a Console API
* prepared to be sent to the remote Web Console instance.
*/
getCachedMessages: function CAL_getCachedMessages()
{

View File

@ -18,7 +18,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "Services",
XPCOMUtils.defineLazyModuleGetter(this, "WebConsoleUtils",
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ConsoleServiceListener",
XPCOMUtils.defineLazyModuleGetter(this, "PageErrorListener",
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ConsoleAPIListener",
@ -165,10 +165,10 @@ WebConsoleActor.prototype =
_window: null,
/**
* The ConsoleServiceListener instance.
* The PageErrorListener instance.
* @type object
*/
consoleServiceListener: null,
pageErrorListener: null,
/**
* The ConsoleAPIListener instance.
@ -211,9 +211,9 @@ WebConsoleActor.prototype =
*/
disconnect: function WCA_disconnect()
{
if (this.consoleServiceListener) {
this.consoleServiceListener.destroy();
this.consoleServiceListener = null;
if (this.pageErrorListener) {
this.pageErrorListener.destroy();
this.pageErrorListener = null;
}
if (this.consoleAPIListener) {
this.consoleAPIListener.destroy();
@ -363,10 +363,10 @@ WebConsoleActor.prototype =
let listener = aRequest.listeners.shift();
switch (listener) {
case "PageError":
if (!this.consoleServiceListener) {
this.consoleServiceListener =
new ConsoleServiceListener(window, this);
this.consoleServiceListener.init();
if (!this.pageErrorListener) {
this.pageErrorListener =
new PageErrorListener(window, this);
this.pageErrorListener.init();
}
startedListeners.push(listener);
break;
@ -426,9 +426,9 @@ WebConsoleActor.prototype =
let listener = toDetach.shift();
switch (listener) {
case "PageError":
if (this.consoleServiceListener) {
this.consoleServiceListener.destroy();
this.consoleServiceListener = null;
if (this.pageErrorListener) {
this.pageErrorListener.destroy();
this.pageErrorListener = null;
}
stoppedListeners.push(listener);
break;
@ -495,24 +495,13 @@ WebConsoleActor.prototype =
}
break;
case "PageError":
if (this.consoleServiceListener) {
let cache = this.consoleServiceListener.getCachedMessages();
cache.forEach((aMessage) => {
let message = null;
if (aMessage instanceof Ci.nsIScriptError) {
message = this.preparePageErrorForRemote(aMessage);
message._type = type;
}
else {
message = {
_type: "LogMessage",
message: aMessage.message,
timeStamp: aMessage.timeStamp,
category: aMessage.category,
};
}
if (this.pageErrorListener) {
let cache = this.pageErrorListener.getCachedMessages();
cache.forEach(function(aMessage) {
let message = this.preparePageErrorForRemote(aMessage);
message._type = type;
messages.push(message);
});
}, this);
}
break;
}
@ -606,10 +595,6 @@ WebConsoleActor.prototype =
let windowId = !this._isGlobalActor ?
WebConsoleUtils.getInnerWindowId(this.window) : null;
ConsoleAPIStorage.clearEvents(windowId);
if (this._isGlobalActor) {
Services.console.logStringMessage(null); // for the Error Console
Services.console.reset();
}
return {};
},
@ -867,31 +852,19 @@ WebConsoleActor.prototype =
//////////////////
/**
* Handler for messages received from the ConsoleServiceListener. This method
* sends the nsIConsoleMessage to the remote Web Console client.
* Handler for page errors received from the PageErrorListener. This method
* sends the nsIScriptError to the remote Web Console client.
*
* @param nsIConsoleMessage aMessage
* The message we need to send to the client.
* @param nsIScriptError aPageError
* The page error we need to send to the client.
*/
onConsoleServiceMessage: function WCA_onConsoleServiceMessage(aMessage)
onPageError: function WCA_onPageError(aPageError)
{
let packet;
if (aMessage instanceof Ci.nsIScriptError) {
packet = {
from: this.actorID,
type: "pageError",
pageError: this.preparePageErrorForRemote(aMessage),
};
}
else {
packet = {
from: this.actorID,
type: "logMessage",
message: aMessage.message,
timeStamp: aMessage.timeStamp,
category: aMessage.category,
};
}
let packet = {
from: this.actorID,
type: "pageError",
pageError: this.preparePageErrorForRemote(aPageError),
};
this.conn.send(packet);
},

View File

@ -24,7 +24,6 @@ MOCHITEST_CHROME_FILES = \
test_bug819670_getter_throws.html \
test_object_actor_native_getters.html \
test_object_actor_native_getters_lenient_this.html \
test_nsiconsolemessage.html \
network_requests_iframe.html \
data.json \
data.json^headers^ \

View File

@ -106,10 +106,7 @@ function checkObject(aObject, aExpected)
function checkValue(aName, aValue, aExpected)
{
if (aExpected === null) {
ok(!aValue, "'" + aName + "' is null");
}
else if (aValue === undefined) {
if (aValue === undefined) {
ok(false, "'" + aName + "' is undefined");
}
else if (typeof aExpected == "string" || typeof aExpected == "number" ||

View File

@ -95,7 +95,7 @@ function doConsoleCalls()
<script class="testbody" type="text/javascript;version=1.8">
SimpleTest.waitForExplicitFinish();
let consoleAPIListener, consoleServiceListener;
let consoleAPIListener, pageErrorListener;
let consoleAPICalls = 0;
let pageErrors = 0;
@ -108,7 +108,7 @@ let handlers = {
}
},
onConsoleServiceMessage: function onConsoleServiceMessage()
onPageError: function onPageError()
{
pageErrors++;
if (pageErrors == expectedPageErrors.length) {
@ -153,16 +153,16 @@ function onCachedConsoleAPI(aState, aResponse)
});
closeDebugger(aState, function() {
consoleServiceListener = new ConsoleServiceListener(null, handlers);
consoleServiceListener.init();
pageErrorListener = new PageErrorListener(null, handlers);
pageErrorListener.init();
doPageErrors();
});
}
function testPageErrors()
{
consoleServiceListener.destroy();
consoleServiceListener = null;
pageErrorListener.destroy();
pageErrorListener = null;
attachConsole(["PageError"], onAttach2);
}

View File

@ -1,126 +0,0 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf8">
<title>Test for nsIConsoleMessages</title>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript;version=1.8" src="common.js"></script>
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
</head>
<body>
<p>Make sure that nsIConsoleMessages are logged. See bug 859756.</p>
<script class="testbody" type="text/javascript;version=1.8">
SimpleTest.waitForExplicitFinish();
let expectedMessages = [];
let testingTabActor = false;
function sendConsoleMessage(aMessage, aCategory, aWindowId)
{
let consoleMsg = Cc["@mozilla.org/consolemessage;1"]
.createInstance(Ci.nsIConsoleMessage);
consoleMsg.initMessage(aMessage, aCategory, aWindowId);
Services.console.logMessage(consoleMsg);
}
function sendMessages()
{
expectedMessages = [
{
message: "hello world! bug859756",
category: null,
timeStamp: /^\d+$/,
},
{
message: "foobarz",
category: null,
timeStamp: /^\d+$/,
},
{
message: "boom",
category: "cat7",
timeStamp: /^\d+$/,
},
{
message: "windowfun",
category: "cat9",
timeStamp: /^\d+$/,
},
];
Services.console.logStringMessage("hello world! bug859756");
sendConsoleMessage("foobarz");
sendConsoleMessage("boom", "cat7");
sendConsoleMessage("windowfun", "cat9", Date.now());
}
function sendMessagesForTab()
{
sendMessages();
expectedMessages = [
{
message: "windowfun3",
category: "cat10",
timeStamp: /^\d+$/,
},
];
let windowID = WebConsoleUtils.getInnerWindowId(top);
sendConsoleMessage("windowfun3", "cat10", windowID);
}
function startTest()
{
removeEventListener("load", startTest);
attachConsole(["PageError"], onAttach);
}
function onAttach(aState, aResponse)
{
window.onLogMessage_ = onLogMessage.bind(null, aState);
aState.dbgClient.addListener("logMessage", onLogMessage_);
if (!testingTabActor) {
sendMessages();
} else {
sendMessagesForTab();
}
info("waiting for messages");
}
let receivedMessages = [];
function onLogMessage(aState, aType, aPacket)
{
is(aPacket.from, aState.actor, "packet actor");
receivedMessages.push(aPacket);
if (receivedMessages.length != expectedMessages.length) {
return;
}
aState.dbgClient.removeListener("logMessage", onLogMessage_);
checkObject(receivedMessages, expectedMessages);
receivedMessages = expectedMessages = [];
window.onLogMessage_ = null;
closeDebugger(aState, () => {
if (!testingTabActor) {
testingTabActor = true;
info("start tab actor test");
attachConsole(["PageError"], onAttach, true);
} else {
SimpleTest.finish();
}
});
}
addEventListener("load", startTest);
</script>
</body>
</html>

View File

@ -103,7 +103,6 @@ endif
LOCAL_INCLUDES += \
-I$(srcdir)/../build \
-I$(topsrcdir)/xpcom/ds \
-I$(topsrcdir)/dom/base \
$(NULL)
# We generate ErrorListCxxDefines.h from ErrorList.h using regex. The -n option

View File

@ -9,115 +9,29 @@
#include "nsConsoleMessage.h"
#include "nsReadableUtils.h"
#include "jsapi.h"
#include "nsGlobalWindow.h"
#include "nsPIDOMWindow.h"
#include "nsILoadContext.h"
#include "nsIDocShell.h"
NS_IMPL_THREADSAFE_ISUPPORTS1(nsConsoleMessage, nsIConsoleMessage)
nsConsoleMessage::nsConsoleMessage()
: mMessage(),
mCategory(),
mOuterWindowID(0),
mInnerWindowID(0),
mTimeStamp(0),
mIsFromPrivateWindow(false)
nsConsoleMessage::nsConsoleMessage()
{
}
nsConsoleMessage::nsConsoleMessage(const PRUnichar *message)
nsConsoleMessage::nsConsoleMessage(const PRUnichar *message)
{
nsString m;
m.Assign(message);
InitMessage(m, nullptr, 0);
mMessage.Assign(message);
}
NS_IMETHODIMP
nsConsoleMessage::InitMessage(const nsAString& message,
const char *category,
uint64_t innerWindowID)
{
mTimeStamp = JS_Now() / 1000;
mMessage.Assign(message);
mCategory.Assign(category);
mInnerWindowID = innerWindowID;
nsConsoleMessage::GetMessageMoz(PRUnichar **result) {
*result = ToNewUnicode(mMessage);
if (innerWindowID) {
nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(innerWindowID);
if (window) {
nsPIDOMWindow* outer = window->GetOuterWindow();
if (outer)
mOuterWindowID = outer->WindowID();
nsIDocShell* docShell = window->GetDocShell();
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
if (loadContext) {
// Never mark exceptions from chrome windows as having come from
// private windows, since we always want them to be reported.
nsIPrincipal* winPrincipal = window->GetPrincipal();
mIsFromPrivateWindow = loadContext->UsePrivateBrowsing() &&
!nsContentUtils::IsSystemPrincipal(winPrincipal);
}
}
}
return NS_OK;
return NS_OK;
}
NS_IMETHODIMP
nsConsoleMessage::GetMessageMoz(PRUnichar **result)
{
*result = ToNewUnicode(mMessage);
// NS_IMETHODIMP
// nsConsoleMessage::Init(const PRUnichar *message) {
// nsAutoString newMessage(message);
// mMessage = ToNewUnicode(newMessage);
// return NS_OK;
// }
return NS_OK;
}
NS_IMETHODIMP
nsConsoleMessage::GetCategory(char **result)
{
*result = ToNewCString(mCategory);
return NS_OK;
}
NS_IMETHODIMP
nsConsoleMessage::GetOuterWindowID(uint64_t *aOuterWindowID)
{
*aOuterWindowID = mOuterWindowID;
return NS_OK;
}
NS_IMETHODIMP
nsConsoleMessage::GetInnerWindowID(uint64_t *aInnerWindowID)
{
*aInnerWindowID = mInnerWindowID;
return NS_OK;
}
NS_IMETHODIMP
nsConsoleMessage::GetTimeStamp(int64_t *aTimeStamp)
{
*aTimeStamp = mTimeStamp;
return NS_OK;
}
NS_IMETHODIMP
nsConsoleMessage::GetIsFromPrivateWindow(bool *aIsFromPrivateWindow)
{
*aIsFromPrivateWindow = mIsFromPrivateWindow;
return NS_OK;
}
NS_IMETHODIMP
nsConsoleMessage::ToString(nsACString& /*UTF8*/ aResult)
{
if (!mCategory.IsEmpty())
aResult.Assign(mCategory + NS_LITERAL_CSTRING(": ") +
NS_ConvertUTF16toUTF8(mMessage));
else
CopyUTF16toUTF8(mMessage, aResult);
return NS_OK;
}

View File

@ -22,11 +22,6 @@ public:
private:
~nsConsoleMessage() {}
int64_t mTimeStamp;
nsCString mCategory;
uint64_t mOuterWindowID;
uint64_t mInnerWindowID;
bool mIsFromPrivateWindow;
nsString mMessage;
};

View File

@ -10,49 +10,13 @@
* provide an object that can be qi'ed to provide more specific
* message information.
*/
[scriptable, uuid(c14c151b-5ea4-47ed-8e85-d392cdd3e154)]
[scriptable, uuid(41bd8784-1dd2-11b2-9553-8606958fffe1)]
interface nsIConsoleMessage : nsISupports
{
void initMessage(in AString message, [optional] in string category, [optional] in unsigned long long innerWindowID);
/**
* The time (in milliseconds from the Epoch) that the message instance
* was initialised.
* The timestamp is initialized as JS_now/1000 so that it can be
* compared to Date.now in Javascript.
*/
readonly attribute long long timeStamp;
/**
* Categories I know about
* - nsIScriptError:
* XUL javascript
* content javascript (both of these from nsDocShell, currently)
* component javascript (errors in JS components)
* - nsIConsoleMessage: none yet.
*/
readonly attribute string category;
/**
* Get the window id this was initialized with.
*/
readonly attribute unsigned long long outerWindowID;
/**
* Get the inner window id this was initialized with.
*/
readonly attribute unsigned long long innerWindowID;
readonly attribute boolean isFromPrivateWindow;
[binaryname(MessageMoz)] readonly attribute wstring message;
AUTF8String toString();
};
%{ C++
#define NS_CONSOLEMESSAGE_CID \
{ 0x024efc9e, 0x54dc, 0x4844, { 0x80, 0x4b, 0x41, 0xd3, 0xf3, 0x69, 0x90, 0x73 }}
#define NS_CONSOLEMESSAGE_CONTRACTID "@mozilla.org/consolemessage;1"
{ 0x56c9d666, 0x1dd2, 0x11b2, { 0xb4, 0x3c, 0xa8, 0x4b, 0xf3, 0xb3, 0xec, 0xbb }}
%}

View File

@ -21,7 +21,6 @@
COMPONENT(ARRAY, nsArray::XPCOMConstructor)
COMPONENT(CONSOLESERVICE, nsConsoleServiceConstructor)
COMPONENT(EXCEPTIONSERVICE, nsExceptionServiceConstructor)
COMPONENT(CONSOLEMESSAGE, nsConsoleMessageConstructor)
COMPONENT(ATOMSERVICE, nsAtomServiceConstructor)
COMPONENT(OBSERVERSERVICE, nsObserverService::Create)
#ifdef MOZ_VISUAL_EVENT_TRACER

View File

@ -39,7 +39,6 @@
#include "nsSupportsPrimitives.h"
#include "nsConsoleService.h"
#include "nsExceptionService.h"
#include "nsConsoleMessage.h"
#include "nsComponentManager.h"
#include "nsCategoryManagerUtils.h"
@ -179,7 +178,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsVoidImpl)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsInterfacePointerImpl)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsConsoleService, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsConsoleMessage)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAtomService)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsExceptionService)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsTimerImpl)