mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge the last PGO-green inbound changeset to m-c.
This commit is contained in:
commit
80fff739e7
@ -161,31 +161,6 @@ var WebConsoleUtils = {
|
||||
return content;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the window that has the given inner ID.
|
||||
*
|
||||
* @param integer aInnerId
|
||||
* @param nsIDOMWindow [aHintWindow]
|
||||
* Optional, the window object used to QueryInterface to
|
||||
* nsIDOMWindowUtils. If this is not given,
|
||||
* Services.wm.getMostRecentWindow() is used.
|
||||
* @return nsIDOMWindow|null
|
||||
* The window object with the given inner ID.
|
||||
*/
|
||||
getWindowByInnerId: function WCU_getWindowByInnerId(aInnerId, aHintWindow)
|
||||
{
|
||||
let someWindow = aHintWindow || Services.wm.getMostRecentWindow(null);
|
||||
let content = null;
|
||||
|
||||
if (someWindow) {
|
||||
let windowUtils = someWindow.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIDOMWindowUtils);
|
||||
content = windowUtils.getInnerWindowWithId(aInnerId);
|
||||
}
|
||||
|
||||
return content;
|
||||
},
|
||||
|
||||
/**
|
||||
* Abbreviates the given source URL so that it can be displayed flush-right
|
||||
* without being too distracting.
|
||||
|
@ -1,4 +1,4 @@
|
||||
This is the pdf.js project output, https://github.com/mozilla/pdf.js
|
||||
|
||||
Current extension version is: 0.3.452
|
||||
Current extension version is: 0.4.11
|
||||
|
||||
|
@ -14,6 +14,7 @@ const MOZ_CENTRAL = true;
|
||||
const PDFJS_EVENT_ID = 'pdf.js.message';
|
||||
const PDF_CONTENT_TYPE = 'application/pdf';
|
||||
const PREF_PREFIX = 'pdfjs';
|
||||
const PDF_VIEWER_WEB_PAGE = 'resource://pdf.js/web/viewer.html';
|
||||
const MAX_DATABASE_LENGTH = 4096;
|
||||
const FIREFOX_ID = '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}';
|
||||
const SEAMONKEY_ID = '{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}';
|
||||
@ -122,9 +123,67 @@ function getLocalizedString(strings, id, property) {
|
||||
return id;
|
||||
}
|
||||
|
||||
// PDF data storage
|
||||
function PdfDataListener(length) {
|
||||
this.length = length; // less than 0, if length is unknown
|
||||
this.data = new Uint8Array(length >= 0 ? length : 0x10000);
|
||||
this.loaded = 0;
|
||||
}
|
||||
|
||||
PdfDataListener.prototype = {
|
||||
append: function PdfDataListener_append(chunk) {
|
||||
var willBeLoaded = this.loaded + chunk.length;
|
||||
if (this.length >= 0 && this.length < willBeLoaded) {
|
||||
this.length = -1; // reset the length, server is giving incorrect one
|
||||
}
|
||||
if (this.length < 0 && this.data.length < willBeLoaded) {
|
||||
// data length is unknown and new chunk will not fit in the existing
|
||||
// buffer, resizing the buffer by doubling the its last length
|
||||
var newLength = this.data.length;
|
||||
for (; newLength < willBeLoaded; newLength *= 2) {}
|
||||
var newData = new Uint8Array(newLength);
|
||||
newData.set(this.data);
|
||||
this.data = newData;
|
||||
}
|
||||
this.data.set(chunk, this.loaded);
|
||||
this.loaded = willBeLoaded;
|
||||
this.onprogress(this.loaded, this.length >= 0 ? this.length : void(0));
|
||||
},
|
||||
getData: function PdfDataListener_getData() {
|
||||
var data = this.data;
|
||||
if (this.loaded != data.length)
|
||||
data = data.subarray(0, this.loaded);
|
||||
delete this.data; // releasing temporary storage
|
||||
return data;
|
||||
},
|
||||
finish: function PdfDataListener_finish() {
|
||||
this.isDataReady = true;
|
||||
if (this.oncompleteCallback) {
|
||||
this.oncompleteCallback(this.getData());
|
||||
}
|
||||
},
|
||||
error: function PdfDataListener_error(errorCode) {
|
||||
this.errorCode = errorCode;
|
||||
if (this.oncompleteCallback) {
|
||||
this.oncompleteCallback(null, errorCode);
|
||||
}
|
||||
},
|
||||
onprogress: function() {},
|
||||
set oncomplete(value) {
|
||||
this.oncompleteCallback = value;
|
||||
if (this.isDataReady) {
|
||||
value(this.getData());
|
||||
}
|
||||
if (this.errorCode) {
|
||||
value(null, this.errorCode);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// All the priviledged actions.
|
||||
function ChromeActions(domWindow) {
|
||||
function ChromeActions(domWindow, dataListener) {
|
||||
this.domWindow = domWindow;
|
||||
this.dataListener = dataListener;
|
||||
}
|
||||
|
||||
ChromeActions.prototype = {
|
||||
@ -194,6 +253,38 @@ 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
|
||||
}, '*');
|
||||
};
|
||||
|
||||
this.dataListener.oncomplete =
|
||||
function ChromeActions_dataListenerComplete(data, errorCode) {
|
||||
|
||||
domWindow.postMessage({
|
||||
pdfjsLoadAction: 'complete',
|
||||
data: data,
|
||||
errorCode: errorCode
|
||||
}, '*');
|
||||
|
||||
delete this.dataListener;
|
||||
};
|
||||
|
||||
return true;
|
||||
},
|
||||
getStrings: function(data) {
|
||||
try {
|
||||
// Lazy initialization of localizedStrings
|
||||
@ -219,9 +310,26 @@ ChromeActions.prototype = {
|
||||
var strings = getLocalizedStrings('chrome.properties');
|
||||
var message = getLocalizedString(strings, 'unsupported_feature');
|
||||
|
||||
var win = Services.wm.getMostRecentWindow('navigator:browser');
|
||||
var browser = win.gBrowser.getBrowserForDocument(domWindow.top.document);
|
||||
var notificationBox = win.gBrowser.getNotificationBox(browser);
|
||||
var notificationBox = null;
|
||||
// Multiple browser windows can be opened, finding one for notification box
|
||||
var windowsEnum = Services.wm
|
||||
.getZOrderDOMWindowEnumerator('navigator:browser', true);
|
||||
while (windowsEnum.hasMoreElements()) {
|
||||
var win = windowsEnum.getNext();
|
||||
if (win.closed)
|
||||
continue;
|
||||
var browser = win.gBrowser.getBrowserForDocument(domWindow.top.document);
|
||||
if (browser) {
|
||||
// right window/browser is found, getting the notification box
|
||||
notificationBox = win.gBrowser.getNotificationBox(browser);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!notificationBox) {
|
||||
log('Unable to get a notification box for the fallback message');
|
||||
return;
|
||||
}
|
||||
|
||||
// Flag so we don't call the response callback twice, since if the user
|
||||
// clicks open with different viewer both the button callback and
|
||||
// eventCallback will be called.
|
||||
@ -324,17 +432,21 @@ PdfStreamConverter.prototype = {
|
||||
asyncConvertData: function(aFromType, aToType, aListener, aCtxt) {
|
||||
if (!isEnabled())
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
// Ignoring HTTP POST requests -- pdf.js has to repeat the request.
|
||||
var skipConversion = false;
|
||||
try {
|
||||
var request = aCtxt;
|
||||
request.QueryInterface(Ci.nsIHttpChannel);
|
||||
skipConversion = (request.requestMethod !== 'GET');
|
||||
} catch (e) {
|
||||
// Non-HTTP request... continue normally.
|
||||
|
||||
var useFetchByChrome = getBoolPref(PREF_PREFIX + '.fetchByChrome', true);
|
||||
if (!useFetchByChrome) {
|
||||
// Ignoring HTTP POST requests -- pdf.js has to repeat the request.
|
||||
var skipConversion = false;
|
||||
try {
|
||||
var request = aCtxt;
|
||||
request.QueryInterface(Ci.nsIHttpChannel);
|
||||
skipConversion = (request.requestMethod !== 'GET');
|
||||
} catch (e) {
|
||||
// Non-HTTP request... continue normally.
|
||||
}
|
||||
if (skipConversion)
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
if (skipConversion)
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
// Store the listener passed to us
|
||||
this.listener = aListener;
|
||||
@ -342,8 +454,14 @@ PdfStreamConverter.prototype = {
|
||||
|
||||
// nsIStreamListener::onDataAvailable
|
||||
onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
|
||||
// Do nothing since all the data loading is handled by the viewer.
|
||||
log('SANITY CHECK: onDataAvailable SHOULD NOT BE CALLED!');
|
||||
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));
|
||||
},
|
||||
|
||||
// nsIRequestObserver::onStartRequest
|
||||
@ -351,15 +469,27 @@ PdfStreamConverter.prototype = {
|
||||
|
||||
// Setup the request so we can use it below.
|
||||
aRequest.QueryInterface(Ci.nsIChannel);
|
||||
// Cancel the request so the viewer can handle it.
|
||||
aRequest.cancel(Cr.NS_BINDING_ABORTED);
|
||||
var useFetchByChrome = getBoolPref(PREF_PREFIX + '.fetchByChrome', true);
|
||||
var dataListener;
|
||||
if (useFetchByChrome) {
|
||||
// Creating storage for PDF data
|
||||
var contentLength = aRequest.contentLength;
|
||||
dataListener = new PdfDataListener(contentLength);
|
||||
this.dataListener = dataListener;
|
||||
this.binaryStream = Cc['@mozilla.org/binaryinputstream;1']
|
||||
.createInstance(Ci.nsIBinaryInputStream);
|
||||
} else {
|
||||
// Cancel the request so the viewer can handle it.
|
||||
aRequest.cancel(Cr.NS_BINDING_ABORTED);
|
||||
}
|
||||
|
||||
// Create a new channel that is viewer loaded as a resource.
|
||||
var ioService = Services.io;
|
||||
var channel = ioService.newChannel(
|
||||
'resource://pdf.js/web/viewer.html', null, null);
|
||||
PDF_VIEWER_WEB_PAGE, null, null);
|
||||
|
||||
var listener = this.listener;
|
||||
var self = this;
|
||||
// Proxy all the request observer calls, when it gets to onStopRequest
|
||||
// we can get the dom window.
|
||||
var proxy = {
|
||||
@ -373,8 +503,8 @@ PdfStreamConverter.prototype = {
|
||||
var domWindow = getDOMWindow(channel);
|
||||
// Double check the url is still the correct one.
|
||||
if (domWindow.document.documentURIObject.equals(aRequest.URI)) {
|
||||
let requestListener = new RequestListener(
|
||||
new ChromeActions(domWindow));
|
||||
let actions = new ChromeActions(domWindow, dataListener);
|
||||
let requestListener = new RequestListener(actions);
|
||||
domWindow.addEventListener(PDFJS_EVENT_ID, function(event) {
|
||||
requestListener.receive(event);
|
||||
}, false, true);
|
||||
@ -386,11 +516,33 @@ PdfStreamConverter.prototype = {
|
||||
// Keep the URL the same so the browser sees it as the same.
|
||||
channel.originalURI = aRequest.URI;
|
||||
channel.asyncOpen(proxy, aContext);
|
||||
if (useFetchByChrome) {
|
||||
// We can use resource principal when data is fetched by the chrome
|
||||
// e.g. useful for NoScript
|
||||
var securityManager = Cc['@mozilla.org/scriptsecuritymanager;1']
|
||||
.getService(Ci.nsIScriptSecurityManager);
|
||||
var uri = ioService.newURI(PDF_VIEWER_WEB_PAGE, null, null);
|
||||
// FF16 and below had getCodebasePrincipal (bug 774585)
|
||||
var resourcePrincipal = 'getSimpleCodebasePrincipal' in securityManager ?
|
||||
securityManager.getSimpleCodebasePrincipal(uri) :
|
||||
securityManager.getCodebasePrincipal(uri);
|
||||
channel.owner = resourcePrincipal;
|
||||
}
|
||||
},
|
||||
|
||||
// nsIRequestObserver::onStopRequest
|
||||
onStopRequest: function(aRequest, aContext, aStatusCode) {
|
||||
// Do nothing.
|
||||
if (!this.dataListener) {
|
||||
// Do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
if (Components.isSuccessCode(aStatusCode))
|
||||
this.dataListener.finish();
|
||||
else
|
||||
this.dataListener.error(aStatusCode);
|
||||
delete this.dataListener;
|
||||
delete this.binaryStream;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -44,7 +44,7 @@ var FontInspector = (function FontInspectorClosure() {
|
||||
}
|
||||
}
|
||||
return {
|
||||
// Poperties/functions needed by PDFBug.
|
||||
// Properties/functions needed by PDFBug.
|
||||
id: 'FontInspector',
|
||||
name: 'Font Inspector',
|
||||
panel: null,
|
||||
@ -140,7 +140,7 @@ var StepperManager = (function StepperManagerClosure() {
|
||||
var stepperChooser = null;
|
||||
var breakPoints = {};
|
||||
return {
|
||||
// Poperties/functions needed by PDFBug.
|
||||
// Properties/functions needed by PDFBug.
|
||||
id: 'Stepper',
|
||||
name: 'Stepper',
|
||||
panel: null,
|
||||
@ -207,7 +207,7 @@ var StepperManager = (function StepperManagerClosure() {
|
||||
var Stepper = (function StepperClosure() {
|
||||
function Stepper(panel, pageIndex, initialBreakPoints) {
|
||||
this.panel = panel;
|
||||
this.len;
|
||||
this.len = 0;
|
||||
this.breakPoint = 0;
|
||||
this.nextBreakPoint = null;
|
||||
this.pageIndex = pageIndex;
|
||||
@ -236,6 +236,7 @@ var Stepper = (function StepperClosure() {
|
||||
headerRow.appendChild(c('th', 'fn'));
|
||||
headerRow.appendChild(c('th', 'args'));
|
||||
|
||||
var self = this;
|
||||
for (var i = 0; i < IRQueue.fnArray.length; i++) {
|
||||
var line = c('tr');
|
||||
line.className = 'line';
|
||||
@ -249,7 +250,6 @@ var Stepper = (function StepperClosure() {
|
||||
cbox.type = 'checkbox';
|
||||
cbox.className = 'points';
|
||||
cbox.checked = checked;
|
||||
var self = this;
|
||||
cbox.onclick = (function(x) {
|
||||
return function() {
|
||||
if (this.checked)
|
||||
@ -298,7 +298,7 @@ var Stepper = (function StepperClosure() {
|
||||
callback();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
dom.addEventListener('keydown', listener, false);
|
||||
self.goTo(idx);
|
||||
},
|
||||
@ -331,7 +331,7 @@ var Stats = (function Stats() {
|
||||
return false;
|
||||
}
|
||||
return {
|
||||
// Poperties/functions needed by PDFBug.
|
||||
// Properties/functions needed by PDFBug.
|
||||
id: 'Stats',
|
||||
name: 'Stats',
|
||||
panel: null,
|
||||
@ -429,12 +429,12 @@ var PDFBug = (function PDFBugClosure() {
|
||||
|
||||
// Initialize all the debugging tools.
|
||||
var tools = this.tools;
|
||||
var self = this;
|
||||
for (var i = 0; i < tools.length; ++i) {
|
||||
var tool = tools[i];
|
||||
var panel = document.createElement('div');
|
||||
var panelButton = document.createElement('button');
|
||||
panelButton.textContent = tool.name;
|
||||
var self = this;
|
||||
panelButton.addEventListener('click', (function(selected) {
|
||||
return function(event) {
|
||||
event.preventDefault();
|
||||
|
@ -27,6 +27,50 @@ select {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#viewerContainer:-webkit-full-screen {
|
||||
top: 0px;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 24px;
|
||||
background-color: #404040;
|
||||
background-image: url(images/texture.png);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
:-webkit-full-screen #viewer {
|
||||
margin: 0pt;
|
||||
padding: 0pt;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:-webkit-full-screen .page {
|
||||
margin: 0px auto;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#viewerContainer:-moz-full-screen {
|
||||
background-color: #404040;
|
||||
background-image: url(images/texture.png);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:-moz-full-screen .page:last-child {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
#viewerContainer:full-screen {
|
||||
top: 0px;
|
||||
background-color: #404040;
|
||||
background-image: url(images/texture.png);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* outer/inner center provides horizontal center */
|
||||
html[dir='ltr'] .outerCenter {
|
||||
float: right;
|
||||
@ -534,7 +578,7 @@ html[dir='rtl'] .dropdownToolbarButton {
|
||||
margin:0;
|
||||
padding:0;
|
||||
border:none;
|
||||
background: transparent;
|
||||
background: rgba(0,0,0,0); /* Opera does not support 'transparent' <select> background */
|
||||
}
|
||||
|
||||
.dropdownToolbarButton > select > option {
|
||||
@ -609,6 +653,11 @@ html[dir='rtl'] .toolbarButton.pageDown::before {
|
||||
content: url(images/toolbarButton-zoomIn.png);
|
||||
}
|
||||
|
||||
.toolbarButton.fullscreen::before {
|
||||
display: inline-block;
|
||||
content: url(images/toolbarButton-fullscreen.png);
|
||||
}
|
||||
|
||||
.toolbarButton.print::before {
|
||||
display: inline-block;
|
||||
content: url(images/toolbarButton-print.png);
|
||||
@ -976,6 +1025,28 @@ canvas {
|
||||
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;
|
||||
@ -1113,6 +1184,17 @@ canvas {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
#viewer.textLayer-visible .textLayer > div,
|
||||
#viewer.textLayer-hover .textLayer > div:hover {
|
||||
background-color: white;
|
||||
color: black;
|
||||
}
|
||||
|
||||
#viewer.textLayer-shadow .textLayer > div {
|
||||
background-color: rgba(255,255,255, .6);
|
||||
color: black;
|
||||
}
|
||||
|
||||
@page {
|
||||
margin: 0;
|
||||
}
|
||||
|
@ -4,11 +4,9 @@
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>PDF.js viewer</title>
|
||||
|
||||
<!-- This snippet is used in firefox extension, see Makefile -->
|
||||
<base href="resource://pdf.js/web/" />
|
||||
<script type="application/l10n">
|
||||
<!-- PDFJSSCRIPT_LOCALE_DATA -->
|
||||
</script>
|
||||
<script type="text/javascript" src="l10n.js"></script>
|
||||
<script type="text/javascript" id="PDFJS_SCRIPT_TAG">
|
||||
<!--
|
||||
@ -23,9 +21,9 @@ var PDFJS = {};
|
||||
// Use strict in our context only - users might not want it
|
||||
'use strict';
|
||||
|
||||
PDFJS.build = 'c757eed';
|
||||
PDFJS.build =
|
||||
'cb05144';
|
||||
|
||||
// Files are inserted below - see Makefile
|
||||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
@ -57,9 +55,7 @@ function getPdf(arg, callback) {
|
||||
var params = arg;
|
||||
if (typeof arg === 'string')
|
||||
params = { url: arg };
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
||||
xhr.open('GET', params.url);
|
||||
|
||||
var headers = params.headers;
|
||||
@ -73,15 +69,23 @@ function getPdf(arg, callback) {
|
||||
}
|
||||
|
||||
xhr.mozResponseType = xhr.responseType = 'arraybuffer';
|
||||
var protocol = params.url.indexOf(':') < 0 ? window.location.protocol :
|
||||
params.url.substring(0, params.url.indexOf(':') + 1);
|
||||
|
||||
var protocol = params.url.substring(0, params.url.indexOf(':') + 1);
|
||||
xhr.expected = (protocol === 'http:' || protocol === 'https:') ? 200 : 0;
|
||||
|
||||
if ('progress' in params)
|
||||
xhr.onprogress = params.progress || undefined;
|
||||
|
||||
if ('error' in params)
|
||||
xhr.onerror = params.error || undefined;
|
||||
var calledErrorBack = false;
|
||||
|
||||
if ('error' in params) {
|
||||
xhr.onerror = function errorBack() {
|
||||
if (!calledErrorBack) {
|
||||
calledErrorBack = true;
|
||||
params.error();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xhr.onreadystatechange = function getPdfOnreadystatechange(e) {
|
||||
if (xhr.readyState === 4) {
|
||||
@ -89,7 +93,8 @@ function getPdf(arg, callback) {
|
||||
var data = (xhr.mozResponseArrayBuffer || xhr.mozResponse ||
|
||||
xhr.responseArrayBuffer || xhr.response);
|
||||
callback(data);
|
||||
} else if (params.error) {
|
||||
} else if (params.error && !calledErrorBack) {
|
||||
calledErrorBack = true;
|
||||
params.error(e);
|
||||
}
|
||||
}
|
||||
@ -422,14 +427,37 @@ var PDFDocument = (function PDFDocumentClosure() {
|
||||
return true; /* found */
|
||||
}
|
||||
|
||||
var DocumentInfoValidators = {
|
||||
get entries() {
|
||||
// Lazily build this since all the validation functions below are not
|
||||
// defined until after this file loads.
|
||||
return shadow(this, 'entries', {
|
||||
Title: isString,
|
||||
Author: isString,
|
||||
Subject: isString,
|
||||
Keywords: isString,
|
||||
Creator: isString,
|
||||
Producer: isString,
|
||||
CreationDate: isString,
|
||||
ModDate: isString,
|
||||
Trapped: isName
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
PDFDocument.prototype = {
|
||||
get linearization() {
|
||||
var length = this.stream.length;
|
||||
var linearization = false;
|
||||
if (length) {
|
||||
linearization = new Linearization(this.stream);
|
||||
if (linearization.length != length)
|
||||
linearization = false;
|
||||
try {
|
||||
linearization = new Linearization(this.stream);
|
||||
if (linearization.length != length)
|
||||
linearization = false;
|
||||
} catch (err) {
|
||||
warn('The linearization data is not available ' +
|
||||
'or unreadable pdf data is found');
|
||||
}
|
||||
}
|
||||
// shadow the prototype getter with a data property
|
||||
return shadow(this, 'linearization', linearization);
|
||||
@ -509,18 +537,27 @@ var PDFDocument = (function PDFDocumentClosure() {
|
||||
return shadow(this, 'numPages', num);
|
||||
},
|
||||
getDocumentInfo: function PDFDocument_getDocumentInfo() {
|
||||
var info;
|
||||
var docInfo;
|
||||
if (this.xref.trailer.has('Info')) {
|
||||
var infoDict = this.xref.trailer.get('Info');
|
||||
|
||||
info = {};
|
||||
infoDict.forEach(function(key, value) {
|
||||
info[key] = typeof value !== 'string' ? value :
|
||||
stringToPDFString(value);
|
||||
});
|
||||
docInfo = {};
|
||||
var validEntries = DocumentInfoValidators.entries;
|
||||
// Only fill the document info with valid entries from the spec.
|
||||
for (var key in validEntries) {
|
||||
if (infoDict.has(key)) {
|
||||
var value = infoDict.get(key);
|
||||
// Make sure the value conforms to the spec.
|
||||
if (validEntries[key](value)) {
|
||||
docInfo[key] = typeof value !== 'string' ? value :
|
||||
stringToPDFString(value);
|
||||
} else {
|
||||
info('Bad value in document info for "' + key + '"');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return shadow(this, 'getDocumentInfo', info);
|
||||
return shadow(this, 'getDocumentInfo', docInfo);
|
||||
},
|
||||
getFingerprint: function PDFDocument_getFingerprint() {
|
||||
var xref = this.xref, fileID;
|
||||
@ -611,6 +648,28 @@ function assert(cond, msg) {
|
||||
error(msg);
|
||||
}
|
||||
|
||||
// Combines two URLs. The baseUrl shall be absolute URL. If the url is an
|
||||
// absolute URL, it will be returned as is.
|
||||
function combineUrl(baseUrl, url) {
|
||||
if (url.indexOf(':') >= 0)
|
||||
return url;
|
||||
if (url.charAt(0) == '/') {
|
||||
// absolute path
|
||||
var i = baseUrl.indexOf('://');
|
||||
i = baseUrl.indexOf('/', i + 3);
|
||||
return baseUrl.substring(0, i) + url;
|
||||
} else {
|
||||
// relative path
|
||||
var pathLength = baseUrl.length, i;
|
||||
i = baseUrl.lastIndexOf('#');
|
||||
pathLength = i >= 0 ? i : pathLength;
|
||||
i = baseUrl.lastIndexOf('?', pathLength);
|
||||
pathLength = i >= 0 ? i : pathLength;
|
||||
var prefixLength = baseUrl.lastIndexOf('/', pathLength);
|
||||
return baseUrl.substring(0, prefixLength + 1) + url;
|
||||
}
|
||||
}
|
||||
|
||||
// In a well-formed PDF, |cond| holds. If it doesn't, subsequent
|
||||
// behavior is undefined.
|
||||
function assertWellFormed(cond, msg) {
|
||||
@ -1188,63 +1247,36 @@ var StatTimer = (function StatTimerClosure() {
|
||||
* @return {Promise} A promise that is resolved with {PDFDocumentProxy} object.
|
||||
*/
|
||||
PDFJS.getDocument = function getDocument(source) {
|
||||
var url, data, headers, password, parameters = {}, workerInitializedPromise,
|
||||
workerReadyPromise, transport;
|
||||
var workerInitializedPromise, workerReadyPromise, transport;
|
||||
|
||||
if (typeof source === 'string') {
|
||||
url = source;
|
||||
source = { url: source };
|
||||
} else if (isArrayBuffer(source)) {
|
||||
data = source;
|
||||
} else if (typeof source === 'object') {
|
||||
url = source.url;
|
||||
data = source.data;
|
||||
headers = source.httpHeaders;
|
||||
password = source.password;
|
||||
parameters.password = password || null;
|
||||
|
||||
if (!url && !data)
|
||||
error('Invalid parameter array, need either .data or .url');
|
||||
} else {
|
||||
source = { data: source };
|
||||
} else if (typeof source !== 'object') {
|
||||
error('Invalid parameter in getDocument, need either Uint8Array, ' +
|
||||
'string or a parameter object');
|
||||
}
|
||||
|
||||
if (!source.url && !source.data)
|
||||
error('Invalid parameter array, need either .data or .url');
|
||||
|
||||
// copy/use all keys as is except 'url' -- full path is required
|
||||
var params = {};
|
||||
for (var key in source) {
|
||||
if (key === 'url' && typeof window !== 'undefined') {
|
||||
params[key] = combineUrl(window.location.href, source[key]);
|
||||
continue;
|
||||
}
|
||||
params[key] = source[key];
|
||||
}
|
||||
|
||||
workerInitializedPromise = new PDFJS.Promise();
|
||||
workerReadyPromise = new PDFJS.Promise();
|
||||
transport = new WorkerTransport(workerInitializedPromise, workerReadyPromise);
|
||||
if (data) {
|
||||
// assuming the data is array, instantiating directly from it
|
||||
transport.sendData(data, parameters);
|
||||
} else if (url) {
|
||||
// fetch url
|
||||
PDFJS.getPdf(
|
||||
{
|
||||
url: url,
|
||||
progress: function getPDFProgress(evt) {
|
||||
if (evt.lengthComputable) {
|
||||
workerReadyPromise.progress({
|
||||
loaded: evt.loaded,
|
||||
total: evt.total
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function getPDFError(e) {
|
||||
workerReadyPromise.reject('Unexpected server response of ' +
|
||||
e.target.status + '.');
|
||||
},
|
||||
headers: headers
|
||||
},
|
||||
function getPDFLoad(data) {
|
||||
// sometimes the pdf has finished downloading before the web worker-test
|
||||
// has finished. In that case the rendering of the final pdf would cause
|
||||
// errors. We have to wait for the WorkerTransport to finalize worker-
|
||||
// support detection
|
||||
workerInitializedPromise.then(function workerInitialized() {
|
||||
transport.sendData(data, parameters);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
workerInitializedPromise.then(function transportInitialized() {
|
||||
transport.fetchDocument(params);
|
||||
});
|
||||
return workerReadyPromise;
|
||||
};
|
||||
|
||||
@ -1627,19 +1659,12 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||
|
||||
try {
|
||||
var worker;
|
||||
if (PDFJS.isFirefoxExtension) {
|
||||
// The firefox extension can't load the worker from the resource://
|
||||
// url so we have to inline the script and then use the blob loader.
|
||||
var bb = new MozBlobBuilder();
|
||||
bb.append(document.querySelector('#PDFJS_SCRIPT_TAG').textContent);
|
||||
var blobUrl = window.URL.createObjectURL(bb.getBlob());
|
||||
worker = new Worker(blobUrl);
|
||||
} else {
|
||||
// Some versions of FF can't create a worker on localhost, see:
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=683280
|
||||
worker = new Worker(workerSrc);
|
||||
}
|
||||
|
||||
// The firefox extension can't load the worker from the resource://
|
||||
// url so we have to inline the script and then use the blob loader.
|
||||
var bb = new MozBlobBuilder();
|
||||
bb.append(document.querySelector('#PDFJS_SCRIPT_TAG').textContent);
|
||||
var blobUrl = window.URL.createObjectURL(bb.getBlob());
|
||||
worker = new Worker(blobUrl);
|
||||
var messageHandler = new MessageHandler('main', worker);
|
||||
this.messageHandler = messageHandler;
|
||||
|
||||
@ -1771,6 +1796,17 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||
}
|
||||
}, this);
|
||||
|
||||
messageHandler.on('DocProgress', function transportDocProgress(data) {
|
||||
this.workerReadyPromise.progress({
|
||||
loaded: data.loaded,
|
||||
total: data.total
|
||||
});
|
||||
}, this);
|
||||
|
||||
messageHandler.on('DocError', function transportDocError(data) {
|
||||
this.workerReadyPromise.reject(data);
|
||||
}, this);
|
||||
|
||||
messageHandler.on('PageError', function transportError(data) {
|
||||
var page = this.pageCache[data.pageNum - 1];
|
||||
if (page.displayReadyPromise)
|
||||
@ -1815,11 +1851,11 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||
});
|
||||
},
|
||||
|
||||
sendData: function WorkerTransport_sendData(data, params) {
|
||||
this.messageHandler.send('GetDocRequest', {data: data, params: params});
|
||||
fetchDocument: function WorkerTransport_fetchDocument(source) {
|
||||
this.messageHandler.send('GetDocRequest', {source: source});
|
||||
},
|
||||
|
||||
getData: function WorkerTransport_sendData(promise) {
|
||||
getData: function WorkerTransport_getData(promise) {
|
||||
this.messageHandler.send('GetData', null, function(data) {
|
||||
promise.resolve(data);
|
||||
});
|
||||
@ -2003,6 +2039,7 @@ var CanvasExtraState = (function CanvasExtraStateClosure() {
|
||||
this.wordSpacing = 0;
|
||||
this.textHScale = 1;
|
||||
this.textRenderingMode = TextRenderingMode.FILL;
|
||||
this.textRise = 0;
|
||||
// Color spaces
|
||||
this.fillColorSpace = new DeviceGrayCS();
|
||||
this.fillColorSpaceObj = null;
|
||||
@ -2447,7 +2484,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
this.current.textRenderingMode = mode;
|
||||
},
|
||||
setTextRise: function CanvasGraphics_setTextRise(rise) {
|
||||
TODO('text rise: ' + rise);
|
||||
this.current.textRise = rise;
|
||||
},
|
||||
moveText: function CanvasGraphics_moveText(x, y) {
|
||||
this.current.x = this.current.lineX += x;
|
||||
@ -2474,7 +2511,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
|
||||
ctx.transform.apply(ctx, current.textMatrix);
|
||||
ctx.scale(1, -1);
|
||||
ctx.translate(current.x, -1 * current.y);
|
||||
ctx.translate(current.x, -current.y - current.textRise);
|
||||
ctx.transform.apply(ctx, fontMatrix);
|
||||
ctx.scale(textHScale, 1);
|
||||
},
|
||||
@ -3042,20 +3079,20 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
// Marked content
|
||||
|
||||
markPoint: function CanvasGraphics_markPoint(tag) {
|
||||
TODO('Marked content');
|
||||
// TODO Marked content.
|
||||
},
|
||||
markPointProps: function CanvasGraphics_markPointProps(tag, properties) {
|
||||
TODO('Marked content');
|
||||
// TODO Marked content.
|
||||
},
|
||||
beginMarkedContent: function CanvasGraphics_beginMarkedContent(tag) {
|
||||
TODO('Marked content');
|
||||
// TODO Marked content.
|
||||
},
|
||||
beginMarkedContentProps: function CanvasGraphics_beginMarkedContentProps(
|
||||
tag, properties) {
|
||||
TODO('Marked content');
|
||||
// TODO Marked content.
|
||||
},
|
||||
endMarkedContent: function CanvasGraphics_endMarkedContent() {
|
||||
TODO('Marked content');
|
||||
// TODO Marked content.
|
||||
},
|
||||
|
||||
// Compatibility
|
||||
@ -3103,7 +3140,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
return CanvasGraphics;
|
||||
})();
|
||||
|
||||
if (!isWorker) {
|
||||
function checkPutBinaryImageDataCompatibility() {
|
||||
// Feature detection if the browser can use an Uint8Array directly as imgData.
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width = 1;
|
||||
@ -3124,20 +3161,26 @@ if (!isWorker) {
|
||||
} catch (e) {
|
||||
CanvasGraphics.prototype.putBinaryImageData =
|
||||
function CanvasGraphicsPutBinaryImageDataShim(ctx, imgData, w, h) {
|
||||
var tmpImgData = ctx.getImageData(0, 0, w, h);
|
||||
var tmpImgData = 'createImageData' in ctx ? ctx.createImageData(w, h) :
|
||||
ctx.getImageData(0, 0, w, h);
|
||||
|
||||
// Copy over the imageData pixel by pixel.
|
||||
var tmpImgDataPixels = tmpImgData.data;
|
||||
var len = tmpImgDataPixels.length;
|
||||
|
||||
while (len--) {
|
||||
tmpImgDataPixels[len] = imgData.data[len];
|
||||
var data = imgData.data;
|
||||
if ('set' in tmpImgDataPixels)
|
||||
tmpImgDataPixels.set(data);
|
||||
else {
|
||||
// Copy over the imageData pixel by pixel.
|
||||
for (var i = 0, ii = tmpImgDataPixels.length; i < ii; i++)
|
||||
tmpImgDataPixels[i] = data[i];
|
||||
}
|
||||
|
||||
ctx.putImageData(tmpImgData, 0, 0);
|
||||
};
|
||||
}
|
||||
}
|
||||
if (!isWorker) {
|
||||
checkPutBinaryImageDataCompatibility();
|
||||
}
|
||||
|
||||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
@ -3765,7 +3808,7 @@ var XRef = (function XRefClosure() {
|
||||
var e = this.entries[i];
|
||||
if (e === null)
|
||||
return null;
|
||||
return e.free ? null : e; // returns null is the entry is free
|
||||
return e.free || !e.offset ? null : e; // returns null if entry is free
|
||||
},
|
||||
fetchIfRef: function XRef_fetchIfRef(obj) {
|
||||
if (!isRef(obj))
|
||||
@ -4076,11 +4119,12 @@ var PDFFunction = (function PDFFunctionClosure() {
|
||||
|
||||
var size = dict.get('Size');
|
||||
var bps = dict.get('BitsPerSample');
|
||||
var order = dict.get('Order');
|
||||
if (!order)
|
||||
order = 1;
|
||||
if (order !== 1)
|
||||
error('No support for cubic spline interpolation: ' + order);
|
||||
var order = dict.get('Order') || 1;
|
||||
if (order !== 1) {
|
||||
// No description how cubic spline interpolation works in PDF32000:2008
|
||||
// As in poppler, ignoring order, linear interpolation may work as good
|
||||
TODO('No support for cubic spline interpolation: ' + order);
|
||||
}
|
||||
|
||||
var encode = dict.get('Encode');
|
||||
if (!encode) {
|
||||
@ -12030,6 +12074,9 @@ var ColorSpace = (function ColorSpaceClosure() {
|
||||
var baseIndexedCS = ColorSpace.parseToIR(cs[1], xref, res);
|
||||
var hiVal = cs[2] + 1;
|
||||
var lookup = xref.fetchIfRef(cs[3]);
|
||||
if (isStream(lookup)) {
|
||||
lookup = lookup.getBytes();
|
||||
}
|
||||
return ['IndexedCS', baseIndexedCS, hiVal, lookup];
|
||||
case 'Separation':
|
||||
case 'DeviceN':
|
||||
@ -12151,14 +12198,18 @@ var IndexedCS = (function IndexedCSClosure() {
|
||||
|
||||
var baseNumComps = base.numComps;
|
||||
var length = baseNumComps * highVal;
|
||||
var lookupArray = new Uint8Array(length);
|
||||
var lookupArray;
|
||||
|
||||
if (isStream(lookup)) {
|
||||
lookupArray = new Uint8Array(length);
|
||||
var bytes = lookup.getBytes(length);
|
||||
lookupArray.set(bytes);
|
||||
} else if (isString(lookup)) {
|
||||
lookupArray = new Uint8Array(length);
|
||||
for (var i = 0; i < length; ++i)
|
||||
lookupArray[i] = lookup.charCodeAt(i);
|
||||
} else if (lookup instanceof Uint8Array) {
|
||||
lookupArray = lookup;
|
||||
} else {
|
||||
error('Unrecognized lookup table: ' + lookup);
|
||||
}
|
||||
@ -13840,7 +13891,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
||||
if (widths) {
|
||||
var start = 0, end = 0;
|
||||
for (var i = 0, ii = widths.length; i < ii; i++) {
|
||||
var code = widths[i];
|
||||
var code = xref.fetchIfRef(widths[i]);
|
||||
if (isArray(code)) {
|
||||
for (var j = 0, jj = code.length; j < jj; j++)
|
||||
glyphsWidths[start++] = code[j];
|
||||
@ -14482,7 +14533,8 @@ var FontLoader = {
|
||||
document.documentElement.removeEventListener(
|
||||
'pdfjsFontLoad', checkFontsLoaded, false);
|
||||
|
||||
callback();
|
||||
// Use timeout to fix chrome intermittent failures on font loading.
|
||||
setTimeout(callback, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -17356,6 +17408,14 @@ var Font = (function FontClosure() {
|
||||
return Font;
|
||||
})();
|
||||
|
||||
var CallothersubrCmd = (function CallothersubrCmdClosure() {
|
||||
function CallothersubrCmd(index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
return CallothersubrCmd;
|
||||
})();
|
||||
|
||||
/*
|
||||
* Type1Parser encapsulate the needed code for parsing a Type1 font
|
||||
* program. Some of its logic depends on the Type2 charstrings
|
||||
@ -17455,8 +17515,8 @@ var Type1Parser = function type1Parser() {
|
||||
'1': 'vstem',
|
||||
'2': 'hstem',
|
||||
|
||||
'6': 'endchar', // seac
|
||||
// Type1 only command with command not (yet) built-in ,throw an error
|
||||
'6': -1, // seac
|
||||
'7': -1, // sbw
|
||||
|
||||
'11': 'sub',
|
||||
@ -17486,6 +17546,43 @@ var Type1Parser = function type1Parser() {
|
||||
|
||||
var kEscapeCommand = 12;
|
||||
|
||||
// Breaks up the stack by arguments and also calculates the value.
|
||||
function breakUpArgs(stack, numArgs) {
|
||||
var args = [];
|
||||
var index = stack.length - 1;
|
||||
for (var i = 0; i < numArgs; i++) {
|
||||
if (index < 0) {
|
||||
args.unshift({ arg: [0],
|
||||
value: 0,
|
||||
offset: 0 });
|
||||
warn('Malformed charstring stack: not enough values on stack.');
|
||||
continue;
|
||||
}
|
||||
var token = stack[index];
|
||||
if (token === 'div') {
|
||||
var a = stack[index - 2];
|
||||
var b = stack[index - 1];
|
||||
if (!isInt(a) || !isInt(b)) {
|
||||
warn('Malformed charsting stack: expected ints on stack for div.');
|
||||
a = 0;
|
||||
b = 1;
|
||||
}
|
||||
args.unshift({ arg: [a, b, 'div'],
|
||||
value: a / b,
|
||||
offset: index - 2 });
|
||||
index -= 3;
|
||||
} else if (isInt(token)) {
|
||||
args.unshift({ arg: stack.slice(index, index + 1),
|
||||
value: token,
|
||||
offset: index });
|
||||
index--;
|
||||
} else {
|
||||
warn('Malformed charsting stack: found bad token ' + token + '.');
|
||||
}
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
function decodeCharString(array) {
|
||||
var charstring = [];
|
||||
var lsb = 0;
|
||||
@ -17524,10 +17621,20 @@ var Type1Parser = function type1Parser() {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(argc == 0, 'callothersubr with arguments is not supported');
|
||||
charstring.push(new CallothersubrCmd(index));
|
||||
continue;
|
||||
} else if (escape == 17 || escape == 33) {
|
||||
// pop or setcurrentpoint commands can be ignored
|
||||
// since we are not doing callothersubr
|
||||
continue;
|
||||
} else if (escape == 6) {
|
||||
// seac is like type 2's special endchar but it doesn't use the
|
||||
// first argument asb, so remove it.
|
||||
var args = breakUpArgs(charstring, 5);
|
||||
var arg0 = args[0];
|
||||
charstring.splice(arg0.offset, arg0.arg.length);
|
||||
} else if (!kHintingEnabled && (escape == 1 || escape == 2)) {
|
||||
charstring.push('drop', 'drop', 'drop', 'drop', 'drop', 'drop');
|
||||
continue;
|
||||
@ -17535,25 +17642,17 @@ var Type1Parser = function type1Parser() {
|
||||
|
||||
command = charStringDictionary['12'][escape];
|
||||
} else {
|
||||
// TODO Clean this code
|
||||
if (value == 13) { // hsbw
|
||||
if (charstring.length == 2) {
|
||||
lsb = charstring[0];
|
||||
width = charstring[1];
|
||||
charstring.splice(0, 1);
|
||||
} else if (charstring.length == 4 && charstring[3] == 'div') {
|
||||
lsb = charstring[0];
|
||||
width = charstring[1] / charstring[2];
|
||||
charstring.splice(0, 1);
|
||||
} else if (charstring.length == 4 && charstring[2] == 'div') {
|
||||
lsb = charstring[0] / charstring[1];
|
||||
width = charstring[3];
|
||||
charstring.splice(0, 3);
|
||||
} else {
|
||||
error('Unsupported hsbw format: ' + charstring);
|
||||
}
|
||||
|
||||
charstring.push(lsb, 'hmoveto');
|
||||
var args = breakUpArgs(charstring, 2);
|
||||
var arg0 = args[0];
|
||||
var arg1 = args[1];
|
||||
lsb = arg0.value;
|
||||
width = arg1.value;
|
||||
// To convert to type2 we have to move the width value to the first
|
||||
// part of the charstring and then use hmoveto with lsb.
|
||||
charstring = arg1.arg;
|
||||
charstring = charstring.concat(arg0.arg);
|
||||
charstring.push('hmoveto');
|
||||
continue;
|
||||
} else if (value == 10) { // callsubr
|
||||
if (charstring[charstring.length - 1] < 3) { // subr #0..2
|
||||
@ -17763,6 +17862,10 @@ var Type1Parser = function type1Parser() {
|
||||
case '/OtherBlues':
|
||||
case '/FamilyBlues':
|
||||
case '/FamilyOtherBlues':
|
||||
var blueArray = readNumberArray(eexecStr, i + 1);
|
||||
if (blueArray.length > 0 && (blueArray.length % 2) == 0)
|
||||
program.properties.privateData[token.substring(1)] = blueArray;
|
||||
break;
|
||||
case '/StemSnapH':
|
||||
case '/StemSnapV':
|
||||
program.properties.privateData[token.substring(1)] =
|
||||
@ -18045,23 +18148,23 @@ Type1Font.prototype = {
|
||||
},
|
||||
|
||||
getType2Charstrings: function Type1Font_getType2Charstrings(
|
||||
type1Charstrings) {
|
||||
type1Subrs) {
|
||||
var type2Charstrings = [];
|
||||
var count = type1Charstrings.length;
|
||||
for (var i = 0; i < count; i++) {
|
||||
var charstring = type1Charstrings[i].charstring;
|
||||
type2Charstrings.push(this.flattenCharstring(charstring.slice(),
|
||||
this.commandsMap));
|
||||
}
|
||||
var count = type1Subrs.length;
|
||||
var type1Charstrings = [];
|
||||
for (var i = 0; i < count; i++)
|
||||
type1Charstrings.push(type1Subrs[i].charstring.slice());
|
||||
for (var i = 0; i < count; i++)
|
||||
type2Charstrings.push(this.flattenCharstring(type1Charstrings, i));
|
||||
return type2Charstrings;
|
||||
},
|
||||
|
||||
getType2Subrs: function Type1Font_getType2Subrs(type1Subrs) {
|
||||
var bias = 0;
|
||||
var count = type1Subrs.length;
|
||||
if (count < 1240)
|
||||
if (count < 1133)
|
||||
bias = 107;
|
||||
else if (count < 33900)
|
||||
else if (count < 33769)
|
||||
bias = 1131;
|
||||
else
|
||||
bias = 32768;
|
||||
@ -18072,11 +18175,7 @@ Type1Font.prototype = {
|
||||
type2Subrs.push([0x0B]);
|
||||
|
||||
for (var i = 0; i < count; i++) {
|
||||
var subr = type1Subrs[i];
|
||||
if (!subr)
|
||||
subr = [0x0B];
|
||||
|
||||
type2Subrs.push(this.flattenCharstring(subr, this.commandsMap));
|
||||
type2Subrs.push(this.flattenCharstring(type1Subrs, i));
|
||||
}
|
||||
|
||||
return type2Subrs;
|
||||
@ -18108,11 +18207,15 @@ Type1Font.prototype = {
|
||||
'hvcurveto': 31
|
||||
},
|
||||
|
||||
flattenCharstring: function Type1Font_flattenCharstring(charstring, map) {
|
||||
flattenCharstring: function Type1Font_flattenCharstring(charstrings, index) {
|
||||
var charstring = charstrings[index];
|
||||
if (!charstring)
|
||||
return [0x0B];
|
||||
var map = this.commandsMap;
|
||||
// charstring changes size - can't cache .length in loop
|
||||
for (var i = 0; i < charstring.length; i++) {
|
||||
var command = charstring[i];
|
||||
if (command.charAt) {
|
||||
if (typeof command === 'string') {
|
||||
var cmd = map[command];
|
||||
assert(cmd, 'Unknow command: ' + command);
|
||||
|
||||
@ -18120,6 +18223,17 @@ Type1Font.prototype = {
|
||||
charstring.splice(i++, 1, cmd[0], cmd[1]);
|
||||
else
|
||||
charstring[i] = cmd;
|
||||
} else if (command instanceof CallothersubrCmd) {
|
||||
var otherSubrCharstring = charstrings[command.index];
|
||||
if (otherSubrCharstring) {
|
||||
var lastCommand = otherSubrCharstring.indexOf('return');
|
||||
if (lastCommand >= 0)
|
||||
otherSubrCharstring = otherSubrCharstring.slice(0, lastCommand);
|
||||
charstring.splice.apply(charstring,
|
||||
[i, 1].concat(otherSubrCharstring));
|
||||
} else
|
||||
charstring.splice(i, 1); // ignoring empty subr call
|
||||
i--;
|
||||
} else {
|
||||
// Type1 charstring use a division for number above 32000
|
||||
if (command > 32000) {
|
||||
@ -24062,6 +24176,10 @@ var PDFImage = (function PDFImageClosure() {
|
||||
var rowBytes = (originalWidth * numComps * bpc + 7) >> 3;
|
||||
var imgArray = this.getImageBytes(originalHeight * rowBytes);
|
||||
|
||||
// imgArray can be incomplete (e.g. after CCITT fax encoding)
|
||||
var actualHeight = 0 | (imgArray.length / rowBytes *
|
||||
height / originalHeight);
|
||||
|
||||
var comps = this.colorSpace.getRgbBuffer(
|
||||
this.getComponents(imgArray), bpc);
|
||||
if (originalWidth != width || originalHeight != height)
|
||||
@ -24070,7 +24188,7 @@ var PDFImage = (function PDFImageClosure() {
|
||||
var compsPos = 0;
|
||||
var opacity = this.getOpacity(width, height);
|
||||
var opacityPos = 0;
|
||||
var length = width * height * 4;
|
||||
var length = width * actualHeight * 4;
|
||||
|
||||
for (var i = 0; i < length; i += 4) {
|
||||
buffer[i] = comps[compsPos++];
|
||||
@ -27762,6 +27880,7 @@ var Pattern = (function PatternClosure() {
|
||||
// Both radial and axial shadings are handled by RadialAxial shading.
|
||||
return new Shadings.RadialAxial(dict, matrix, xref, res);
|
||||
default:
|
||||
TODO('Unsupported shading type: ' + type);
|
||||
return new Shadings.Dummy();
|
||||
}
|
||||
};
|
||||
@ -27898,7 +28017,12 @@ Shadings.Dummy = (function DummyClosure() {
|
||||
}
|
||||
|
||||
Dummy.fromIR = function Dummy_fromIR() {
|
||||
return 'hotpink';
|
||||
return {
|
||||
type: 'Pattern',
|
||||
getPattern: function Dummy_fromIR_getPattern() {
|
||||
return 'hotpink';
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
Dummy.prototype = {
|
||||
@ -28880,7 +29004,7 @@ var JpegStream = (function JpegStreamClosure() {
|
||||
*/
|
||||
JpegStream.prototype.isNativelySupported =
|
||||
function JpegStream_isNativelySupported(xref, res) {
|
||||
var cs = ColorSpace.parse(this.dict.get('ColorSpace'), xref, res);
|
||||
var cs = ColorSpace.parse(this.dict.get('ColorSpace', 'CS'), xref, res);
|
||||
// when bug 674619 lands, let's check if browser can do
|
||||
// normal cmyk and then we won't need to decode in JS
|
||||
if (cs.name === 'DeviceGray' || cs.name === 'DeviceRGB')
|
||||
@ -28895,7 +29019,7 @@ var JpegStream = (function JpegStreamClosure() {
|
||||
*/
|
||||
JpegStream.prototype.isNativelyDecodable =
|
||||
function JpegStream_isNativelyDecodable(xref, res) {
|
||||
var cs = ColorSpace.parse(this.dict.get('ColorSpace'), xref, res);
|
||||
var cs = ColorSpace.parse(this.dict.get('ColorSpace', 'CS'), xref, res);
|
||||
var numComps = cs.numComps;
|
||||
if (numComps == 1 || numComps == 3)
|
||||
return true;
|
||||
@ -30451,15 +30575,10 @@ var WorkerMessageHandler = {
|
||||
setup: function wphSetup(handler) {
|
||||
var pdfModel = null;
|
||||
|
||||
handler.on('test', function wphSetupTest(data) {
|
||||
handler.send('test', data instanceof Uint8Array);
|
||||
});
|
||||
|
||||
handler.on('GetDocRequest', function wphSetupDoc(data) {
|
||||
function loadDocument(pdfData, pdfModelSource) {
|
||||
// Create only the model of the PDFDoc, which is enough for
|
||||
// processing the content of the pdf.
|
||||
var pdfData = data.data;
|
||||
var pdfPassword = data.params.password;
|
||||
var pdfPassword = pdfModelSource.password;
|
||||
try {
|
||||
pdfModel = new PDFDocument(new Stream(pdfData), pdfPassword);
|
||||
} catch (e) {
|
||||
@ -30489,6 +30608,38 @@ var WorkerMessageHandler = {
|
||||
encrypted: !!pdfModel.xref.encrypt
|
||||
};
|
||||
handler.send('GetDoc', {pdfInfo: doc});
|
||||
}
|
||||
|
||||
handler.on('test', function wphSetupTest(data) {
|
||||
handler.send('test', data instanceof Uint8Array);
|
||||
});
|
||||
|
||||
handler.on('GetDocRequest', function wphSetupDoc(data) {
|
||||
var source = data.source;
|
||||
if (source.data) {
|
||||
// the data is array, instantiating directly from it
|
||||
loadDocument(source.data, source);
|
||||
return;
|
||||
}
|
||||
|
||||
PDFJS.getPdf(
|
||||
{
|
||||
url: source.url,
|
||||
progress: function getPDFProgress(evt) {
|
||||
handler.send('DocProgress', {
|
||||
loaded: evt.loaded,
|
||||
total: evt.lengthComputable ? evt.total : void(0)
|
||||
});
|
||||
},
|
||||
error: function getPDFError(e) {
|
||||
handler.send('DocError', 'Unexpected server response of ' +
|
||||
e.target.status + '.');
|
||||
},
|
||||
headers: source.httpHeaders
|
||||
},
|
||||
function getPDFLoad(data) {
|
||||
loadDocument(data, source);
|
||||
});
|
||||
});
|
||||
|
||||
handler.on('GetPageRequest', function wphSetupGetPage(data) {
|
||||
@ -35023,7 +35174,10 @@ var Metadata = PDFJS.Metadata = (function MetadataClosure() {
|
||||
return Metadata;
|
||||
})();
|
||||
|
||||
|
||||
}).call((typeof window === 'undefined') ? this : window);
|
||||
|
||||
|
||||
-->
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
@ -35032,10 +35186,14 @@ var Metadata = PDFJS.Metadata = (function MetadataClosure() {
|
||||
PDFJS.workerSrc = 'none';
|
||||
</script>
|
||||
|
||||
|
||||
<link rel="stylesheet" href="viewer.css"/>
|
||||
|
||||
|
||||
<!-- PDFJSSCRIPT_INCLUDE_BUILD -->
|
||||
|
||||
|
||||
|
||||
|
||||
<script type="text/javascript" src="debugger.js"></script>
|
||||
<script type="text/javascript" src="viewer.js"></script>
|
||||
</head>
|
||||
@ -35096,19 +35254,25 @@ var Metadata = PDFJS.Metadata = (function MetadataClosure() {
|
||||
</div>
|
||||
<div id="toolbarViewerRight">
|
||||
<input id="fileInput" class="fileInput" type="file" oncontextmenu="return false;" style="visibility: hidden; position: fixed; right: 0; top: 0" />
|
||||
<button id="openFile" class="toolbarButton openFile" title="Open File" tabindex="11" data-l10n-id="open_file" onclick="document.getElementById('fileInput').click()">
|
||||
|
||||
|
||||
<button id="fullscreen" class="toolbarButton fullscreen" title="Fullscreen" tabindex="11" data-l10n-id="fullscreen" onclick="PDFView.fullscreen();">
|
||||
<span data-l10n-id="fullscreen_label">Fullscreen</span>
|
||||
</button>
|
||||
|
||||
<button id="openFile" class="toolbarButton openFile" title="Open File" tabindex="12" data-l10n-id="open_file" onclick="document.getElementById('fileInput').click()">
|
||||
<span data-l10n-id="open_file_label">Open</span>
|
||||
</button>
|
||||
|
||||
<button id="print" class="toolbarButton print" title="Print" tabindex="11" data-l10n-id="print" onclick="window.print()">
|
||||
<button id="print" class="toolbarButton print" title="Print" tabindex="13" data-l10n-id="print" onclick="window.print()">
|
||||
<span data-l10n-id="print_label">Print</span>
|
||||
</button>
|
||||
|
||||
<button id="download" class="toolbarButton download" title="Download" onclick="PDFView.download();" tabindex="12" data-l10n-id="download">
|
||||
<button id="download" class="toolbarButton download" title="Download" onclick="PDFView.download();" tabindex="14" data-l10n-id="download">
|
||||
<span data-l10n-id="download_label">Download</span>
|
||||
</button>
|
||||
<!-- <div class="toolbarButtonSpacer"></div> -->
|
||||
<a href="#" id="viewBookmark" class="toolbarButton bookmark" title="Current view (copy or open in new window)" tabindex="13" data-l10n-id="bookmark"><span data-l10n-id="bookmark_label">Current View</span></a>
|
||||
<a href="#" id="viewBookmark" class="toolbarButton bookmark" title="Current view (copy or open in new window)" tabindex="15" data-l10n-id="bookmark"><span data-l10n-id="bookmark_label">Current View</span></a>
|
||||
</div>
|
||||
<div class="outerCenter">
|
||||
<div class="innerCenter" id="toolbarViewerMiddle">
|
||||
@ -35175,3 +35339,4 @@ var Metadata = PDFJS.Metadata = (function MetadataClosure() {
|
||||
<div id="printContainer"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -60,7 +60,6 @@ var ProgressBar = (function ProgressBarClosure() {
|
||||
this.height = opts.height || 100;
|
||||
this.width = opts.width || 100;
|
||||
this.units = opts.units || '%';
|
||||
this.percent = opts.percent || 0;
|
||||
|
||||
// Initialize heights
|
||||
this.div.style.height = this.height + this.units;
|
||||
@ -69,10 +68,18 @@ var ProgressBar = (function ProgressBarClosure() {
|
||||
ProgressBar.prototype = {
|
||||
|
||||
updateBar: function ProgressBar_updateBar() {
|
||||
if (this._indeterminate) {
|
||||
this.div.classList.add('indeterminate');
|
||||
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');
|
||||
|
||||
this.div.style.width = progressSize + this.units;
|
||||
},
|
||||
@ -82,6 +89,7 @@ var ProgressBar = (function ProgressBarClosure() {
|
||||
},
|
||||
|
||||
set percent(val) {
|
||||
this._indeterminate = isNaN(val);
|
||||
this._percent = clamp(val, 0, 100);
|
||||
this.updateBar();
|
||||
}
|
||||
@ -151,6 +159,7 @@ var FirefoxCom = (function FirefoxComClosure() {
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
// Settings Manager - This is a utility for saving settings
|
||||
// First we see if localStorage is available
|
||||
// If not, we use FUEL in FF
|
||||
@ -167,17 +176,10 @@ var Settings = (function SettingsClosure() {
|
||||
}
|
||||
})();
|
||||
|
||||
var isFirefoxExtension = PDFJS.isFirefoxExtension;
|
||||
|
||||
function Settings(fingerprint) {
|
||||
var database = null;
|
||||
var index;
|
||||
if (isFirefoxExtension)
|
||||
database = FirefoxCom.requestSync('getDatabase', null) || '{}';
|
||||
else if (isLocalStorageEnabled)
|
||||
database = localStorage.getItem('database') || '{}';
|
||||
else
|
||||
return false;
|
||||
database = FirefoxCom.requestSync('getDatabase', null) || '{}';
|
||||
|
||||
database = JSON.parse(database);
|
||||
if (!('files' in database))
|
||||
@ -205,10 +207,7 @@ var Settings = (function SettingsClosure() {
|
||||
var file = this.file;
|
||||
file[name] = val;
|
||||
var database = JSON.stringify(this.database);
|
||||
if (isFirefoxExtension)
|
||||
FirefoxCom.requestSync('setDatabase', database);
|
||||
else if (isLocalStorageEnabled)
|
||||
localStorage.setItem('database', database);
|
||||
FirefoxCom.requestSync('setDatabase', database);
|
||||
},
|
||||
|
||||
get: function settingsGet(name, defaultValue) {
|
||||
@ -241,6 +240,8 @@ var PDFView = {
|
||||
sidebarOpen: false,
|
||||
pageViewScroll: null,
|
||||
thumbnailViewScroll: null,
|
||||
isFullscreen: false,
|
||||
previousScale: null,
|
||||
|
||||
// called once when the document is loaded
|
||||
initialize: function pdfViewInitialize() {
|
||||
@ -307,6 +308,7 @@ var PDFView = {
|
||||
|
||||
var container = this.container;
|
||||
var currentPage = this.pages[this.page - 1];
|
||||
|
||||
var pageWidthScale = (container.clientWidth - kScrollbarPadding) /
|
||||
currentPage.width * currentPage.scale / kCssUnits;
|
||||
var pageHeightScale = (container.clientHeight - kScrollbarPadding) /
|
||||
@ -348,9 +350,10 @@ var PDFView = {
|
||||
set page(val) {
|
||||
var pages = this.pages;
|
||||
var input = document.getElementById('pageNumber');
|
||||
var event = document.createEvent('UIEvents');
|
||||
event.initUIEvent('pagechange', false, false, window, 0);
|
||||
|
||||
if (!(0 < val && val <= pages.length)) {
|
||||
var event = document.createEvent('UIEvents');
|
||||
event.initUIEvent('pagechange', false, false, window, 0);
|
||||
event.pageNumber = this.page;
|
||||
window.dispatchEvent(event);
|
||||
return;
|
||||
@ -358,8 +361,6 @@ var PDFView = {
|
||||
|
||||
pages[val - 1].updateStats();
|
||||
currentPageNumber = val;
|
||||
var event = document.createEvent('UIEvents');
|
||||
event.initUIEvent('pagechange', false, false, window, 0);
|
||||
event.pageNumber = val;
|
||||
window.dispatchEvent(event);
|
||||
|
||||
@ -390,11 +391,53 @@ var PDFView = {
|
||||
return value;
|
||||
},
|
||||
|
||||
get supportsFullscreen() {
|
||||
var doc = document.documentElement;
|
||||
var support = doc.requestFullScreen || doc.mozRequestFullScreen ||
|
||||
doc.webkitRequestFullScreen;
|
||||
Object.defineProperty(this, 'supportsFullScreen', { value: support,
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: false });
|
||||
return support;
|
||||
},
|
||||
|
||||
initPassiveLoading: function pdfViewInitPassiveLoading() {
|
||||
if (!PDFView.loadingBar) {
|
||||
PDFView.loadingBar = new ProgressBar('#loadingBar', {});
|
||||
}
|
||||
|
||||
window.addEventListener('message', function window_message(e) {
|
||||
var args = e.data;
|
||||
|
||||
if (typeof args !== 'object' || !('pdfjsLoadAction' in args))
|
||||
return;
|
||||
switch (args.pdfjsLoadAction) {
|
||||
case 'progress':
|
||||
PDFView.progress(args.loaded / args.total);
|
||||
break;
|
||||
case 'complete':
|
||||
if (!args.data) {
|
||||
PDFView.error(mozL10n.get('loading_error', null,
|
||||
'An error occurred while loading the PDF.'), e);
|
||||
break;
|
||||
}
|
||||
PDFView.open(args.data, 0);
|
||||
break;
|
||||
}
|
||||
});
|
||||
FirefoxCom.requestSync('initPassiveLoading', null);
|
||||
},
|
||||
|
||||
setTitleUsingUrl: function pdfViewSetTitleUsingUrl(url) {
|
||||
this.url = url;
|
||||
document.title = decodeURIComponent(getFileName(url)) || url;
|
||||
},
|
||||
|
||||
open: function pdfViewOpen(url, scale, password) {
|
||||
var parameters = {password: password};
|
||||
if (typeof url === 'string') { // URL
|
||||
this.url = url;
|
||||
document.title = decodeURIComponent(getFileName(url)) || url;
|
||||
this.setTitleUsingUrl(url);
|
||||
parameters.url = url;
|
||||
} else if (url && 'byteLength' in url) { // ArrayBuffer
|
||||
parameters.data = url;
|
||||
@ -446,41 +489,34 @@ var PDFView = {
|
||||
}
|
||||
|
||||
var url = this.url.split('#')[0];
|
||||
if (PDFJS.isFirefoxExtension) {
|
||||
// Document isn't ready just try to download with the url.
|
||||
if (!this.pdfDocument) {
|
||||
noData();
|
||||
return;
|
||||
}
|
||||
this.pdfDocument.getData().then(
|
||||
function getDataSuccess(data) {
|
||||
var bb = new MozBlobBuilder();
|
||||
bb.append(data.buffer);
|
||||
var blobUrl = window.URL.createObjectURL(
|
||||
bb.getBlob('application/pdf'));
|
||||
|
||||
FirefoxCom.request('download', { blobUrl: blobUrl, originalUrl: url },
|
||||
function response(err) {
|
||||
if (err) {
|
||||
// This error won't really be helpful because it's likely the
|
||||
// fallback won't work either (or is already open).
|
||||
PDFView.error('PDF failed to download.');
|
||||
}
|
||||
window.URL.revokeObjectURL(blobUrl);
|
||||
}
|
||||
);
|
||||
},
|
||||
noData // Error ocurred try downloading with just the url.
|
||||
);
|
||||
} else {
|
||||
url += '#pdfjs.action=download', '_parent';
|
||||
window.open(url, '_parent');
|
||||
// Document isn't ready just try to download with the url.
|
||||
if (!this.pdfDocument) {
|
||||
noData();
|
||||
return;
|
||||
}
|
||||
this.pdfDocument.getData().then(
|
||||
function getDataSuccess(data) {
|
||||
var bb = new MozBlobBuilder();
|
||||
bb.append(data.buffer);
|
||||
var blobUrl = window.URL.createObjectURL(
|
||||
bb.getBlob('application/pdf'));
|
||||
|
||||
FirefoxCom.request('download', { blobUrl: blobUrl, originalUrl: url },
|
||||
function response(err) {
|
||||
if (err) {
|
||||
// This error won't really be helpful because it's likely the
|
||||
// fallback won't work either (or is already open).
|
||||
PDFView.error('PDF failed to download.');
|
||||
}
|
||||
window.URL.revokeObjectURL(blobUrl);
|
||||
}
|
||||
);
|
||||
},
|
||||
noData // Error occurred try downloading with just the url.
|
||||
);
|
||||
},
|
||||
|
||||
fallback: function pdfViewFallback() {
|
||||
if (!PDFJS.isFirefoxExtension)
|
||||
return;
|
||||
// Only trigger the fallback once so we don't spam the user with messages
|
||||
// for one PDF.
|
||||
if (this.fellback)
|
||||
@ -543,9 +579,7 @@ var PDFView = {
|
||||
* @param {String} anchor The anchor hash include the #.
|
||||
*/
|
||||
getAnchorUrl: function getAnchorUrl(anchor) {
|
||||
if (PDFJS.isFirefoxExtension)
|
||||
return this.url.split('#')[0] + anchor;
|
||||
return anchor;
|
||||
return this.url.split('#')[0] + anchor;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -579,40 +613,12 @@ var PDFView = {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (PDFJS.isFirefoxExtension) {
|
||||
console.error(message + '\n' + moreInfoText);
|
||||
this.fallback();
|
||||
return;
|
||||
}
|
||||
var errorWrapper = document.getElementById('errorWrapper');
|
||||
errorWrapper.removeAttribute('hidden');
|
||||
|
||||
var errorMessage = document.getElementById('errorMessage');
|
||||
errorMessage.textContent = message;
|
||||
var loadingBox = document.getElementById('loadingBox');
|
||||
loadingBox.setAttribute('hidden', 'true');
|
||||
|
||||
var closeButton = document.getElementById('errorClose');
|
||||
closeButton.onclick = function() {
|
||||
errorWrapper.setAttribute('hidden', 'true');
|
||||
};
|
||||
|
||||
var errorMoreInfo = document.getElementById('errorMoreInfo');
|
||||
var moreInfoButton = document.getElementById('errorShowMore');
|
||||
var lessInfoButton = document.getElementById('errorShowLess');
|
||||
moreInfoButton.onclick = function() {
|
||||
errorMoreInfo.removeAttribute('hidden');
|
||||
moreInfoButton.setAttribute('hidden', 'true');
|
||||
lessInfoButton.removeAttribute('hidden');
|
||||
};
|
||||
lessInfoButton.onclick = function() {
|
||||
errorMoreInfo.setAttribute('hidden', 'true');
|
||||
moreInfoButton.removeAttribute('hidden');
|
||||
lessInfoButton.setAttribute('hidden', 'true');
|
||||
};
|
||||
moreInfoButton.removeAttribute('hidden');
|
||||
lessInfoButton.setAttribute('hidden', 'true');
|
||||
errorMoreInfo.value = moreInfoText;
|
||||
|
||||
errorMoreInfo.rows = moreInfoText.split('\n').length - 1;
|
||||
console.error(message + '\n' + moreInfoText);
|
||||
this.fallback();
|
||||
},
|
||||
|
||||
progress: function pdfViewProgress(level) {
|
||||
@ -771,7 +777,7 @@ var PDFView = {
|
||||
}
|
||||
},
|
||||
|
||||
getHighestPriority: function pdfViewGetHighestPriority(visibleViews, views,
|
||||
getHighestPriority: function pdfViewGetHighestPriority(visible, views,
|
||||
scrolledDown) {
|
||||
// The state has changed figure out which page has the highest priority to
|
||||
// render next (if any).
|
||||
@ -779,35 +785,35 @@ var PDFView = {
|
||||
// 1 visible pages
|
||||
// 2 if last scrolled down page after the visible pages
|
||||
// 2 if last scrolled up page before the visible pages
|
||||
var visibleViews = visible.views;
|
||||
|
||||
var numVisible = visibleViews.length;
|
||||
if (numVisible === 0) {
|
||||
info('No visible views.');
|
||||
return false;
|
||||
}
|
||||
for (var i = 0; i < numVisible; ++i) {
|
||||
var view = visibleViews[i].view;
|
||||
if (!this.isViewFinshed(view))
|
||||
if (!this.isViewFinished(view))
|
||||
return view;
|
||||
}
|
||||
|
||||
// All the visible views have rendered, try to render next/previous pages.
|
||||
if (scrolledDown) {
|
||||
var lastVisible = visibleViews[visibleViews.length - 1];
|
||||
var nextPageIndex = lastVisible.id;
|
||||
var nextPageIndex = visible.last.id;
|
||||
// ID's start at 1 so no need to add 1.
|
||||
if (views[nextPageIndex] && !this.isViewFinshed(views[nextPageIndex]))
|
||||
if (views[nextPageIndex] && !this.isViewFinished(views[nextPageIndex]))
|
||||
return views[nextPageIndex];
|
||||
} else {
|
||||
var previousPageIndex = visibleViews[0].id - 2;
|
||||
var previousPageIndex = visible.first.id - 2;
|
||||
if (views[previousPageIndex] &&
|
||||
!this.isViewFinshed(views[previousPageIndex]))
|
||||
!this.isViewFinished(views[previousPageIndex]))
|
||||
return views[previousPageIndex];
|
||||
}
|
||||
// Everything that needs to be rendered has been.
|
||||
return false;
|
||||
},
|
||||
|
||||
isViewFinshed: function pdfViewNeedsRendering(view) {
|
||||
isViewFinished: function pdfViewNeedsRendering(view) {
|
||||
return view.renderingState === RenderingStates.FINISHED;
|
||||
},
|
||||
|
||||
@ -836,14 +842,14 @@ var PDFView = {
|
||||
search: function pdfViewStartSearch() {
|
||||
// Limit this function to run every <SEARCH_TIMEOUT>ms.
|
||||
var SEARCH_TIMEOUT = 250;
|
||||
var lastSeach = this.lastSearch;
|
||||
var lastSearch = this.lastSearch;
|
||||
var now = Date.now();
|
||||
if (lastSeach && (now - lastSeach) < SEARCH_TIMEOUT) {
|
||||
if (lastSearch && (now - lastSearch) < SEARCH_TIMEOUT) {
|
||||
if (!this.searchTimer) {
|
||||
this.searchTimer = setTimeout(function resumeSearch() {
|
||||
PDFView.search();
|
||||
},
|
||||
SEARCH_TIMEOUT - (now - lastSeach)
|
||||
SEARCH_TIMEOUT - (now - lastSearch)
|
||||
);
|
||||
}
|
||||
return;
|
||||
@ -912,7 +918,6 @@ var PDFView = {
|
||||
}
|
||||
if ('page' in params) {
|
||||
var pageNumber = (params.page | 0) || 1;
|
||||
this.page = pageNumber;
|
||||
if ('zoom' in params) {
|
||||
var zoomArgs = params.zoom.split(','); // scale,left,top
|
||||
// building destination array
|
||||
@ -928,9 +933,9 @@ var PDFView = {
|
||||
(zoomArgs[2] | 0), zoomArg];
|
||||
var currentPage = this.pages[pageNumber - 1];
|
||||
currentPage.scrollIntoView(dest);
|
||||
} else
|
||||
this.page = params.page; // simple page
|
||||
return;
|
||||
} else {
|
||||
this.page = pageNumber; // simple page
|
||||
}
|
||||
}
|
||||
} else if (/^\d+$/.test(hash)) // page number
|
||||
this.page = hash;
|
||||
@ -1001,13 +1006,13 @@ var PDFView = {
|
||||
extractPageText(pageIndex + 1);
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
extractPageText(0);
|
||||
},
|
||||
|
||||
getVisiblePages: function pdfViewGetVisiblePages() {
|
||||
return this.getVisibleElements(this.container,
|
||||
this.pages);
|
||||
this.pages, true);
|
||||
},
|
||||
|
||||
getVisibleThumbs: function pdfViewGetVisibleThumbs() {
|
||||
@ -1016,11 +1021,12 @@ var PDFView = {
|
||||
},
|
||||
|
||||
// Generic helper to find out what elements are visible within a scroll pane.
|
||||
getVisibleElements: function pdfViewGetVisibleElements(scrollEl, views) {
|
||||
getVisibleElements: function pdfViewGetVisibleElements(
|
||||
scrollEl, views, sortByVisibility) {
|
||||
var currentHeight = 0, view;
|
||||
var top = scrollEl.scrollTop;
|
||||
|
||||
for (var i = 1; i <= views.length; ++i) {
|
||||
for (var i = 1, ii = views.length; i <= ii; ++i) {
|
||||
view = views[i - 1];
|
||||
currentHeight = view.el.offsetTop;
|
||||
if (currentHeight + view.el.clientHeight > top)
|
||||
@ -1029,16 +1035,47 @@ var PDFView = {
|
||||
}
|
||||
|
||||
var visible = [];
|
||||
var bottom = top + scrollEl.clientHeight;
|
||||
for (; i <= views.length && currentHeight < bottom; ++i) {
|
||||
view = views[i - 1];
|
||||
currentHeight = view.el.offsetTop;
|
||||
visible.push({ id: view.id, y: currentHeight,
|
||||
view: view });
|
||||
currentHeight += view.el.clientHeight;
|
||||
|
||||
// Algorithm broken in fullscreen mode
|
||||
if (this.isFullscreen) {
|
||||
var currentPage = this.pages[this.page - 1];
|
||||
visible.push({
|
||||
id: currentPage.id,
|
||||
view: currentPage
|
||||
});
|
||||
|
||||
return { first: currentPage, last: currentPage, views: visible};
|
||||
}
|
||||
|
||||
return visible;
|
||||
var bottom = top + scrollEl.clientHeight;
|
||||
var nextHeight, hidden, percent, viewHeight;
|
||||
for (; i <= ii && currentHeight < bottom; ++i) {
|
||||
view = views[i - 1];
|
||||
viewHeight = view.el.clientHeight;
|
||||
currentHeight = view.el.offsetTop;
|
||||
nextHeight = currentHeight + viewHeight;
|
||||
hidden = Math.max(0, top - currentHeight) +
|
||||
Math.max(0, nextHeight - bottom);
|
||||
percent = Math.floor((viewHeight - hidden) * 100.0 / viewHeight);
|
||||
visible.push({ id: view.id, y: currentHeight,
|
||||
view: view, percent: percent });
|
||||
currentHeight = nextHeight;
|
||||
}
|
||||
|
||||
var first = visible[0];
|
||||
var last = visible[visible.length - 1];
|
||||
|
||||
if (sortByVisibility) {
|
||||
visible.sort(function(a, b) {
|
||||
var pc = a.percent - b.percent;
|
||||
if (Math.abs(pc) > 0.001)
|
||||
return -pc;
|
||||
|
||||
return a.id - b.id; // ensure stability
|
||||
});
|
||||
}
|
||||
|
||||
return {first: first, last: last, views: visible};
|
||||
},
|
||||
|
||||
// Helper function to parse query string (e.g. ?param1=value&parm2=...).
|
||||
@ -1072,6 +1109,44 @@ var PDFView = {
|
||||
var div = document.getElementById('printContainer');
|
||||
while (div.hasChildNodes())
|
||||
div.removeChild(div.lastChild);
|
||||
},
|
||||
|
||||
fullscreen: function pdfViewFullscreen() {
|
||||
var isFullscreen = document.fullscreen || document.mozFullScreen ||
|
||||
document.webkitIsFullScreen;
|
||||
|
||||
if (isFullscreen) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var wrapper = document.getElementById('viewerContainer');
|
||||
if (document.documentElement.requestFullScreen) {
|
||||
wrapper.requestFullScreen();
|
||||
} else if (document.documentElement.mozRequestFullScreen) {
|
||||
wrapper.mozRequestFullScreen();
|
||||
} else if (document.documentElement.webkitRequestFullScreen) {
|
||||
wrapper.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.isFullscreen = true;
|
||||
var currentPage = this.pages[this.page - 1];
|
||||
this.previousScale = this.currentScaleValue;
|
||||
this.parseScale('page-fit', true);
|
||||
|
||||
// Wait for fullscreen to take effect
|
||||
setTimeout(function() {
|
||||
currentPage.scrollIntoView();
|
||||
}, 0);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
exitFullscreen: function pdfViewExitFullscreen() {
|
||||
this.isFullscreen = false;
|
||||
this.parseScale(this.previousScale);
|
||||
this.page = this.page;
|
||||
}
|
||||
};
|
||||
|
||||
@ -1637,13 +1712,13 @@ var CustomStyle = (function CustomStyleClosure() {
|
||||
|
||||
//if all fails then set to undefined
|
||||
return (_cache[propName] = 'undefined');
|
||||
}
|
||||
};
|
||||
|
||||
CustomStyle.setProp = function set(propName, element, str) {
|
||||
var prop = this.getProp(propName);
|
||||
if (prop != 'undefined')
|
||||
element.style[prop] = str;
|
||||
}
|
||||
};
|
||||
|
||||
return CustomStyle;
|
||||
})();
|
||||
@ -1665,11 +1740,15 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv) {
|
||||
var renderInterval = 0;
|
||||
var resumeInterval = 500; // in ms
|
||||
|
||||
var canvas = document.createElement('canvas');
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
// Render the text layer, one div at a time
|
||||
function renderTextLayer() {
|
||||
if (textDivs.length === 0) {
|
||||
clearInterval(renderTimer);
|
||||
renderingDone = true;
|
||||
self.textLayerDiv = textLayerDiv = canvas = ctx = null;
|
||||
return;
|
||||
}
|
||||
var textDiv = textDivs.shift();
|
||||
@ -1678,9 +1757,12 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv) {
|
||||
|
||||
if (textDiv.dataset.textLength > 1) { // avoid div by zero
|
||||
// Adjust div width to match canvas text
|
||||
// Due to the .offsetWidth calls, this is slow
|
||||
// This needs to come after appending to the DOM
|
||||
var textScale = textDiv.dataset.canvasWidth / textDiv.offsetWidth;
|
||||
|
||||
ctx.font = textDiv.style.fontSize + ' sans-serif';
|
||||
var width = ctx.measureText(textDiv.textContent).width;
|
||||
|
||||
var textScale = textDiv.dataset.canvasWidth / width;
|
||||
|
||||
CustomStyle.setProp('transform' , textDiv,
|
||||
'scale(' + textScale + ', 1)');
|
||||
CustomStyle.setProp('transformOrigin' , textDiv, '0% 0%');
|
||||
@ -1706,7 +1788,7 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv) {
|
||||
// Resume rendering
|
||||
renderTimer = setInterval(renderTextLayer, renderInterval);
|
||||
}, resumeInterval);
|
||||
}; // textLayerOnScroll
|
||||
} // textLayerOnScroll
|
||||
|
||||
window.addEventListener('scroll', textLayerOnScroll, false);
|
||||
}; // endLayout
|
||||
@ -1730,19 +1812,13 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv) {
|
||||
};
|
||||
};
|
||||
|
||||
window.addEventListener('load', function webViewerLoad(evt) {
|
||||
document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) {
|
||||
PDFView.initialize();
|
||||
var params = PDFView.parseQueryString(document.location.search.substring(1));
|
||||
|
||||
var file = PDFJS.isFirefoxExtension ?
|
||||
window.location.toString() : params.file || kDefaultURL;
|
||||
var file = window.location.toString()
|
||||
|
||||
if (PDFJS.isFirefoxExtension || !window.File || !window.FileReader ||
|
||||
!window.FileList || !window.Blob) {
|
||||
document.getElementById('openFile').setAttribute('hidden', 'true');
|
||||
} else {
|
||||
document.getElementById('fileInput').value = null;
|
||||
}
|
||||
document.getElementById('openFile').setAttribute('hidden', 'true');
|
||||
|
||||
// Special debugging flags in the hash section of the URL.
|
||||
var hash = document.location.hash.substring(1);
|
||||
@ -1751,18 +1827,22 @@ window.addEventListener('load', function webViewerLoad(evt) {
|
||||
if ('disableWorker' in hashParams)
|
||||
PDFJS.disableWorker = (hashParams['disableWorker'] === 'true');
|
||||
|
||||
if (!PDFJS.isFirefoxExtension) {
|
||||
var locale = navigator.language;
|
||||
if ('locale' in hashParams)
|
||||
locale = hashParams['locale'];
|
||||
mozL10n.language.code = locale;
|
||||
|
||||
if ('textLayer' in hashParams) {
|
||||
switch (hashParams['textLayer']) {
|
||||
case 'off':
|
||||
PDFJS.disableTextLayer = true;
|
||||
break;
|
||||
case 'visible':
|
||||
case 'shadow':
|
||||
case 'hover':
|
||||
var viewer = document.getElementById('viewer');
|
||||
viewer.classList.add('textLayer-' + hashParams['textLayer']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ('disableTextLayer' in hashParams)
|
||||
PDFJS.disableTextLayer = (hashParams['disableTextLayer'] === 'true');
|
||||
|
||||
if ('pdfBug' in hashParams &&
|
||||
(!PDFJS.isFirefoxExtension || FirefoxCom.requestSync('pdfBugEnabled'))) {
|
||||
if ('pdfBug' in hashParams && FirefoxCom.requestSync('pdfBugEnabled')) {
|
||||
PDFJS.pdfBug = true;
|
||||
var pdfBug = hashParams['pdfBug'];
|
||||
var enabled = pdfBug.split(',');
|
||||
@ -1770,8 +1850,7 @@ window.addEventListener('load', function webViewerLoad(evt) {
|
||||
PDFBug.init();
|
||||
}
|
||||
|
||||
if (!PDFJS.isFirefoxExtension ||
|
||||
(PDFJS.isFirefoxExtension && FirefoxCom.requestSync('searchEnabled'))) {
|
||||
if (FirefoxCom.requestSync('searchEnabled')) {
|
||||
document.querySelector('#viewSearch').classList.remove('hidden');
|
||||
}
|
||||
|
||||
@ -1779,6 +1858,10 @@ window.addEventListener('load', function webViewerLoad(evt) {
|
||||
document.getElementById('print').classList.add('hidden');
|
||||
}
|
||||
|
||||
if (!PDFView.supportsFullscreen) {
|
||||
document.getElementById('fullscreen').classList.add('hidden');
|
||||
}
|
||||
|
||||
// Listen for warnings to trigger the fallback UI. Errors should be caught
|
||||
// and call PDFView.error() so we don't need to listen for those.
|
||||
PDFJS.LogManager.addLogger({
|
||||
@ -1807,21 +1890,49 @@ window.addEventListener('load', function webViewerLoad(evt) {
|
||||
PDFView.renderHighestPriority();
|
||||
});
|
||||
|
||||
if (FirefoxCom.requestSync('getLoadingType') == 'passive') {
|
||||
PDFView.setTitleUsingUrl(file);
|
||||
PDFView.initPassiveLoading();
|
||||
return;
|
||||
}
|
||||
|
||||
PDFView.open(file, 0);
|
||||
}, true);
|
||||
|
||||
function updateViewarea() {
|
||||
|
||||
if (!PDFView.initialized)
|
||||
return;
|
||||
var visiblePages = PDFView.getVisiblePages();
|
||||
var visible = PDFView.getVisiblePages();
|
||||
var visiblePages = visible.views;
|
||||
|
||||
PDFView.renderHighestPriority();
|
||||
|
||||
updateViewarea.inProgress = true; // used in "set page"
|
||||
var currentId = PDFView.page;
|
||||
var firstPage = visiblePages[0];
|
||||
PDFView.page = firstPage.id;
|
||||
updateViewarea.inProgress = false;
|
||||
var firstPage = visible.first;
|
||||
|
||||
for (var i = 0, ii = visiblePages.length, stillFullyVisible = false;
|
||||
i < ii; ++i) {
|
||||
var page = visiblePages[i];
|
||||
|
||||
if (page.percent < 100)
|
||||
break;
|
||||
|
||||
if (page.id === PDFView.page) {
|
||||
stillFullyVisible = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!stillFullyVisible) {
|
||||
currentId = visiblePages[0].id;
|
||||
}
|
||||
|
||||
if (!PDFView.isFullscreen) {
|
||||
updateViewarea.inProgress = true; // used in "set page"
|
||||
PDFView.page = currentId;
|
||||
updateViewarea.inProgress = false;
|
||||
}
|
||||
|
||||
var currentScale = PDFView.currentScale;
|
||||
var currentScaleValue = PDFView.currentScaleValue;
|
||||
@ -1867,21 +1978,14 @@ window.addEventListener('change', function webViewerChange(evt) {
|
||||
// Read the local file into a Uint8Array.
|
||||
var fileReader = new FileReader();
|
||||
fileReader.onload = function webViewerChangeFileReaderOnload(evt) {
|
||||
var data = evt.target.result;
|
||||
var buffer = new ArrayBuffer(data.length);
|
||||
var buffer = evt.target.result;
|
||||
var uint8Array = new Uint8Array(buffer);
|
||||
|
||||
for (var i = 0; i < data.length; i++)
|
||||
uint8Array[i] = data.charCodeAt(i);
|
||||
|
||||
PDFView.open(uint8Array, 0);
|
||||
};
|
||||
|
||||
// Read as a binary string since "readAsArrayBuffer" is not yet
|
||||
// implemented in Firefox.
|
||||
var file = files[0];
|
||||
fileReader.readAsBinaryString(file);
|
||||
document.title = file.name;
|
||||
fileReader.readAsArrayBuffer(file);
|
||||
PDFView.setTitleUsingUrl(file.name);
|
||||
|
||||
// URL does not reflect proper document location - hiding some icons.
|
||||
document.getElementById('viewBookmark').setAttribute('hidden', 'true');
|
||||
@ -1938,13 +2042,13 @@ window.addEventListener('pagechange', function pagechange(evt) {
|
||||
var thumbnail = document.getElementById('thumbnailContainer' + page);
|
||||
thumbnail.classList.add('selected');
|
||||
var visibleThumbs = PDFView.getVisibleThumbs();
|
||||
var numVisibleThumbs = visibleThumbs.length;
|
||||
var numVisibleThumbs = visibleThumbs.views.length;
|
||||
// If the thumbnail isn't currently visible scroll it into view.
|
||||
if (numVisibleThumbs > 0) {
|
||||
var first = visibleThumbs[0].id;
|
||||
var first = visibleThumbs.first.id;
|
||||
// Account for only one thumbnail being visible.
|
||||
var last = numVisibleThumbs > 1 ?
|
||||
visibleThumbs[numVisibleThumbs - 1].id : first;
|
||||
visibleThumbs.last.id : first;
|
||||
if (page <= first || page >= last)
|
||||
thumbnail.scrollIntoView();
|
||||
}
|
||||
@ -2007,7 +2111,7 @@ window.addEventListener('keydown', function keydown(evt) {
|
||||
return;
|
||||
var controlsElement = document.getElementById('controls');
|
||||
while (curElement) {
|
||||
if (curElement === controlsElement)
|
||||
if (curElement === controlsElement && !PDFView.isFullscreen)
|
||||
return; // ignoring if the 'controls' element is focused
|
||||
curElement = curElement.parentNode;
|
||||
}
|
||||
@ -2026,6 +2130,13 @@ window.addEventListener('keydown', function keydown(evt) {
|
||||
PDFView.page++;
|
||||
handled = true;
|
||||
break;
|
||||
|
||||
case 32: // spacebar
|
||||
if (PDFView.isFullscreen) {
|
||||
PDFView.page++;
|
||||
handled = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2041,3 +2152,20 @@ window.addEventListener('beforeprint', function beforePrint(evt) {
|
||||
window.addEventListener('afterprint', function afterPrint(evt) {
|
||||
PDFView.afterPrint();
|
||||
});
|
||||
|
||||
(function fullscreenClosure() {
|
||||
function fullscreenChange(e) {
|
||||
var isFullscreen = document.fullscreen || document.mozFullScreen ||
|
||||
document.webkitIsFullScreen;
|
||||
|
||||
if (!isFullscreen) {
|
||||
PDFView.exitFullscreen();
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('fullscreenchange', fullscreenChange, false);
|
||||
window.addEventListener('mozfullscreenchange', fullscreenChange, false);
|
||||
window.addEventListener('webkitfullscreenchange', fullscreenChange, false);
|
||||
})();
|
||||
|
||||
|
||||
|
@ -9,6 +9,7 @@ content/web/images/loading-icon.gif
|
||||
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
|
||||
|
@ -264,6 +264,9 @@ class Automation(object):
|
||||
# Open database and create table
|
||||
permDB = sqlite3.connect(os.path.join(profileDir, "permissions.sqlite"))
|
||||
cursor = permDB.cursor();
|
||||
|
||||
cursor.execute("PRAGMA user_version=3");
|
||||
|
||||
# SQL copied from nsPermissionManager.cpp
|
||||
cursor.execute("""CREATE TABLE moz_hosts (
|
||||
id INTEGER PRIMARY KEY,
|
||||
@ -271,14 +274,16 @@ class Automation(object):
|
||||
type TEXT,
|
||||
permission INTEGER,
|
||||
expireType INTEGER,
|
||||
expireTime INTEGER)""")
|
||||
expireTime INTEGER,
|
||||
appId INTEGER,
|
||||
isInBrowserElement INTEGER)""")
|
||||
|
||||
# Insert desired permissions
|
||||
c = 0
|
||||
for perm in permissions.keys():
|
||||
for host,allow in permissions[perm]:
|
||||
c += 1
|
||||
cursor.execute("INSERT INTO moz_hosts values(?, ?, ?, ?, 0, 0)",
|
||||
cursor.execute("INSERT INTO moz_hosts values(?, ?, ?, ?, 0, 0, 0, 0)",
|
||||
(c, host, perm, 1 if allow else 2))
|
||||
|
||||
# Commit and close
|
||||
|
@ -389,6 +389,8 @@ function runTest() {
|
||||
checkIFrame(this, data);
|
||||
};
|
||||
iframe.addChild = function() {
|
||||
SpecialPowers.addPermission("browser", true, iframe.contentDocument);
|
||||
|
||||
var childFrame = document.createElement('iframe');
|
||||
|
||||
if (data.child.app) {
|
||||
@ -429,7 +431,6 @@ function runTest() {
|
||||
|
||||
var gTestRunner = runTest();
|
||||
|
||||
SpecialPowers.addPermission("browser", true, "http://example.org");
|
||||
SpecialPowers.pushPrefEnv({'set':[["dom.mozBrowserFramesEnabled", true]]},
|
||||
function() { gTestRunner.next(); });
|
||||
|
||||
|
@ -1771,8 +1771,8 @@ protected:
|
||||
// We hold a strong reference to mNodeInfoManager through mNodeInfo
|
||||
nsNodeInfoManager* mNodeInfoManager; // [STRONG]
|
||||
nsRefPtr<mozilla::css::Loader> mCSSLoader;
|
||||
mozilla::css::ImageLoader* mStyleImageLoader; // [STRONG]
|
||||
nsHTMLStyleSheet* mAttrStyleSheet;
|
||||
nsRefPtr<mozilla::css::ImageLoader> mStyleImageLoader;
|
||||
nsRefPtr<nsHTMLStyleSheet> mAttrStyleSheet;
|
||||
|
||||
// The set of all object, embed, applet, video and audio elements for
|
||||
// which this is the owner document. (They might not be in the document.)
|
||||
|
@ -1622,7 +1622,6 @@ nsDocument::~nsDocument()
|
||||
}
|
||||
if (mAttrStyleSheet) {
|
||||
mAttrStyleSheet->SetOwningDocument(nullptr);
|
||||
NS_RELEASE(mAttrStyleSheet);
|
||||
}
|
||||
if (mStyleAttrStyleSheet)
|
||||
mStyleAttrStyleSheet->SetOwningDocument(nullptr);
|
||||
@ -1643,7 +1642,6 @@ nsDocument::~nsDocument()
|
||||
|
||||
if (mStyleImageLoader) {
|
||||
mStyleImageLoader->DropDocumentReference();
|
||||
NS_RELEASE(mStyleImageLoader);
|
||||
}
|
||||
|
||||
delete mHeaderData;
|
||||
@ -2001,7 +1999,6 @@ nsDocument::Init()
|
||||
mCSSLoader->SetCompatibilityMode(eCompatibility_FullStandards);
|
||||
|
||||
mStyleImageLoader = new mozilla::css::ImageLoader(this);
|
||||
NS_ADDREF(mStyleImageLoader);
|
||||
|
||||
mNodeInfoManager = new nsNodeInfoManager();
|
||||
nsresult rv = mNodeInfoManager->Init(this);
|
||||
@ -2278,7 +2275,6 @@ nsDocument::ResetStylesheetsToURI(nsIURI* aURI)
|
||||
mAttrStyleSheet->Reset(aURI);
|
||||
} else {
|
||||
mAttrStyleSheet = new nsHTMLStyleSheet(aURI, this);
|
||||
NS_ADDREF(mAttrStyleSheet);
|
||||
}
|
||||
|
||||
// Don't use AddStyleSheet, since it'll put the sheet into style
|
||||
|
@ -18,6 +18,11 @@ function runTest() {
|
||||
browserElementTestHelpers.setEnabledPref(true);
|
||||
browserElementTestHelpers.addPermission();
|
||||
|
||||
var principal = SpecialPowers.wrap(SpecialPowers.getNodePrincipal(document));
|
||||
SpecialPowers.addPermission("browser", true, { url: SpecialPowers.wrap(principal.URI).spec,
|
||||
appId: principal.appId,
|
||||
isInBrowserElement: true });
|
||||
|
||||
iframe = document.createElement('iframe');
|
||||
iframe.mozbrowser = true;
|
||||
|
||||
@ -55,6 +60,12 @@ function finish() {
|
||||
// expected, but if we don't remove our listener, then we'll end up causing
|
||||
// the /next/ test to fail!
|
||||
iframe.removeEventListener('mozbrowsershowmodalprompt', checkMessage);
|
||||
|
||||
var principal = SpecialPowers.wrap(SpecialPowers.getNodePrincipal(document));
|
||||
SpecialPowers.removePermission("browser", { url: SpecialPowers.wrap(principal.URI).spec,
|
||||
appId: principal.appId,
|
||||
isInBrowserElement: true });
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,11 @@ function runTest() {
|
||||
browserElementTestHelpers.setEnabledPref(true);
|
||||
browserElementTestHelpers.addPermission();
|
||||
|
||||
var principal = SpecialPowers.wrap(SpecialPowers.getNodePrincipal(document));
|
||||
SpecialPowers.addPermission("browser", true, { url: SpecialPowers.wrap(principal.URI).spec,
|
||||
appId: principal.appId,
|
||||
isInBrowserElement: true });
|
||||
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.mozbrowser = true;
|
||||
|
||||
@ -35,7 +40,7 @@ function runTest() {
|
||||
SimpleTest.executeSoon(function() {
|
||||
SimpleTest.executeSoon(function() {
|
||||
SimpleTest.executeSoon(function() {
|
||||
SimpleTest.finish();
|
||||
finish();
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -50,4 +55,13 @@ function runTest() {
|
||||
document.body.appendChild(iframe);
|
||||
}
|
||||
|
||||
function finish() {
|
||||
var principal = SpecialPowers.wrap(SpecialPowers.getNodePrincipal(document));
|
||||
SpecialPowers.removePermission("browser", { url: SpecialPowers.wrap(principal.URI).spec,
|
||||
appId: principal.appId,
|
||||
isInBrowserElement: true });
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
runTest();
|
||||
|
@ -95,6 +95,9 @@
|
||||
#include "nsIRemoteBlob.h"
|
||||
#include "StructuredCloneUtils.h"
|
||||
#include "URIUtils.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIPrincipal.h"
|
||||
|
||||
using namespace mozilla::docshell;
|
||||
using namespace mozilla::dom::devicestorage;
|
||||
@ -847,7 +850,20 @@ ContentChild::RecvAddPermission(const IPC::Permission& permission)
|
||||
NS_ABORT_IF_FALSE(permissionManager,
|
||||
"We have no permissionManager in the Content process !");
|
||||
|
||||
permissionManager->AddInternal(nsCString(permission.host),
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("http://") + nsCString(permission.host));
|
||||
NS_ENSURE_TRUE(uri, true);
|
||||
|
||||
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
|
||||
MOZ_ASSERT(secMan);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
nsresult rv = secMan->GetAppCodebasePrincipal(uri, permission.appId,
|
||||
permission.isInBrowserElement,
|
||||
getter_AddRefs(principal));
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
|
||||
permissionManager->AddInternal(principal,
|
||||
nsCString(permission.type),
|
||||
permission.capability,
|
||||
0,
|
||||
|
@ -784,6 +784,10 @@ ContentParent::RecvReadPermissions(InfallibleTArray<IPC::Permission>* aPermissio
|
||||
|
||||
nsCString host;
|
||||
perm->GetHost(host);
|
||||
uint32_t appId;
|
||||
perm->GetAppId(&appId);
|
||||
bool isInBrowserElement;
|
||||
perm->GetIsInBrowserElement(&isInBrowserElement);
|
||||
nsCString type;
|
||||
perm->GetType(type);
|
||||
uint32_t capability;
|
||||
@ -793,8 +797,10 @@ ContentParent::RecvReadPermissions(InfallibleTArray<IPC::Permission>* aPermissio
|
||||
int64_t expireTime;
|
||||
perm->GetExpireTime(&expireTime);
|
||||
|
||||
aPermissions->AppendElement(IPC::Permission(host, type, capability,
|
||||
expireType, expireTime));
|
||||
aPermissions->AppendElement(IPC::Permission(host, appId,
|
||||
isInBrowserElement, type,
|
||||
capability, expireType,
|
||||
expireTime));
|
||||
}
|
||||
|
||||
// Ask for future changes
|
||||
|
@ -10,6 +10,8 @@
|
||||
NS_IMPL_ISUPPORTS1(nsPermission, nsIPermission)
|
||||
|
||||
nsPermission::nsPermission(const nsACString &aHost,
|
||||
uint32_t aAppId,
|
||||
bool aIsInBrowserElement,
|
||||
const nsACString &aType,
|
||||
uint32_t aCapability,
|
||||
uint32_t aExpireType,
|
||||
@ -19,10 +21,8 @@ nsPermission::nsPermission(const nsACString &aHost,
|
||||
, mCapability(aCapability)
|
||||
, mExpireType(aExpireType)
|
||||
, mExpireTime(aExpireTime)
|
||||
{
|
||||
}
|
||||
|
||||
nsPermission::~nsPermission()
|
||||
, mAppId(aAppId)
|
||||
, mIsInBrowserElement(aIsInBrowserElement)
|
||||
{
|
||||
}
|
||||
|
||||
@ -33,6 +33,20 @@ nsPermission::GetHost(nsACString &aHost)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPermission::GetAppId(uint32_t* aAppId)
|
||||
{
|
||||
*aAppId = mAppId;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPermission::GetIsInBrowserElement(bool* aIsInBrowserElement)
|
||||
{
|
||||
*aIsInBrowserElement = mIsInBrowserElement;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPermission::GetType(nsACString &aType)
|
||||
{
|
||||
|
@ -19,19 +19,23 @@ public:
|
||||
NS_DECL_NSIPERMISSION
|
||||
|
||||
nsPermission(const nsACString &aHost,
|
||||
const nsACString &aType,
|
||||
uint32_t aAppId,
|
||||
bool aIsInBrowserElement,
|
||||
const nsACString &aType,
|
||||
uint32_t aCapability,
|
||||
uint32_t aExpireType,
|
||||
int64_t aExpireTime);
|
||||
|
||||
virtual ~nsPermission();
|
||||
|
||||
virtual ~nsPermission() {};
|
||||
|
||||
protected:
|
||||
nsCString mHost;
|
||||
nsCString mType;
|
||||
uint32_t mCapability;
|
||||
uint32_t mExpireType;
|
||||
int64_t mExpireTime;
|
||||
uint32_t mAppId;
|
||||
bool mIsInBrowserElement;
|
||||
};
|
||||
|
||||
#endif // nsPermission_h__
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
|
||||
static nsPermissionManager *gPermissionManager = nullptr;
|
||||
|
||||
@ -70,42 +71,66 @@ ChildProcess()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define PL_ARENA_CONST_ALIGN_MASK 3
|
||||
#include "plarena.h"
|
||||
namespace {
|
||||
|
||||
static PLArenaPool *gHostArena = nullptr;
|
||||
|
||||
// making sHostArena 512b for nice allocation
|
||||
// growing is quite cheap
|
||||
#define HOST_ARENA_SIZE 512
|
||||
|
||||
// equivalent to strdup() - does no error checking,
|
||||
// we're assuming we're only called with a valid pointer
|
||||
static char *
|
||||
ArenaStrDup(const char* str, PLArenaPool* aArena)
|
||||
nsresult
|
||||
GetPrincipal(const nsACString& aHost, uint32_t aAppId, bool aIsInBrowserElement,
|
||||
nsIPrincipal** aPrincipal)
|
||||
{
|
||||
void* mem;
|
||||
const uint32_t size = strlen(str) + 1;
|
||||
PL_ARENA_ALLOCATE(mem, aArena, size);
|
||||
if (mem)
|
||||
memcpy(mem, str, size);
|
||||
return static_cast<char*>(mem);
|
||||
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
|
||||
NS_ENSURE_TRUE(secMan, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
// NOTE: we use "http://" as a protocal but we will just use the host so it
|
||||
// doesn't really matter.
|
||||
NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("http://") + aHost);
|
||||
|
||||
return secMan->GetAppCodebasePrincipal(uri, aAppId, aIsInBrowserElement, aPrincipal);
|
||||
}
|
||||
|
||||
nsHostEntry::nsHostEntry(const char* aHost)
|
||||
nsresult
|
||||
GetPrincipal(nsIURI* aURI, nsIPrincipal** aPrincipal)
|
||||
{
|
||||
mHost = ArenaStrDup(aHost, gHostArena);
|
||||
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
|
||||
NS_ENSURE_TRUE(secMan, NS_ERROR_FAILURE);
|
||||
|
||||
return secMan->GetNoAppCodebasePrincipal(aURI, aPrincipal);
|
||||
}
|
||||
|
||||
// XXX this can fail on OOM
|
||||
nsHostEntry::nsHostEntry(const nsHostEntry& toCopy)
|
||||
: mHost(toCopy.mHost)
|
||||
, mPermissions(toCopy.mPermissions)
|
||||
nsresult
|
||||
GetPrincipal(const nsACString& aHost, nsIPrincipal** aPrincipal)
|
||||
{
|
||||
return GetPrincipal(aHost, nsIScriptSecurityManager::NO_APP_ID, false, aPrincipal);
|
||||
}
|
||||
|
||||
nsresult
|
||||
GetHostForPrincipal(nsIPrincipal* aPrincipal, nsACString& aHost)
|
||||
{
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uri = NS_GetInnermostURI(uri);
|
||||
NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
|
||||
|
||||
rv = uri->GetAsciiHost(aHost);
|
||||
if (NS_FAILED(rv) || aHost.IsEmpty()) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsPermissionManager::PermissionKey::PermissionKey(nsIPrincipal* aPrincipal)
|
||||
{
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(GetHostForPrincipal(aPrincipal, mHost)));
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(aPrincipal->GetAppId(&mAppId)));
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(aPrincipal->GetIsInBrowserElement(&mIsInBrowserElement)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple callback used by |AsyncClose| to trigger a treatment once
|
||||
@ -217,7 +242,7 @@ NS_IMETHODIMP DeleteFromMozHostListener::HandleCompletion(uint16_t aReason)
|
||||
// nsPermissionManager Implementation
|
||||
|
||||
static const char kPermissionsFileName[] = "permissions.sqlite";
|
||||
#define HOSTS_SCHEMA_VERSION 2
|
||||
#define HOSTS_SCHEMA_VERSION 3
|
||||
|
||||
static const char kHostpermFileName[] = "hostperm.1";
|
||||
|
||||
@ -268,7 +293,7 @@ nsPermissionManager::Init()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
mHostTable.Init();
|
||||
mPermissionTable.Init();
|
||||
|
||||
mObserverService = do_GetService("@mozilla.org/observer-service;1", &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
@ -283,7 +308,12 @@ nsPermissionManager::Init()
|
||||
|
||||
for (uint32_t i = 0; i < perms.Length(); i++) {
|
||||
const IPC::Permission &perm = perms[i];
|
||||
AddInternal(perm.host, perm.type, perm.capability, 0, perm.expireType,
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
rv = GetPrincipal(perm.host, perm.appId, perm.isInBrowserElement, getter_AddRefs(principal));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
AddInternal(principal, perm.type, perm.capability, 0, perm.expireType,
|
||||
perm.expireTime, eNotify, eNoDBOperation);
|
||||
}
|
||||
|
||||
@ -374,31 +404,33 @@ nsPermissionManager::InitDB(bool aRemoveFile)
|
||||
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"ALTER TABLE moz_hosts ADD expireTime INTEGER"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// fall through to the next upgrade
|
||||
|
||||
// TODO: we want to make default version as version 2 in order to fix bug 784875.
|
||||
case 0:
|
||||
case 2:
|
||||
{
|
||||
// Add appId/isInBrowserElement fields.
|
||||
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"ALTER TABLE moz_hosts ADD appId INTEGER"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"ALTER TABLE moz_hosts ADD isInBrowserElement INTEGER"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mDBConn->SetSchemaVersion(HOSTS_SCHEMA_VERSION);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// fall through to the next upgrade
|
||||
|
||||
|
||||
// current version.
|
||||
case HOSTS_SCHEMA_VERSION:
|
||||
break;
|
||||
|
||||
case 0:
|
||||
{
|
||||
NS_WARNING("couldn't get schema version!");
|
||||
|
||||
// the table may be usable; someone might've just clobbered the schema
|
||||
// version. we can treat this case like a downgrade using the codepath
|
||||
// below, by verifying the columns we care about are all there. for now,
|
||||
// re-set the schema version in the db, in case the checks succeed (if
|
||||
// they don't, we're dropping the table anyway).
|
||||
rv = mDBConn->SetSchemaVersion(HOSTS_SCHEMA_VERSION);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
// fall through to downgrade check
|
||||
|
||||
// downgrading.
|
||||
// if columns have been added to the table, we can still use the ones we
|
||||
// understand safely. if columns have been deleted or altered, just
|
||||
@ -410,7 +442,7 @@ nsPermissionManager::InitDB(bool aRemoveFile)
|
||||
// check if all the expected columns exist
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT host, type, permission, expireType, expireTime FROM moz_hosts"),
|
||||
"SELECT host, type, permission, expireType, expireTime, appId, isInBrowserElement FROM moz_hosts"),
|
||||
getter_AddRefs(stmt));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
break;
|
||||
@ -432,8 +464,8 @@ nsPermissionManager::InitDB(bool aRemoveFile)
|
||||
// cache frequently used statements (for insertion, deletion, and updating)
|
||||
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"INSERT INTO moz_hosts "
|
||||
"(id, host, type, permission, expireType, expireTime) "
|
||||
"VALUES (?1, ?2, ?3, ?4, ?5, ?6)"), getter_AddRefs(mStmtInsert));
|
||||
"(id, host, type, permission, expireType, expireTime, appId, isInBrowserElement) "
|
||||
"VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)"), getter_AddRefs(mStmtInsert));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
@ -473,6 +505,8 @@ nsPermissionManager::CreateTable()
|
||||
",permission INTEGER"
|
||||
",expireType INTEGER"
|
||||
",expireTime INTEGER"
|
||||
",appId INTEGER"
|
||||
",isInBrowserElement INTEGER"
|
||||
")"));
|
||||
}
|
||||
|
||||
@ -483,28 +517,13 @@ nsPermissionManager::Add(nsIURI *aURI,
|
||||
uint32_t aExpireType,
|
||||
int64_t aExpireTime)
|
||||
{
|
||||
ENSURE_NOT_CHILD_PROCESS;
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aURI);
|
||||
NS_ENSURE_ARG_POINTER(aType);
|
||||
NS_ENSURE_TRUE(aExpireType == nsIPermissionManager::EXPIRE_NEVER ||
|
||||
aExpireType == nsIPermissionManager::EXPIRE_TIME ||
|
||||
aExpireType == nsIPermissionManager::EXPIRE_SESSION,
|
||||
NS_ERROR_INVALID_ARG);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// Skip addition if the permission is already expired.
|
||||
if (aExpireType == nsIPermissionManager::EXPIRE_TIME &&
|
||||
aExpireTime <= PR_Now() / 1000)
|
||||
return NS_OK;
|
||||
|
||||
nsCAutoString host;
|
||||
rv = GetHost(aURI, host);
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
nsresult rv = GetPrincipal(aURI, getter_AddRefs(principal));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return AddInternal(host, nsDependentCString(aType), aPermission, 0,
|
||||
aExpireType, aExpireTime, eNotify, eWriteToDB);
|
||||
return AddFromPrincipal(principal, aType, aPermission, aExpireType, aExpireTime);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -512,7 +531,19 @@ nsPermissionManager::AddFromPrincipal(nsIPrincipal* aPrincipal,
|
||||
const char* aType, uint32_t aPermission,
|
||||
uint32_t aExpireType, int64_t aExpireTime)
|
||||
{
|
||||
ENSURE_NOT_CHILD_PROCESS;
|
||||
NS_ENSURE_ARG_POINTER(aPrincipal);
|
||||
NS_ENSURE_ARG_POINTER(aType);
|
||||
NS_ENSURE_TRUE(aExpireType == nsIPermissionManager::EXPIRE_NEVER ||
|
||||
aExpireType == nsIPermissionManager::EXPIRE_TIME ||
|
||||
aExpireType == nsIPermissionManager::EXPIRE_SESSION,
|
||||
NS_ERROR_INVALID_ARG);
|
||||
|
||||
// Skip addition if the permission is already expired.
|
||||
if (aExpireType == nsIPermissionManager::EXPIRE_TIME &&
|
||||
aExpireTime <= (PR_Now() / 1000)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// We don't add the system principal because it actually has no URI and we
|
||||
// always allow action for them.
|
||||
@ -520,14 +551,12 @@ nsPermissionManager::AddFromPrincipal(nsIPrincipal* aPrincipal,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
aPrincipal->GetURI(getter_AddRefs(uri));
|
||||
|
||||
return Add(uri, aType, aPermission, aExpireType, aExpireTime);
|
||||
return AddInternal(aPrincipal, nsDependentCString(aType), aPermission, 0,
|
||||
aExpireType, aExpireTime, eNotify, eWriteToDB);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPermissionManager::AddInternal(const nsAFlatCString &aHost,
|
||||
nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal,
|
||||
const nsAFlatCString &aType,
|
||||
uint32_t aPermission,
|
||||
int64_t aID,
|
||||
@ -536,9 +565,20 @@ nsPermissionManager::AddInternal(const nsAFlatCString &aHost,
|
||||
NotifyOperationType aNotifyOperation,
|
||||
DBOperationType aDBOperation)
|
||||
{
|
||||
nsCAutoString host;
|
||||
nsresult rv = GetHostForPrincipal(aPrincipal, host);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!IsChildProcess()) {
|
||||
IPC::Permission permission((aHost),
|
||||
(aType),
|
||||
uint32_t appId;
|
||||
rv = aPrincipal->GetAppId(&appId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool isInBrowserElement;
|
||||
rv = aPrincipal->GetIsInBrowserElement(&isInBrowserElement);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
IPC::Permission permission(host, appId, isInBrowserElement, aType,
|
||||
aPermission, aExpireType, aExpireTime);
|
||||
|
||||
nsTArray<ContentParent*> cplist;
|
||||
@ -550,23 +590,17 @@ nsPermissionManager::AddInternal(const nsAFlatCString &aHost,
|
||||
}
|
||||
}
|
||||
|
||||
if (!gHostArena) {
|
||||
gHostArena = new PLArenaPool;
|
||||
if (!gHostArena)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
PL_INIT_ARENA_POOL(gHostArena, "PermissionHostArena", HOST_ARENA_SIZE);
|
||||
}
|
||||
|
||||
// look up the type index
|
||||
int32_t typeIndex = GetTypeIndex(aType.get(), true);
|
||||
NS_ENSURE_TRUE(typeIndex != -1, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// When an entry already exists, PutEntry will return that, instead
|
||||
// of adding a new one
|
||||
nsHostEntry *entry = mHostTable.PutEntry(aHost.get());
|
||||
nsRefPtr<PermissionKey> key = new PermissionKey(aPrincipal);
|
||||
PermissionHashKey* entry = mPermissionTable.PutEntry(key);
|
||||
if (!entry) return NS_ERROR_FAILURE;
|
||||
if (!entry->GetKey()) {
|
||||
mHostTable.RawRemoveEntry(entry);
|
||||
mPermissionTable.RawRemoveEntry(entry);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
@ -580,7 +614,7 @@ nsPermissionManager::AddInternal(const nsAFlatCString &aHost,
|
||||
op = eOperationAdding;
|
||||
|
||||
} else {
|
||||
nsPermissionEntry oldPermissionEntry = entry->GetPermissions()[index];
|
||||
PermissionEntry oldPermissionEntry = entry->GetPermissions()[index];
|
||||
|
||||
// remove the permission if the permission is UNKNOWN, update the
|
||||
// permission if its value or expire type have changed OR if the time has
|
||||
@ -618,13 +652,24 @@ nsPermissionManager::AddInternal(const nsAFlatCString &aHost,
|
||||
id = aID;
|
||||
}
|
||||
|
||||
entry->GetPermissions().AppendElement(nsPermissionEntry(typeIndex, aPermission, id, aExpireType, aExpireTime));
|
||||
entry->GetPermissions().AppendElement(PermissionEntry(id, typeIndex, aPermission, aExpireType, aExpireTime));
|
||||
|
||||
if (aDBOperation == eWriteToDB && aExpireType != nsIPermissionManager::EXPIRE_SESSION)
|
||||
UpdateDB(op, mStmtInsert, id, aHost, aType, aPermission, aExpireType, aExpireTime);
|
||||
if (aDBOperation == eWriteToDB && aExpireType != nsIPermissionManager::EXPIRE_SESSION) {
|
||||
uint32_t appId;
|
||||
rv = aPrincipal->GetAppId(&appId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool isInBrowserElement;
|
||||
rv = aPrincipal->GetIsInBrowserElement(&isInBrowserElement);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
UpdateDB(op, mStmtInsert, id, host, aType, aPermission, aExpireType, aExpireTime, appId, isInBrowserElement);
|
||||
}
|
||||
|
||||
if (aNotifyOperation == eNotify) {
|
||||
NotifyObserversWithPermission(aHost,
|
||||
NotifyObserversWithPermission(host,
|
||||
entry->GetKey()->mAppId,
|
||||
entry->GetKey()->mIsInBrowserElement,
|
||||
mTypeArray[typeIndex],
|
||||
aPermission,
|
||||
aExpireType,
|
||||
@ -637,20 +682,24 @@ nsPermissionManager::AddInternal(const nsAFlatCString &aHost,
|
||||
|
||||
case eOperationRemoving:
|
||||
{
|
||||
nsPermissionEntry oldPermissionEntry = entry->GetPermissions()[index];
|
||||
PermissionEntry oldPermissionEntry = entry->GetPermissions()[index];
|
||||
id = oldPermissionEntry.mID;
|
||||
entry->GetPermissions().RemoveElementAt(index);
|
||||
|
||||
// If no more types are present, remove the entry
|
||||
if (entry->GetPermissions().IsEmpty())
|
||||
mHostTable.RawRemoveEntry(entry);
|
||||
mPermissionTable.RawRemoveEntry(entry);
|
||||
|
||||
if (aDBOperation == eWriteToDB)
|
||||
UpdateDB(op, mStmtDelete, id, EmptyCString(), EmptyCString(), 0,
|
||||
nsIPermissionManager::EXPIRE_NEVER, 0);
|
||||
// We care only about the id here so we pass dummy values for all other
|
||||
// parameters.
|
||||
UpdateDB(op, mStmtDelete, id, EmptyCString(), EmptyCString(), 0,
|
||||
nsIPermissionManager::EXPIRE_NEVER, 0, 0, false);
|
||||
|
||||
if (aNotifyOperation == eNotify) {
|
||||
NotifyObserversWithPermission(aHost,
|
||||
NotifyObserversWithPermission(host,
|
||||
entry->GetKey()->mAppId,
|
||||
entry->GetKey()->mIsInBrowserElement,
|
||||
mTypeArray[typeIndex],
|
||||
oldPermissionEntry.mPermission,
|
||||
oldPermissionEntry.mExpireType,
|
||||
@ -667,10 +716,15 @@ nsPermissionManager::AddInternal(const nsAFlatCString &aHost,
|
||||
entry->GetPermissions()[index].mPermission = aPermission;
|
||||
|
||||
if (aDBOperation == eWriteToDB && aExpireType != nsIPermissionManager::EXPIRE_SESSION)
|
||||
UpdateDB(op, mStmtUpdate, id, EmptyCString(), EmptyCString(), aPermission, aExpireType, aExpireTime);
|
||||
// We care only about the id, the permission and expireType/expireTime here.
|
||||
// We pass dummy values for all other parameters.
|
||||
UpdateDB(op, mStmtUpdate, id, EmptyCString(), EmptyCString(),
|
||||
aPermission, aExpireType, aExpireTime, 0, false);
|
||||
|
||||
if (aNotifyOperation == eNotify) {
|
||||
NotifyObserversWithPermission(aHost,
|
||||
NotifyObserversWithPermission(host,
|
||||
entry->GetKey()->mAppId,
|
||||
entry->GetKey()->mIsInBrowserElement,
|
||||
mTypeArray[typeIndex],
|
||||
aPermission,
|
||||
aExpireType,
|
||||
@ -689,12 +743,28 @@ NS_IMETHODIMP
|
||||
nsPermissionManager::Remove(const nsACString &aHost,
|
||||
const char *aType)
|
||||
{
|
||||
ENSURE_NOT_CHILD_PROCESS;
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
nsresult rv = GetPrincipal(aHost, getter_AddRefs(principal));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return RemoveFromPrincipal(principal, aType);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPermissionManager::RemoveFromPrincipal(nsIPrincipal* aPrincipal,
|
||||
const char* aType)
|
||||
{
|
||||
ENSURE_NOT_CHILD_PROCESS;
|
||||
NS_ENSURE_ARG_POINTER(aPrincipal);
|
||||
NS_ENSURE_ARG_POINTER(aType);
|
||||
|
||||
// System principals are never added to the database, no need to remove them.
|
||||
if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// AddInternal() handles removal, just let it do the work
|
||||
return AddInternal(PromiseFlatCString(aHost),
|
||||
return AddInternal(aPrincipal,
|
||||
nsDependentCString(aType),
|
||||
nsIPermissionManager::UNKNOWN_ACTION,
|
||||
0,
|
||||
@ -704,27 +774,6 @@ nsPermissionManager::Remove(const nsACString &aHost,
|
||||
eWriteToDB);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPermissionManager::RemoveFromPrincipal(nsIPrincipal* aPrincipal,
|
||||
const char* aType)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aPrincipal);
|
||||
|
||||
// System principals are never added to the database, no need to remove them.
|
||||
if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
aPrincipal->GetURI(getter_AddRefs(uri));
|
||||
NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
|
||||
|
||||
nsCAutoString host;
|
||||
uri->GetHost(host);
|
||||
|
||||
return Remove(host, aType);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPermissionManager::RemoveAll()
|
||||
{
|
||||
@ -786,35 +835,11 @@ nsPermissionManager::TestExactPermission(nsIURI *aURI,
|
||||
const char *aType,
|
||||
uint32_t *aPermission)
|
||||
{
|
||||
return CommonTestPermission(aURI, aType, aPermission, true);
|
||||
}
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
nsresult rv = GetPrincipal(aURI, getter_AddRefs(principal));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPermissionManager::TestPermission(nsIURI *aURI,
|
||||
const char *aType,
|
||||
uint32_t *aPermission)
|
||||
{
|
||||
return CommonTestPermission(aURI, aType, aPermission, false);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPermissionManager::TestPermissionFromPrincipal(nsIPrincipal* aPrincipal,
|
||||
const char* aType,
|
||||
uint32_t* aPermission)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aPrincipal);
|
||||
|
||||
// System principals do not have URI so we can't try to get
|
||||
// retro-compatibility here.
|
||||
if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
|
||||
*aPermission = nsIPermissionManager::ALLOW_ACTION;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
aPrincipal->GetURI(getter_AddRefs(uri));
|
||||
|
||||
return TestPermission(uri, aType, aPermission);
|
||||
return TestExactPermissionFromPrincipal(principal, aType, aPermission);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -831,31 +856,62 @@ nsPermissionManager::TestExactPermissionFromPrincipal(nsIPrincipal* aPrincipal,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
aPrincipal->GetURI(getter_AddRefs(uri));
|
||||
return CommonTestPermission(aPrincipal, aType, aPermission, true);
|
||||
}
|
||||
|
||||
return TestExactPermission(uri, aType, aPermission);
|
||||
NS_IMETHODIMP
|
||||
nsPermissionManager::TestPermission(nsIURI *aURI,
|
||||
const char *aType,
|
||||
uint32_t *aPermission)
|
||||
{
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
nsresult rv = GetPrincipal(aURI, getter_AddRefs(principal));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return TestPermissionFromPrincipal(principal, aType, aPermission);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPermissionManager::TestPermissionFromPrincipal(nsIPrincipal* aPrincipal,
|
||||
const char* aType,
|
||||
uint32_t* aPermission)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aPrincipal);
|
||||
|
||||
// System principals do not have URI so we can't try to get
|
||||
// retro-compatibility here.
|
||||
if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
|
||||
*aPermission = nsIPermissionManager::ALLOW_ACTION;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return CommonTestPermission(aPrincipal, aType, aPermission, false);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPermissionManager::CommonTestPermission(nsIURI *aURI,
|
||||
nsPermissionManager::CommonTestPermission(nsIPrincipal* aPrincipal,
|
||||
const char *aType,
|
||||
uint32_t *aPermission,
|
||||
bool aExactHostMatch)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aURI);
|
||||
NS_ENSURE_ARG_POINTER(aPrincipal);
|
||||
NS_ENSURE_ARG_POINTER(aType);
|
||||
|
||||
// set the default
|
||||
*aPermission = nsIPermissionManager::UNKNOWN_ACTION;
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCAutoString host;
|
||||
nsresult rv = GetHost(aURI, host);
|
||||
rv = GetHostForPrincipal(aPrincipal, host);
|
||||
|
||||
// No host doesn't mean an error. Just return the default. Unless this is
|
||||
// a file uri. In that case use a magic host.
|
||||
if (NS_FAILED(rv)) {
|
||||
bool isFile;
|
||||
rv = aURI->SchemeIs("file", &isFile);
|
||||
rv = uri->SchemeIs("file", &isFile);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (isFile) {
|
||||
host.AssignLiteral("<file>");
|
||||
@ -864,44 +920,74 @@ nsPermissionManager::CommonTestPermission(nsIURI *aURI,
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int32_t typeIndex = GetTypeIndex(aType, false);
|
||||
// If type == -1, the type isn't known,
|
||||
// so just return NS_OK
|
||||
if (typeIndex == -1) return NS_OK;
|
||||
|
||||
nsHostEntry *entry = GetHostEntry(host, typeIndex, aExactHostMatch);
|
||||
if (entry)
|
||||
uint32_t appId;
|
||||
rv = aPrincipal->GetAppId(&appId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool isInBrowserElement;
|
||||
rv = aPrincipal->GetIsInBrowserElement(&isInBrowserElement);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PermissionHashKey* entry = GetPermissionHashKey(host, appId, isInBrowserElement,
|
||||
typeIndex, aExactHostMatch);
|
||||
if (entry) {
|
||||
*aPermission = entry->GetPermission(typeIndex).mPermission;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Get hostentry for given host string and permission type.
|
||||
// walk up the domain if needed.
|
||||
// return null if nothing found.
|
||||
// Returns PermissionHashKey for a given { host, appId, isInBrowserElement } tuple.
|
||||
// This is not simply using PermissionKey because we will walk-up domains in
|
||||
// case of |host| contains sub-domains.
|
||||
// Returns null if nothing found.
|
||||
// Also accepts host on the format "<foo>". This will perform an exact match
|
||||
// lookup as the string doesn't contain any dots.
|
||||
nsHostEntry *
|
||||
nsPermissionManager::GetHostEntry(const nsAFlatCString &aHost,
|
||||
uint32_t aType,
|
||||
bool aExactHostMatch)
|
||||
nsPermissionManager::PermissionHashKey*
|
||||
nsPermissionManager::GetPermissionHashKey(const nsACString& aHost,
|
||||
uint32_t aAppId,
|
||||
bool aIsInBrowserElement,
|
||||
uint32_t aType,
|
||||
bool aExactHostMatch)
|
||||
{
|
||||
uint32_t offset = 0;
|
||||
nsHostEntry *entry;
|
||||
PermissionHashKey* entry;
|
||||
int64_t now = PR_Now() / 1000;
|
||||
|
||||
do {
|
||||
entry = mHostTable.GetEntry(aHost.get() + offset);
|
||||
nsRefPtr<PermissionKey> key = new PermissionKey(Substring(aHost, offset), aAppId, aIsInBrowserElement);
|
||||
entry = mPermissionTable.GetEntry(key);
|
||||
|
||||
if (!entry) {
|
||||
// This is a temporary fix to have Gaia working and allow a time frame to
|
||||
// update profiles. With this hack, if a permission isn't found for an app
|
||||
// the check will be done for the same host outside of any app.
|
||||
// TODO: remove this with bug 785632.
|
||||
key = new PermissionKey(Substring(aHost, offset), nsIScriptSecurityManager::NO_APP_ID, false);
|
||||
entry = mPermissionTable.GetEntry(key);
|
||||
}
|
||||
|
||||
if (entry) {
|
||||
nsPermissionEntry permEntry = entry->GetPermission(aType);
|
||||
PermissionEntry permEntry = entry->GetPermission(aType);
|
||||
|
||||
// if the entry is expired, remove and keep looking for others.
|
||||
if (permEntry.mExpireType == nsIPermissionManager::EXPIRE_TIME &&
|
||||
permEntry.mExpireTime <= now)
|
||||
Remove(aHost, mTypeArray[aType].get());
|
||||
else if (permEntry.mPermission != nsIPermissionManager::UNKNOWN_ACTION)
|
||||
permEntry.mExpireTime <= now) {
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
if (NS_FAILED(GetPrincipal(aHost, aAppId, aIsInBrowserElement, getter_AddRefs(principal)))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RemoveFromPrincipal(principal, mTypeArray[aType].get());
|
||||
} else if (permEntry.mPermission != nsIPermissionManager::UNKNOWN_ACTION) {
|
||||
break;
|
||||
}
|
||||
|
||||
// reset entry, to be able to return null on failure
|
||||
entry = nullptr;
|
||||
@ -929,14 +1015,16 @@ struct nsGetEnumeratorData
|
||||
};
|
||||
|
||||
static PLDHashOperator
|
||||
AddPermissionsToList(nsHostEntry *entry, void *arg)
|
||||
AddPermissionsToList(nsPermissionManager::PermissionHashKey* entry, void *arg)
|
||||
{
|
||||
nsGetEnumeratorData *data = static_cast<nsGetEnumeratorData *>(arg);
|
||||
|
||||
for (uint32_t i = 0; i < entry->GetPermissions().Length(); ++i) {
|
||||
nsPermissionEntry &permEntry = entry->GetPermissions()[i];
|
||||
nsPermissionManager::PermissionEntry& permEntry = entry->GetPermissions()[i];
|
||||
|
||||
nsPermission *perm = new nsPermission(entry->GetHost(),
|
||||
nsPermission *perm = new nsPermission(entry->GetKey()->mHost,
|
||||
entry->GetKey()->mAppId,
|
||||
entry->GetKey()->mIsInBrowserElement,
|
||||
data->types->ElementAt(permEntry.mType),
|
||||
permEntry.mPermission,
|
||||
permEntry.mExpireType,
|
||||
@ -954,7 +1042,7 @@ NS_IMETHODIMP nsPermissionManager::GetEnumerator(nsISimpleEnumerator **aEnum)
|
||||
nsCOMArray<nsIPermission> array;
|
||||
nsGetEnumeratorData data(&array, &mTypeArray);
|
||||
|
||||
mHostTable.EnumerateEntries(AddPermissionsToList, &data);
|
||||
mPermissionTable.EnumerateEntries(AddPermissionsToList, &data);
|
||||
|
||||
return NS_NewArrayEnumerator(aEnum, array);
|
||||
}
|
||||
@ -992,12 +1080,8 @@ nsPermissionManager::RemoveAllFromMemory()
|
||||
{
|
||||
mLargestID = 0;
|
||||
mTypeArray.Clear();
|
||||
mHostTable.Clear();
|
||||
if (gHostArena) {
|
||||
PL_FinishArenaPool(gHostArena);
|
||||
delete gHostArena;
|
||||
}
|
||||
gHostArena = nullptr;
|
||||
mPermissionTable.Clear();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1029,6 +1113,8 @@ nsPermissionManager::GetTypeIndex(const char *aType,
|
||||
// set into an nsIPermission.
|
||||
void
|
||||
nsPermissionManager::NotifyObserversWithPermission(const nsACString &aHost,
|
||||
uint32_t aAppId,
|
||||
bool aIsInBrowserElement,
|
||||
const nsCString &aType,
|
||||
uint32_t aPermission,
|
||||
uint32_t aExpireType,
|
||||
@ -1036,7 +1122,8 @@ nsPermissionManager::NotifyObserversWithPermission(const nsACString &aHost,
|
||||
const PRUnichar *aData)
|
||||
{
|
||||
nsCOMPtr<nsIPermission> permission =
|
||||
new nsPermission(aHost, aType, aPermission, aExpireType, aExpireTime);
|
||||
new nsPermission(aHost, aAppId, aIsInBrowserElement, aType, aPermission,
|
||||
aExpireType, aExpireTime);
|
||||
if (permission)
|
||||
NotifyObservers(permission, aData);
|
||||
}
|
||||
@ -1086,7 +1173,7 @@ nsPermissionManager::Read()
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT id, host, type, permission, expireType, expireTime "
|
||||
"SELECT id, host, type, permission, expireType, expireTime, appId, isInBrowserElement "
|
||||
"FROM moz_hosts"), getter_AddRefs(stmt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
@ -1095,6 +1182,8 @@ nsPermissionManager::Read()
|
||||
uint32_t permission;
|
||||
uint32_t expireType;
|
||||
int64_t expireTime;
|
||||
uint32_t appId;
|
||||
bool isInBrowserElement;
|
||||
bool hasResult;
|
||||
while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
|
||||
// explicitly set our entry id counter for use in AddInternal(),
|
||||
@ -1115,7 +1204,15 @@ nsPermissionManager::Read()
|
||||
// convert into int64_t value (milliseconds)
|
||||
expireTime = stmt->AsInt64(5);
|
||||
|
||||
rv = AddInternal(host, type, permission, id, expireType, expireTime,
|
||||
MOZ_ASSERT(stmt->AsInt64(6) >= 0);
|
||||
appId = static_cast<uint32_t>(stmt->AsInt64(6));
|
||||
isInBrowserElement = static_cast<bool>(stmt->AsInt32(7));
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
nsresult rv = GetPrincipal(host, appId, isInBrowserElement, getter_AddRefs(principal));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = AddInternal(principal, type, permission, id, expireType, expireTime,
|
||||
eDontNotify, eNoDBOperation);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
@ -1185,7 +1282,11 @@ nsPermissionManager::Import()
|
||||
continue;
|
||||
}
|
||||
|
||||
rv = AddInternal(lineArray[3], lineArray[1], permission, 0,
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
nsresult rv = GetPrincipal(lineArray[3], getter_AddRefs(principal));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = AddInternal(principal, lineArray[1], permission, 0,
|
||||
nsIPermissionManager::EXPIRE_NEVER, 0, eDontNotify, eWriteToDB);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
@ -1210,20 +1311,6 @@ nsPermissionManager::NormalizeToACE(nsCString &aHost)
|
||||
return mIDNService->ConvertUTF8toACE(aHost, aHost);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPermissionManager::GetHost(nsIURI *aURI, nsACString &aResult)
|
||||
{
|
||||
nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(aURI);
|
||||
if (!innerURI) return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv = innerURI->GetAsciiHost(aResult);
|
||||
|
||||
if (NS_FAILED(rv) || aResult.IsEmpty())
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsPermissionManager::UpdateDB(OperationType aOp,
|
||||
mozIStorageStatement* aStmt,
|
||||
@ -1232,7 +1319,9 @@ nsPermissionManager::UpdateDB(OperationType aOp,
|
||||
const nsACString &aType,
|
||||
uint32_t aPermission,
|
||||
uint32_t aExpireType,
|
||||
int64_t aExpireTime)
|
||||
int64_t aExpireTime,
|
||||
uint32_t aAppId,
|
||||
bool aIsInBrowserElement)
|
||||
{
|
||||
ENSURE_NOT_CHILD_PROCESS_NORET;
|
||||
|
||||
@ -1261,6 +1350,12 @@ nsPermissionManager::UpdateDB(OperationType aOp,
|
||||
if (NS_FAILED(rv)) break;
|
||||
|
||||
rv = aStmt->BindInt64ByIndex(5, aExpireTime);
|
||||
if (NS_FAILED(rv)) break;
|
||||
|
||||
rv = aStmt->BindInt64ByIndex(6, aAppId);
|
||||
if (NS_FAILED(rv)) break;
|
||||
|
||||
rv = aStmt->BindInt64ByIndex(7, aIsInBrowserElement);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include "nsTArray.h"
|
||||
#include "nsString.h"
|
||||
#include "nsPermission.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
class nsIPermission;
|
||||
class nsIIDNService;
|
||||
@ -24,107 +26,132 @@ class mozIStorageStatement;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class nsPermissionEntry
|
||||
{
|
||||
public:
|
||||
nsPermissionEntry(uint32_t aType, uint32_t aPermission, int64_t aID,
|
||||
uint32_t aExpireType, int64_t aExpireTime)
|
||||
: mType(aType)
|
||||
, mPermission(aPermission)
|
||||
, mID(aID)
|
||||
, mExpireType(aExpireType)
|
||||
, mExpireTime(aExpireTime) {}
|
||||
|
||||
uint32_t mType;
|
||||
uint32_t mPermission;
|
||||
int64_t mID;
|
||||
uint32_t mExpireType;
|
||||
int64_t mExpireTime;
|
||||
};
|
||||
|
||||
class nsHostEntry : public PLDHashEntryHdr
|
||||
{
|
||||
public:
|
||||
// Hash methods
|
||||
typedef const char* KeyType;
|
||||
typedef const char* KeyTypePointer;
|
||||
|
||||
nsHostEntry(const char* aHost);
|
||||
nsHostEntry(const nsHostEntry& toCopy);
|
||||
|
||||
~nsHostEntry()
|
||||
{
|
||||
}
|
||||
|
||||
KeyType GetKey() const
|
||||
{
|
||||
return mHost;
|
||||
}
|
||||
|
||||
bool KeyEquals(KeyTypePointer aKey) const
|
||||
{
|
||||
return !strcmp(mHost, aKey);
|
||||
}
|
||||
|
||||
static KeyTypePointer KeyToPointer(KeyType aKey)
|
||||
{
|
||||
return aKey;
|
||||
}
|
||||
|
||||
static PLDHashNumber HashKey(KeyTypePointer aKey)
|
||||
{
|
||||
// PL_DHashStringKey doesn't use the table parameter, so we can safely
|
||||
// pass nullptr
|
||||
return PL_DHashStringKey(nullptr, aKey);
|
||||
}
|
||||
|
||||
// force the hashtable to use the copy constructor when shuffling entries
|
||||
// around, otherwise the Auto part of our nsAutoTArray won't be happy!
|
||||
enum { ALLOW_MEMMOVE = false };
|
||||
|
||||
// Permissions methods
|
||||
inline const nsDependentCString GetHost() const
|
||||
{
|
||||
return nsDependentCString(mHost);
|
||||
}
|
||||
|
||||
inline nsTArray<nsPermissionEntry> & GetPermissions()
|
||||
{
|
||||
return mPermissions;
|
||||
}
|
||||
|
||||
inline int32_t GetPermissionIndex(uint32_t aType) const
|
||||
{
|
||||
for (uint32_t i = 0; i < mPermissions.Length(); ++i)
|
||||
if (mPermissions[i].mType == aType)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline nsPermissionEntry GetPermission(uint32_t aType) const
|
||||
{
|
||||
for (uint32_t i = 0; i < mPermissions.Length(); ++i)
|
||||
if (mPermissions[i].mType == aType)
|
||||
return mPermissions[i];
|
||||
|
||||
// unknown permission... return relevant data
|
||||
nsPermissionEntry unk = nsPermissionEntry(aType, nsIPermissionManager::UNKNOWN_ACTION,
|
||||
-1, nsIPermissionManager::EXPIRE_NEVER, 0);
|
||||
return unk;
|
||||
}
|
||||
|
||||
private:
|
||||
const char *mHost;
|
||||
nsAutoTArray<nsPermissionEntry, 1> mPermissions;
|
||||
};
|
||||
|
||||
|
||||
class nsPermissionManager : public nsIPermissionManager,
|
||||
public nsIObserver,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
class PermissionEntry
|
||||
{
|
||||
public:
|
||||
PermissionEntry(int64_t aID, uint32_t aType, uint32_t aPermission,
|
||||
uint32_t aExpireType, int64_t aExpireTime)
|
||||
: mID(aID)
|
||||
, mType(aType)
|
||||
, mPermission(aPermission)
|
||||
, mExpireType(aExpireType)
|
||||
, mExpireTime(aExpireTime)
|
||||
{}
|
||||
|
||||
int64_t mID;
|
||||
uint32_t mType;
|
||||
uint32_t mPermission;
|
||||
uint32_t mExpireType;
|
||||
int64_t mExpireTime;
|
||||
};
|
||||
|
||||
/**
|
||||
* PermissionKey is the key used by PermissionHashKey hash table.
|
||||
*
|
||||
* NOTE: It could be implementing nsIHashable but there is no reason to worry
|
||||
* with XPCOM interfaces while we don't need to.
|
||||
*/
|
||||
class PermissionKey
|
||||
{
|
||||
public:
|
||||
PermissionKey(nsIPrincipal* aPrincipal);
|
||||
PermissionKey(const nsACString& aHost,
|
||||
uint32_t aAppId,
|
||||
bool aIsInBrowserElement)
|
||||
: mHost(aHost)
|
||||
, mAppId(aAppId)
|
||||
, mIsInBrowserElement(aIsInBrowserElement)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const PermissionKey& aKey) const {
|
||||
return mHost.Equals(aKey.mHost) &&
|
||||
mAppId == aKey.mAppId &&
|
||||
mIsInBrowserElement == aKey.mIsInBrowserElement;
|
||||
}
|
||||
|
||||
PLDHashNumber GetHashCode() const {
|
||||
nsCAutoString str;
|
||||
str.Assign(mHost);
|
||||
str.AppendInt(mAppId);
|
||||
str.AppendInt(static_cast<int32_t>(mIsInBrowserElement));
|
||||
|
||||
return mozilla::HashString(str);
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PermissionKey);
|
||||
|
||||
nsCString mHost;
|
||||
uint32_t mAppId;
|
||||
bool mIsInBrowserElement;
|
||||
|
||||
private:
|
||||
// Default ctor shouldn't be used.
|
||||
PermissionKey() MOZ_DELETE;
|
||||
|
||||
// Dtor shouldn't be used outside of the class.
|
||||
~PermissionKey() {};
|
||||
};
|
||||
|
||||
class PermissionHashKey : public nsRefPtrHashKey<PermissionKey>
|
||||
{
|
||||
public:
|
||||
PermissionHashKey(const PermissionKey* aPermissionKey)
|
||||
: nsRefPtrHashKey<PermissionKey>(aPermissionKey)
|
||||
{}
|
||||
|
||||
PermissionHashKey(const PermissionHashKey& toCopy)
|
||||
: nsRefPtrHashKey<PermissionKey>(toCopy)
|
||||
, mPermissions(toCopy.mPermissions)
|
||||
{}
|
||||
|
||||
bool KeyEquals(const PermissionKey* aKey) const
|
||||
{
|
||||
return *aKey == *GetKey();
|
||||
}
|
||||
|
||||
static PLDHashNumber HashKey(const PermissionKey* aKey)
|
||||
{
|
||||
return aKey->GetHashCode();
|
||||
}
|
||||
|
||||
// Force the hashtable to use the copy constructor when shuffling entries
|
||||
// around, otherwise the Auto part of our nsAutoTArray won't be happy!
|
||||
enum { ALLOW_MEMMOVE = false };
|
||||
|
||||
inline nsTArray<PermissionEntry> & GetPermissions()
|
||||
{
|
||||
return mPermissions;
|
||||
}
|
||||
|
||||
inline int32_t GetPermissionIndex(uint32_t aType) const
|
||||
{
|
||||
for (uint32_t i = 0; i < mPermissions.Length(); ++i)
|
||||
if (mPermissions[i].mType == aType)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline PermissionEntry GetPermission(uint32_t aType) const
|
||||
{
|
||||
for (uint32_t i = 0; i < mPermissions.Length(); ++i)
|
||||
if (mPermissions[i].mType == aType)
|
||||
return mPermissions[i];
|
||||
|
||||
// unknown permission... return relevant data
|
||||
return PermissionEntry(-1, aType, nsIPermissionManager::UNKNOWN_ACTION,
|
||||
nsIPermissionManager::EXPIRE_NEVER, 0);
|
||||
}
|
||||
|
||||
private:
|
||||
nsAutoTArray<PermissionEntry, 1> mPermissions;
|
||||
};
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS
|
||||
@ -154,7 +181,7 @@ public:
|
||||
eNotify
|
||||
};
|
||||
|
||||
nsresult AddInternal(const nsAFlatCString &aHost,
|
||||
nsresult AddInternal(nsIPrincipal* aPrincipal,
|
||||
const nsAFlatCString &aType,
|
||||
uint32_t aPermission,
|
||||
int64_t aID,
|
||||
@ -164,15 +191,16 @@ public:
|
||||
DBOperationType aDBOperation);
|
||||
|
||||
private:
|
||||
|
||||
int32_t GetTypeIndex(const char *aTypeString,
|
||||
bool aAdd);
|
||||
|
||||
nsHostEntry *GetHostEntry(const nsAFlatCString &aHost,
|
||||
uint32_t aType,
|
||||
bool aExactHostMatch);
|
||||
PermissionHashKey* GetPermissionHashKey(const nsACString& aHost,
|
||||
uint32_t aAppId,
|
||||
bool aIsInBrowserElement,
|
||||
uint32_t aType,
|
||||
bool aExactHostMatch);
|
||||
|
||||
nsresult CommonTestPermission(nsIURI *aURI,
|
||||
nsresult CommonTestPermission(nsIPrincipal* aPrincipal,
|
||||
const char *aType,
|
||||
uint32_t *aPermission,
|
||||
bool aExactHostMatch);
|
||||
@ -182,6 +210,8 @@ private:
|
||||
nsresult Import();
|
||||
nsresult Read();
|
||||
void NotifyObserversWithPermission(const nsACString &aHost,
|
||||
uint32_t aAppId,
|
||||
bool aIsInBrowserElement,
|
||||
const nsCString &aType,
|
||||
uint32_t aPermission,
|
||||
uint32_t aExpireType,
|
||||
@ -196,7 +226,6 @@ private:
|
||||
nsresult RemoveAllInternal(bool aNotifyObservers);
|
||||
nsresult RemoveAllFromMemory();
|
||||
nsresult NormalizeToACE(nsCString &aHost);
|
||||
nsresult GetHost(nsIURI *aURI, nsACString &aResult);
|
||||
static void UpdateDB(OperationType aOp,
|
||||
mozIStorageStatement* aStmt,
|
||||
int64_t aID,
|
||||
@ -204,7 +233,9 @@ private:
|
||||
const nsACString &aType,
|
||||
uint32_t aPermission,
|
||||
uint32_t aExpireType,
|
||||
int64_t aExpireTime);
|
||||
int64_t aExpireTime,
|
||||
uint32_t aAppId,
|
||||
bool aIsInBrowserElement);
|
||||
|
||||
nsCOMPtr<nsIObserverService> mObserverService;
|
||||
nsCOMPtr<nsIIDNService> mIDNService;
|
||||
@ -214,7 +245,7 @@ private:
|
||||
nsCOMPtr<mozIStorageStatement> mStmtDelete;
|
||||
nsCOMPtr<mozIStorageStatement> mStmtUpdate;
|
||||
|
||||
nsTHashtable<nsHostEntry> mHostTable;
|
||||
nsTHashtable<PermissionHashKey> mPermissionTable;
|
||||
// a unique, monotonically increasing id used to identify each database entry
|
||||
int64_t mLargestID;
|
||||
|
||||
|
@ -52,6 +52,10 @@ MOCHITEST_FILES = \
|
||||
file_loopback_inner.html \
|
||||
$(NULL)
|
||||
|
||||
MOCHITEST_CHROME_FILES = \
|
||||
test_permissionmanager_app_isolation.html \
|
||||
$(NULL)
|
||||
|
||||
MOCHITEST_BROWSER_FILES = \
|
||||
browser_test_favicon.js \
|
||||
$(NULL)
|
||||
|
168
extensions/cookie/test/test_permissionmanager_app_isolation.html
Normal file
168
extensions/cookie/test/test_permissionmanager_app_isolation.html
Normal file
@ -0,0 +1,168 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=758258
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for nsIPrincipal extendedOrigin, appStatus and appId</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=758258">Mozilla Bug 758258</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
/** Test for Bug 758258 **/
|
||||
|
||||
var Ci = Components.interfaces;
|
||||
var Cc = Components.classes;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var permManager = Cc["@mozilla.org/permissionmanager;1"]
|
||||
.getService(Ci.nsIPermissionManager);
|
||||
|
||||
const gPermName = 'foobar';
|
||||
|
||||
var previousPrefs = {
|
||||
mozBrowserFramesEnabled: undefined,
|
||||
};
|
||||
|
||||
try {
|
||||
previousPrefs.mozBrowserFramesEnabled = SpecialPowers.getBoolPref('dom.mozBrowserFramesEnabled');
|
||||
} catch(e)
|
||||
{
|
||||
}
|
||||
|
||||
SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', true);
|
||||
|
||||
// We use http://test/ as url so all apps use the same url and app isolation is
|
||||
// more obvious.
|
||||
var gData = [
|
||||
// APP 1
|
||||
{
|
||||
app: 'http://example.org/manifest.webapp',
|
||||
action: 'read-no',
|
||||
src: 'http://test/',
|
||||
},
|
||||
{
|
||||
app: 'http://example.org/manifest.webapp',
|
||||
action: 'write',
|
||||
src: 'http://test/',
|
||||
},
|
||||
{
|
||||
app: 'http://example.org/manifest.webapp',
|
||||
action: 'read-yes',
|
||||
src: 'http://test/',
|
||||
},
|
||||
// APP 2
|
||||
{
|
||||
app: 'https://example.com/manifest.webapp',
|
||||
action: 'read-no',
|
||||
src: 'http://test/',
|
||||
},
|
||||
{
|
||||
app: 'https://example.com/manifest.webapp',
|
||||
action: 'write',
|
||||
src: 'http://test/',
|
||||
},
|
||||
{
|
||||
app: 'https://example.com/manifest.webapp',
|
||||
action: 'read-yes',
|
||||
src: 'http://test/',
|
||||
},
|
||||
// Browser
|
||||
{
|
||||
browser: true,
|
||||
action: 'read-no',
|
||||
src: 'http://test/',
|
||||
},
|
||||
{
|
||||
browser: true,
|
||||
action: 'write',
|
||||
src: 'http://test/',
|
||||
},
|
||||
{
|
||||
browser: true,
|
||||
action: 'read-yes',
|
||||
src: 'http://test/',
|
||||
},
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
for (var i in gData) {
|
||||
var iframe = document.createElement('iframe');
|
||||
var data = gData[i];
|
||||
|
||||
if (data.app) {
|
||||
iframe.setAttribute('mozbrowser', '');
|
||||
iframe.setAttribute('mozapp', data.app);
|
||||
} else if (data.browser) {
|
||||
iframe.setAttribute('mozbrowser', '');
|
||||
}
|
||||
|
||||
if (data.app || data.browser) {
|
||||
iframe.addEventListener('load', function(e) {
|
||||
var principal = iframe.contentDocument.nodePrincipal;
|
||||
|
||||
switch (data.action) {
|
||||
case 'read-no':
|
||||
is(permManager.testPermissionFromPrincipal(principal, gPermName),
|
||||
Ci.nsIPermissionManager.UNKNOWN_ACTION,
|
||||
"Permission should not be set yet");
|
||||
is(permManager.testExactPermissionFromPrincipal(principal, gPermName),
|
||||
Ci.nsIPermissionManager.UNKNOWN_ACTION,
|
||||
"Permission should not be set yet");
|
||||
break;
|
||||
case 'write':
|
||||
permManager.addFromPrincipal(principal, gPermName, Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
break;
|
||||
case 'read-yes':
|
||||
is(permManager.testPermissionFromPrincipal(principal, gPermName),
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||
"Permission should be set");
|
||||
is(permManager.testExactPermissionFromPrincipal(principal, gPermName),
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||
"Permission should be set");
|
||||
break;
|
||||
default:
|
||||
ok(false, "shouldn't be there");
|
||||
}
|
||||
|
||||
// Calling removeChild() produces an error that creates failures.
|
||||
//document.getElementById('content').removeChild(iframe);
|
||||
|
||||
i++;
|
||||
if (i >= gData.length) {
|
||||
if (previousPrefs.mozBrowserFramesEnabled !== undefined) {
|
||||
SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', previousPrefs.mozBrowserFramesEnabled);
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
} else {
|
||||
gTestRunner.next();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
iframe.src = data.src;
|
||||
|
||||
document.getElementById('content').appendChild(iframe);
|
||||
|
||||
yield;
|
||||
}
|
||||
}
|
||||
|
||||
var gTestRunner = runTest();
|
||||
gTestRunner.next();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
52
js/src/jit-test/lib/parallelarray-helpers.js
Normal file
52
js/src/jit-test/lib/parallelarray-helpers.js
Normal file
@ -0,0 +1,52 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
load(libdir + "eqArrayHelper.js");
|
||||
|
||||
function assertEqParallelArray(a, b) {
|
||||
assertEq(a instanceof ParallelArray, true);
|
||||
assertEq(b instanceof ParallelArray, true);
|
||||
|
||||
var shape = a.shape;
|
||||
assertEqArray(shape, b.shape);
|
||||
|
||||
function bump(indices) {
|
||||
var d = indices.length - 1;
|
||||
while (d >= 0) {
|
||||
if (++indices[d] < shape[d])
|
||||
break;
|
||||
indices[d] = 0;
|
||||
d--;
|
||||
}
|
||||
return d >= 0;
|
||||
}
|
||||
|
||||
var iv = shape.map(function () { return 0; });
|
||||
do {
|
||||
var e1 = a.get(iv);
|
||||
var e2 = b.get(iv);
|
||||
if (e1 instanceof ParallelArray && e2 instanceof ParallelArray)
|
||||
assertEqParallelArray(e1, e2);
|
||||
else if (e1 instanceof Array && e2 instanceof Array)
|
||||
assertEqArray(e1, e2);
|
||||
else
|
||||
assertEq(e1, e2);
|
||||
} while (bump(iv));
|
||||
}
|
||||
|
||||
function assertParallelArrayModesCommute(modes, pa, op) {
|
||||
var args = Array.slice(arguments, 3);
|
||||
var acc;
|
||||
modes.forEach(function (mode) {
|
||||
var result = op.apply(pa, args.concat([{ mode: mode, expect: "success" }]));
|
||||
if (acc) {
|
||||
if (acc instanceof ParallelArray)
|
||||
assertEqParallelArray(acc, result);
|
||||
else
|
||||
assertEq(acc, result);
|
||||
} else {
|
||||
acc = result;
|
||||
}
|
||||
});
|
||||
}
|
@ -1,9 +1,10 @@
|
||||
load(libdir + "parallelarray-helpers.js")
|
||||
|
||||
function buildComprehension() {
|
||||
// 1D comprehension
|
||||
// 1D comprehension
|
||||
var p = new ParallelArray(10, function (idx) { return idx; });
|
||||
var a = [0,1,2,3,4,5,6,7,8,9];
|
||||
assertEq(p.toString(), "<" + a.join(",") + ">");
|
||||
var a = new ParallelArray([0,1,2,3,4,5,6,7,8,9]);
|
||||
assertEqParallelArray(p, a);
|
||||
}
|
||||
|
||||
buildComprehension();
|
||||
|
@ -1,9 +1,12 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
load(libdir + "eqArrayHelper.js");
|
||||
|
||||
function buildMultidim() {
|
||||
// 2D comprehension
|
||||
var p = new ParallelArray([2,2], function (i,j) { return i + j; });
|
||||
assertEq(p.shape.toString(), [2,2].toString());
|
||||
assertEq(p.toString(), "<<0,1>,<1,2>>");
|
||||
var a = new ParallelArray([0,1,1,2]).partition(2);
|
||||
assertEqArray(p.shape, [2,2]);
|
||||
assertEqParallelArray(p, a);
|
||||
}
|
||||
|
||||
buildMultidim();
|
||||
|
@ -1,3 +1,4 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function buildComprehension() {
|
||||
var H = 96;
|
||||
@ -5,27 +6,16 @@ function buildComprehension() {
|
||||
var d = 4;
|
||||
// 3D 96x96x4 texture-like PA
|
||||
var p = new ParallelArray([H,W,d], function (i,j,k) { return i + j + k; });
|
||||
var a = "<";
|
||||
var a = [];
|
||||
for (var i = 0; i < H; i++) {
|
||||
a += "<";
|
||||
for (var j = 0; j < W; j++) {
|
||||
a += "<";
|
||||
for (var k = 0; k < d; k++) {
|
||||
a += i+j+k;
|
||||
if (k !== d - 1)
|
||||
a += ",";
|
||||
a.push(i+j+k);
|
||||
}
|
||||
a += ">";
|
||||
if (j !== W - 1)
|
||||
a += ","
|
||||
}
|
||||
a += ">";
|
||||
if (i !== H - 1)
|
||||
a += ","
|
||||
}
|
||||
a += ">"
|
||||
|
||||
assertEq(p.toString(), a);
|
||||
var p2 = new ParallelArray(a).partition(d).partition(H);
|
||||
assertEqParallelArray(p, p2);
|
||||
}
|
||||
|
||||
buildComprehension();
|
||||
|
@ -1,16 +1,14 @@
|
||||
function bracket(s) {
|
||||
return "<" + s + ">";
|
||||
}
|
||||
load(libdir + "eqArrayHelper.js");
|
||||
|
||||
function buildSimple() {
|
||||
// Simple constructor
|
||||
var a = [1,2,3,4,5];
|
||||
var p = new ParallelArray(a);
|
||||
var e = a.join(",");
|
||||
assertEq(p.toString(), bracket(e));
|
||||
assertEqArray(p, a);
|
||||
var a2 = a.slice();
|
||||
a[0] = 9;
|
||||
// No sharing
|
||||
assertEq(p.toString(), bracket(e));
|
||||
assertEqArray(p, a2);
|
||||
}
|
||||
|
||||
buildSimple();
|
||||
|
@ -1,9 +1,10 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function buildPA() {
|
||||
// Construct copying from PA
|
||||
var p1 = new ParallelArray([1,2,3,4]);
|
||||
var p2 = new ParallelArray(p1);
|
||||
assertEq(p1.toString(), p2.toString());
|
||||
assertEqParallelArray(p1, p2);
|
||||
var p1d = new ParallelArray([2,2], function(i,j) { return i + j; });
|
||||
var p2d = new ParallelArray(p1d);
|
||||
assertEq(p1d.toString(), p2d.toString());
|
||||
|
@ -1,7 +1,10 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testElement() {
|
||||
// Test getting element from higher dimension
|
||||
var p = new ParallelArray([2,2,2], function () { return 0; });
|
||||
assertEq(p[0].toString(), "<<0,0>,<0,0>>");
|
||||
var p0 = new ParallelArray([2,2], function () { return 0; });
|
||||
assertEqParallelArray(p[0], p0);
|
||||
// Should create new wrapper
|
||||
assertEq(p[0] !== p[0], true);
|
||||
// Test out of bounds
|
||||
|
@ -1,13 +1,14 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testFilterAll() {
|
||||
// Test filtering everything (leaving everything in)
|
||||
var p = new ParallelArray([0,1,2,3,4]);
|
||||
var all = p.map(function (i) { return true; });
|
||||
var r = p.filter(all);
|
||||
assertEq(r.toString(), "<0,1,2,3,4>");
|
||||
assertEqParallelArray(r, p);
|
||||
var p = new ParallelArray([5,2], function(i,j) { return i+j; });
|
||||
var r = p.filter(all);
|
||||
assertEq(r.toString(), "<<0,1>,<1,2>,<2,3>,<3,4>,<4,5>>");
|
||||
assertEqParallelArray(r, new ParallelArray(p));
|
||||
}
|
||||
|
||||
testFilterAll();
|
||||
|
@ -1,12 +1,14 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testFilterNone() {
|
||||
// Test filtering (removing everything)
|
||||
var p = new ParallelArray([0,1,2,3,4]);
|
||||
var none = p.map(function () { return false; });
|
||||
var r = p.filter(none);
|
||||
assertEq(r.toString(), "<>");
|
||||
assertEqParallelArray(r, new ParallelArray);
|
||||
var p = new ParallelArray([5,2], function(i,j) { return i+j; });
|
||||
var r = p.filter(none);
|
||||
assertEq(r.toString(), "<>");
|
||||
assertEqParallelArray(r, new ParallelArray);
|
||||
}
|
||||
|
||||
testFilterNone();
|
||||
|
@ -1,16 +1,14 @@
|
||||
function bracket(s) {
|
||||
return "<" + s + ">";
|
||||
}
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testFilterSome() {
|
||||
var p = new ParallelArray([0,1,2,3,4]);
|
||||
var evenBelowThree = p.map(function (i) { return ((i%2) === 0) && (i < 3); });
|
||||
var r = p.filter(evenBelowThree);
|
||||
assertEq(r.toString(), bracket([0,2].join(",")));
|
||||
assertEqParallelArray(r, new ParallelArray([0,2]));
|
||||
var p = new ParallelArray([5,2], function (i,j) { return i; });
|
||||
var evenBelowThree = p.map(function (i) { return ((i[0]%2) === 0) && (i[0] < 3); });
|
||||
var r = p.filter(evenBelowThree);
|
||||
assertEq(r.toString(), bracket(["<0,0>","<2,2>"].join(",")));
|
||||
assertEqParallelArray(r, new ParallelArray([p[0], p[2]]));
|
||||
}
|
||||
|
||||
testFilterSome();
|
||||
|
@ -1,18 +1,16 @@
|
||||
function bracket(s) {
|
||||
return "<" + s + ">";
|
||||
}
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testFilterMisc() {
|
||||
var p = new ParallelArray([0,1,2]);
|
||||
// Test array
|
||||
var r = p.filter([true, false, true]);
|
||||
assertEq(r.toString(), bracket([0,2].join(",")));
|
||||
assertEqParallelArray(r, new ParallelArray([p[0], p[2]]));
|
||||
// Test array-like
|
||||
var r = p.filter({ 0: true, 1: false, 2: true, length: 3 });
|
||||
assertEq(r.toString(), bracket([0,2].join(",")));
|
||||
assertEqParallelArray(r, new ParallelArray([p[0], p[2]]));
|
||||
// Test truthy
|
||||
var r = p.filter([1, "", {}]);
|
||||
assertEq(r.toString(), bracket([0,2].join(",")));
|
||||
assertEqParallelArray(r, new ParallelArray([p[0], p[2]]));
|
||||
}
|
||||
|
||||
testFilterMisc();
|
||||
|
@ -1,10 +1,12 @@
|
||||
load(libdir + "eqArrayHelper.js");
|
||||
|
||||
function testFlatten() {
|
||||
var shape = [5];
|
||||
for (var i = 0; i < 7; i++) {
|
||||
shape.push(i+1);
|
||||
var p = new ParallelArray(shape, function(i,j) { return i+j; });
|
||||
var flatShape = ([shape[0] * shape[1]]).concat(shape.slice(2));
|
||||
assertEq(p.flatten().shape.toString(), flatShape.toString());
|
||||
assertEqArray(p.flatten().shape, flatShape);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testFlatten() {
|
||||
var p = new ParallelArray([2,2], function(i,j) { return i+j; });
|
||||
var p2 = new ParallelArray([0,1,1,2]);
|
||||
assertEq(p.flatten().toString(), p2.toString());
|
||||
assertEqParallelArray(p.flatten(), p2);
|
||||
}
|
||||
|
||||
testFlatten();
|
||||
|
@ -1,10 +1,12 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testGet() {
|
||||
var p = new ParallelArray([2,2,2], function(i,j,k) { return i+j+k; });
|
||||
assertEq(p.get([1,1,1]), 1+1+1);
|
||||
var p2 = new ParallelArray([2], function(i) { return 1+1+i; });
|
||||
assertEq(p.get([1,1]).toString(), p2.toString());
|
||||
assertEqParallelArray(p.get([1,1]), p2);
|
||||
var p3 = new ParallelArray([2,2], function(i,j) { return 1+i+j; });
|
||||
assertEq(p.get([1]).toString(), p3.toString());
|
||||
assertEqParallelArray(p.get([1]), p3);
|
||||
}
|
||||
|
||||
testGet();
|
||||
|
@ -1,11 +1,10 @@
|
||||
function bracket(s) {
|
||||
return "<" + s + ">";
|
||||
}
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testMap() {
|
||||
var p = new ParallelArray([0,1,2,3,4]);
|
||||
var m = p.map(function (v) { return v+1; });
|
||||
assertEq(m.toString(), bracket([1,2,3,4,5].join(",")));
|
||||
var p = new ParallelArray([0,1,2,3,4]);
|
||||
var m = p.map(function (v) { return v+1; });
|
||||
var p2 = new ParallelArray([1,2,3,4,5]);
|
||||
assertEqParallelArray(m, p2);
|
||||
}
|
||||
|
||||
testMap();
|
||||
|
@ -1,8 +1,11 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testMap() {
|
||||
// Test mapping higher dimensional
|
||||
var p = new ParallelArray([2,2], function (i,j) { return i+j; });
|
||||
var m = p.map(function(x) { return x.toString(); });
|
||||
assertEq(m.toString(), "<<0,1>,<1,2>>");
|
||||
var m = p.map(function(x) { return x; });
|
||||
var p2 = new ParallelArray(p);
|
||||
assertEqParallelArray(m, p2);
|
||||
}
|
||||
|
||||
testMap();
|
||||
|
@ -1,12 +1,14 @@
|
||||
load(libdir + "eqArrayHelper.js");
|
||||
|
||||
function testPartition() {
|
||||
var p = new ParallelArray([1,2,3,4,5,6,7,8]);
|
||||
var pp = p.partition(2);
|
||||
var ppp = pp.partition(2);
|
||||
var ppShape = [p.shape[0] / 2, 2].concat(p.shape.slice(1));
|
||||
var pppShape = [pp.shape[0] / 2, 2].concat(pp.shape.slice(1));
|
||||
assertEq(pp.shape.toString(), ppShape.toString())
|
||||
assertEqArray(pp.shape, ppShape);
|
||||
assertEq(pp.toString(), "<<1,2>,<3,4>,<5,6>,<7,8>>");
|
||||
assertEq(ppp.shape.toString(), pppShape.toString())
|
||||
assertEqArray(ppp.shape, pppShape);
|
||||
assertEq(ppp.toString(), "<<<1,2>,<3,4>>,<<5,6>,<7,8>>>");
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ function testScan() {
|
||||
var r = p.reduce(f);
|
||||
var s = p.scan(f)
|
||||
for (var j = 0; j < s.length; j++)
|
||||
assertEq(s[0].shape.length, i + 1);
|
||||
assertEq(s[j].shape.length, i + 1);
|
||||
assertEq(r.shape.length, i + 1);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testScatterIdentity() {
|
||||
var p = new ParallelArray([1,2,3,4,5]);
|
||||
var r = p.scatter([0,1,2,3,4]);
|
||||
assertEq(p.toString(), r.toString());
|
||||
assertEqParallelArray(p, r);
|
||||
}
|
||||
|
||||
testScatterIdentity();
|
||||
|
@ -1,9 +1,10 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testScatter() {
|
||||
var p = new ParallelArray([1,2,3,4,5]);
|
||||
var r = p.scatter([1,0,3,2,4]);
|
||||
var p2 = new ParallelArray([2,1,4,3,5]);
|
||||
assertEq(r.toString(), p2.toString());
|
||||
assertEqParallelArray(r, p2);
|
||||
}
|
||||
|
||||
testScatter();
|
||||
|
@ -1,11 +1,9 @@
|
||||
function bracket(s) {
|
||||
return "<" + s + ">";
|
||||
}
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testScatterDefault() {
|
||||
var p = new ParallelArray([1,2,3,4,5]);
|
||||
var r = p.scatter([0,2,4], 9);
|
||||
assertEq(r.toString(), bracket([1,9,2,9,3].join(",")));
|
||||
assertEqParallelArray(r, new ParallelArray([1,9,2,9,3]));
|
||||
}
|
||||
|
||||
testScatterDefault();
|
||||
|
@ -1,11 +1,9 @@
|
||||
function bracket(s) {
|
||||
return "<" + s + ">";
|
||||
}
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testScatterConflict() {
|
||||
var p = new ParallelArray([1,2,3,4,5]);
|
||||
var r = p.scatter([0,1,0,3,4], 9, function (a,b) { return a+b; });
|
||||
assertEq(r.toString(), bracket([4,2,9,4,5].join(",")));
|
||||
var p = new ParallelArray([1,2,3,4,5]);
|
||||
var r = p.scatter([0,1,0,3,4], 9, function (a,b) { return a+b; });
|
||||
assertEqParallelArray(r, new ParallelArray([4,2,9,4,5]));
|
||||
}
|
||||
|
||||
testScatterConflict();
|
||||
|
@ -1,3 +1,4 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testScatterIdentity() {
|
||||
var shape = [5];
|
||||
@ -5,7 +6,8 @@ function testScatterIdentity() {
|
||||
shape.push(i+1);
|
||||
var p = new ParallelArray(shape, function(k) { return k; });
|
||||
var r = p.scatter([0,1,2,3,4]);
|
||||
assertEq(p.toString(), r.toString());
|
||||
var p2 = new ParallelArray([p[0], p[1], p[2], p[3], p[4]]);
|
||||
assertEqParallelArray(p2, r);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testScatter() {
|
||||
var shape = [5];
|
||||
@ -6,7 +7,7 @@ function testScatter() {
|
||||
var p = new ParallelArray(shape, function(k) { return k; });
|
||||
var r = p.scatter([1,0,3,2,4]);
|
||||
var p2 = new ParallelArray([p[1], p[0], p[3], p[2], p[4]]);
|
||||
assertEq(p2.toString(), r.toString());
|
||||
assertEqParallelArray(p2, r);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testScatter() {
|
||||
// Ignore the rest of the scatter vector if longer than source
|
||||
var p = new ParallelArray([1,2,3,4,5]);
|
||||
var r = p.scatter([1,0,3,2,4,1,2,3]);
|
||||
var p2 = new ParallelArray([2,1,4,3,5]);
|
||||
assertEq(r.toString(), p2.toString());
|
||||
assertEqParallelArray(r, p2);
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
load(libdir + "eqArrayHelper.js");
|
||||
|
||||
function testShape() {
|
||||
// Test higher dimension shape up to 8D
|
||||
var shape = [];
|
||||
@ -7,7 +9,7 @@ function testShape() {
|
||||
// Test shape identity and shape
|
||||
assertEq(p.shape, p.shape);
|
||||
assertEq(p.shape !== shape, true);
|
||||
assertEq(p.shape.toString(), shape.toString());
|
||||
assertEqArray(p.shape, shape);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(5036f0f6-f77b-4168-9d57-a1c0dd66cf02)]
|
||||
[scriptable, uuid(cfb08e46-193c-4be7-a467-d7775fb2a31e)]
|
||||
/**
|
||||
* This interface defines a "permission" object,
|
||||
* used to specify allowed/blocked objects from
|
||||
@ -20,6 +20,16 @@ interface nsIPermission : nsISupports
|
||||
*/
|
||||
readonly attribute AUTF8String host;
|
||||
|
||||
/**
|
||||
* The id of the app for which the permission is set.
|
||||
*/
|
||||
readonly attribute unsigned long appId;
|
||||
|
||||
/**
|
||||
* Whether the permission has been set to a page inside a browser element.
|
||||
*/
|
||||
readonly attribute boolean isInBrowserElement;
|
||||
|
||||
/**
|
||||
* a case-sensitive ASCII string, indicating the type of permission
|
||||
* (e.g., "cookie", "image", etc).
|
||||
|
@ -20,9 +20,13 @@ struct Permission
|
||||
nsCString host, type;
|
||||
uint32_t capability, expireType;
|
||||
int64_t expireTime;
|
||||
uint32_t appId;
|
||||
bool isInBrowserElement;
|
||||
|
||||
Permission() { }
|
||||
Permission(const nsCString& aHost,
|
||||
const uint32_t aAppId,
|
||||
const bool aIsInBrowserElement,
|
||||
const nsCString& aType,
|
||||
const uint32_t aCapability,
|
||||
const uint32_t aExpireType,
|
||||
@ -30,7 +34,10 @@ struct Permission
|
||||
type(aType),
|
||||
capability(aCapability),
|
||||
expireType(aExpireType),
|
||||
expireTime(aExpireTime) { }
|
||||
expireTime(aExpireTime),
|
||||
appId(aAppId),
|
||||
isInBrowserElement(aIsInBrowserElement)
|
||||
{}
|
||||
};
|
||||
|
||||
template<>
|
||||
@ -43,6 +50,8 @@ struct ParamTraits<Permission>
|
||||
WriteParam(aMsg, aParam.capability);
|
||||
WriteParam(aMsg, aParam.expireType);
|
||||
WriteParam(aMsg, aParam.expireTime);
|
||||
WriteParam(aMsg, aParam.appId);
|
||||
WriteParam(aMsg, aParam.isInBrowserElement);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, Permission* aResult)
|
||||
@ -51,12 +60,26 @@ struct ParamTraits<Permission>
|
||||
ReadParam(aMsg, aIter, &aResult->type) &&
|
||||
ReadParam(aMsg, aIter, &aResult->capability) &&
|
||||
ReadParam(aMsg, aIter, &aResult->expireType) &&
|
||||
ReadParam(aMsg, aIter, &aResult->expireTime);
|
||||
ReadParam(aMsg, aIter, &aResult->expireTime) &&
|
||||
ReadParam(aMsg, aIter, &aResult->appId) &&
|
||||
ReadParam(aMsg, aIter, &aResult->isInBrowserElement);
|
||||
}
|
||||
|
||||
static void Log(const Permission& aParam, std::wstring* aLog)
|
||||
static void Log(const Permission& p, std::wstring* l)
|
||||
{
|
||||
aLog->append(StringPrintf(L"[%s]", aParam.host.get()));
|
||||
l->append(L"(");
|
||||
LogParam(p.host, l);
|
||||
l->append(L", ");
|
||||
LogParam(p.appId, l);
|
||||
l->append(L", ");
|
||||
LogParam(p.isInBrowserElement, l);
|
||||
l->append(L", ");
|
||||
LogParam(p.capability, l);
|
||||
l->append(L", ");
|
||||
LogParam(p.expireTime, l);
|
||||
l->append(L", ");
|
||||
LogParam(p.expireType, l);
|
||||
l->append(L")");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -231,6 +231,9 @@ class Permissions(object):
|
||||
# Open database and create table
|
||||
permDB = sqlite3.connect(os.path.join(self._profileDir, "permissions.sqlite"))
|
||||
cursor = permDB.cursor();
|
||||
|
||||
cursor.execute("PRAGMA user_version=3");
|
||||
|
||||
# SQL copied from
|
||||
# http://mxr.mozilla.org/mozilla-central/source/extensions/cookie/nsPermissionManager.cpp
|
||||
cursor.execute("""CREATE TABLE IF NOT EXISTS moz_hosts (
|
||||
@ -239,7 +242,9 @@ class Permissions(object):
|
||||
type TEXT,
|
||||
permission INTEGER,
|
||||
expireType INTEGER,
|
||||
expireTime INTEGER)""")
|
||||
expireTime INTEGER,
|
||||
appId INTEGER,
|
||||
isInBrowserElement INTEGER)""")
|
||||
|
||||
for location in locations:
|
||||
# set the permissions
|
||||
@ -250,7 +255,7 @@ class Permissions(object):
|
||||
permission_type = 1
|
||||
else:
|
||||
permission_type = 2
|
||||
cursor.execute("INSERT INTO moz_hosts values(?, ?, ?, ?, 0, 0)",
|
||||
cursor.execute("INSERT INTO moz_hosts values(?, ?, ?, ?, 0, 0, 0, 0)",
|
||||
(self._num_permissions, location.host, perm,
|
||||
permission_type))
|
||||
|
||||
|
@ -165,7 +165,7 @@ endif
|
||||
#
|
||||
# OpenBSD/ARM
|
||||
#
|
||||
ifneq (,$(filter OpenBSDarmish OpenBSDzaurus,$(OS_ARCH)$(OS_TEST)))
|
||||
ifeq ($(OS_ARCH)$(OS_TEST),OpenBSDarm)
|
||||
CPPSRCS := xptcinvoke_arm_openbsd.cpp xptcstubs_arm_openbsd.cpp
|
||||
endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user