зеркало из https://github.com/mozilla/gecko-dev.git
Merge fx-team to m-c. a=merge
This commit is contained in:
Коммит
289a16635a
|
@ -42,31 +42,7 @@ rdf/**
|
|||
security/**
|
||||
services/**
|
||||
startupcache/**
|
||||
storage/**
|
||||
testing/**
|
||||
toolkit/components/**
|
||||
toolkit/content/**
|
||||
toolkit/crashreporter/**
|
||||
toolkit/forgetaboutsite/**
|
||||
toolkit/identity/**
|
||||
toolkit/library/**
|
||||
toolkit/locales/**
|
||||
toolkit/modules/**
|
||||
# This file contains preprocessor statements.
|
||||
toolkit/mozapps/extensions/internal/AddonConstants.jsm
|
||||
toolkit/mozapps/downloads/**
|
||||
toolkit/mozapps/handling/**
|
||||
toolkit/mozapps/installer/**
|
||||
toolkit/mozapps/preferences/**
|
||||
toolkit/mozapps/update/**
|
||||
toolkit/obsolete/**
|
||||
toolkit/pluginproblem/**
|
||||
toolkit/profile/**
|
||||
toolkit/system/**
|
||||
toolkit/themes/**
|
||||
toolkit/toolkit.mozbuild/**
|
||||
toolkit/webapps/**
|
||||
toolkit/xre/**
|
||||
tools/**
|
||||
uriloader/**
|
||||
view/**
|
||||
|
@ -196,3 +172,34 @@ mobile/android/components/Snippets.js
|
|||
|
||||
# Bug 1178739: Ignore this file as a quick fix for "Illegal yield expression"
|
||||
mobile/android/modules/HomeProvider.jsm
|
||||
|
||||
# toolkit/ exclusions
|
||||
|
||||
# Not part of the default build
|
||||
toolkit/components/help/**
|
||||
|
||||
# Intentionally invalid JS
|
||||
toolkit/components/workerloader/tests/moduleF-syntax-error.js
|
||||
|
||||
# Tests old non-star function generators
|
||||
toolkit/modules/tests/xpcshell/test_task.js
|
||||
|
||||
# Not yet updated
|
||||
toolkit/components/osfile/**
|
||||
toolkit/components/passwordmgr/**
|
||||
toolkit/components/places/**
|
||||
toolkit/mozapps/extensions/**
|
||||
|
||||
# Uses preprocessing
|
||||
toolkit/content/contentAreaUtils.js
|
||||
toolkit/components/jsdownloads/src/DownloadIntegration.jsm
|
||||
toolkit/components/search/nsSearchService.js
|
||||
toolkit/components/url-classifier/**
|
||||
toolkit/components/urlformatter/nsURLFormatter.js
|
||||
toolkit/identity/FirefoxAccounts.jsm
|
||||
toolkit/modules/AppConstants.jsm
|
||||
toolkit/modules/SessionRecorder.jsm
|
||||
toolkit/mozapps/downloads/nsHelperAppDlg.js
|
||||
toolkit/mozapps/extensions/internal/AddonConstants.jsm
|
||||
toolkit/mozapps/update/tests/data/xpcshellConstantsPP.js
|
||||
toolkit/webapps/**
|
||||
|
|
|
@ -285,7 +285,6 @@
|
|||
// almost certainly useless.
|
||||
document.getElementById("errorTryAgain").style.display = "none";
|
||||
document.getElementById("errorPageContainer").setAttribute("class", "certerror");
|
||||
addDomainErrorLink();
|
||||
}
|
||||
else {
|
||||
// Remove the override block for non-certificate errors. CSS-hiding
|
||||
|
@ -293,6 +292,7 @@
|
|||
var secOverride = document.getElementById("securityOverrideDiv");
|
||||
secOverride.parentNode.removeChild(secOverride);
|
||||
}
|
||||
addDomainErrorLinks();
|
||||
}
|
||||
|
||||
function showSecuritySection() {
|
||||
|
@ -301,13 +301,16 @@
|
|||
document.getElementById('securityOverrideLink').style.display = 'none';
|
||||
}
|
||||
|
||||
/* In the case of SSL error pages about domain mismatch, see if
|
||||
/* Try to preserve the links contained in the error description, like
|
||||
the error code.
|
||||
|
||||
Also, in the case of SSL error pages about domain mismatch, see if
|
||||
we can hyperlink the user to the correct site. We don't want
|
||||
to do this generically since it allows MitM attacks to redirect
|
||||
users to a site under attacker control, but in certain cases
|
||||
it is safe (and helpful!) to do so. Bug 402210
|
||||
*/
|
||||
function addDomainErrorLink() {
|
||||
function addDomainErrorLinks() {
|
||||
// Rather than textContent, we need to treat description as HTML
|
||||
var sd = document.getElementById("errorShortDescText");
|
||||
if (sd) {
|
||||
|
@ -315,30 +318,39 @@
|
|||
|
||||
// sanitize description text - see bug 441169
|
||||
|
||||
// First, find the index of the <a> tag we care about, being careful not to
|
||||
// use an over-greedy regex
|
||||
var re = /<a id="cert_domain_link" title="([^"]+)">/;
|
||||
var result = re.exec(desc);
|
||||
if(!result)
|
||||
return;
|
||||
// First, find the index of the <a> tags we care about, being
|
||||
// careful not to use an over-greedy regex.
|
||||
var codeRe = /<a id="errorCode" title="([^"]+)">/;
|
||||
var codeResult = codeRe.exec(desc);
|
||||
var domainRe = /<a id="cert_domain_link" title="([^"]+)">/;
|
||||
var domainResult = domainRe.exec(desc);
|
||||
|
||||
// The order of these links in the description is fixed in
|
||||
// TransportSecurityInfo.cpp:formatOverridableCertErrorMessage.
|
||||
var firstResult = domainResult;
|
||||
if(!domainResult)
|
||||
firstResult = codeResult;
|
||||
if (!firstResult)
|
||||
return;
|
||||
// Remove sd's existing children
|
||||
sd.textContent = "";
|
||||
|
||||
// Everything up to the link should be text content
|
||||
sd.appendChild(document.createTextNode(desc.slice(0, result.index)));
|
||||
// Everything up to the first link should be text content.
|
||||
sd.appendChild(document.createTextNode(desc.slice(0, firstResult.index)));
|
||||
|
||||
// Now create the link itself
|
||||
var anchorEl = document.createElement("a");
|
||||
anchorEl.setAttribute("id", "cert_domain_link");
|
||||
anchorEl.setAttribute("title", result[1]);
|
||||
anchorEl.appendChild(document.createTextNode(result[1]));
|
||||
sd.appendChild(anchorEl);
|
||||
// Now create the actual links.
|
||||
if (domainResult) {
|
||||
createLink(sd, "cert_domain_link", domainResult[1])
|
||||
// Append text for anything between the two links.
|
||||
sd.appendChild(document.createTextNode(desc.slice(desc.indexOf("</a>") + "</a>".length, codeResult.index)));
|
||||
}
|
||||
createLink(sd, "errorCode", codeResult[1])
|
||||
|
||||
// Finally, append text for anything after the closing </a>
|
||||
sd.appendChild(document.createTextNode(desc.slice(desc.indexOf("</a>") + "</a>".length)));
|
||||
// Finally, append text for anything after the last closing </a>.
|
||||
sd.appendChild(document.createTextNode(desc.slice(desc.lastIndexOf("</a>") + "</a>".length)));
|
||||
}
|
||||
|
||||
// Initialize the cert domain link.
|
||||
var link = document.getElementById('cert_domain_link');
|
||||
if (!link)
|
||||
return;
|
||||
|
@ -365,7 +377,7 @@
|
|||
* domain names are famous for having '.' characters in them,
|
||||
* which would allow spurious and possibly hostile matches.
|
||||
*/
|
||||
if (endsWith(okHost, "." + thisHost))
|
||||
if (okHost.endsWith("." + thisHost))
|
||||
link.href = proto + okHost;
|
||||
|
||||
/* case #2:
|
||||
|
@ -373,12 +385,21 @@
|
|||
*
|
||||
* The certificate is only valid for garage.maemo.org
|
||||
*/
|
||||
if (endsWith(thisHost, "." + okHost))
|
||||
if (thisHost.endsWith("." + okHost))
|
||||
link.href = proto + okHost;
|
||||
|
||||
// If we set a link, meaning there's something helpful for
|
||||
// the user here, expand the section by default
|
||||
if (link.href && getCSSClass() != "expertBadCert")
|
||||
toggleVisibility("advancedPanel");
|
||||
}
|
||||
|
||||
function endsWith(haystack, needle) {
|
||||
return haystack.slice(-needle.length) == needle;
|
||||
function createLink(el, id, text) {
|
||||
var anchorEl = document.createElement("a");
|
||||
anchorEl.setAttribute("id", id);
|
||||
anchorEl.setAttribute("title", text);
|
||||
anchorEl.appendChild(document.createTextNode(text));
|
||||
el.appendChild(anchorEl);
|
||||
}
|
||||
]]></script>
|
||||
</head>
|
||||
|
@ -444,8 +465,8 @@
|
|||
<div id="ed_cspBlocked">&cspBlocked.longDesc;</div>
|
||||
<div id="ed_remoteXUL">&remoteXUL.longDesc;</div>
|
||||
<div id="ed_corruptedContentError">&corruptedContentError.longDesc;</div>
|
||||
<div id="ed_sslv3Used">&sslv3Used.longDesc;</div>
|
||||
<div id="ed_weakCryptoUsed">&weakCryptoUsed.longDesc;</div>
|
||||
<div id="ed_sslv3Used">&sslv3Used.longDesc2;</div>
|
||||
<div id="ed_weakCryptoUsed">&weakCryptoUsed.longDesc2;</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -55,6 +55,13 @@
|
|||
{
|
||||
var node = document.getElementById(id);
|
||||
node.style.visibility = node.style.visibility == "" ? "hidden" : "";
|
||||
// Toggling the advanced panel must ensure that the debugging
|
||||
// information panel is hidden as well, since it's opened by the
|
||||
// error code link in the advanced panel.
|
||||
if (id == "advancedPanel") {
|
||||
var div = document.getElementById("certificateErrorDebugInformation");
|
||||
div.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
function getDescription()
|
||||
|
@ -95,16 +102,22 @@
|
|||
if (tech)
|
||||
tech.textContent = getDescription();
|
||||
|
||||
addDomainErrorLink();
|
||||
var event = new CustomEvent("AboutCertErrorLoad", {bubbles:true});
|
||||
document.getElementById("advancedButton").dispatchEvent(event);
|
||||
|
||||
addDomainErrorLinks();
|
||||
}
|
||||
|
||||
/* In the case of SSL error pages about domain mismatch, see if
|
||||
/* Try to preserve the links contained in the error description, like
|
||||
the error code.
|
||||
|
||||
Also, in the case of SSL error pages about domain mismatch, see if
|
||||
we can hyperlink the user to the correct site. We don't want
|
||||
to do this generically since it allows MitM attacks to redirect
|
||||
users to a site under attacker control, but in certain cases
|
||||
it is safe (and helpful!) to do so. Bug 402210
|
||||
*/
|
||||
function addDomainErrorLink() {
|
||||
function addDomainErrorLinks() {
|
||||
// Rather than textContent, we need to treat description as HTML
|
||||
var sd = document.getElementById("technicalContentText");
|
||||
if (sd) {
|
||||
|
@ -112,30 +125,56 @@
|
|||
|
||||
// sanitize description text - see bug 441169
|
||||
|
||||
// First, find the index of the <a> tag we care about, being careful not to
|
||||
// use an over-greedy regex
|
||||
var re = /<a id="cert_domain_link" title="([^"]+)">/;
|
||||
var result = re.exec(desc);
|
||||
if(!result)
|
||||
// First, find the index of the <a> tags we care about, being
|
||||
// careful not to use an over-greedy regex.
|
||||
var codeRe = /<a id="errorCode" title="([^"]+)">/;
|
||||
var codeResult = codeRe.exec(desc);
|
||||
var domainRe = /<a id="cert_domain_link" title="([^"]+)">/;
|
||||
var domainResult = domainRe.exec(desc);
|
||||
|
||||
// The order of these links in the description is fixed in
|
||||
// TransportSecurityInfo.cpp:formatOverridableCertErrorMessage.
|
||||
var firstResult = domainResult;
|
||||
if(!domainResult)
|
||||
firstResult = codeResult;
|
||||
if (!firstResult)
|
||||
return;
|
||||
|
||||
// Remove sd's existing children
|
||||
sd.textContent = "";
|
||||
|
||||
// Everything up to the link should be text content
|
||||
sd.appendChild(document.createTextNode(desc.slice(0, result.index)));
|
||||
// Everything up to the first link should be text content.
|
||||
sd.appendChild(document.createTextNode(desc.slice(0, firstResult.index)));
|
||||
|
||||
// Now create the link itself
|
||||
var anchorEl = document.createElement("a");
|
||||
anchorEl.setAttribute("id", "cert_domain_link");
|
||||
anchorEl.setAttribute("title", result[1]);
|
||||
anchorEl.appendChild(document.createTextNode(result[1]));
|
||||
sd.appendChild(anchorEl);
|
||||
// Now create the actual links.
|
||||
if (domainResult) {
|
||||
createLink(sd, "cert_domain_link", domainResult[1])
|
||||
// Append text for anything between the two links.
|
||||
sd.appendChild(document.createTextNode(desc.slice(desc.indexOf("</a>") + "</a>".length, codeResult.index)));
|
||||
}
|
||||
createLink(sd, "errorCode", codeResult[1])
|
||||
|
||||
// Finally, append text for anything after the closing </a>
|
||||
sd.appendChild(document.createTextNode(desc.slice(desc.indexOf("</a>") + "</a>".length)));
|
||||
// Finally, append text for anything after the last closing </a>.
|
||||
sd.appendChild(document.createTextNode(desc.slice(desc.lastIndexOf("</a>") + "</a>".length)));
|
||||
}
|
||||
|
||||
// Initialize the error code link embedded in the error message to
|
||||
// display debug information about the cert error.
|
||||
var errorCode = document.getElementById("errorCode");
|
||||
if (errorCode) {
|
||||
errorCode.href = "#technicalInformation";
|
||||
errorCode.addEventListener("click", () => {
|
||||
var div = document.getElementById("certificateErrorDebugInformation");
|
||||
if (div.style.display == "block") {
|
||||
div.style.display = "none";
|
||||
} else {
|
||||
div.style.display = "block";
|
||||
div.scrollIntoView(true);
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
// Then initialize the cert domain link.
|
||||
var link = document.getElementById('cert_domain_link');
|
||||
if (!link)
|
||||
return;
|
||||
|
@ -178,6 +217,14 @@
|
|||
if (link.href && getCSSClass() != "expertBadCert")
|
||||
toggleVisibility("advancedPanel");
|
||||
}
|
||||
|
||||
function createLink(el, id, text) {
|
||||
var anchorEl = document.createElement("a");
|
||||
anchorEl.setAttribute("id", id);
|
||||
anchorEl.setAttribute("title", text);
|
||||
anchorEl.appendChild(document.createTextNode(text));
|
||||
el.appendChild(anchorEl);
|
||||
}
|
||||
]]></script>
|
||||
</head>
|
||||
|
||||
|
@ -210,11 +257,18 @@
|
|||
<!-- Advanced panel, which is hidden by default -->
|
||||
<div id="advancedPanel" style="visibility: hidden;">
|
||||
<p id="technicalContentText"/>
|
||||
<button id='exceptionDialogButton'>&certerror.addException.label;</button>
|
||||
<button id="exceptionDialogButton">&certerror.addException.label;</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="certificateErrorDebugInformation">
|
||||
<a name="technicalInformation"></a>
|
||||
<button id="copyToClipboard">&certerror.copyToClipboard.label;</button>
|
||||
<div id="certificateErrorText"/>
|
||||
<button id="copyToClipboard">&certerror.copyToClipboard.label;</button>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
- Note: It is important to run the script this way, instead of using
|
||||
- an onload handler. This is because error pages are loaded as
|
||||
|
|
|
@ -2701,7 +2701,7 @@ var BrowserOnClick = {
|
|||
case "Browser:CertExceptionError":
|
||||
this.onAboutCertError(msg.target, msg.data.elementId,
|
||||
msg.data.isTopFrame, msg.data.location,
|
||||
msg.data.sslStatusAsString);
|
||||
msg.data.securityInfoAsString);
|
||||
break;
|
||||
case "Browser:SiteBlockedError":
|
||||
this.onAboutBlocked(msg.data.elementId, msg.data.reason,
|
||||
|
@ -2787,19 +2787,6 @@ var BrowserOnClick = {
|
|||
* The request data should be added to the report by the receiving server.
|
||||
*/
|
||||
|
||||
// TODO: can we pull this in from pippki.js isntead of duplicating it
|
||||
// here?
|
||||
function getDERString(cert)
|
||||
{
|
||||
var length = {};
|
||||
var derArray = cert.getRawDER(length);
|
||||
var derString = '';
|
||||
for (var i = 0; i < derArray.length; i++) {
|
||||
derString += String.fromCharCode(derArray[i]);
|
||||
}
|
||||
return derString;
|
||||
}
|
||||
|
||||
// Convert the nsIX509CertList into a format that can be parsed into
|
||||
// JSON
|
||||
let asciiCertChain = [];
|
||||
|
@ -2856,7 +2843,7 @@ var BrowserOnClick = {
|
|||
xhr.send(JSON.stringify(report));
|
||||
},
|
||||
|
||||
onAboutCertError: function (browser, elementId, isTopFrame, location, sslStatusAsString) {
|
||||
onAboutCertError: function (browser, elementId, isTopFrame, location, securityInfoAsString) {
|
||||
let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
|
||||
|
||||
switch (elementId) {
|
||||
|
@ -2867,8 +2854,9 @@ var BrowserOnClick = {
|
|||
|
||||
let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
|
||||
.getService(Ci.nsISerializationHelper);
|
||||
let sslStatus = serhelper.deserializeObject(sslStatusAsString);
|
||||
sslStatus.QueryInterface(Components.interfaces.nsISSLStatus);
|
||||
let securityInfo = serhelper.deserializeObject(securityInfoAsString);
|
||||
let sslStatus = securityInfo.QueryInterface(Ci.nsISSLStatusProvider)
|
||||
.SSLStatus;
|
||||
let params = { exceptionAdded : false,
|
||||
sslStatus : sslStatus };
|
||||
|
||||
|
@ -2903,6 +2891,19 @@ var BrowserOnClick = {
|
|||
if (isTopFrame) {
|
||||
secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_BAD_CERT_TOP_UNDERSTAND_RISKS);
|
||||
}
|
||||
|
||||
let errorInfo = getDetailedCertErrorInfo(location,
|
||||
securityInfoAsString);
|
||||
browser.messageManager.sendAsyncMessage("AboutCertErrorDetails",
|
||||
{ info: errorInfo });
|
||||
break;
|
||||
|
||||
case "copyToClipboard":
|
||||
const gClipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"]
|
||||
.getService(Ci.nsIClipboardHelper);
|
||||
let detailedInfo = getDetailedCertErrorInfo(location,
|
||||
securityInfoAsString);
|
||||
gClipboardHelper.copyString(detailedInfo);
|
||||
break;
|
||||
|
||||
}
|
||||
|
@ -3157,6 +3158,76 @@ function BrowserReloadWithFlags(reloadFlags) {
|
|||
handlingUserInput: windowUtils.isHandlingUserInput });
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string with detailed information about the certificate validation
|
||||
* failure from the specified URI that can be used to send a report.
|
||||
*/
|
||||
function getDetailedCertErrorInfo(location, securityInfoAsString) {
|
||||
if (!securityInfoAsString)
|
||||
return "";
|
||||
|
||||
let details = [];
|
||||
details.push(location);
|
||||
|
||||
const serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
|
||||
.getService(Ci.nsISerializationHelper);
|
||||
let securityInfo = serhelper.deserializeObject(securityInfoAsString);
|
||||
securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
|
||||
|
||||
let errors = Cc["@mozilla.org/nss_errors_service;1"]
|
||||
.getService(Ci.nsINSSErrorsService);
|
||||
let code = securityInfo.errorCode;
|
||||
details.push(errors.getErrorMessage(errors.getXPCOMFromNSSError(code)));
|
||||
|
||||
const sss = Cc["@mozilla.org/ssservice;1"]
|
||||
.getService(Ci.nsISiteSecurityService);
|
||||
// SiteSecurityService uses different storage if the channel is
|
||||
// private. Thus we must give isSecureHost correct flags or we
|
||||
// might get incorrect results.
|
||||
let flags = PrivateBrowsingUtils.isWindowPrivate(window) ?
|
||||
Ci.nsISocketProvider.NO_PERMANENT_STORAGE : 0;
|
||||
|
||||
let uri = Services.io.newURI(location, null, null);
|
||||
details.push(sss.isSecureHost(sss.HEADER_HSTS, uri.host, flags));
|
||||
details.push(sss.isSecureHost(sss.HEADER_HPKP, uri.host, flags));
|
||||
|
||||
let certChain = "";
|
||||
if (securityInfo.failedCertChain) {
|
||||
let certs = securityInfo.failedCertChain.getEnumerator();
|
||||
while (certs.hasMoreElements()) {
|
||||
let cert = certs.getNext();
|
||||
cert.QueryInterface(Ci.nsIX509Cert);
|
||||
certChain += getPEMString(cert);
|
||||
}
|
||||
}
|
||||
details.push(certChain);
|
||||
return gNavigatorBundle.getFormattedString("certErrorDetails.label", details, 5);
|
||||
}
|
||||
|
||||
// TODO: can we pull getDERString and getPEMString in from pippki.js instead of
|
||||
// duplicating them here?
|
||||
function getDERString(cert)
|
||||
{
|
||||
var length = {};
|
||||
var derArray = cert.getRawDER(length);
|
||||
var derString = '';
|
||||
for (var i = 0; i < derArray.length; i++) {
|
||||
derString += String.fromCharCode(derArray[i]);
|
||||
}
|
||||
return derString;
|
||||
}
|
||||
|
||||
function getPEMString(cert)
|
||||
{
|
||||
var derb64 = btoa(getDERString(cert));
|
||||
// Wrap the Base64 string into lines of 64 characters,
|
||||
// with CRLF line breaks (as specified in RFC 1421).
|
||||
var wrapped = derb64.replace(/(\S{64}(?!$))/g, "$1\r\n");
|
||||
return "-----BEGIN CERTIFICATE-----\r\n"
|
||||
+ wrapped
|
||||
+ "\r\n-----END CERTIFICATE-----\r\n";
|
||||
}
|
||||
|
||||
var PrintPreviewListener = {
|
||||
_printPreviewTab: null,
|
||||
_tabBeforePrintPreview: null,
|
||||
|
@ -5323,10 +5394,14 @@ function hrefAndLinkNodeForClickEvent(event)
|
|||
let href, baseURI;
|
||||
node = event.target;
|
||||
while (node && !href) {
|
||||
if (node.nodeType == Node.ELEMENT_NODE) {
|
||||
if (node.nodeType == Node.ELEMENT_NODE &&
|
||||
(node.localName == "a" ||
|
||||
node.namespaceURI == "http://www.w3.org/1998/Math/MathML")) {
|
||||
href = node.getAttributeNS("http://www.w3.org/1999/xlink", "href");
|
||||
if (href)
|
||||
if (href) {
|
||||
baseURI = node.baseURI;
|
||||
break;
|
||||
}
|
||||
}
|
||||
node = node.parentNode;
|
||||
}
|
||||
|
@ -7941,4 +8016,3 @@ TabModalPromptBox.prototype = {
|
|||
return browser;
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -316,7 +316,6 @@ var AboutNetErrorListener = {
|
|||
}
|
||||
});
|
||||
|
||||
let failedChannel = docShell.failedChannel;
|
||||
let location = contentDoc.location.href;
|
||||
|
||||
let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
|
||||
|
@ -436,21 +435,21 @@ var ClickEventHandler = {
|
|||
.QueryInterface(Ci.nsIDocShell);
|
||||
let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
|
||||
.getService(Ci.nsISerializationHelper);
|
||||
let serializedSSLStatus = "";
|
||||
let serializedSecurityInfo = "";
|
||||
|
||||
try {
|
||||
let serializable = docShell.failedChannel.securityInfo
|
||||
.QueryInterface(Ci.nsISSLStatusProvider)
|
||||
.SSLStatus
|
||||
.QueryInterface(Ci.nsITransportSecurityInfo)
|
||||
.QueryInterface(Ci.nsISerializable);
|
||||
serializedSSLStatus = serhelper.serializeToString(serializable);
|
||||
|
||||
serializedSecurityInfo = serhelper.serializeToString(serializable);
|
||||
} catch (e) { }
|
||||
|
||||
sendAsyncMessage("Browser:CertExceptionError", {
|
||||
location: ownerDoc.location.href,
|
||||
elementId: targetElement.getAttribute("id"),
|
||||
isTopFrame: (ownerDoc.defaultView.parent === ownerDoc.defaultView),
|
||||
sslStatusAsString: serializedSSLStatus
|
||||
securityInfoAsString: serializedSecurityInfo
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -520,7 +519,9 @@ var ClickEventHandler = {
|
|||
let href, baseURI;
|
||||
node = event.target;
|
||||
while (node && !href) {
|
||||
if (node.nodeType == content.Node.ELEMENT_NODE) {
|
||||
if (node.nodeType == content.Node.ELEMENT_NODE &&
|
||||
(node.localName == "a" ||
|
||||
node.namespaceURI == "http://www.w3.org/1998/Math/MathML")) {
|
||||
href = node.getAttributeNS("http://www.w3.org/1999/xlink", "href");
|
||||
if (href) {
|
||||
baseURI = node.ownerDocument.baseURIObject;
|
||||
|
@ -552,6 +553,17 @@ addEventListener("DOMServiceWorkerFocusClient", function(event) {
|
|||
sendAsyncMessage("DOMServiceWorkerFocusClient", {});
|
||||
}, false);
|
||||
|
||||
addEventListener("AboutCertErrorLoad", function(event) {
|
||||
let originalTarget = event.originalTarget;
|
||||
let ownerDoc = originalTarget.ownerDocument;
|
||||
ClickEventHandler.onAboutCertError(originalTarget, ownerDoc);
|
||||
}, false, true);
|
||||
|
||||
addMessageListener("AboutCertErrorDetails", function(message) {
|
||||
let div = content.document.getElementById("certificateErrorText");
|
||||
div.textContent = message.data.info;
|
||||
});
|
||||
|
||||
ContentWebRTC.init();
|
||||
addMessageListener("rtcpeer:Allow", ContentWebRTC);
|
||||
addMessageListener("rtcpeer:Deny", ContentWebRTC);
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// This is testing the aboutCertError page (Bug 1207107). It's a start,
|
||||
// but should be expanded to include cert_domain_link
|
||||
// This is testing the aboutCertError page (Bug 1207107).
|
||||
|
||||
const GOOD_PAGE = "https://example.com/";
|
||||
const BAD_CERT = "https://expired.example.com/";
|
||||
|
@ -103,6 +102,138 @@ add_task(function* checkBadStsCert() {
|
|||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* checkAdvancedDetails() {
|
||||
info("Loading a bad cert page and verifying the advanced details section");
|
||||
let browser;
|
||||
let certErrorLoaded;
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
|
||||
gBrowser.selectedTab = gBrowser.addTab(BAD_CERT);
|
||||
browser = gBrowser.selectedBrowser;
|
||||
certErrorLoaded = waitForCertErrorLoad(browser);
|
||||
}, false);
|
||||
|
||||
info("Loading and waiting for the cert error");
|
||||
yield certErrorLoaded;
|
||||
|
||||
let message = yield ContentTask.spawn(browser, null, function* () {
|
||||
let doc = content.document;
|
||||
let advancedButton = doc.getElementById("advancedButton");
|
||||
advancedButton.click();
|
||||
let el = doc.getElementById("errorCode");
|
||||
return { textContent: el.textContent, tagName: el.tagName };
|
||||
});
|
||||
is(message.textContent, "SEC_ERROR_EXPIRED_CERTIFICATE",
|
||||
"Correct error message found");
|
||||
is(message.tagName, "a", "Error message is a link");
|
||||
|
||||
message = yield ContentTask.spawn(browser, null, function* () {
|
||||
let doc = content.document;
|
||||
let errorCode = doc.getElementById("errorCode");
|
||||
errorCode.click();
|
||||
let div = doc.getElementById("certificateErrorDebugInformation");
|
||||
let text = doc.getElementById("certificateErrorText");
|
||||
|
||||
let docshell = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell);
|
||||
let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
|
||||
.getService(Ci.nsISerializationHelper);
|
||||
let serializable = docShell.failedChannel.securityInfo
|
||||
.QueryInterface(Ci.nsITransportSecurityInfo)
|
||||
.QueryInterface(Ci.nsISerializable);
|
||||
let serializedSecurityInfo = serhelper.serializeToString(serializable);
|
||||
return {
|
||||
divDisplay: div.style.display,
|
||||
text: text.textContent,
|
||||
securityInfoAsString: serializedSecurityInfo
|
||||
};
|
||||
});
|
||||
is(message.divDisplay, "block", "Debug information is visible");
|
||||
ok(message.text.contains(BAD_CERT), "Correct URL found");
|
||||
ok(message.text.contains("Certificate has expired"),
|
||||
"Correct error message found");
|
||||
ok(message.text.contains("HTTP Strict Transport Security: false"),
|
||||
"Correct HSTS value found");
|
||||
ok(message.text.contains("HTTP Public Key Pinning: false"),
|
||||
"Correct HPKP value found");
|
||||
let certChain = getCertChain(message.securityInfoAsString);
|
||||
ok(message.text.contains(certChain), "Found certificate chain");
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* checkAdvancedDetailsForHSTS() {
|
||||
info("Loading a bad STS cert page and verifying the advanced details section");
|
||||
let browser;
|
||||
let certErrorLoaded;
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
|
||||
gBrowser.selectedTab = gBrowser.addTab(BAD_STS_CERT);
|
||||
browser = gBrowser.selectedBrowser;
|
||||
certErrorLoaded = waitForCertErrorLoad(browser);
|
||||
}, false);
|
||||
|
||||
info("Loading and waiting for the cert error");
|
||||
yield certErrorLoaded;
|
||||
|
||||
let message = yield ContentTask.spawn(browser, null, function* () {
|
||||
let doc = content.document;
|
||||
let advancedButton = doc.getElementById("advancedButton");
|
||||
advancedButton.click();
|
||||
let ec = doc.getElementById("errorCode");
|
||||
let cdl = doc.getElementById("cert_domain_link");
|
||||
return {
|
||||
ecTextContent: ec.textContent,
|
||||
ecTagName: ec.tagName,
|
||||
cdlTextContent: cdl.textContent,
|
||||
cdlTagName: cdl.tagName
|
||||
};
|
||||
});
|
||||
|
||||
const badStsUri = Services.io.newURI(BAD_STS_CERT, null, null);
|
||||
is(message.ecTextContent, "SSL_ERROR_BAD_CERT_DOMAIN",
|
||||
"Correct error message found");
|
||||
is(message.ecTagName, "a", "Error message is a link");
|
||||
const url = badStsUri.prePath.slice(badStsUri.prePath.indexOf(".") + 1);
|
||||
is(message.cdlTextContent, url,
|
||||
"Correct cert_domain_link contents found");
|
||||
is(message.cdlTagName, "a", "cert_domain_link is a link");
|
||||
|
||||
message = yield ContentTask.spawn(browser, null, function* () {
|
||||
let doc = content.document;
|
||||
let errorCode = doc.getElementById("errorCode");
|
||||
errorCode.click();
|
||||
let div = doc.getElementById("certificateErrorDebugInformation");
|
||||
let text = doc.getElementById("certificateErrorText");
|
||||
|
||||
let docshell = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell);
|
||||
let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
|
||||
.getService(Ci.nsISerializationHelper);
|
||||
let serializable = docShell.failedChannel.securityInfo
|
||||
.QueryInterface(Ci.nsITransportSecurityInfo)
|
||||
.QueryInterface(Ci.nsISerializable);
|
||||
let serializedSecurityInfo = serhelper.serializeToString(serializable);
|
||||
return {
|
||||
divDisplay: div.style.display,
|
||||
text: text.textContent,
|
||||
securityInfoAsString: serializedSecurityInfo
|
||||
};
|
||||
});
|
||||
is(message.divDisplay, "block", "Debug information is visible");
|
||||
ok(message.text.contains(badStsUri.spec), "Correct URL found");
|
||||
ok(message.text.contains("requested domain name does not match the server's certificate"),
|
||||
"Correct error message found");
|
||||
ok(message.text.contains("HTTP Strict Transport Security: false"),
|
||||
"Correct HSTS value found");
|
||||
ok(message.text.contains("HTTP Public Key Pinning: true"),
|
||||
"Correct HPKP value found");
|
||||
let certChain = getCertChain(message.securityInfoAsString);
|
||||
ok(message.text.contains(certChain), "Found certificate chain");
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
function waitForCertErrorLoad(browser) {
|
||||
return new Promise(resolve => {
|
||||
info("Waiting for DOMContentLoaded event");
|
||||
|
@ -112,3 +243,40 @@ function waitForCertErrorLoad(browser) {
|
|||
}, false, true);
|
||||
});
|
||||
}
|
||||
|
||||
function getCertChain(securityInfoAsString) {
|
||||
let certChain = "";
|
||||
const serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
|
||||
.getService(Ci.nsISerializationHelper);
|
||||
let securityInfo = serhelper.deserializeObject(securityInfoAsString);
|
||||
securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
|
||||
let certs = securityInfo.failedCertChain.getEnumerator();
|
||||
while (certs.hasMoreElements()) {
|
||||
let cert = certs.getNext();
|
||||
cert.QueryInterface(Ci.nsIX509Cert);
|
||||
certChain += getPEMString(cert);
|
||||
}
|
||||
return certChain;
|
||||
}
|
||||
|
||||
function getDERString(cert)
|
||||
{
|
||||
var length = {};
|
||||
var derArray = cert.getRawDER(length);
|
||||
var derString = '';
|
||||
for (var i = 0; i < derArray.length; i++) {
|
||||
derString += String.fromCharCode(derArray[i]);
|
||||
}
|
||||
return derString;
|
||||
}
|
||||
|
||||
function getPEMString(cert)
|
||||
{
|
||||
var derb64 = btoa(getDERString(cert));
|
||||
// Wrap the Base64 string into lines of 64 characters,
|
||||
// with CRLF line breaks (as specified in RFC 1421).
|
||||
var wrapped = derb64.replace(/(\S{64}(?!$))/g, "$1\r\n");
|
||||
return "-----BEGIN CERTIFICATE-----\r\n"
|
||||
+ wrapped
|
||||
+ "\r\n-----END CERTIFICATE-----\r\n";
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ var certErrorProgressListener = {
|
|||
if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
|
||||
let textElement = content.document.getElementById("errorShortDescText");
|
||||
let text = textElement.innerHTML;
|
||||
ok(text.indexOf("mozilla_pkix_error_key_pinning_failure") > 0,
|
||||
ok(text.indexOf("MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE") > 0,
|
||||
"Got a pinning error page");
|
||||
gBrowser.removeProgressListener(this);
|
||||
gBrowser.selectedBrowser.addEventListener("load",
|
||||
|
|
|
@ -39,6 +39,9 @@ const kPrefCustomizationDebug = "browser.uiCustomization.debug";
|
|||
const kPrefDrawInTitlebar = "browser.tabs.drawInTitlebar";
|
||||
const kPrefWebIDEInNavbar = "devtools.webide.widget.inNavbarByDefault";
|
||||
|
||||
const kExpectedWindowURL = "chrome://browser/content/browser.xul";
|
||||
|
||||
|
||||
/**
|
||||
* The keys are the handlers that are fired when the event type (the value)
|
||||
* is fired on the subview. A widget that provides a subview has the option
|
||||
|
@ -1300,6 +1303,9 @@ var CustomizableUIInternal = {
|
|||
},
|
||||
|
||||
buildWidget: function(aDocument, aWidget) {
|
||||
if (aDocument.documentURI != kExpectedWindowURL) {
|
||||
throw new Error("buildWidget was called for a non-browser window!");
|
||||
}
|
||||
if (typeof aWidget == "string") {
|
||||
aWidget = gPalette.get(aWidget);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"extends": "../../../toolkit/components/extensions/.eslintrc",
|
||||
|
||||
"globals": {
|
||||
"currentWindow": true,
|
||||
"EventEmitter": true,
|
||||
"IconDetails": true,
|
||||
"openPanel": true,
|
||||
"makeWidgetId": true,
|
||||
"TabContext": true,
|
||||
"AllWindowEvents": true,
|
||||
"WindowEventManager": true,
|
||||
"WindowListManager": true,
|
||||
"WindowManager": true,
|
||||
},
|
||||
}
|
|
@ -1,3 +1,7 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/PlacesUtils.jsm");
|
||||
|
@ -5,7 +9,6 @@ var Bookmarks = PlacesUtils.bookmarks;
|
|||
|
||||
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
|
||||
var {
|
||||
EventManager,
|
||||
runSafe,
|
||||
} = ExtensionUtils;
|
||||
|
||||
|
@ -40,11 +43,12 @@ function getTree(rootGuid, onlyChildren) {
|
|||
}
|
||||
|
||||
return PlacesUtils.promiseBookmarksTree(rootGuid, {
|
||||
excludeItemsCallback: aItem => {
|
||||
if (aItem.type == PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR)
|
||||
excludeItemsCallback: item => {
|
||||
if (item.type == PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR) {
|
||||
return true;
|
||||
return aItem.annos &&
|
||||
aItem.annos.find(a => a.name == PlacesUtils.EXCLUDE_FROM_BACKUP_ANNO);
|
||||
}
|
||||
return item.annos &&
|
||||
item.annos.find(a => a.name == PlacesUtils.EXCLUDE_FROM_BACKUP_ANNO);
|
||||
},
|
||||
}).then(root => {
|
||||
if (onlyChildren) {
|
||||
|
@ -168,14 +172,14 @@ extensions.registerPrivilegedAPI("bookmarks", (extension, context) => {
|
|||
runSafe(context, callback, convert(result));
|
||||
}
|
||||
}, failure);
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
failure(e);
|
||||
}
|
||||
},
|
||||
|
||||
move: function(id, destination, callback) {
|
||||
let info = {
|
||||
guid: id
|
||||
guid: id,
|
||||
};
|
||||
|
||||
if ("parentId" in destination) {
|
||||
|
@ -204,7 +208,7 @@ extensions.registerPrivilegedAPI("bookmarks", (extension, context) => {
|
|||
|
||||
update: function(id, changes, callback) {
|
||||
let info = {
|
||||
guid: id
|
||||
guid: id,
|
||||
};
|
||||
|
||||
if ("title" in changes) {
|
||||
|
@ -233,7 +237,7 @@ extensions.registerPrivilegedAPI("bookmarks", (extension, context) => {
|
|||
|
||||
remove: function(id, callback) {
|
||||
let info = {
|
||||
guid: id
|
||||
guid: id,
|
||||
};
|
||||
|
||||
let failure = reason => {
|
||||
|
@ -252,8 +256,8 @@ extensions.registerPrivilegedAPI("bookmarks", (extension, context) => {
|
|||
} catch (e) {
|
||||
failure(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
@ -10,24 +10,19 @@ Cu.import("resource://devtools/shared/event-emitter.js");
|
|||
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
|
||||
var {
|
||||
EventManager,
|
||||
DefaultWeakMap,
|
||||
runSafe,
|
||||
} = ExtensionUtils;
|
||||
|
||||
// WeakMap[Extension -> BrowserAction]
|
||||
var browserActionMap = new WeakMap();
|
||||
|
||||
function browserActionOf(extension)
|
||||
{
|
||||
function browserActionOf(extension) {
|
||||
return browserActionMap.get(extension);
|
||||
}
|
||||
|
||||
var nextActionId = 0;
|
||||
|
||||
// Responsible for the browser_action section of the manifest as well
|
||||
// as the associated popup.
|
||||
function BrowserAction(options, extension)
|
||||
{
|
||||
function BrowserAction(options, extension) {
|
||||
this.extension = extension;
|
||||
this.id = makeWidgetId(extension.id) + "-browser-action";
|
||||
this.widget = null;
|
||||
|
@ -73,7 +68,7 @@ BrowserAction.prototype = {
|
|||
|
||||
let tabbrowser = document.defaultView.gBrowser;
|
||||
|
||||
node.addEventListener("command", event => {
|
||||
node.addEventListener("command", event => { // eslint-disable-line mozilla/balanced-listeners
|
||||
let tab = tabbrowser.selectedTab;
|
||||
let popup = this.getProperty(tab, "popup");
|
||||
this.tabManager.addActiveTabPermission(tab);
|
||||
|
@ -88,8 +83,8 @@ BrowserAction.prototype = {
|
|||
},
|
||||
});
|
||||
|
||||
this.tabContext.on("tab-select",
|
||||
(evt, tab) => { this.updateWindow(tab.ownerDocument.defaultView); })
|
||||
this.tabContext.on("tab-select", // eslint-disable-line mozilla/balanced-listeners
|
||||
(evt, tab) => { this.updateWindow(tab.ownerDocument.defaultView); });
|
||||
|
||||
this.widget = widget;
|
||||
},
|
||||
|
@ -124,7 +119,7 @@ BrowserAction.prototype = {
|
|||
}
|
||||
|
||||
let badgeNode = node.ownerDocument.getAnonymousElementByAttribute(node,
|
||||
'class', 'toolbarbutton-badge');
|
||||
"class", "toolbarbutton-badge");
|
||||
if (badgeNode) {
|
||||
let color = tabData.badgeBackgroundColor;
|
||||
if (Array.isArray(color)) {
|
||||
|
@ -190,6 +185,7 @@ BrowserAction.prototype = {
|
|||
},
|
||||
};
|
||||
|
||||
/* eslint-disable mozilla/balanced-listeners */
|
||||
extensions.on("manifest_browser_action", (type, directive, extension, manifest) => {
|
||||
let browserAction = new BrowserAction(manifest.browser_action, extension);
|
||||
browserAction.build();
|
||||
|
@ -202,6 +198,7 @@ extensions.on("shutdown", (type, extension) => {
|
|||
browserActionMap.delete(extension);
|
||||
}
|
||||
});
|
||||
/* eslint-enable mozilla/balanced-listeners */
|
||||
|
||||
extensions.registerAPI((extension, context) => {
|
||||
return {
|
||||
|
@ -273,7 +270,6 @@ extensions.registerAPI((extension, context) => {
|
|||
},
|
||||
|
||||
setBadgeBackgroundColor: function(details) {
|
||||
let color = details.color;
|
||||
let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
|
||||
browserActionOf(extension).setProperty(tab, "badgeBackgroundColor", details.color);
|
||||
},
|
||||
|
@ -283,6 +279,6 @@ extensions.registerAPI((extension, context) => {
|
|||
let color = browserActionOf(extension).getProperty(tab, "badgeBackgroundColor");
|
||||
runSafe(context, callback, color);
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
|
||||
Cu.import("resource://gre/modules/MatchPattern.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
@ -5,8 +9,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|||
|
||||
var {
|
||||
EventManager,
|
||||
contextMenuItems,
|
||||
runSafe
|
||||
runSafe,
|
||||
} = ExtensionUtils;
|
||||
|
||||
|
||||
|
@ -21,11 +24,6 @@ var onClickedCallbacksMap = new WeakMap();
|
|||
// If id is not specified for an item we use an integer.
|
||||
var nextID = 0;
|
||||
|
||||
function contextMenuObserver(subject, topic, data) {
|
||||
subject = subject.wrappedJSObject;
|
||||
menuBuilder.build(subject);
|
||||
}
|
||||
|
||||
// When a new contextMenu is opened, this function is called and
|
||||
// we populate the |xulMenu| with all the items from extensions
|
||||
// to be displayed. We always clear all the items again when
|
||||
|
@ -82,7 +80,7 @@ var menuBuilder = {
|
|||
topLevelItems.add(element);
|
||||
}
|
||||
|
||||
element.addEventListener("command", event => {
|
||||
element.addEventListener("command", event => { // eslint-disable-line mozilla/balanced-listeners
|
||||
item.tabManager.addActiveTabPermission();
|
||||
if (item.onclick) {
|
||||
let clickData = item.getClickData(contextData, event);
|
||||
|
@ -124,6 +122,11 @@ var menuBuilder = {
|
|||
},
|
||||
|
||||
_itemsToCleanUp: new Set(),
|
||||
};
|
||||
|
||||
function contextMenuObserver(subject, topic, data) {
|
||||
subject = subject.wrappedJSObject;
|
||||
menuBuilder.build(subject);
|
||||
}
|
||||
|
||||
function getContexts(contextData) {
|
||||
|
@ -132,38 +135,37 @@ function getContexts(contextData) {
|
|||
contexts.add("page");
|
||||
|
||||
if (contextData.inFrame) {
|
||||
contexts.add("frame")
|
||||
contexts.add("frame");
|
||||
}
|
||||
|
||||
if (contextData.isTextSelected) {
|
||||
contexts.add("selection")
|
||||
contexts.add("selection");
|
||||
}
|
||||
|
||||
if (contextData.onLink) {
|
||||
contexts.add("link")
|
||||
contexts.add("link");
|
||||
}
|
||||
|
||||
if (contextData.onEditableArea) {
|
||||
contexts.add("editable")
|
||||
contexts.add("editable");
|
||||
}
|
||||
|
||||
if (contextData.onImage) {
|
||||
contexts.add("image")
|
||||
contexts.add("image");
|
||||
}
|
||||
|
||||
if (contextData.onVideo) {
|
||||
contexts.add("video")
|
||||
contexts.add("video");
|
||||
}
|
||||
|
||||
if (contextData.onAudio) {
|
||||
contexts.add("audio")
|
||||
contexts.add("audio");
|
||||
}
|
||||
|
||||
return contexts;
|
||||
}
|
||||
|
||||
function MenuItem(extension, extContext, createProperties)
|
||||
{
|
||||
function MenuItem(extension, extContext, createProperties) {
|
||||
this.extension = extension;
|
||||
this.extContext = extContext;
|
||||
|
||||
|
@ -175,7 +177,7 @@ function MenuItem(extension, extContext, createProperties)
|
|||
MenuItem.prototype = {
|
||||
// init is called from the MenuItem ctor and from update. The |update|
|
||||
// flag is for the later case.
|
||||
init(createProperties, update=false) {
|
||||
init(createProperties, update = false) {
|
||||
let item = this;
|
||||
// return true if the prop was set on |this|
|
||||
function parseProp(propName, defaultValue = null) {
|
||||
|
@ -214,8 +216,8 @@ MenuItem.prototype = {
|
|||
let found = false;
|
||||
let menuMap = contextMenuMap.get(this.extension);
|
||||
if (menuMap.has(this.parentId)) {
|
||||
found = true;
|
||||
menuMap.get(this.parentId).isMenu = true;
|
||||
found = true;
|
||||
menuMap.get(this.parentId).isMenu = true;
|
||||
}
|
||||
if (!found) {
|
||||
throw new Error("MenuItem with this parentId not found");
|
||||
|
@ -265,7 +267,7 @@ MenuItem.prototype = {
|
|||
|
||||
let toRemove = new Set();
|
||||
toRemove.add(this.id);
|
||||
for (let [id, item] of menuMap) {
|
||||
for (let [, item] of menuMap) {
|
||||
if (hasAncestorWithId(item, this.id)) {
|
||||
toRemove.add(item.id);
|
||||
}
|
||||
|
@ -288,7 +290,7 @@ MenuItem.prototype = {
|
|||
}
|
||||
|
||||
let clickData = {
|
||||
menuItemId: this.id
|
||||
menuItemId: this.id,
|
||||
};
|
||||
|
||||
function setIfDefined(argName, value) {
|
||||
|
@ -318,7 +320,7 @@ MenuItem.prototype = {
|
|||
for (let c of this.contexts) {
|
||||
if (contexts.has(c)) {
|
||||
enabled = true;
|
||||
break
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!enabled) {
|
||||
|
@ -342,6 +344,7 @@ MenuItem.prototype = {
|
|||
};
|
||||
|
||||
var extCount = 0;
|
||||
/* eslint-disable mozilla/balanced-listeners */
|
||||
extensions.on("startup", (type, extension) => {
|
||||
contextMenuMap.set(extension, new Map());
|
||||
if (++extCount == 1) {
|
||||
|
@ -358,6 +361,7 @@ extensions.on("shutdown", (type, extension) => {
|
|||
"on-build-contextmenu");
|
||||
}
|
||||
});
|
||||
/* eslint-enable mozilla/balanced-listeners */
|
||||
|
||||
extensions.registerPrivilegedAPI("contextMenus", (extension, context) => {
|
||||
return {
|
||||
|
@ -392,7 +396,7 @@ extensions.registerPrivilegedAPI("contextMenus", (extension, context) => {
|
|||
},
|
||||
|
||||
removeAll: function(callback) {
|
||||
for (let [id, menuItem] of contextMenuMap.get(extension)) {
|
||||
for (let [, menuItem] of contextMenuMap.get(extension)) {
|
||||
menuItem.remove();
|
||||
}
|
||||
if (callback) {
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
|
||||
var {
|
||||
EventManager,
|
||||
DefaultWeakMap,
|
||||
runSafe,
|
||||
} = ExtensionUtils;
|
||||
|
||||
|
@ -15,8 +14,7 @@ var pageActionMap = new WeakMap();
|
|||
|
||||
// Handles URL bar icons, including the |page_action| manifest entry
|
||||
// and associated API.
|
||||
function PageAction(options, extension)
|
||||
{
|
||||
function PageAction(options, extension) {
|
||||
this.extension = extension;
|
||||
this.id = makeWidgetId(extension.id) + "-page-action";
|
||||
|
||||
|
@ -39,7 +37,7 @@ function PageAction(options, extension)
|
|||
this.tabContext = new TabContext(tab => Object.create(this.defaults),
|
||||
extension);
|
||||
|
||||
this.tabContext.on("location-change", this.handleLocationChange.bind(this));
|
||||
this.tabContext.on("location-change", this.handleLocationChange.bind(this)); // eslint-disable-line mozilla/balanced-listeners
|
||||
|
||||
// WeakMap[ChromeWindow -> <xul:image>]
|
||||
this.buttons = new WeakMap();
|
||||
|
@ -110,7 +108,7 @@ PageAction.prototype = {
|
|||
button.id = this.id;
|
||||
button.setAttribute("class", "urlbar-icon");
|
||||
|
||||
button.addEventListener("click", event => {
|
||||
button.addEventListener("click", event => { // eslint-disable-line mozilla/balanced-listeners
|
||||
if (event.button == 0) {
|
||||
this.handleClick(window);
|
||||
}
|
||||
|
@ -173,6 +171,7 @@ PageAction.for = extension => {
|
|||
};
|
||||
|
||||
|
||||
/* eslint-disable mozilla/balanced-listeners */
|
||||
extensions.on("manifest_page_action", (type, directive, extension, manifest) => {
|
||||
let pageAction = new PageAction(manifest.page_action, extension);
|
||||
pageActionMap.set(extension, pageAction);
|
||||
|
@ -184,6 +183,7 @@ extensions.on("shutdown", (type, extension) => {
|
|||
pageActionMap.delete(extension);
|
||||
}
|
||||
});
|
||||
/* eslint-enable mozilla/balanced-listeners */
|
||||
|
||||
|
||||
extensions.registerAPI((extension, context) => {
|
||||
|
@ -244,6 +244,6 @@ extensions.registerAPI((extension, context) => {
|
|||
let popup = PageAction.for(extension).getProperty(tab, "popup");
|
||||
runSafe(context, callback, popup);
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
|
||||
|
@ -10,6 +12,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "MatchPattern",
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
||||
"resource://gre/modules/Services.jsm");
|
||||
|
||||
/* globals aboutNewTabService */
|
||||
|
||||
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
|
||||
|
||||
var {
|
||||
|
@ -20,8 +24,7 @@ var {
|
|||
|
||||
// This function is pretty tightly tied to Extension.jsm.
|
||||
// Its job is to fill in the |tab| property of the sender.
|
||||
function getSender(context, target, sender)
|
||||
{
|
||||
function getSender(context, target, sender) {
|
||||
// The message was sent from a content script to a <browser> element.
|
||||
// We can just get the |tab| from |target|.
|
||||
if (target instanceof Ci.nsIDOMXULElement) {
|
||||
|
@ -33,20 +36,19 @@ function getSender(context, target, sender)
|
|||
let tab = tabbrowser.getTabForBrowser(target);
|
||||
|
||||
sender.tab = TabManager.convert(context.extension, tab);
|
||||
} else {
|
||||
} else if ("tabId" in sender) {
|
||||
// The message came from an ExtensionPage. In that case, it should
|
||||
// include a tabId property (which is filled in by the page-open
|
||||
// listener below).
|
||||
if ("tabId" in sender) {
|
||||
sender.tab = TabManager.convert(context.extension, TabManager.getTab(sender.tabId));
|
||||
delete sender.tabId;
|
||||
}
|
||||
sender.tab = TabManager.convert(context.extension, TabManager.getTab(sender.tabId));
|
||||
delete sender.tabId;
|
||||
}
|
||||
}
|
||||
|
||||
// WeakMap[ExtensionPage -> {tab, parentWindow}]
|
||||
var pageDataMap = new WeakMap();
|
||||
|
||||
/* eslint-disable mozilla/balanced-listeners */
|
||||
// This listener fires whenever an extension page opens in a tab
|
||||
// (either initiated by the extension or the user). Its job is to fill
|
||||
// in some tab-specific details and keep data around about the
|
||||
|
@ -95,15 +97,15 @@ extensions.on("fill-browser-data", (type, browser, data, result) => {
|
|||
|
||||
data.tabId = tabId;
|
||||
});
|
||||
/* eslint-enable mozilla/balanced-listeners */
|
||||
|
||||
global.currentWindow = function(context)
|
||||
{
|
||||
global.currentWindow = function(context) {
|
||||
let pageData = pageDataMap.get(context);
|
||||
if (pageData) {
|
||||
return pageData.parentWindow;
|
||||
}
|
||||
return WindowManager.topWindow;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: activeTab permission
|
||||
|
||||
|
@ -211,7 +213,7 @@ extensions.registerAPI((extension, context) => {
|
|||
let tabId = TabManager.getId(tab);
|
||||
let [needed, changeInfo] = sanitize(extension, {
|
||||
status: webProgress.isLoadingDocument ? "loading" : "complete",
|
||||
url: locationURI.spec
|
||||
url: locationURI.spec,
|
||||
});
|
||||
if (needed) {
|
||||
fire(tabId, changeInfo, TabManager.convert(extension, tab));
|
||||
|
@ -389,7 +391,7 @@ extensions.registerAPI((extension, context) => {
|
|||
getAllInWindow: function(...args) {
|
||||
let window, callback;
|
||||
if (args.length == 1) {
|
||||
callbacks = args[0];
|
||||
callback = args[0];
|
||||
} else {
|
||||
window = WindowManager.getWindow(args[0]);
|
||||
callback = args[1];
|
||||
|
@ -435,10 +437,8 @@ extensions.registerAPI((extension, context) => {
|
|||
if (currentWindow(context) != window) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (queryInfo.windowId != tab.windowId) {
|
||||
return false;
|
||||
}
|
||||
} else if (queryInfo.windowId != tab.windowId) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -495,7 +495,7 @@ extensions.registerAPI((extension, context) => {
|
|||
}
|
||||
|
||||
if (details.code) {
|
||||
options[kind + 'Code'] = details.code;
|
||||
options[kind + "Code"] = details.code;
|
||||
}
|
||||
if (details.file) {
|
||||
let url = context.uri.resolve(details.file);
|
||||
|
@ -522,17 +522,17 @@ extensions.registerAPI((extension, context) => {
|
|||
|
||||
executeScript: function(...args) {
|
||||
if (args.length == 1) {
|
||||
self.tabs._execute(undefined, args[0], 'js', undefined);
|
||||
self.tabs._execute(undefined, args[0], "js", undefined);
|
||||
} else {
|
||||
self.tabs._execute(args[0], args[1], 'js', args[2]);
|
||||
self.tabs._execute(args[0], args[1], "js", args[2]);
|
||||
}
|
||||
},
|
||||
|
||||
insertCss: function(tabId, details, callback) {
|
||||
insertCss: function(...args) {
|
||||
if (args.length == 1) {
|
||||
self.tabs._execute(undefined, args[0], 'css', undefined);
|
||||
self.tabs._execute(undefined, args[0], "css", undefined);
|
||||
} else {
|
||||
self.tabs._execute(args[0], args[1], 'css', args[2]);
|
||||
self.tabs._execute(args[0], args[1], "css", args[2]);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ global.IconDetails = {
|
|||
//
|
||||
// If no context is specified, instead of throwing an error, this
|
||||
// function simply logs a warning message.
|
||||
normalize(details, extension, context=null, localize=false) {
|
||||
normalize(details, extension, context = null, localize = false) {
|
||||
let result = {};
|
||||
|
||||
try {
|
||||
|
@ -112,14 +112,14 @@ global.IconDetails = {
|
|||
canvas.getContext("2d").putImageData(imageData, 0, 0);
|
||||
|
||||
return canvas.toDataURL("image/png");
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
global.makeWidgetId = id => {
|
||||
id = id.toLowerCase();
|
||||
// FIXME: This allows for collisions.
|
||||
return id.replace(/[^a-z0-9_-]/g, "_");
|
||||
}
|
||||
};
|
||||
|
||||
// Open a panel anchored to the given node, containing a browser opened
|
||||
// to the given URL, owned by the given extension. If |popupURL| is not
|
||||
|
@ -161,14 +161,16 @@ global.openPanel = (node, popupURL, extension) => {
|
|||
|
||||
let titleChangedListener = () => {
|
||||
panel.setAttribute("aria-label", browser.contentTitle);
|
||||
}
|
||||
};
|
||||
|
||||
let context;
|
||||
panel.addEventListener("popuphidden", () => {
|
||||
let popuphidden = () => {
|
||||
panel.removeEventListener("popuphidden", popuphidden);
|
||||
browser.removeEventListener("DOMTitleChanged", titleChangedListener, true);
|
||||
context.unload();
|
||||
panel.remove();
|
||||
});
|
||||
};
|
||||
panel.addEventListener("popuphidden", popuphidden);
|
||||
|
||||
let loadListener = () => {
|
||||
panel.removeEventListener("load", loadListener);
|
||||
|
@ -216,7 +218,7 @@ global.openPanel = (node, popupURL, extension) => {
|
|||
panel.addEventListener("load", loadListener);
|
||||
|
||||
return panel;
|
||||
}
|
||||
};
|
||||
|
||||
// Manages tab-specific context data, and dispatching tab select events
|
||||
// across all windows.
|
||||
|
@ -230,7 +232,7 @@ global.TabContext = function TabContext(getDefaults, extension) {
|
|||
AllWindowEvents.addListener("TabSelect", this);
|
||||
|
||||
EventEmitter.decorate(this);
|
||||
}
|
||||
};
|
||||
|
||||
TabContext.prototype = {
|
||||
get(tab) {
|
||||
|
@ -311,7 +313,6 @@ ExtensionTabManager.prototype = {
|
|||
|
||||
convert(tab) {
|
||||
let window = tab.ownerDocument.defaultView;
|
||||
let windowActive = window == WindowManager.topWindow;
|
||||
|
||||
let result = {
|
||||
id: TabManager.getId(tab),
|
||||
|
@ -411,16 +412,18 @@ let tabManagers = new WeakMap();
|
|||
|
||||
// Returns the extension-specific tab manager for the given extension, or
|
||||
// creates one if it doesn't already exist.
|
||||
TabManager.for = function (extension) {
|
||||
TabManager.for = function(extension) {
|
||||
if (!tabManagers.has(extension)) {
|
||||
tabManagers.set(extension, new ExtensionTabManager(extension));
|
||||
}
|
||||
return tabManagers.get(extension);
|
||||
};
|
||||
|
||||
/* eslint-disable mozilla/balanced-listeners */
|
||||
extensions.on("shutdown", (type, extension) => {
|
||||
tabManagers.delete(extension);
|
||||
});
|
||||
/* eslint-enable mozilla/balanced-listeners */
|
||||
|
||||
// Manages mapping between XUL windows and extension window IDs.
|
||||
global.WindowManager = {
|
||||
|
@ -489,7 +492,7 @@ global.WindowListManager = {
|
|||
|
||||
// Returns an iterator for all browser windows. Unless |includeIncomplete| is
|
||||
// true, only fully-loaded windows are returned.
|
||||
*browserWindows(includeIncomplete = false) {
|
||||
* browserWindows(includeIncomplete = false) {
|
||||
// The window type parameter is only available once the window's document
|
||||
// element has been created. This means that, when looking for incomplete
|
||||
// browser windows, we need to ignore the type entirely for windows which
|
||||
|
@ -654,15 +657,14 @@ AllWindowEvents.openListener = AllWindowEvents.openListener.bind(AllWindowEvents
|
|||
|
||||
// Subclass of EventManager where we just need to call
|
||||
// add/removeEventListener on each XUL window.
|
||||
global.WindowEventManager = function(context, name, event, listener)
|
||||
{
|
||||
global.WindowEventManager = function(context, name, event, listener) {
|
||||
EventManager.call(this, context, name, fire => {
|
||||
let listener2 = (...args) => listener(fire, ...args);
|
||||
AllWindowEvents.addListener(event, listener2);
|
||||
return () => {
|
||||
AllWindowEvents.removeListener(event, listener2);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
WindowEventManager.prototype = Object.create(EventManager.prototype);
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
|
||||
"@mozilla.org/browser/aboutnewtab-service;1",
|
||||
"nsIAboutNewTabService");
|
||||
|
||||
/* globals aboutNewTabService */
|
||||
|
||||
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
|
||||
var {
|
||||
EventManager,
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
"extends": "../../.eslintrc",
|
||||
|
||||
"globals": {
|
||||
// DOM window globals
|
||||
"CustomEvent": false,
|
||||
"document": false,
|
||||
"ImageData": false,
|
||||
"MouseEvent": false,
|
||||
"window": false,
|
||||
"XMLHttpRequest": false,
|
||||
|
||||
"gBrowser": false,
|
||||
|
||||
"sendAsyncMessage": false,
|
||||
|
||||
"NetUtil": true,
|
||||
"XPCOMUtils": true,
|
||||
"Task": true,
|
||||
|
||||
"browser": false,
|
||||
|
||||
// Test harness globals
|
||||
"add_task": false,
|
||||
"BrowserTestUtils": false,
|
||||
"ContentTask": false,
|
||||
"EventUtils": false,
|
||||
"ExtensionTestUtils": false,
|
||||
"info": false,
|
||||
"is": false,
|
||||
"ok": false,
|
||||
"registerCleanupFunction": false,
|
||||
"SimpleTest": false,
|
||||
"SpecialPowers": false,
|
||||
"waitForFocus": false,
|
||||
|
||||
"clickBrowserAction": true,
|
||||
"clickPageAction": true,
|
||||
"CustomizableUI": true,
|
||||
"focusWindow": true,
|
||||
"makeWidgetId": true,
|
||||
}
|
||||
}
|
|
@ -3,7 +3,6 @@
|
|||
"use strict";
|
||||
|
||||
add_task(function* testTabSwitchContext() {
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"browser_action": {
|
||||
|
@ -14,8 +13,8 @@ add_task(function* testTabSwitchContext() {
|
|||
"permissions": ["tabs"],
|
||||
},
|
||||
|
||||
background: function () {
|
||||
var details = [
|
||||
background: function() {
|
||||
let details = [
|
||||
{ "icon": browser.runtime.getURL("default.png"),
|
||||
"popup": browser.runtime.getURL("default.html"),
|
||||
"title": "Default Title",
|
||||
|
@ -51,9 +50,10 @@ add_task(function* testTabSwitchContext() {
|
|||
"badgeBackgroundColor": [0, 0xff, 0] },
|
||||
];
|
||||
|
||||
var tabs = [];
|
||||
let tabs = [];
|
||||
|
||||
var tests = [
|
||||
let expectDefaults;
|
||||
let tests = [
|
||||
expect => {
|
||||
browser.test.log("Initial state, expect default properties.");
|
||||
expectDefaults(details[0]).then(() => {
|
||||
|
@ -78,7 +78,7 @@ add_task(function* testTabSwitchContext() {
|
|||
},
|
||||
expect => {
|
||||
browser.test.log("Change properties. Expect new properties.");
|
||||
var tabId = tabs[1];
|
||||
let tabId = tabs[1];
|
||||
browser.browserAction.setIcon({ tabId, path: "2.png" });
|
||||
browser.browserAction.setPopup({ tabId, popup: "2.html" });
|
||||
browser.browserAction.setTitle({ tabId, title: "Title 2" });
|
||||
|
@ -191,14 +191,14 @@ add_task(function* testTabSwitchContext() {
|
|||
});
|
||||
}
|
||||
|
||||
function expectDefaults(expecting) {
|
||||
expectDefaults = expecting => {
|
||||
return checkDetails(expecting);
|
||||
}
|
||||
};
|
||||
|
||||
// Runs the next test in the `tests` array, checks the results,
|
||||
// and passes control back to the outer test scope.
|
||||
function nextTest() {
|
||||
var test = tests.shift();
|
||||
let test = tests.shift();
|
||||
|
||||
test(expecting => {
|
||||
// Check that the API returns the expected values, and then
|
||||
|
@ -247,11 +247,11 @@ add_task(function* testTabSwitchContext() {
|
|||
|
||||
if (details.badge && details.badgeBackgroundColor) {
|
||||
let badge = button.ownerDocument.getAnonymousElementByAttribute(
|
||||
button, 'class', 'toolbarbutton-badge');
|
||||
button, "class", "toolbarbutton-badge");
|
||||
|
||||
let badgeColor = window.getComputedStyle(badge).backgroundColor;
|
||||
let color = details.badgeBackgroundColor;
|
||||
let expectedColor = `rgb(${color[0]}, ${color[1]}, ${color[2]})`
|
||||
let expectedColor = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
|
||||
|
||||
is(badgeColor, expectedColor, "badge color is correct");
|
||||
}
|
||||
|
@ -265,7 +265,7 @@ add_task(function* testTabSwitchContext() {
|
|||
checkDetails(expecting);
|
||||
|
||||
if (testsRemaining) {
|
||||
extension.sendMessage("runNextTest")
|
||||
extension.sendMessage("runNextTest");
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
|
|
|
@ -3,14 +3,13 @@
|
|||
"use strict";
|
||||
|
||||
add_task(function* testDisabled() {
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"browser_action": {}
|
||||
"browser_action": {},
|
||||
},
|
||||
|
||||
background: function () {
|
||||
var clicked = false;
|
||||
background: function() {
|
||||
let clicked = false;
|
||||
|
||||
browser.browserAction.onClicked.addListener(() => {
|
||||
browser.test.log("Got click event");
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
add_task(function* testDetailsObjects() {
|
||||
function background() {
|
||||
function getImageData(color) {
|
||||
var canvas = document.createElement("canvas");
|
||||
let canvas = document.createElement("canvas");
|
||||
canvas.width = 2;
|
||||
canvas.height = 2;
|
||||
var canvasContext = canvas.getContext("2d");
|
||||
let canvasContext = canvas.getContext("2d");
|
||||
|
||||
canvasContext.clearRect(0, 0, canvas.width, canvas.height);
|
||||
canvasContext.fillStyle = color;
|
||||
|
@ -23,12 +23,13 @@ add_task(function* testDetailsObjects() {
|
|||
};
|
||||
}
|
||||
|
||||
var imageData = {
|
||||
let imageData = {
|
||||
red: getImageData("red"),
|
||||
green: getImageData("green"),
|
||||
};
|
||||
|
||||
var iconDetails = [
|
||||
/* eslint-disable comma-dangle, indent */
|
||||
let iconDetails = [
|
||||
// Only paths.
|
||||
{ details: { "path": "a.png" },
|
||||
resolutions: {
|
||||
|
@ -129,18 +130,18 @@ add_task(function* testDetailsObjects() {
|
|||
// Allow serializing ImageData objects for logging.
|
||||
ImageData.prototype.toJSON = () => "<ImageData>";
|
||||
|
||||
var tabId;
|
||||
let tabId;
|
||||
|
||||
browser.test.onMessage.addListener((msg, test) => {
|
||||
if (msg != "setIcon") {
|
||||
browser.test.fail("expecting 'setIcon' message");
|
||||
}
|
||||
|
||||
var details = iconDetails[test.index];
|
||||
var expectedURL = details.resolutions[test.resolution];
|
||||
let details = iconDetails[test.index];
|
||||
let expectedURL = details.resolutions[test.resolution];
|
||||
|
||||
var detailString = JSON.stringify(details);
|
||||
browser.test.log(`Setting browerAction/pageAction to ${detailString} expecting URL ${expectedURL}`)
|
||||
let detailString = JSON.stringify(details);
|
||||
browser.test.log(`Setting browerAction/pageAction to ${detailString} expecting URL ${expectedURL}`);
|
||||
|
||||
browser.browserAction.setIcon(Object.assign({tabId}, details.details));
|
||||
browser.pageAction.setIcon(Object.assign({tabId}, details.details));
|
||||
|
@ -158,9 +159,9 @@ add_task(function* testDetailsObjects() {
|
|||
// objects without issue. Unfortunately, |cloneInto| implements a slightly
|
||||
// different algorithm than we use in web APIs, and does not handle them
|
||||
// correctly.
|
||||
var tests = [];
|
||||
for (var [idx, icon] of iconDetails.entries()) {
|
||||
for (var res of Object.keys(icon.resolutions)) {
|
||||
let tests = [];
|
||||
for (let [idx, icon] of iconDetails.entries()) {
|
||||
for (let res of Object.keys(icon.resolutions)) {
|
||||
tests.push({ index: idx, resolution: Number(res) });
|
||||
}
|
||||
}
|
||||
|
@ -221,19 +222,18 @@ add_task(function* testDetailsObjects() {
|
|||
});
|
||||
|
||||
// Test that an error is thrown when providing invalid icon sizes
|
||||
add_task(function *testInvalidIconSizes() {
|
||||
|
||||
add_task(function* testInvalidIconSizes() {
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"browser_action": {},
|
||||
"page_action": {},
|
||||
},
|
||||
|
||||
background: function () {
|
||||
background: function() {
|
||||
browser.tabs.query({ active: true, currentWindow: true }, tabs => {
|
||||
var tabId = tabs[0].id;
|
||||
let tabId = tabs[0].id;
|
||||
|
||||
for (var api of ["pageAction", "browserAction"]) {
|
||||
for (let api of ["pageAction", "browserAction"]) {
|
||||
// helper function to run setIcon and check if it fails
|
||||
let assertSetIconThrows = function(detail, error, message) {
|
||||
try {
|
||||
|
@ -246,10 +246,10 @@ add_task(function *testInvalidIconSizes() {
|
|||
} catch (e) {
|
||||
browser.test.succeed("setIcon with invalid icon size");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// test invalid icon size inputs
|
||||
for (var type of ["path", "imageData"]) {
|
||||
for (let type of ["path", "imageData"]) {
|
||||
assertSetIconThrows({ [type]: { "abcdef": "test.png" } });
|
||||
assertSetIconThrows({ [type]: { "48px": "test.png" } });
|
||||
assertSetIconThrows({ [type]: { "20.5": "test.png" } });
|
||||
|
@ -278,7 +278,7 @@ add_task(function *testInvalidIconSizes() {
|
|||
|
||||
// Test that default icon details in the manifest.json file are handled
|
||||
// correctly.
|
||||
add_task(function *testDefaultDetails() {
|
||||
add_task(function* testDefaultDetails() {
|
||||
// TODO: Test localized variants.
|
||||
let icons = [
|
||||
"foo/bar.png",
|
||||
|
@ -297,9 +297,9 @@ add_task(function *testDefaultDetails() {
|
|||
"page_action": { "default_icon": icon },
|
||||
},
|
||||
|
||||
background: function () {
|
||||
background: function() {
|
||||
browser.tabs.query({ active: true, currentWindow: true }, tabs => {
|
||||
var tabId = tabs[0].id;
|
||||
let tabId = tabs[0].id;
|
||||
|
||||
browser.pageAction.show(tabId);
|
||||
browser.test.sendMessage("ready");
|
||||
|
@ -332,7 +332,6 @@ add_task(function *testDefaultDetails() {
|
|||
|
||||
// Check that attempts to load a privileged URL as an icon image fail.
|
||||
add_task(function* testSecureURLsDenied() {
|
||||
|
||||
// Test URLs passed to setIcon.
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
|
@ -341,15 +340,15 @@ add_task(function* testSecureURLsDenied() {
|
|||
"page_action": {},
|
||||
},
|
||||
|
||||
background: function () {
|
||||
background: function() {
|
||||
browser.tabs.query({ active: true, currentWindow: true }, tabs => {
|
||||
var tabId = tabs[0].id;
|
||||
let tabId = tabs[0].id;
|
||||
|
||||
var urls = ["chrome://browser/content/browser.xul",
|
||||
let urls = ["chrome://browser/content/browser.xul",
|
||||
"javascript:true"];
|
||||
|
||||
for (var url of urls) {
|
||||
for (var api of ["pageAction", "browserAction"]) {
|
||||
for (let url of urls) {
|
||||
for (let api of ["pageAction", "browserAction"]) {
|
||||
try {
|
||||
browser[api].setIcon({tabId, path: url});
|
||||
|
||||
|
|
|
@ -20,11 +20,11 @@ add_task(function* testPageActionPopup() {
|
|||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"background": {
|
||||
"page": "data/background.html"
|
||||
"page": "data/background.html",
|
||||
},
|
||||
"browser_action": {
|
||||
"default_popup": "popup-a.html"
|
||||
}
|
||||
"default_popup": "popup-a.html",
|
||||
},
|
||||
},
|
||||
|
||||
files: {
|
||||
|
@ -41,7 +41,8 @@ add_task(function* testPageActionPopup() {
|
|||
"data/background.html": `<script src="background.js"></script>`,
|
||||
|
||||
"data/background.js": function() {
|
||||
var tests = [
|
||||
let sendClick;
|
||||
let tests = [
|
||||
() => {
|
||||
sendClick({ expectEvent: false, expectPopup: "a" });
|
||||
},
|
||||
|
@ -68,11 +69,11 @@ add_task(function* testPageActionPopup() {
|
|||
},
|
||||
];
|
||||
|
||||
var expect = {};
|
||||
function sendClick({ expectEvent, expectPopup }) {
|
||||
let expect = {};
|
||||
sendClick = ({ expectEvent, expectPopup }) => {
|
||||
expect = { event: expectEvent, popup: expectPopup };
|
||||
browser.test.sendMessage("send-click");
|
||||
}
|
||||
};
|
||||
|
||||
browser.runtime.onMessage.addListener(msg => {
|
||||
if (expect.popup) {
|
||||
|
@ -103,7 +104,7 @@ add_task(function* testPageActionPopup() {
|
|||
}
|
||||
|
||||
if (tests.length) {
|
||||
var test = tests.shift();
|
||||
let test = tests.shift();
|
||||
test();
|
||||
} else {
|
||||
browser.test.notifyPass("browseraction-tests-done");
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
add_task(function* () {
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"browser_action": {
|
||||
"default_popup": "popup.html"
|
||||
}
|
||||
"default_popup": "popup.html",
|
||||
},
|
||||
},
|
||||
|
||||
files: {
|
||||
|
@ -16,7 +20,7 @@ add_task(function* () {
|
|||
|
||||
"popup.js": function() {
|
||||
browser.runtime.sendMessage("from-popup");
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
background: function() {
|
||||
|
@ -36,7 +40,7 @@ add_task(function* () {
|
|||
for (let i = 0; i < 3; i++) {
|
||||
let evt = new CustomEvent("command", {
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
cancelable: true,
|
||||
});
|
||||
node.dispatchEvent(evt);
|
||||
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
add_task(function* () {
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://mochi.test:8888/");
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"permissions": ["http://mochi.test/"]
|
||||
"permissions": ["http://mochi.test/"],
|
||||
},
|
||||
|
||||
background: function() {
|
||||
var ports_received = 0;
|
||||
var port_messages_received = 0;
|
||||
let ports_received = 0;
|
||||
let port_messages_received = 0;
|
||||
|
||||
browser.runtime.onConnect.addListener((port) => {
|
||||
browser.test.assertTrue(!!port, "port1 received");
|
||||
|
@ -19,9 +23,9 @@ add_task(function* () {
|
|||
port.onMessage.addListener((msg, sender) => {
|
||||
browser.test.assertEq("port message", msg, "listener1 port message received");
|
||||
|
||||
port_messages_received++
|
||||
port_messages_received++;
|
||||
browser.test.assertEq(1, port_messages_received, "1 port message received");
|
||||
})
|
||||
});
|
||||
});
|
||||
browser.runtime.onConnect.addListener((port) => {
|
||||
browser.test.assertTrue(!!port, "port2 received");
|
||||
|
@ -32,7 +36,7 @@ add_task(function* () {
|
|||
port.onMessage.addListener((msg, sender) => {
|
||||
browser.test.assertEq("port message", msg, "listener2 port message received");
|
||||
|
||||
port_messages_received++
|
||||
port_messages_received++;
|
||||
browser.test.assertEq(2, port_messages_received, "2 port messages received");
|
||||
|
||||
browser.test.notifyPass("contentscript_connect.pass");
|
||||
|
@ -44,10 +48,10 @@ add_task(function* () {
|
|||
|
||||
files: {
|
||||
"script.js": function() {
|
||||
var port = browser.runtime.connect();
|
||||
let port = browser.runtime.connect();
|
||||
port.postMessage("port message");
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
yield extension.startup();
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
/* globals content */
|
||||
/* eslint-disable mozilla/no-cpows-in-tests */
|
||||
|
||||
add_task(function* () {
|
||||
let tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser,
|
||||
"http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html");
|
||||
|
@ -6,7 +13,7 @@ add_task(function* () {
|
|||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"permissions": ["contextMenus"]
|
||||
"permissions": ["contextMenus"],
|
||||
},
|
||||
|
||||
background: function() {
|
||||
|
@ -17,27 +24,27 @@ add_task(function* () {
|
|||
|
||||
browser.contextMenus.create({ "contexts": ["all"], "type": "separator" });
|
||||
|
||||
var contexts = ["page", "selection", "image"];
|
||||
for (var i = 0; i < contexts.length; i++) {
|
||||
var context = contexts[i];
|
||||
var title = context;
|
||||
var id = browser.contextMenus.create({ "title": title, "contexts": [context], "id": "ext-" + context,
|
||||
"onclick": genericOnClick });
|
||||
let contexts = ["page", "selection", "image"];
|
||||
for (let i = 0; i < contexts.length; i++) {
|
||||
let context = contexts[i];
|
||||
let title = context;
|
||||
browser.contextMenus.create({ "title": title, "contexts": [context], "id": "ext-" + context,
|
||||
"onclick": genericOnClick });
|
||||
if (context == "selection") {
|
||||
browser.contextMenus.update("ext-selection", { "title": "selection-edited" });
|
||||
}
|
||||
}
|
||||
|
||||
var parent = browser.contextMenus.create({ "title": "parent" });
|
||||
var child1 = browser.contextMenus.create(
|
||||
let parent = browser.contextMenus.create({ "title": "parent" });
|
||||
browser.contextMenus.create(
|
||||
{ "title": "child1", "parentId": parent, "onclick": genericOnClick });
|
||||
var child2 = browser.contextMenus.create(
|
||||
browser.contextMenus.create(
|
||||
{ "title": "child2", "parentId": parent, "onclick": genericOnClick });
|
||||
|
||||
var parentToDel = browser.contextMenus.create({ "title": "parentToDel" });
|
||||
var child1ToDel = browser.contextMenus.create(
|
||||
let parentToDel = browser.contextMenus.create({ "title": "parentToDel" });
|
||||
browser.contextMenus.create(
|
||||
{ "title": "child1", "parentId": parentToDel, "onclick": genericOnClick });
|
||||
var child2ToDel = browser.contextMenus.create(
|
||||
browser.contextMenus.create(
|
||||
{ "title": "child2", "parentId": parentToDel, "onclick": genericOnClick });
|
||||
browser.contextMenus.remove(parentToDel);
|
||||
|
||||
|
@ -84,7 +91,7 @@ add_task(function* () {
|
|||
items = top.getElementsByAttribute("label", "parent");
|
||||
is(items.length, 1, "contextMenu item for parent was found (context=image)");
|
||||
|
||||
is(items.item(0).childNodes[0].childNodes.length, 2, "child items for parent were found (context=image)")
|
||||
is(items.item(0).childNodes[0].childNodes.length, 2, "child items for parent were found (context=image)");
|
||||
|
||||
// Click on ext-image item and check the results
|
||||
let popupHiddenPromise = BrowserTestUtils.waitForEvent(contentAreaContextMenu, "popuphidden");
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
function genericChecker()
|
||||
{
|
||||
var kind = "background";
|
||||
var path = window.location.pathname;
|
||||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
function genericChecker() {
|
||||
let kind = "background";
|
||||
let path = window.location.pathname;
|
||||
if (path.indexOf("popup") != -1) {
|
||||
kind = "popup";
|
||||
} else if (path.indexOf("page") != -1) {
|
||||
|
@ -11,13 +14,13 @@ function genericChecker()
|
|||
browser.test.onMessage.addListener((msg, ...args) => {
|
||||
if (msg == kind + "-check-current1") {
|
||||
browser.tabs.query({
|
||||
currentWindow: true
|
||||
currentWindow: true,
|
||||
}, function(tabs) {
|
||||
browser.test.sendMessage("result", tabs[0].windowId);
|
||||
});
|
||||
} else if (msg == kind + "-check-current2") {
|
||||
browser.tabs.query({
|
||||
windowId: browser.windows.WINDOW_ID_CURRENT
|
||||
windowId: browser.windows.WINDOW_ID_CURRENT,
|
||||
}, function(tabs) {
|
||||
browser.test.sendMessage("result", tabs[0].windowId);
|
||||
});
|
||||
|
@ -26,12 +29,12 @@ function genericChecker()
|
|||
browser.test.sendMessage("result", window.id);
|
||||
});
|
||||
} else if (msg == kind + "-open-page") {
|
||||
browser.tabs.create({windowId: args[0], url: chrome.runtime.getURL("page.html")});
|
||||
browser.tabs.create({windowId: args[0], url: browser.runtime.getURL("page.html")});
|
||||
} else if (msg == kind + "-close-page") {
|
||||
browser.tabs.query({
|
||||
windowId: args[0],
|
||||
}, tabs => {
|
||||
var tab = tabs.find(tab => tab.url.indexOf("page.html") != -1);
|
||||
let tab = tabs.find(tab => tab.url.indexOf("page.html") != -1);
|
||||
browser.tabs.remove(tab.id, () => {
|
||||
browser.test.sendMessage("closed");
|
||||
});
|
||||
|
@ -58,7 +61,7 @@ add_task(function* () {
|
|||
"permissions": ["tabs"],
|
||||
|
||||
"browser_action": {
|
||||
"default_popup": "popup.html"
|
||||
"default_popup": "popup.html",
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -87,7 +90,7 @@ add_task(function* () {
|
|||
|
||||
yield Promise.all([extension.startup(), extension.awaitMessage("background-ready")]);
|
||||
|
||||
let {TabManager, WindowManager} = Cu.import("resource://gre/modules/Extension.jsm", {});
|
||||
let {WindowManager} = Cu.import("resource://gre/modules/Extension.jsm", {});
|
||||
|
||||
let winId1 = WindowManager.getId(win1);
|
||||
let winId2 = WindowManager.getId(win2);
|
||||
|
@ -112,7 +115,7 @@ add_task(function* () {
|
|||
|
||||
let evt = new CustomEvent("command", {
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
cancelable: true,
|
||||
});
|
||||
node.dispatchEvent(evt);
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
function genericChecker()
|
||||
{
|
||||
var kind = "background";
|
||||
var path = window.location.pathname;
|
||||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
function genericChecker() {
|
||||
let kind = "background";
|
||||
let path = window.location.pathname;
|
||||
if (path.indexOf("popup") != -1) {
|
||||
kind = "popup";
|
||||
} else if (path.indexOf("tab") != -1) {
|
||||
|
@ -11,14 +14,14 @@ function genericChecker()
|
|||
|
||||
browser.test.onMessage.addListener((msg, ...args) => {
|
||||
if (msg == kind + "-check-views") {
|
||||
var views = browser.extension.getViews();
|
||||
var counts = {
|
||||
let views = browser.extension.getViews();
|
||||
let counts = {
|
||||
"background": 0,
|
||||
"tab": 0,
|
||||
"popup": 0
|
||||
"popup": 0,
|
||||
};
|
||||
for (var i = 0; i < views.length; i++) {
|
||||
var view = views[i];
|
||||
for (let i = 0; i < views.length; i++) {
|
||||
let view = views[i];
|
||||
browser.test.assertTrue(view.kind in counts, "view type is valid");
|
||||
counts[view.kind]++;
|
||||
if (view.kind == "background") {
|
||||
|
@ -28,12 +31,12 @@ function genericChecker()
|
|||
}
|
||||
browser.test.sendMessage("counts", counts);
|
||||
} else if (msg == kind + "-open-tab") {
|
||||
browser.tabs.create({windowId: args[0], url: chrome.runtime.getURL("tab.html")});
|
||||
browser.tabs.create({windowId: args[0], url: browser.runtime.getURL("tab.html")});
|
||||
} else if (msg == kind + "-close-tab") {
|
||||
browser.tabs.query({
|
||||
windowId: args[0],
|
||||
}, tabs => {
|
||||
var tab = tabs.find(tab => tab.url.indexOf("tab.html") != -1);
|
||||
let tab = tabs.find(tab => tab.url.indexOf("tab.html") != -1);
|
||||
browser.tabs.remove(tab.id, () => {
|
||||
browser.test.sendMessage("closed");
|
||||
});
|
||||
|
@ -52,7 +55,7 @@ add_task(function* () {
|
|||
"permissions": ["tabs"],
|
||||
|
||||
"browser_action": {
|
||||
"default_popup": "popup.html"
|
||||
"default_popup": "popup.html",
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -83,7 +86,7 @@ add_task(function* () {
|
|||
|
||||
info("started");
|
||||
|
||||
let {TabManager, WindowManager} = Cu.import("resource://gre/modules/Extension.jsm", {});
|
||||
let {WindowManager} = Cu.import("resource://gre/modules/Extension.jsm", {});
|
||||
|
||||
let winId1 = WindowManager.getId(win1);
|
||||
let winId2 = WindowManager.getId(win2);
|
||||
|
@ -118,7 +121,7 @@ add_task(function* () {
|
|||
|
||||
let evt = new CustomEvent("command", {
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
cancelable: true,
|
||||
});
|
||||
node.dispatchEvent(evt);
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
"use strict";
|
||||
|
||||
add_task(function* testTabSwitchContext() {
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"page_action": {
|
||||
|
@ -14,8 +13,8 @@ add_task(function* testTabSwitchContext() {
|
|||
"permissions": ["tabs"],
|
||||
},
|
||||
|
||||
background: function () {
|
||||
var details = [
|
||||
background: function() {
|
||||
let details = [
|
||||
{ "icon": browser.runtime.getURL("default.png"),
|
||||
"popup": browser.runtime.getURL("default.html"),
|
||||
"title": "Default Title" },
|
||||
|
@ -27,9 +26,9 @@ add_task(function* testTabSwitchContext() {
|
|||
"title": "Title 2" },
|
||||
];
|
||||
|
||||
var tabs;
|
||||
var tests;
|
||||
var allTests = [
|
||||
let tabs;
|
||||
let tests;
|
||||
let allTests = [
|
||||
expect => {
|
||||
browser.test.log("Initial state. No icon visible.");
|
||||
expect(null);
|
||||
|
@ -53,7 +52,7 @@ add_task(function* testTabSwitchContext() {
|
|||
},
|
||||
expect => {
|
||||
browser.test.log("Change properties. Expect new properties.");
|
||||
var tabId = tabs[1];
|
||||
let tabId = tabs[1];
|
||||
browser.pageAction.show(tabId);
|
||||
browser.pageAction.setIcon({ tabId, path: "2.png" });
|
||||
browser.pageAction.setPopup({ tabId, popup: "2.html" });
|
||||
|
@ -112,10 +111,10 @@ add_task(function* testTabSwitchContext() {
|
|||
return new Promise(resolve => {
|
||||
return browser.tabs.query({ active: true, currentWindow: true }, resolve);
|
||||
}).then(tabs => {
|
||||
var tabId = tabs[0].id;
|
||||
let tabId = tabs[0].id;
|
||||
return Promise.all([
|
||||
new Promise(resolve => browser.pageAction.getTitle({tabId}, resolve)),
|
||||
new Promise(resolve => browser.pageAction.getPopup({tabId}, resolve))])
|
||||
new Promise(resolve => browser.pageAction.getPopup({tabId}, resolve))]);
|
||||
}).then(details => {
|
||||
return Promise.resolve({ title: details[0],
|
||||
popup: details[1] });
|
||||
|
@ -126,7 +125,7 @@ add_task(function* testTabSwitchContext() {
|
|||
// Runs the next test in the `tests` array, checks the results,
|
||||
// and passes control back to the outer test scope.
|
||||
function nextTest() {
|
||||
var test = tests.shift();
|
||||
let test = tests.shift();
|
||||
|
||||
test(expecting => {
|
||||
function finish() {
|
||||
|
@ -153,16 +152,6 @@ add_task(function* testTabSwitchContext() {
|
|||
});
|
||||
}
|
||||
|
||||
browser.test.onMessage.addListener((msg) => {
|
||||
if (msg == "runTests") {
|
||||
runTests();
|
||||
} else if (msg == "runNextTest") {
|
||||
nextTest();
|
||||
} else {
|
||||
browser.test.fail(`Unexpected message: ${msg}`);
|
||||
}
|
||||
});
|
||||
|
||||
function runTests() {
|
||||
tabs = [];
|
||||
tests = allTests.slice();
|
||||
|
@ -174,6 +163,16 @@ add_task(function* testTabSwitchContext() {
|
|||
});
|
||||
}
|
||||
|
||||
browser.test.onMessage.addListener((msg) => {
|
||||
if (msg == "runTests") {
|
||||
runTests();
|
||||
} else if (msg == "runNextTest") {
|
||||
nextTest();
|
||||
} else {
|
||||
browser.test.fail(`Unexpected message: ${msg}`);
|
||||
}
|
||||
});
|
||||
|
||||
runTests();
|
||||
},
|
||||
});
|
||||
|
@ -203,7 +202,7 @@ add_task(function* testTabSwitchContext() {
|
|||
checkDetails(expecting);
|
||||
|
||||
if (testsRemaining) {
|
||||
extension.sendMessage("runNextTest")
|
||||
extension.sendMessage("runNextTest");
|
||||
} else if (testNewWindows) {
|
||||
testNewWindows--;
|
||||
|
||||
|
@ -212,7 +211,7 @@ add_task(function* testTabSwitchContext() {
|
|||
currentWindow = window;
|
||||
return focusWindow(window);
|
||||
}).then(() => {
|
||||
extension.sendMessage("runTests")
|
||||
extension.sendMessage("runTests");
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
|
|
|
@ -20,11 +20,11 @@ add_task(function* testPageActionPopup() {
|
|||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"background": {
|
||||
"page": "data/background.html"
|
||||
"page": "data/background.html",
|
||||
},
|
||||
"page_action": {
|
||||
"default_popup": "popup-a.html"
|
||||
}
|
||||
"default_popup": "popup-a.html",
|
||||
},
|
||||
},
|
||||
|
||||
files: {
|
||||
|
@ -41,9 +41,10 @@ add_task(function* testPageActionPopup() {
|
|||
"data/background.html": `<script src="background.js"></script>`,
|
||||
|
||||
"data/background.js": function() {
|
||||
var tabId;
|
||||
let tabId;
|
||||
|
||||
var tests = [
|
||||
let sendClick;
|
||||
let tests = [
|
||||
() => {
|
||||
sendClick({ expectEvent: false, expectPopup: "a" });
|
||||
},
|
||||
|
@ -70,11 +71,11 @@ add_task(function* testPageActionPopup() {
|
|||
},
|
||||
];
|
||||
|
||||
var expect = {};
|
||||
function sendClick({ expectEvent, expectPopup }) {
|
||||
let expect = {};
|
||||
sendClick = ({ expectEvent, expectPopup }) => {
|
||||
expect = { event: expectEvent, popup: expectPopup };
|
||||
browser.test.sendMessage("send-click");
|
||||
}
|
||||
};
|
||||
|
||||
browser.runtime.onMessage.addListener(msg => {
|
||||
if (expect.popup) {
|
||||
|
@ -105,7 +106,7 @@ add_task(function* testPageActionPopup() {
|
|||
}
|
||||
|
||||
if (tests.length) {
|
||||
var test = tests.shift();
|
||||
let test = tests.shift();
|
||||
test();
|
||||
} else {
|
||||
browser.test.notifyPass("pageaction-tests-done");
|
||||
|
@ -159,10 +160,6 @@ add_task(function* testPageActionPopup() {
|
|||
add_task(function* testPageActionSecurity() {
|
||||
const URL = "chrome://browser/content/browser.xul";
|
||||
|
||||
let matchURLForbidden = url => ({
|
||||
message: new RegExp(`Loading extension.*Access to.*'${URL}' denied`),
|
||||
});
|
||||
|
||||
let messages = [/Access to restricted URI denied/,
|
||||
/Access to restricted URI denied/];
|
||||
|
||||
|
@ -180,9 +177,9 @@ add_task(function* testPageActionSecurity() {
|
|||
"page_action": { "default_popup": URL },
|
||||
},
|
||||
|
||||
background: function () {
|
||||
background: function() {
|
||||
browser.tabs.query({ active: true, currentWindow: true }, tabs => {
|
||||
var tabId = tabs[0].id;
|
||||
let tabId = tabs[0].id;
|
||||
|
||||
browser.pageAction.show(tabId);
|
||||
browser.test.sendMessage("ready");
|
||||
|
|
|
@ -26,7 +26,7 @@ add_task(function* testPageActionPopup() {
|
|||
},
|
||||
|
||||
background: function() {
|
||||
let tabId
|
||||
let tabId;
|
||||
browser.tabs.query({ active: true, currentWindow: true }, tabs => {
|
||||
tabId = tabs[0].id;
|
||||
browser.pageAction.show(tabId);
|
||||
|
@ -53,7 +53,7 @@ add_task(function* testPageActionPopup() {
|
|||
} else {
|
||||
EventUtils.synthesizeMouseAtCenter(button, {}, window);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let promiseConsoleMessage = pattern => new Promise(resolve => {
|
||||
Services.console.registerListener(function listener(msg) {
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
add_task(function* test_simple() {
|
||||
let extensionData = {
|
||||
manifest: {
|
||||
"name": "Simple extension test",
|
||||
"version": "1.0",
|
||||
"manifest_version": 2,
|
||||
"description": ""
|
||||
}
|
||||
"description": "",
|
||||
},
|
||||
};
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension(extensionData);
|
||||
|
@ -36,8 +40,8 @@ add_task(function* test_background() {
|
|||
"name": "Simple extension test",
|
||||
"version": "1.0",
|
||||
"manifest_version": 2,
|
||||
"description": ""
|
||||
}
|
||||
"description": "",
|
||||
},
|
||||
};
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension(extensionData);
|
||||
|
|
|
@ -1,19 +1,23 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
add_task(function* () {
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://mochi.test:8888/");
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"permissions": ["tabs"]
|
||||
"permissions": ["tabs"],
|
||||
},
|
||||
|
||||
background: function() {
|
||||
var messages_received = [];
|
||||
let messages_received = [];
|
||||
|
||||
var tabId;
|
||||
let tabId;
|
||||
|
||||
browser.runtime.onConnect.addListener((port) => {
|
||||
browser.test.assertTrue(!!port, "tab to background port received");
|
||||
browser.test.assertEq("tab-connection-name", port.name, "port name should be defined and equal to connectInfo.name")
|
||||
browser.test.assertEq("tab-connection-name", port.name, "port name should be defined and equal to connectInfo.name");
|
||||
browser.test.assertTrue(!!port.sender.tab, "port.sender.tab should be defined");
|
||||
browser.test.assertEq(tabId, port.sender.tab.id, "port.sender.tab.id should be equal to the expected tabId");
|
||||
|
||||
|
@ -31,17 +35,16 @@ add_task(function* () {
|
|||
|
||||
browser.test.notifyPass("tabRuntimeConnect.pass");
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
browser.tabs.create({
|
||||
url: "tab.html"
|
||||
}, (tab) => { tabId = tab.id });
|
||||
browser.tabs.create({ url: "tab.html" },
|
||||
(tab) => { tabId = tab.id; });
|
||||
},
|
||||
|
||||
files: {
|
||||
"tab.js": function() {
|
||||
var port = browser.runtime.connect({ name: "tab-connection-name"});
|
||||
let port = browser.runtime.connect({ name: "tab-connection-name"});
|
||||
port.postMessage("tab to background port message");
|
||||
port.onMessage.addListener((msg) => {
|
||||
port.postMessage({ tabReceived: msg });
|
||||
|
@ -59,8 +62,8 @@ add_task(function* () {
|
|||
<h1>test tab extension page</h1>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
}
|
||||
`,
|
||||
},
|
||||
});
|
||||
|
||||
yield extension.startup();
|
||||
|
|
|
@ -5,38 +5,40 @@
|
|||
function* testHasNoPermission(params) {
|
||||
let contentSetup = params.contentSetup || (() => Promise.resolve());
|
||||
|
||||
function background(contentSetup) {
|
||||
browser.runtime.onMessage.addListener((msg, sender) => {
|
||||
browser.test.assertEq(msg, "second script ran", "second script ran");
|
||||
browser.test.notifyPass("executeScript");
|
||||
});
|
||||
|
||||
browser.test.onMessage.addListener(msg => {
|
||||
browser.test.assertEq(msg, "execute-script");
|
||||
|
||||
browser.tabs.query({ activeWindow: true }, tabs => {
|
||||
browser.tabs.executeScript({
|
||||
file: "script.js",
|
||||
});
|
||||
|
||||
// Execute a script we know we have permissions for in the
|
||||
// second tab, in the hopes that it will execute after the
|
||||
// first one. This has intermittent failure written all over
|
||||
// it, but it's just about the best we can do until we
|
||||
// support callbacks for executeScript.
|
||||
browser.tabs.executeScript(tabs[1].id, {
|
||||
file: "second-script.js",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
contentSetup().then(() => {
|
||||
browser.test.sendMessage("ready");
|
||||
});
|
||||
}
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: params.manifest,
|
||||
|
||||
background: `(${function(contentSetup) {
|
||||
browser.runtime.onMessage.addListener((msg, sender) => {
|
||||
browser.test.assertEq(msg, "second script ran", "second script ran");
|
||||
browser.test.notifyPass("executeScript");
|
||||
});
|
||||
|
||||
browser.test.onMessage.addListener(msg => {
|
||||
browser.test.assertEq(msg, "execute-script");
|
||||
|
||||
browser.tabs.query({ activeWindow: true }, tabs => {
|
||||
browser.tabs.executeScript({
|
||||
file: "script.js"
|
||||
});
|
||||
|
||||
// Execute a script we know we have permissions for in the
|
||||
// second tab, in the hopes that it will execute after the
|
||||
// first one. This has intermittent failure written all over
|
||||
// it, but it's just about the best we can do until we
|
||||
// support callbacks for executeScript.
|
||||
browser.tabs.executeScript(tabs[1].id, {
|
||||
file: "second-script.js"
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
contentSetup().then(() => {
|
||||
browser.test.sendMessage("ready");
|
||||
});
|
||||
}})(${contentSetup})`,
|
||||
background: `(${background})(${contentSetup})`,
|
||||
|
||||
files: {
|
||||
"script.js": function() {
|
||||
|
@ -45,8 +47,8 @@ function* testHasNoPermission(params) {
|
|||
|
||||
"second-script.js": function() {
|
||||
browser.runtime.sendMessage("second script ran");
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
yield extension.startup();
|
||||
|
@ -68,12 +70,12 @@ add_task(function* testBadPermissions() {
|
|||
|
||||
info("Test no special permissions");
|
||||
yield testHasNoPermission({
|
||||
manifest: { "permissions": ["http://example.com/"] }
|
||||
manifest: { "permissions": ["http://example.com/"] },
|
||||
});
|
||||
|
||||
info("Test tabs permissions");
|
||||
yield testHasNoPermission({
|
||||
manifest: { "permissions": ["http://example.com/", "tabs"] }
|
||||
manifest: { "permissions": ["http://example.com/", "tabs"] },
|
||||
});
|
||||
|
||||
info("Test active tab, browser action, no click");
|
||||
|
@ -97,7 +99,7 @@ add_task(function* testBadPermissions() {
|
|||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
yield BrowserTestUtils.removeTab(tab2);
|
||||
|
|
|
@ -1,35 +1,39 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
function* testHasPermission(params) {
|
||||
let contentSetup = params.contentSetup || (() => Promise.resolve());
|
||||
|
||||
function background(contentSetup) {
|
||||
browser.runtime.onMessage.addListener((msg, sender) => {
|
||||
browser.test.assertEq(msg, "script ran", "script ran");
|
||||
browser.test.notifyPass("executeScript");
|
||||
});
|
||||
|
||||
browser.test.onMessage.addListener(msg => {
|
||||
browser.test.assertEq(msg, "execute-script");
|
||||
|
||||
browser.tabs.executeScript({
|
||||
file: "script.js",
|
||||
});
|
||||
});
|
||||
|
||||
contentSetup().then(() => {
|
||||
browser.test.sendMessage("ready");
|
||||
});
|
||||
}
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: params.manifest,
|
||||
|
||||
background: `(${function(contentSetup) {
|
||||
browser.runtime.onMessage.addListener((msg, sender) => {
|
||||
browser.test.assertEq(msg, "script ran", "script ran");
|
||||
browser.test.notifyPass("executeScript");
|
||||
});
|
||||
|
||||
browser.test.onMessage.addListener(msg => {
|
||||
browser.test.assertEq(msg, "execute-script");
|
||||
|
||||
browser.tabs.executeScript({
|
||||
file: "script.js"
|
||||
});
|
||||
});
|
||||
|
||||
contentSetup().then(() => {
|
||||
browser.test.sendMessage("ready");
|
||||
});
|
||||
}})(${contentSetup})`,
|
||||
background: `(${background})(${contentSetup})`,
|
||||
|
||||
files: {
|
||||
"script.js": function() {
|
||||
browser.runtime.sendMessage("script ran");
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
yield extension.startup();
|
||||
|
@ -50,17 +54,17 @@ add_task(function* testGoodPermissions() {
|
|||
|
||||
info("Test explicit host permission");
|
||||
yield testHasPermission({
|
||||
manifest: { "permissions": ["http://mochi.test/"] }
|
||||
manifest: { "permissions": ["http://mochi.test/"] },
|
||||
});
|
||||
|
||||
info("Test explicit host subdomain permission");
|
||||
yield testHasPermission({
|
||||
manifest: { "permissions": ["http://*.mochi.test/"] }
|
||||
manifest: { "permissions": ["http://*.mochi.test/"] },
|
||||
});
|
||||
|
||||
info("Test explicit <all_urls> permission");
|
||||
yield testHasPermission({
|
||||
manifest: { "permissions": ["<all_urls>"] }
|
||||
manifest: { "permissions": ["<all_urls>"] },
|
||||
});
|
||||
|
||||
info("Test activeTab permission with a browser action click");
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
add_task(function* () {
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
add_task(function* () {
|
||||
let win1 = yield BrowserTestUtils.openNewBrowserWindow();
|
||||
|
||||
|
@ -9,49 +13,49 @@ add_task(function* () {
|
|||
"content_scripts": [{
|
||||
"matches": ["http://mochi.test/*/context_tabs_onUpdated_page.html"],
|
||||
"js": ["content-script.js"],
|
||||
"run_at": "document_start"
|
||||
},],
|
||||
"run_at": "document_start",
|
||||
}],
|
||||
},
|
||||
|
||||
background: function() {
|
||||
var pageURL = "http://mochi.test:8888/browser/browser/components/extensions/test/browser/context_tabs_onUpdated_page.html";
|
||||
let pageURL = "http://mochi.test:8888/browser/browser/components/extensions/test/browser/context_tabs_onUpdated_page.html";
|
||||
|
||||
var expectedSequence = [
|
||||
let expectedSequence = [
|
||||
{ status: "loading" },
|
||||
{ status: "loading", url: pageURL },
|
||||
{ status: "complete" }
|
||||
{ status: "complete" },
|
||||
];
|
||||
var collectedSequence = [];
|
||||
let collectedSequence = [];
|
||||
|
||||
browser.tabs.onUpdated.addListener(function (tabId, updatedInfo) {
|
||||
browser.tabs.onUpdated.addListener(function(tabId, updatedInfo) {
|
||||
collectedSequence.push(updatedInfo);
|
||||
});
|
||||
|
||||
browser.runtime.onMessage.addListener(function () {
|
||||
if (collectedSequence.length !== expectedSequence.length) {
|
||||
browser.runtime.onMessage.addListener(function() {
|
||||
if (collectedSequence.length !== expectedSequence.length) {
|
||||
browser.test.assertEq(
|
||||
JSON.stringify(expectedSequence),
|
||||
JSON.stringify(collectedSequence),
|
||||
"got unexpected number of updateInfo data"
|
||||
);
|
||||
} else {
|
||||
for (let i = 0; i < expectedSequence.length; i++) {
|
||||
browser.test.assertEq(
|
||||
JSON.stringify(expectedSequence),
|
||||
JSON.stringify(collectedSequence),
|
||||
"got unexpected number of updateInfo data"
|
||||
expectedSequence[i].status,
|
||||
collectedSequence[i].status,
|
||||
"check updatedInfo status"
|
||||
);
|
||||
} else {
|
||||
for (var i = 0; i < expectedSequence.length; i++) {
|
||||
if (expectedSequence[i].url || collectedSequence[i].url) {
|
||||
browser.test.assertEq(
|
||||
expectedSequence[i].status,
|
||||
collectedSequence[i].status,
|
||||
"check updatedInfo status"
|
||||
expectedSequence[i].url,
|
||||
collectedSequence[i].url,
|
||||
"check updatedInfo url"
|
||||
);
|
||||
if (expectedSequence[i].url || collectedSequence[i].url) {
|
||||
browser.test.assertEq(
|
||||
expectedSequence[i].url,
|
||||
collectedSequence[i].url,
|
||||
"check updatedInfo url"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
browser.test.notifyPass("tabs.onUpdated");
|
||||
browser.test.notifyPass("tabs.onUpdated");
|
||||
});
|
||||
|
||||
browser.tabs.create({ url: pageURL });
|
||||
|
@ -64,12 +68,12 @@ add_task(function* () {
|
|||
}
|
||||
}, true);
|
||||
`,
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
yield Promise.all([
|
||||
extension.startup(),
|
||||
extension.awaitFinish("tabs.onUpdated")
|
||||
extension.awaitFinish("tabs.onUpdated"),
|
||||
]);
|
||||
|
||||
yield extension.unload();
|
||||
|
@ -84,7 +88,7 @@ function* do_test_update(background) {
|
|||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"permissions": ["tabs"]
|
||||
"permissions": ["tabs"],
|
||||
},
|
||||
|
||||
background: background,
|
||||
|
@ -92,7 +96,7 @@ function* do_test_update(background) {
|
|||
|
||||
yield Promise.all([
|
||||
yield extension.startup(),
|
||||
yield extension.awaitFinish("finish")
|
||||
yield extension.awaitFinish("finish"),
|
||||
]);
|
||||
|
||||
yield extension.unload();
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
add_task(function* () {
|
||||
let tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:robots");
|
||||
let tab2 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:config");
|
||||
|
@ -6,16 +10,16 @@ add_task(function* () {
|
|||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"permissions": ["tabs"]
|
||||
"permissions": ["tabs"],
|
||||
},
|
||||
|
||||
background: function() {
|
||||
browser.tabs.query({
|
||||
lastFocusedWindow: true
|
||||
lastFocusedWindow: true,
|
||||
}, function(tabs) {
|
||||
browser.test.assertEq(tabs.length, 3, "should have three tabs");
|
||||
|
||||
tabs.sort(function (tab1, tab2) { return tab1.index - tab2.index; });
|
||||
tabs.sort((tab1, tab2) => tab1.index - tab2.index);
|
||||
|
||||
browser.test.assertEq(tabs[0].url, "about:blank", "first tab blank");
|
||||
tabs.shift();
|
||||
|
@ -53,16 +57,16 @@ add_task(function* () {
|
|||
// test simple queries
|
||||
extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"permissions": ["tabs"]
|
||||
"permissions": ["tabs"],
|
||||
},
|
||||
|
||||
background: function() {
|
||||
browser.tabs.query({
|
||||
url: "<all_urls>"
|
||||
url: "<all_urls>",
|
||||
}, function(tabs) {
|
||||
browser.test.assertEq(tabs.length, 3, "should have three tabs");
|
||||
|
||||
tabs.sort(function (tab1, tab2) { return tab1.index - tab2.index; });
|
||||
tabs.sort((tab1, tab2) => tab1.index - tab2.index);
|
||||
|
||||
browser.test.assertEq(tabs[0].url, "http://example.com/", "tab 0 url correct");
|
||||
browser.test.assertEq(tabs[1].url, "http://example.net/", "tab 1 url correct");
|
||||
|
@ -80,12 +84,12 @@ add_task(function* () {
|
|||
// match pattern
|
||||
extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"permissions": ["tabs"]
|
||||
"permissions": ["tabs"],
|
||||
},
|
||||
|
||||
background: function() {
|
||||
browser.tabs.query({
|
||||
url: "http://*/MochiKit*"
|
||||
url: "http://*/MochiKit*",
|
||||
}, function(tabs) {
|
||||
browser.test.assertEq(tabs.length, 1, "should have one tab");
|
||||
|
||||
|
@ -103,16 +107,16 @@ add_task(function* () {
|
|||
// match array of patterns
|
||||
extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"permissions": ["tabs"]
|
||||
"permissions": ["tabs"],
|
||||
},
|
||||
|
||||
background: function() {
|
||||
browser.tabs.query({
|
||||
url: ["http://*/MochiKit*", "http://*.com/*"]
|
||||
url: ["http://*/MochiKit*", "http://*.com/*"],
|
||||
}, function(tabs) {
|
||||
browser.test.assertEq(tabs.length, 2, "should have two tabs");
|
||||
|
||||
tabs.sort(function (tab1, tab2) { return tab1.index - tab2.index; });
|
||||
tabs.sort((tab1, tab2) => tab1.index - tab2.index);
|
||||
|
||||
browser.test.assertEq(tabs[0].url, "http://example.com/", "tab 0 url correct");
|
||||
browser.test.assertEq(tabs[1].url, "http://test1.example.org/MochiKit/", "tab 1 url correct");
|
||||
|
|
|
@ -1,30 +1,34 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
add_task(function* tabsSendMessageNoExceptionOnNonExistentTab() {
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"permissions": ["tabs"]
|
||||
"permissions": ["tabs"],
|
||||
},
|
||||
|
||||
background: function() {
|
||||
chrome.tabs.create({ url: "about:robots"}, function (tab) {
|
||||
var exception;
|
||||
browser.tabs.create({ url: "about:robots"}, tab => {
|
||||
let exception;
|
||||
try {
|
||||
browser.tabs.sendMessage(tab.id, "message");
|
||||
browser.tabs.sendMessage(tab.id + 100, "message");
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
exception = e;
|
||||
}
|
||||
|
||||
browser.test.assertEq(undefined, exception, "no exception should be raised on tabs.sendMessage to unexistent tabs");
|
||||
chrome.tabs.remove(tab.id, function() {
|
||||
browser.tabs.remove(tab.id, function() {
|
||||
browser.test.notifyPass("tabs.sendMessage");
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
yield Promise.all([
|
||||
extension.startup(),
|
||||
extension.awaitFinish("tabs.sendMessage")
|
||||
extension.awaitFinish("tabs.sendMessage"),
|
||||
]);
|
||||
|
||||
yield extension.unload();
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
add_task(function* () {
|
||||
let tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:robots");
|
||||
let tab2 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:config");
|
||||
|
@ -6,7 +10,7 @@ add_task(function* () {
|
|||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"permissions": ["tabs"]
|
||||
"permissions": ["tabs"],
|
||||
},
|
||||
|
||||
background: function() {
|
||||
|
@ -15,7 +19,7 @@ add_task(function* () {
|
|||
}, function(tabs) {
|
||||
browser.test.assertEq(tabs.length, 3, "should have three tabs");
|
||||
|
||||
tabs.sort(function (tab1, tab2) { return tab1.index - tab2.index; });
|
||||
tabs.sort((tab1, tab2) => tab1.index - tab2.index);
|
||||
|
||||
browser.test.assertEq(tabs[0].url, "about:blank", "first tab blank");
|
||||
tabs.shift();
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
add_task(function* () {
|
||||
function promiseWaitForFocus(aWindow) {
|
||||
return new Promise(function(aResolve, aReject) {
|
||||
function promiseWaitForFocus(window) {
|
||||
return new Promise(resolve => {
|
||||
waitForFocus(function() {
|
||||
ok(Services.focus.activeWindow === aWindow, "correct window focused");
|
||||
aResolve();
|
||||
}, aWindow);
|
||||
ok(Services.focus.activeWindow === window, "correct window focused");
|
||||
resolve();
|
||||
}, window);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -16,7 +20,7 @@ add_task(function* () {
|
|||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"permissions": ["windows"]
|
||||
"permissions": ["windows"],
|
||||
},
|
||||
|
||||
background: function() {
|
||||
|
@ -35,7 +39,6 @@ add_task(function* () {
|
|||
browser.windows.update(wins[0].id, {focused: true}, function() {
|
||||
browser.test.sendMessage("check");
|
||||
});
|
||||
|
||||
});
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
/* exported CustomizableUI makeWidgetId focusWindow clickBrowserAction clickPageAction */
|
||||
|
||||
var {CustomizableUI} = Cu.import("resource:///modules/CustomizableUI.jsm");
|
||||
|
||||
function makeWidgetId(id)
|
||||
{
|
||||
function makeWidgetId(id) {
|
||||
id = id.toLowerCase();
|
||||
return id.replace(/[^a-z0-9_-]/g, "_");
|
||||
}
|
||||
|
||||
var focusWindow = Task.async(function* focusWindow(win)
|
||||
{
|
||||
var focusWindow = Task.async(function* focusWindow(win) {
|
||||
let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
|
||||
if (fm.activeWindow == win) {
|
||||
return;
|
||||
|
@ -39,6 +43,7 @@ function clickPageAction(extension, win = window) {
|
|||
//
|
||||
// Unfortunately, that doesn't happen automatically in browser chrome
|
||||
// tests.
|
||||
/* globals SetPageProxyState */
|
||||
SetPageProxyState("valid");
|
||||
|
||||
let pageActionId = makeWidgetId(extension.id) + "-page-action";
|
||||
|
|
|
@ -1293,8 +1293,7 @@ PlacesController.prototype = {
|
|||
let itemsToSelect = [];
|
||||
if (PlacesUIUtils.useAsyncTransactions) {
|
||||
if (ip.isTag) {
|
||||
let uris = [for (item of items) if ("uri" in item)
|
||||
NetUtil.newURI(item.uri)];
|
||||
let uris = items.filter(item => "uri" in item).map(item => NetUtil.newURI(item.uri));
|
||||
yield PlacesTransactions.Tag({ uris: uris, tag: ip.tagName }).transact();
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -673,7 +673,7 @@ var PlacesOrganizer = {
|
|||
}
|
||||
else if (!selectedNode && aNodeList[0]) {
|
||||
if (aNodeList.every(PlacesUtils.nodeIsURI)) {
|
||||
let uris = [for (node of aNodeList) PlacesUtils._uri(node.uri)];
|
||||
let uris = aNodeList.map(node => PlacesUtils._uri(node.uri));
|
||||
detailsDeck.selectedIndex = 1;
|
||||
gEditItemOverlay.initPanel({ uris
|
||||
, hiddenRows: ["folderPicker",
|
||||
|
|
|
@ -154,7 +154,7 @@ PlacesTreeView.prototype = {
|
|||
// A node is removed form the view either if it has no parent or if its
|
||||
// root-ancestor is not the root node (in which case that's the node
|
||||
// for which nodeRemoved was called).
|
||||
let ancestors = [x for (x of PlacesUtils.nodeAncestors(aNode))];
|
||||
let ancestors = Array.from(PlacesUtils.nodeAncestors(aNode));
|
||||
if (ancestors.length == 0 ||
|
||||
ancestors[ancestors.length - 1] != this._rootNode) {
|
||||
throw new Error("Removed node passed to _getRowForNode");
|
||||
|
|
|
@ -401,6 +401,20 @@ var SessionStoreInternal = {
|
|||
// that is being stored in _closedWindows for that tab.
|
||||
_closedWindowTabs: new WeakMap(),
|
||||
|
||||
// A set of window data that has the potential to be saved in the _closedWindows
|
||||
// array for the session. We will remove window data from this set whenever
|
||||
// forgetClosedWindow is called for the window, or when session history is
|
||||
// purged, so that we don't accidentally save that data after the flush has
|
||||
// completed. Closed tabs use a more complicated mechanism for this particular
|
||||
// problem. When forgetClosedTab is called, the browser is removed from the
|
||||
// _closedTabs map, so its data is not recorded. In the purge history case,
|
||||
// the closedTabs array per window is overwritten so that once the flush is
|
||||
// complete, the tab would only ever add itself to an array that SessionStore
|
||||
// no longer cares about. Bug 1230636 has been filed to make the tab case
|
||||
// work more like the window case, which is more explicit, and easier to
|
||||
// reason about.
|
||||
_saveableClosedWindowData: new WeakSet(),
|
||||
|
||||
// A map (xul:browser -> object) that maps a browser that is switching
|
||||
// remoteness via navigateAndRestore, to the loadArguments that were
|
||||
// most recently passed when calling navigateAndRestore.
|
||||
|
@ -1270,6 +1284,10 @@ var SessionStoreInternal = {
|
|||
// clear this window from the list, since it has definitely been closed.
|
||||
delete this._windows[aWindow.__SSi];
|
||||
|
||||
// This window has the potential to be saved in the _closedWindows
|
||||
// array (maybeSaveClosedWindows gets the final call on that).
|
||||
this._saveableClosedWindowData.add(winData);
|
||||
|
||||
// Now we have to figure out if this window is worth saving in the _closedWindows
|
||||
// Object.
|
||||
//
|
||||
|
@ -1352,6 +1370,7 @@ var SessionStoreInternal = {
|
|||
let mm = aWindow.getGroupMessageManager("browsers");
|
||||
MESSAGES.forEach(msg => mm.removeMessageListener(msg, this));
|
||||
|
||||
this._saveableClosedWindowData.delete(winData);
|
||||
delete aWindow.__SSi;
|
||||
},
|
||||
|
||||
|
@ -1373,7 +1392,9 @@ var SessionStoreInternal = {
|
|||
* a window flush).
|
||||
*/
|
||||
maybeSaveClosedWindow(winData, isLastWindow) {
|
||||
if (RunState.isRunning) {
|
||||
// Make sure SessionStore is still running, and make sure that we
|
||||
// haven't chosen to forget this window.
|
||||
if (RunState.isRunning && this._saveableClosedWindowData.has(winData)) {
|
||||
// Determine whether the window has any tabs worth saving.
|
||||
let hasSaveableTabs = winData.tabs.some(this._shouldSaveTabState);
|
||||
|
||||
|
@ -1546,6 +1567,7 @@ var SessionStoreInternal = {
|
|||
}
|
||||
|
||||
this._clearRestoringWindows();
|
||||
this._saveableClosedWindowData.clear();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -2190,7 +2212,9 @@ var SessionStoreInternal = {
|
|||
}
|
||||
|
||||
// remove closed window from the array
|
||||
let winData = this._closedWindows[aIndex];
|
||||
this._closedWindows.splice(aIndex, 1);
|
||||
this._saveableClosedWindowData.delete(winData);
|
||||
},
|
||||
|
||||
getWindowValue: function ssi_getWindowValue(aWindow, aKey) {
|
||||
|
|
|
@ -218,3 +218,4 @@ skip-if = os == "mac"
|
|||
[browser_multiple_navigateAndRestore.js]
|
||||
run-if = e10s
|
||||
[browser_async_window_flushing.js]
|
||||
[browser_forget_async_closings.js]
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
"use strict";
|
||||
|
||||
const PAGE = "http://example.com/";
|
||||
|
||||
/**
|
||||
* Creates a tab in the current window worth storing in the
|
||||
* closedTabs array, and then closes it. Runs a synchronous
|
||||
* forgetFn passed in that should cause us to forget the tab,
|
||||
* and then ensures that after the tab has sent its final
|
||||
* update message that we didn't accidentally store it in
|
||||
* the closedTabs array.
|
||||
*
|
||||
* @param forgetFn (function)
|
||||
* A synchronous function that should cause the tab
|
||||
* to be forgotten.
|
||||
* @returns Promise
|
||||
*/
|
||||
let forgetTabHelper = Task.async(function*(forgetFn) {
|
||||
// We want to suppress all non-final updates from the browser tabs
|
||||
// so as to eliminate any racy-ness with this test.
|
||||
yield pushPrefs(["browser.sessionstore.debug.no_auto_updates", true]);
|
||||
|
||||
// Forget any previous closed tabs from other tests that may have
|
||||
// run in the same session.
|
||||
Services.obs.notifyObservers(null, "browser:purge-session-history", 0);
|
||||
|
||||
is(ss.getClosedTabCount(window), 0,
|
||||
"We should have 0 closed tabs being stored.");
|
||||
|
||||
// Create a tab worth remembering.
|
||||
let tab = gBrowser.addTab(PAGE);
|
||||
let browser = tab.linkedBrowser;
|
||||
yield BrowserTestUtils.browserLoaded(browser, false, PAGE);
|
||||
yield TabStateFlusher.flush(browser);
|
||||
|
||||
// Now close the tab, and immediately choose to forget it.
|
||||
let promise = BrowserTestUtils.removeTab(tab);
|
||||
|
||||
// At this point, the tab will have closed, but the final update
|
||||
// to SessionStore hasn't come up yet. Now do the operation that
|
||||
// should cause us to forget the tab.
|
||||
forgetFn();
|
||||
|
||||
is(ss.getClosedTabCount(window), 0, "Should have forgotten the closed tab");
|
||||
|
||||
// Now wait for the final update to come up.
|
||||
yield promise;
|
||||
|
||||
is(ss.getClosedTabCount(window), 0,
|
||||
"Should not have stored the forgotten closed tab");
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a new window worth storing in the closeWIndows array,
|
||||
* and then closes it. Runs a synchronous forgetFn passed in that
|
||||
* should cause us to forget the window, and then ensures that after
|
||||
* the window has sent its final update message that we didn't
|
||||
* accidentally store it in the closedWindows array.
|
||||
*
|
||||
* @param forgetFn (function)
|
||||
* A synchronous function that should cause the window
|
||||
* to be forgotten.
|
||||
* @returns Promise
|
||||
*/
|
||||
let forgetWinHelper = Task.async(function*(forgetFn) {
|
||||
// We want to suppress all non-final updates from the browser tabs
|
||||
// so as to eliminate any racy-ness with this test.
|
||||
yield pushPrefs(["browser.sessionstore.debug.no_auto_updates", true]);
|
||||
|
||||
// Forget any previous closed windows from other tests that may have
|
||||
// run in the same session.
|
||||
Services.obs.notifyObservers(null, "browser:purge-session-history", 0);
|
||||
|
||||
is(ss.getClosedWindowCount(), 0, "We should have 0 closed windows being stored.");
|
||||
|
||||
let newWin = yield BrowserTestUtils.openNewBrowserWindow();
|
||||
|
||||
// Create a tab worth remembering.
|
||||
let tab = newWin.gBrowser.selectedTab;
|
||||
let browser = tab.linkedBrowser;
|
||||
browser.loadURI(PAGE);
|
||||
yield BrowserTestUtils.browserLoaded(browser, false, PAGE);
|
||||
yield TabStateFlusher.flush(browser);
|
||||
|
||||
// Now close the window and immediately choose to forget it.
|
||||
let windowClosed = BrowserTestUtils.windowClosed(newWin);
|
||||
let domWindowClosed = BrowserTestUtils.domWindowClosed(newWin);
|
||||
|
||||
newWin.close();
|
||||
yield domWindowClosed;
|
||||
|
||||
// At this point, the window will have closed and the onClose handler
|
||||
// has run, but the final update to SessionStore hasn't come up yet.
|
||||
// Now do the oepration that should cause us to forget the window.
|
||||
forgetFn();
|
||||
|
||||
is(ss.getClosedWindowCount(), 0, "Should have forgotten the closed window");
|
||||
|
||||
// Now wait for the final update to come up.
|
||||
yield windowClosed;
|
||||
|
||||
is(ss.getClosedWindowCount(), 0, "Should not have stored the closed window");
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that if we choose to forget a tab while waiting for its
|
||||
* final flush to complete, we don't accidentally store it.
|
||||
*/
|
||||
add_task(function* test_forget_closed_tab() {
|
||||
yield forgetTabHelper(() => {
|
||||
ss.forgetClosedTab(window, 0);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that if we choose to forget a tab while waiting for its
|
||||
* final flush to complete, we don't accidentally store it.
|
||||
*/
|
||||
add_task(function* test_forget_closed_window() {
|
||||
yield forgetWinHelper(() => {
|
||||
ss.forgetClosedWindow(0);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that if we choose to purge history while waiting for a
|
||||
* final flush of a tab to complete, we don't accidentally store it.
|
||||
*/
|
||||
add_task(function* test_forget_purged_tab() {
|
||||
yield forgetTabHelper(() => {
|
||||
Services.obs.notifyObservers(null, "browser:purge-session-history", 0);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that if we choose to purge history while waiting for a
|
||||
* final flush of a window to complete, we don't accidentally
|
||||
* store it.
|
||||
*/
|
||||
add_task(function* test_forget_purged_window() {
|
||||
yield forgetWinHelper(() => {
|
||||
Services.obs.notifyObservers(null, "browser:purge-session-history", 0);
|
||||
});
|
||||
});
|
|
@ -29,6 +29,7 @@ describe("loop.conversation", function() {
|
|||
GetLoopPref: function(prefName) {
|
||||
switch (prefName) {
|
||||
case "debug.sdk":
|
||||
case "debug.dispatcher":
|
||||
return false;
|
||||
default:
|
||||
return "http://fake";
|
||||
|
|
|
@ -56,7 +56,11 @@ describe("loop.panel", function() {
|
|||
GetPluralRule: sinon.stub(),
|
||||
SetLoopPref: sinon.stub(),
|
||||
GetLoopPref: function(prefName) {
|
||||
return "unseen";
|
||||
if (prefName === "gettingStarted.seen") {
|
||||
return "unseen";
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
GetPluralForm: function() {
|
||||
return "fakeText";
|
||||
|
|
|
@ -50,8 +50,10 @@ describe("loop.store.RoomStore", function() {
|
|||
};
|
||||
},
|
||||
CopyString: sinon.stub(),
|
||||
GetLoopPref: function(pref) {
|
||||
return pref;
|
||||
GetLoopPref: function(prefName) {
|
||||
if (prefName === "debug.dispatcher") {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
NotifyUITour: function() {},
|
||||
"Rooms:Create": sinon.stub().returns({ roomToken: "fakeToken" }),
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
This is the pdf.js project output, https://github.com/mozilla/pdf.js
|
||||
|
||||
Current extension version is: 1.3.42
|
||||
Current extension version is: 1.3.56
|
||||
|
|
|
@ -20,8 +20,8 @@ if (typeof PDFJS === 'undefined') {
|
|||
(typeof window !== 'undefined' ? window : this).PDFJS = {};
|
||||
}
|
||||
|
||||
PDFJS.version = '1.3.42';
|
||||
PDFJS.build = '84a47f8';
|
||||
PDFJS.version = '1.3.56';
|
||||
PDFJS.build = 'e2aca38';
|
||||
|
||||
(function pdfjsWrapper() {
|
||||
// Use strict in our context only - users might not want it
|
||||
|
@ -248,7 +248,6 @@ function error(msg) {
|
|||
console.log('Error: ' + msg);
|
||||
console.log(backtrace());
|
||||
}
|
||||
UnsupportedManager.notify(UNSUPPORTED_FEATURES.unknown);
|
||||
throw new Error(msg);
|
||||
}
|
||||
|
||||
|
@ -275,22 +274,6 @@ var UNSUPPORTED_FEATURES = PDFJS.UNSUPPORTED_FEATURES = {
|
|||
font: 'font'
|
||||
};
|
||||
|
||||
var UnsupportedManager = PDFJS.UnsupportedManager =
|
||||
(function UnsupportedManagerClosure() {
|
||||
var listeners = [];
|
||||
return {
|
||||
listen: function (cb) {
|
||||
listeners.push(cb);
|
||||
},
|
||||
notify: function (featureId) {
|
||||
warn('Unsupported feature "' + featureId + '"');
|
||||
for (var i = 0, ii = listeners.length; i < ii; i++) {
|
||||
listeners[i](featureId);
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
// 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) {
|
||||
|
@ -1772,6 +1755,12 @@ var PDFDocumentLoadingTask = (function PDFDocumentLoadingTaskClosure() {
|
|||
* an {Object} with the properties: {number} loaded and {number} total.
|
||||
*/
|
||||
this.onProgress = null;
|
||||
|
||||
/**
|
||||
* Callback to when unsupported feature is used. The callback receives
|
||||
* an {PDFJS.UNSUPPORTED_FEATURES} argument.
|
||||
*/
|
||||
this.onUnsupportedFeature = null;
|
||||
}
|
||||
|
||||
PDFDocumentLoadingTask.prototype =
|
||||
|
@ -2530,9 +2519,6 @@ var PDFWorker = (function PDFWorkerClosure() {
|
|||
messageHandler.on('console_error', function (data) {
|
||||
console.error.apply(console, data);
|
||||
});
|
||||
messageHandler.on('_unsupported_feature', function (data) {
|
||||
UnsupportedManager.notify(data);
|
||||
});
|
||||
|
||||
var testObj = new Uint8Array([PDFJS.postMessageTransfers ? 255 : 0]);
|
||||
// Some versions of Opera throw a DATA_CLONE_ERR on serializing the
|
||||
|
@ -2899,6 +2885,19 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
|||
}
|
||||
}, this);
|
||||
|
||||
messageHandler.on('UnsupportedFeature',
|
||||
function transportUnsupportedFeature(data) {
|
||||
if (this.destroyed) {
|
||||
return; // Ignore any pending requests if the worker was terminated.
|
||||
}
|
||||
var featureId = data.featureId;
|
||||
var loadingTask = this.loadingTask;
|
||||
if (loadingTask.onUnsupportedFeature) {
|
||||
loadingTask.onUnsupportedFeature(featureId);
|
||||
}
|
||||
PDFJS.UnsupportedManager.notify(featureId);
|
||||
}, this);
|
||||
|
||||
messageHandler.on('JpegDecode', function(data) {
|
||||
if (this.destroyed) {
|
||||
return Promise.reject('Worker was terminated');
|
||||
|
@ -3316,6 +3315,26 @@ var InternalRenderTask = (function InternalRenderTaskClosure() {
|
|||
return InternalRenderTask;
|
||||
})();
|
||||
|
||||
/**
|
||||
* (Deprecated) Global observer of unsupported feature usages. Use
|
||||
* onUnsupportedFeature callback of the {PDFDocumentLoadingTask} instance.
|
||||
*/
|
||||
PDFJS.UnsupportedManager = (function UnsupportedManagerClosure() {
|
||||
var listeners = [];
|
||||
return {
|
||||
listen: function (cb) {
|
||||
deprecated('Global UnsupportedManager.listen is used: ' +
|
||||
' use PDFDocumentLoadingTask.onUnsupportedFeature instead');
|
||||
listeners.push(cb);
|
||||
},
|
||||
notify: function (featureId) {
|
||||
for (var i = 0, ii = listeners.length; i < ii; i++) {
|
||||
listeners[i](featureId);
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
var Metadata = PDFJS.Metadata = (function MetadataClosure() {
|
||||
function fixMetadata(meta) {
|
||||
|
@ -4352,6 +4371,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||
|
||||
composeSMask(this.ctx, this.current.activeSMask, groupCtx);
|
||||
this.ctx.restore();
|
||||
copyCtxState(groupCtx, this.ctx);
|
||||
},
|
||||
save: function CanvasGraphics_save() {
|
||||
this.ctx.save();
|
||||
|
@ -5471,7 +5491,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||
},
|
||||
|
||||
paintXObject: function CanvasGraphics_paintXObject() {
|
||||
UnsupportedManager.notify(UNSUPPORTED_FEATURES.unknown);
|
||||
warn('Unsupported \'paintXObject\' command.');
|
||||
},
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@ if (typeof PDFJS === 'undefined') {
|
|||
(typeof window !== 'undefined' ? window : this).PDFJS = {};
|
||||
}
|
||||
|
||||
PDFJS.version = '1.3.42';
|
||||
PDFJS.build = '84a47f8';
|
||||
PDFJS.version = '1.3.56';
|
||||
PDFJS.build = 'e2aca38';
|
||||
|
||||
(function pdfjsWrapper() {
|
||||
// Use strict in our context only - users might not want it
|
||||
|
@ -248,7 +248,6 @@ function error(msg) {
|
|||
console.log('Error: ' + msg);
|
||||
console.log(backtrace());
|
||||
}
|
||||
UnsupportedManager.notify(UNSUPPORTED_FEATURES.unknown);
|
||||
throw new Error(msg);
|
||||
}
|
||||
|
||||
|
@ -275,22 +274,6 @@ var UNSUPPORTED_FEATURES = PDFJS.UNSUPPORTED_FEATURES = {
|
|||
font: 'font'
|
||||
};
|
||||
|
||||
var UnsupportedManager = PDFJS.UnsupportedManager =
|
||||
(function UnsupportedManagerClosure() {
|
||||
var listeners = [];
|
||||
return {
|
||||
listen: function (cb) {
|
||||
listeners.push(cb);
|
||||
},
|
||||
notify: function (featureId) {
|
||||
warn('Unsupported feature "' + featureId + '"');
|
||||
for (var i = 0, ii = listeners.length; i < ii; i++) {
|
||||
listeners[i](featureId);
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
// 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) {
|
||||
|
@ -1876,7 +1859,6 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
|
|||
})();
|
||||
|
||||
|
||||
// TODO(mack): Make use of PDFJS.Util.inherit() when it becomes available
|
||||
var BasePdfManager = (function BasePdfManagerClosure() {
|
||||
function BasePdfManager() {
|
||||
throw new Error('Cannot initialize BaseManagerManager');
|
||||
|
@ -1903,7 +1885,7 @@ var BasePdfManager = (function BasePdfManagerClosure() {
|
|||
return this.ensure(this.pdfDocument.catalog, prop, args);
|
||||
},
|
||||
|
||||
getPage: function BasePdfManager_pagePage(pageIndex) {
|
||||
getPage: function BasePdfManager_getPage(pageIndex) {
|
||||
return this.pdfDocument.getPage(pageIndex);
|
||||
},
|
||||
|
||||
|
@ -1915,7 +1897,7 @@ var BasePdfManager = (function BasePdfManagerClosure() {
|
|||
return new NotImplementedException();
|
||||
},
|
||||
|
||||
requestRange: function BasePdfManager_ensure(begin, end) {
|
||||
requestRange: function BasePdfManager_requestRange(begin, end) {
|
||||
return new NotImplementedException();
|
||||
},
|
||||
|
||||
|
@ -1956,45 +1938,40 @@ var LocalPdfManager = (function LocalPdfManagerClosure() {
|
|||
this._loadedStreamCapability.resolve(stream);
|
||||
}
|
||||
|
||||
LocalPdfManager.prototype = Object.create(BasePdfManager.prototype);
|
||||
LocalPdfManager.prototype.constructor = LocalPdfManager;
|
||||
|
||||
LocalPdfManager.prototype.ensure =
|
||||
function LocalPdfManager_ensure(obj, prop, args) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
try {
|
||||
var value = obj[prop];
|
||||
var result;
|
||||
if (typeof value === 'function') {
|
||||
result = value.apply(obj, args);
|
||||
} else {
|
||||
result = value;
|
||||
Util.inherit(LocalPdfManager, BasePdfManager, {
|
||||
ensure: function LocalPdfManager_ensure(obj, prop, args) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
try {
|
||||
var value = obj[prop];
|
||||
var result;
|
||||
if (typeof value === 'function') {
|
||||
result = value.apply(obj, args);
|
||||
} else {
|
||||
result = value;
|
||||
}
|
||||
resolve(result);
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
resolve(result);
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
LocalPdfManager.prototype.requestRange =
|
||||
function LocalPdfManager_requestRange(begin, end) {
|
||||
return Promise.resolve();
|
||||
};
|
||||
requestRange: function LocalPdfManager_requestRange(begin, end) {
|
||||
return Promise.resolve();
|
||||
},
|
||||
|
||||
LocalPdfManager.prototype.requestLoadedStream =
|
||||
function LocalPdfManager_requestLoadedStream() {
|
||||
};
|
||||
requestLoadedStream: function LocalPdfManager_requestLoadedStream() {
|
||||
return;
|
||||
},
|
||||
|
||||
LocalPdfManager.prototype.onLoadedStream =
|
||||
function LocalPdfManager_getLoadedStream() {
|
||||
return this._loadedStreamCapability.promise;
|
||||
};
|
||||
onLoadedStream: function LocalPdfManager_onLoadedStream() {
|
||||
return this._loadedStreamCapability.promise;
|
||||
},
|
||||
|
||||
LocalPdfManager.prototype.terminate =
|
||||
function LocalPdfManager_terminate() {
|
||||
return;
|
||||
};
|
||||
terminate: function LocalPdfManager_terminate() {
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
return LocalPdfManager;
|
||||
})();
|
||||
|
@ -2015,67 +1992,60 @@ var NetworkPdfManager = (function NetworkPdfManagerClosure() {
|
|||
this.streamManager = new ChunkedStreamManager(args.length,
|
||||
args.rangeChunkSize,
|
||||
args.url, params);
|
||||
|
||||
this.pdfDocument = new PDFDocument(this, this.streamManager.getStream(),
|
||||
args.password);
|
||||
args.password);
|
||||
}
|
||||
|
||||
NetworkPdfManager.prototype = Object.create(BasePdfManager.prototype);
|
||||
NetworkPdfManager.prototype.constructor = NetworkPdfManager;
|
||||
Util.inherit(NetworkPdfManager, BasePdfManager, {
|
||||
ensure: function NetworkPdfManager_ensure(obj, prop, args) {
|
||||
var pdfManager = this;
|
||||
|
||||
NetworkPdfManager.prototype.ensure =
|
||||
function NetworkPdfManager_ensure(obj, prop, args) {
|
||||
var pdfManager = this;
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
function ensureHelper() {
|
||||
try {
|
||||
var result;
|
||||
var value = obj[prop];
|
||||
if (typeof value === 'function') {
|
||||
result = value.apply(obj, args);
|
||||
} else {
|
||||
result = value;
|
||||
return new Promise(function (resolve, reject) {
|
||||
function ensureHelper() {
|
||||
try {
|
||||
var result;
|
||||
var value = obj[prop];
|
||||
if (typeof value === 'function') {
|
||||
result = value.apply(obj, args);
|
||||
} else {
|
||||
result = value;
|
||||
}
|
||||
resolve(result);
|
||||
} catch(e) {
|
||||
if (!(e instanceof MissingDataException)) {
|
||||
reject(e);
|
||||
return;
|
||||
}
|
||||
pdfManager.streamManager.requestRange(e.begin, e.end).
|
||||
then(ensureHelper, reject);
|
||||
}
|
||||
resolve(result);
|
||||
} catch(e) {
|
||||
if (!(e instanceof MissingDataException)) {
|
||||
reject(e);
|
||||
return;
|
||||
}
|
||||
pdfManager.streamManager.requestRange(e.begin, e.end).
|
||||
then(ensureHelper, reject);
|
||||
}
|
||||
}
|
||||
|
||||
ensureHelper();
|
||||
});
|
||||
};
|
||||
ensureHelper();
|
||||
});
|
||||
},
|
||||
|
||||
NetworkPdfManager.prototype.requestRange =
|
||||
function NetworkPdfManager_requestRange(begin, end) {
|
||||
return this.streamManager.requestRange(begin, end);
|
||||
};
|
||||
requestRange: function NetworkPdfManager_requestRange(begin, end) {
|
||||
return this.streamManager.requestRange(begin, end);
|
||||
},
|
||||
|
||||
NetworkPdfManager.prototype.requestLoadedStream =
|
||||
function NetworkPdfManager_requestLoadedStream() {
|
||||
this.streamManager.requestAllChunks();
|
||||
};
|
||||
requestLoadedStream: function NetworkPdfManager_requestLoadedStream() {
|
||||
this.streamManager.requestAllChunks();
|
||||
},
|
||||
|
||||
NetworkPdfManager.prototype.sendProgressiveData =
|
||||
function NetworkPdfManager_sendProgressiveData(chunk) {
|
||||
this.streamManager.onReceiveData({ chunk: chunk });
|
||||
};
|
||||
sendProgressiveData:
|
||||
function NetworkPdfManager_sendProgressiveData(chunk) {
|
||||
this.streamManager.onReceiveData({ chunk: chunk });
|
||||
},
|
||||
|
||||
NetworkPdfManager.prototype.onLoadedStream =
|
||||
function NetworkPdfManager_getLoadedStream() {
|
||||
return this.streamManager.onLoadedStream();
|
||||
};
|
||||
onLoadedStream: function NetworkPdfManager_onLoadedStream() {
|
||||
return this.streamManager.onLoadedStream();
|
||||
},
|
||||
|
||||
NetworkPdfManager.prototype.terminate =
|
||||
function NetworkPdfManager_terminate() {
|
||||
this.streamManager.abort();
|
||||
};
|
||||
terminate: function NetworkPdfManager_terminate() {
|
||||
this.streamManager.abort();
|
||||
}
|
||||
});
|
||||
|
||||
return NetworkPdfManager;
|
||||
})();
|
||||
|
@ -2270,7 +2240,7 @@ var Page = (function PageClosure() {
|
|||
}
|
||||
|
||||
var annotationsReadyPromise = Annotation.appendToOperatorList(
|
||||
annotations, pageOpList, pdfManager, partialEvaluator, task, intent);
|
||||
annotations, pageOpList, partialEvaluator, task, intent);
|
||||
return annotationsReadyPromise.then(function () {
|
||||
pageOpList.flush(true);
|
||||
return pageOpList;
|
||||
|
@ -4543,25 +4513,22 @@ var Annotation = (function AnnotationClosure() {
|
|||
|
||||
function Annotation(params) {
|
||||
var dict = params.dict;
|
||||
var data = this.data = {};
|
||||
|
||||
data.subtype = dict.get('Subtype').name;
|
||||
|
||||
this.setFlags(dict.get('F'));
|
||||
data.annotationFlags = this.flags;
|
||||
|
||||
this.setRectangle(dict.get('Rect'));
|
||||
data.rect = this.rectangle;
|
||||
|
||||
this.setColor(dict.get('C'));
|
||||
data.color = this.color;
|
||||
|
||||
this.borderStyle = data.borderStyle = new AnnotationBorderStyle();
|
||||
this.setBorderStyle(dict);
|
||||
|
||||
this.appearance = getDefaultAppearance(dict);
|
||||
data.hasAppearance = !!this.appearance;
|
||||
data.id = params.ref.num;
|
||||
|
||||
// Expose public properties using a data object.
|
||||
this.data = {};
|
||||
this.data.id = params.ref.num;
|
||||
this.data.subtype = dict.get('Subtype').name;
|
||||
this.data.annotationFlags = this.flags;
|
||||
this.data.rect = this.rectangle;
|
||||
this.data.color = this.color;
|
||||
this.data.borderStyle = this.borderStyle;
|
||||
this.data.hasAppearance = !!this.appearance;
|
||||
}
|
||||
|
||||
Annotation.prototype = {
|
||||
|
@ -4688,6 +4655,7 @@ var Annotation = (function AnnotationClosure() {
|
|||
* @param {Dict} borderStyle - The border style dictionary
|
||||
*/
|
||||
setBorderStyle: function Annotation_setBorderStyle(borderStyle) {
|
||||
this.borderStyle = new AnnotationBorderStyle();
|
||||
if (!isDict(borderStyle)) {
|
||||
return;
|
||||
}
|
||||
|
@ -4740,13 +4708,11 @@ var Annotation = (function AnnotationClosure() {
|
|||
},
|
||||
|
||||
getOperatorList: function Annotation_getOperatorList(evaluator, task) {
|
||||
|
||||
if (!this.appearance) {
|
||||
return Promise.resolve(new OperatorList());
|
||||
}
|
||||
|
||||
var data = this.data;
|
||||
|
||||
var appearanceDict = this.appearance.dict;
|
||||
var resourcesPromise = this.loadResources([
|
||||
'ExtGState',
|
||||
|
@ -4778,33 +4744,22 @@ var Annotation = (function AnnotationClosure() {
|
|||
};
|
||||
|
||||
Annotation.appendToOperatorList = function Annotation_appendToOperatorList(
|
||||
annotations, opList, pdfManager, partialEvaluator, task, intent) {
|
||||
|
||||
function reject(e) {
|
||||
annotationsReadyCapability.reject(e);
|
||||
}
|
||||
|
||||
var annotationsReadyCapability = createPromiseCapability();
|
||||
|
||||
annotations, opList, partialEvaluator, task, intent) {
|
||||
var annotationPromises = [];
|
||||
for (var i = 0, n = annotations.length; i < n; ++i) {
|
||||
if (intent === 'display' && annotations[i].viewable ||
|
||||
intent === 'print' && annotations[i].printable) {
|
||||
if ((intent === 'display' && annotations[i].viewable) ||
|
||||
(intent === 'print' && annotations[i].printable)) {
|
||||
annotationPromises.push(
|
||||
annotations[i].getOperatorList(partialEvaluator, task));
|
||||
}
|
||||
}
|
||||
Promise.all(annotationPromises).then(function(datas) {
|
||||
return Promise.all(annotationPromises).then(function(operatorLists) {
|
||||
opList.addOp(OPS.beginAnnotations, []);
|
||||
for (var i = 0, n = datas.length; i < n; ++i) {
|
||||
var annotOpList = datas[i];
|
||||
opList.addOpList(annotOpList);
|
||||
for (var i = 0, n = operatorLists.length; i < n; ++i) {
|
||||
opList.addOpList(operatorLists[i]);
|
||||
}
|
||||
opList.addOp(OPS.endAnnotations, []);
|
||||
annotationsReadyCapability.resolve();
|
||||
}, reject);
|
||||
|
||||
return annotationsReadyCapability.promise;
|
||||
});
|
||||
};
|
||||
|
||||
return Annotation;
|
||||
|
@ -4949,7 +4904,6 @@ var AnnotationBorderStyle = (function AnnotationBorderStyleClosure() {
|
|||
})();
|
||||
|
||||
var WidgetAnnotation = (function WidgetAnnotationClosure() {
|
||||
|
||||
function WidgetAnnotation(params) {
|
||||
Annotation.call(this, params);
|
||||
|
||||
|
@ -5073,7 +5027,7 @@ var TextAnnotation = (function TextAnnotationClosure() {
|
|||
}
|
||||
}
|
||||
|
||||
Util.inherit(TextAnnotation, Annotation, { });
|
||||
Util.inherit(TextAnnotation, Annotation, {});
|
||||
|
||||
return TextAnnotation;
|
||||
})();
|
||||
|
@ -5149,7 +5103,7 @@ var LinkAnnotation = (function LinkAnnotationClosure() {
|
|||
return url;
|
||||
}
|
||||
|
||||
Util.inherit(LinkAnnotation, Annotation, { });
|
||||
Util.inherit(LinkAnnotation, Annotation, {});
|
||||
|
||||
return LinkAnnotation;
|
||||
})();
|
||||
|
@ -9567,7 +9521,7 @@ var Pattern = (function PatternClosure() {
|
|||
};
|
||||
|
||||
Pattern.parseShading = function Pattern_parseShading(shading, matrix, xref,
|
||||
res) {
|
||||
res, handler) {
|
||||
|
||||
var dict = isStream(shading) ? shading.dict : shading;
|
||||
var type = dict.get('ShadingType');
|
||||
|
@ -9590,7 +9544,8 @@ var Pattern = (function PatternClosure() {
|
|||
if (ex instanceof MissingDataException) {
|
||||
throw ex;
|
||||
}
|
||||
UnsupportedManager.notify(UNSUPPORTED_FEATURES.shadingPattern);
|
||||
handler.send('UnsupportedFeature',
|
||||
{featureId: UNSUPPORTED_FEATURES.shadingPattern});
|
||||
warn(ex);
|
||||
return new Shadings.Dummy();
|
||||
}
|
||||
|
@ -10628,6 +10583,9 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||
then(function () {
|
||||
return translated;
|
||||
}, function (reason) {
|
||||
// Error in the font data -- sending unsupported feature notification.
|
||||
self.handler.send('UnsupportedFeature',
|
||||
{featureId: UNSUPPORTED_FEATURES.font});
|
||||
return new TranslatedFont('g_font_error',
|
||||
new ErrorFont('Type3 font load error: ' + reason), translated.font);
|
||||
});
|
||||
|
@ -10852,6 +10810,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||
translatedPromise = Promise.reject(e);
|
||||
}
|
||||
|
||||
var self = this;
|
||||
translatedPromise.then(function (translatedFont) {
|
||||
if (translatedFont.fontType !== undefined) {
|
||||
var xrefFontStats = xref.stats.fontTypes;
|
||||
|
@ -10862,7 +10821,9 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||
translatedFont, font));
|
||||
}, function (reason) {
|
||||
// TODO fontCapability.reject?
|
||||
UnsupportedManager.notify(UNSUPPORTED_FEATURES.font);
|
||||
// Error in the font data -- sending unsupported feature notification.
|
||||
self.handler.send('UnsupportedFeature',
|
||||
{featureId: UNSUPPORTED_FEATURES.font});
|
||||
|
||||
try {
|
||||
// error, but it's still nice to have font type reported
|
||||
|
@ -10915,7 +10876,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||
} else if (typeNum === SHADING_PATTERN) {
|
||||
var shading = dict.get('Shading');
|
||||
var matrix = dict.get('Matrix');
|
||||
pattern = Pattern.parseShading(shading, matrix, xref, resources);
|
||||
pattern = Pattern.parseShading(shading, matrix, xref, resources,
|
||||
this.handler);
|
||||
operatorList.addOp(fn, pattern.getIR());
|
||||
return Promise.resolve();
|
||||
} else {
|
||||
|
@ -11152,7 +11114,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||
}
|
||||
|
||||
var shadingFill = Pattern.parseShading(shading, null, xref,
|
||||
resources);
|
||||
resources, self.handler);
|
||||
var patternIR = shadingFill.getIR();
|
||||
args = [patternIR];
|
||||
fn = OPS.shadingFill;
|
||||
|
@ -16929,11 +16891,15 @@ var Font = (function FontClosure() {
|
|||
};
|
||||
}
|
||||
|
||||
function getRanges(glyphs) {
|
||||
function getRanges(glyphs, numGlyphs) {
|
||||
// Array.sort() sorts by characters, not numerically, so convert to an
|
||||
// array of characters.
|
||||
var codes = [];
|
||||
for (var charCode in glyphs) {
|
||||
// Remove an invalid glyph ID mappings to make OTS happy.
|
||||
if (glyphs[charCode] >= numGlyphs) {
|
||||
continue;
|
||||
}
|
||||
codes.push({ fontCharCode: charCode | 0, glyphId: glyphs[charCode] });
|
||||
}
|
||||
codes.sort(function fontGetRangesSort(a, b) {
|
||||
|
@ -16962,8 +16928,8 @@ var Font = (function FontClosure() {
|
|||
return ranges;
|
||||
}
|
||||
|
||||
function createCmapTable(glyphs) {
|
||||
var ranges = getRanges(glyphs);
|
||||
function createCmapTable(glyphs, numGlyphs) {
|
||||
var ranges = getRanges(glyphs, numGlyphs);
|
||||
var numTables = ranges[ranges.length - 1][1] > 0xFFFF ? 2 : 1;
|
||||
var cmap = '\x00\x00' + // version
|
||||
string16(numTables) + // numTables
|
||||
|
@ -18466,7 +18432,7 @@ var Font = (function FontClosure() {
|
|||
this.toFontChar = newMapping.toFontChar;
|
||||
tables.cmap = {
|
||||
tag: 'cmap',
|
||||
data: createCmapTable(newMapping.charCodeToGlyphId)
|
||||
data: createCmapTable(newMapping.charCodeToGlyphId, numGlyphs)
|
||||
};
|
||||
|
||||
if (!tables['OS/2'] || !validateOS2Table(tables['OS/2'])) {
|
||||
|
@ -18604,7 +18570,8 @@ var Font = (function FontClosure() {
|
|||
builder.addTable('OS/2', createOS2Table(properties,
|
||||
newMapping.charCodeToGlyphId));
|
||||
// Character to glyphs mapping
|
||||
builder.addTable('cmap', createCmapTable(newMapping.charCodeToGlyphId));
|
||||
builder.addTable('cmap', createCmapTable(newMapping.charCodeToGlyphId,
|
||||
numGlyphs));
|
||||
// Font header
|
||||
builder.addTable('head',
|
||||
'\x00\x01\x00\x00' + // Version number
|
||||
|
@ -31007,17 +30974,32 @@ var Lexer = (function LexerClosure() {
|
|||
return strBuf.join('');
|
||||
},
|
||||
getName: function Lexer_getName() {
|
||||
var ch;
|
||||
var ch, previousCh;
|
||||
var strBuf = this.strBuf;
|
||||
strBuf.length = 0;
|
||||
while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) {
|
||||
if (ch === 0x23) { // '#'
|
||||
ch = this.nextChar();
|
||||
if (specialChars[ch]) {
|
||||
warn('Lexer_getName: ' +
|
||||
'NUMBER SIGN (#) should be followed by a hexadecimal number.');
|
||||
strBuf.push('#');
|
||||
break;
|
||||
}
|
||||
var x = toHexDigit(ch);
|
||||
if (x !== -1) {
|
||||
var x2 = toHexDigit(this.nextChar());
|
||||
previousCh = ch;
|
||||
ch = this.nextChar();
|
||||
var x2 = toHexDigit(ch);
|
||||
if (x2 === -1) {
|
||||
error('Illegal digit in hex char in name: ' + x2);
|
||||
warn('Lexer_getName: Illegal digit (' +
|
||||
String.fromCharCode(ch) +') in hexadecimal number.');
|
||||
strBuf.push('#', String.fromCharCode(previousCh));
|
||||
if (specialChars[ch]) {
|
||||
break;
|
||||
}
|
||||
strBuf.push(String.fromCharCode(ch));
|
||||
continue;
|
||||
}
|
||||
strBuf.push(String.fromCharCode((x << 4) | x2));
|
||||
} else {
|
||||
|
@ -34351,6 +34333,11 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
|||
return; // ignoring errors from the terminated thread
|
||||
}
|
||||
|
||||
// For compatibility with older behavior, generating unknown
|
||||
// unsupported feature notification on errors.
|
||||
handler.send('UnsupportedFeature',
|
||||
{featureId: UNSUPPORTED_FEATURES.unknown});
|
||||
|
||||
var minimumStackMessage =
|
||||
'worker.js: while trying to getPage() and getOperatorList()';
|
||||
|
||||
|
@ -34485,15 +34472,6 @@ if (typeof window === 'undefined') {
|
|||
globalScope.console = workerConsole;
|
||||
}
|
||||
|
||||
// Listen for unsupported features so we can pass them on to the main thread.
|
||||
PDFJS.UnsupportedManager.listen(function (msg) {
|
||||
globalScope.postMessage({
|
||||
targetName: 'main',
|
||||
action: '_unsupported_feature',
|
||||
data: msg
|
||||
});
|
||||
});
|
||||
|
||||
var handler = new MessageHandler('worker', 'main', this);
|
||||
WorkerMessageHandler.setup(handler, this);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
bottom: 0;
|
||||
overflow: hidden;
|
||||
opacity: 0.2;
|
||||
line-height: 1.0;
|
||||
}
|
||||
|
||||
.textLayer > div {
|
||||
|
|
|
@ -6513,6 +6513,9 @@ var PDFViewerApplication = {
|
|||
self.progress(progressData.loaded / progressData.total);
|
||||
};
|
||||
|
||||
// Listen for unsupported features to trigger the fallback UI.
|
||||
loadingTask.onUnsupportedFeature = this.fallback.bind(this);
|
||||
|
||||
var result = loadingTask.promise.then(
|
||||
function getDocumentCallback(pdfDocument) {
|
||||
self.load(pdfDocument, scale);
|
||||
|
@ -7248,10 +7251,6 @@ function webViewerInitialized() {
|
|||
document.getElementById('viewFind').classList.add('hidden');
|
||||
}
|
||||
|
||||
// Listen for unsupported features to trigger the fallback UI.
|
||||
PDFJS.UnsupportedManager.listen(
|
||||
PDFViewerApplication.fallback.bind(PDFViewerApplication));
|
||||
|
||||
// Suppress context menus for some controls
|
||||
document.getElementById('scaleSelect').oncontextmenu = noContextMenuHandler;
|
||||
|
||||
|
|
|
@ -33,3 +33,4 @@ tampering with your connection.</b>">
|
|||
<!ENTITY certerror.expert.contentPara2 "Don't add an exception unless
|
||||
you know there's a good reason why this site doesn't use trusted identification.">
|
||||
<!ENTITY certerror.addException.label "Add Exception…">
|
||||
<!ENTITY certerror.copyToClipboard.label "Copy text to clipboard">
|
||||
|
|
|
@ -801,6 +801,13 @@ unmuteTab.accesskey = M
|
|||
weakCryptoOverriding.message = %S recommends that you don't enter your password, credit card and other personal information on this website.
|
||||
revokeOverride.label = Don't Trust This Website
|
||||
revokeOverride.accesskey = D
|
||||
# LOCALIZATION NOTE (certErrorDetails.label): This is a text string that
|
||||
# appears in the about:certerror page, so that the user can copy and send it to
|
||||
# the server administrators for troubleshooting. %1$S is the visited URL, %2$S
|
||||
# is the error message, %3$S is true or false, depending on whether the server
|
||||
# supports HSTS, %4$S is true or false, depending on whether the server
|
||||
# supports HPKP, %5$S is the certificate chain in PEM format.
|
||||
certErrorDetails.label = %1$S\r\n\r\n%2$S\r\n\r\nHTTP Strict Transport Security: %3$S\r\nHTTP Public Key Pinning: %4$S\r\n\r\nCertificate chain:\r\n\r\n%5$S
|
||||
|
||||
# LOCALIZATION NOTE (tabgroups.migration.anonGroup):
|
||||
# %S is the group number/ID
|
||||
|
|
|
@ -215,14 +215,14 @@ functionality specific to firefox. -->
|
|||
<!ENTITY remoteXUL.longDesc "<p><ul><li>Please contact the website owners to inform them of this problem.</li></ul></p>">
|
||||
|
||||
<!ENTITY sslv3Used.title "Unable to Connect Securely">
|
||||
<!-- LOCALIZATION NOTE (sslv3Used.longDesc) - Do not translate
|
||||
"ssl_error_unsupported_version". -->
|
||||
<!ENTITY sslv3Used.longDesc "Advanced info: ssl_error_unsupported_version">
|
||||
<!-- LOCALIZATION NOTE (sslv3Used.longDesc2) - Do not translate
|
||||
"SSL_ERROR_UNSUPPORTED_VERSION". -->
|
||||
<!ENTITY sslv3Used.longDesc2 "Advanced info: SSL_ERROR_UNSUPPORTED_VERSION">
|
||||
|
||||
<!ENTITY weakCryptoUsed.title "Your connection is not secure">
|
||||
<!-- LOCALIZATION NOTE (weakCryptoUsed.longDesc) - Do not translate
|
||||
"ssl_error_no_cypher_overlap". -->
|
||||
<!ENTITY weakCryptoUsed.longDesc "Advanced info: ssl_error_no_cypher_overlap">
|
||||
<!-- LOCALIZATION NOTE (weakCryptoUsed.longDesc2) - Do not translate
|
||||
"SSL_ERROR_NO_CYPHER_OVERLAP". -->
|
||||
<!ENTITY weakCryptoUsed.longDesc2 "Advanced info: SSL_ERROR_NO_CYPHER_OVERLAP">
|
||||
<!ENTITY weakCryptoAdvanced.title "Advanced">
|
||||
<!ENTITY weakCryptoAdvanced.longDesc "<span class='hostname'></span> uses security technology that is outdated and vulnerable to attack. An attacker could easily reveal information which you thought to be safe.">
|
||||
<!ENTITY weakCryptoAdvanced.override "(Not secure) Try loading <span class='hostname'></span> using outdated security">
|
||||
|
|
|
@ -53,6 +53,27 @@ body {
|
|||
flex: 1;
|
||||
}
|
||||
|
||||
#certificateErrorDebugInformation {
|
||||
display: none;
|
||||
background-color: var(--in-content-box-background-hover) !important;
|
||||
border-top: 1px solid var(--in-content-border-color);
|
||||
position: absolute;
|
||||
left: 0%;
|
||||
top: 100%;
|
||||
width: 65%;
|
||||
padding: 1em 17.5%;
|
||||
}
|
||||
|
||||
#certificateErrorText {
|
||||
font-family: monospace;
|
||||
white-space: pre-wrap;
|
||||
padding: 1em 0;
|
||||
}
|
||||
|
||||
#errorCode {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#returnButton {
|
||||
background-color: var(--in-content-primary-button-background);
|
||||
border: none;
|
||||
|
|
|
@ -173,3 +173,9 @@ span#hostname {
|
|||
#automaticallyReportInFuture {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#errorCode {
|
||||
color: var(--in-content-page-color);
|
||||
cursor: text;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
<item name="android:windowContentOverlay">@null</item>
|
||||
<item name="android:actionBarStyle">@style/GeckoActionBar</item>
|
||||
<!-- TODO (bug 1220863): Once we extend AppCompatActivity, set actionBarStyle. -->
|
||||
<item name="android:alertDialogTheme">@style/GeckoAlertDialog</item>
|
||||
</style>
|
||||
|
||||
<style name="GeckoPreferencesBase" parent="Gecko">
|
||||
|
@ -25,6 +26,10 @@
|
|||
<item name="android:actionBarTheme">@style/ActionBarThemeGeckoPreferences</item>
|
||||
</style>
|
||||
|
||||
<style name="GeckoAlertDialog" parent="@android:style/Theme.Material.Light.Dialog.Alert">
|
||||
<item name="android:colorAccent">@color/fennec_ui_orange</item>
|
||||
</style>
|
||||
|
||||
<style name="ActionBar.FxAccountStatusActivity" parent="@android:style/Widget.Material.ActionBar.Solid">
|
||||
<item name="android:displayOptions">homeAsUp|showTitle</item>
|
||||
<item name="android:titleTextStyle">@style/ActionBarTitleTextStyle</item>
|
||||
|
|
|
@ -292,7 +292,8 @@ certErrorExpiredNow=The certificate expired on %1$S. The current time is %2$S.
|
|||
# LOCALIZATION NOTE (certErrorNotYetValidNow): Do not translate %1$S (date+time certificate will become valid) or %2$S (current date+time)
|
||||
certErrorNotYetValidNow=The certificate will not be valid until %1$S. The current time is %2$S.
|
||||
|
||||
certErrorCodePrefix=(Error code: %S)
|
||||
# LOCALIZATION NOTE (certErrorCodePrefix2): Do not translate <a id="errorCode" title="%1$S">%1$S</a>
|
||||
certErrorCodePrefix2=Error code: <a id="errorCode" title="%1$S">%1$S</a>
|
||||
|
||||
CertInfoIssuedFor=Issued to:
|
||||
CertInfoIssuedBy=Issued by:
|
||||
|
|
|
@ -882,7 +882,6 @@ AppendErrorTextCode(PRErrorCode errorCodeToReport,
|
|||
if (codeName)
|
||||
{
|
||||
nsCString error_id(codeName);
|
||||
ToLowerCase(error_id);
|
||||
NS_ConvertASCIItoUTF16 idU(error_id);
|
||||
|
||||
const char16_t *params[1];
|
||||
|
@ -890,7 +889,7 @@ AppendErrorTextCode(PRErrorCode errorCodeToReport,
|
|||
|
||||
nsString formattedString;
|
||||
nsresult rv;
|
||||
rv = component->PIPBundleFormatStringFromName("certErrorCodePrefix",
|
||||
rv = component->PIPBundleFormatStringFromName("certErrorCodePrefix2",
|
||||
params, 1,
|
||||
formattedString);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
|
|
|
@ -78,14 +78,13 @@ nsNSSErrors::getErrorMessageFromCode(PRErrorCode err,
|
|||
{
|
||||
nsresult rv;
|
||||
nsCString error_id(nss_error_id_str);
|
||||
ToLowerCase(error_id);
|
||||
NS_ConvertASCIItoUTF16 idU(error_id);
|
||||
|
||||
const char16_t *params[1];
|
||||
params[0] = idU.get();
|
||||
|
||||
nsString formattedString;
|
||||
rv = component->PIPBundleFormatStringFromName("certErrorCodePrefix",
|
||||
rv = component->PIPBundleFormatStringFromName("certErrorCodePrefix2",
|
||||
params, 1,
|
||||
formattedString);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"extends": [
|
||||
"../toolkit/.eslintrc"
|
||||
]
|
||||
}
|
|
@ -16,6 +16,8 @@ do_get_profile();
|
|||
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
|
||||
getService(Ci.nsIProperties);
|
||||
|
||||
var gDBConn = null;
|
||||
|
||||
function getTestDB()
|
||||
{
|
||||
var db = dirSvc.get("ProfD", Ci.nsIFile);
|
||||
|
@ -53,7 +55,7 @@ function cleanup()
|
|||
print("*** Storage Tests: Trying to remove file!");
|
||||
var dbFile = getTestDB();
|
||||
if (dbFile.exists())
|
||||
try { dbFile.remove(false); } catch(e) { /* stupid windows box */ }
|
||||
try { dbFile.remove(false); } catch (e) { /* stupid windows box */ }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -66,7 +68,7 @@ function asyncCleanup()
|
|||
|
||||
// close the connection
|
||||
print("*** Storage Tests: Trying to asyncClose!");
|
||||
getOpenedDatabase().asyncClose(function() { closed = true; });
|
||||
getOpenedDatabase().asyncClose(function () { closed = true; });
|
||||
|
||||
let curThread = Components.classes["@mozilla.org/thread-manager;1"]
|
||||
.getService().currentThread;
|
||||
|
@ -81,7 +83,7 @@ function asyncCleanup()
|
|||
print("*** Storage Tests: Trying to remove file!");
|
||||
var dbFile = getTestDB();
|
||||
if (dbFile.exists())
|
||||
try { dbFile.remove(false); } catch(e) { /* stupid windows box */ }
|
||||
try { dbFile.remove(false); } catch (e) { /* stupid windows box */ }
|
||||
}
|
||||
|
||||
function getService()
|
||||
|
@ -89,8 +91,6 @@ function getService()
|
|||
return Cc["@mozilla.org/storage/service;1"].getService(Ci.mozIStorageService);
|
||||
}
|
||||
|
||||
var gDBConn = null;
|
||||
|
||||
/**
|
||||
* Get a connection to the test database. Creates and caches the connection
|
||||
* if necessary, otherwise reuses the existing cached connection. This
|
||||
|
@ -169,7 +169,7 @@ function expectError(aErrorCode, aFunction)
|
|||
try {
|
||||
aFunction();
|
||||
}
|
||||
catch(e) {
|
||||
catch (e) {
|
||||
if (e.result != aErrorCode) {
|
||||
do_throw("Got an exception, but the result code was not the expected " +
|
||||
"one. Expected " + aErrorCode + ", got " + e.result);
|
||||
|
@ -208,7 +208,7 @@ function verifyQuery(aSQLString, aBind, aResults)
|
|||
do_check_eq(stmt.VALUE_TYPE_NULL, valType);
|
||||
do_check_true(stmt.getIsNull(iCol));
|
||||
}
|
||||
else if (typeof(expectedVal) == "number") {
|
||||
else if (typeof expectedVal == "number") {
|
||||
if (Math.floor(expectedVal) == expectedVal) {
|
||||
do_check_eq(stmt.VALUE_TYPE_INTEGER, valType);
|
||||
do_check_eq(expectedVal, stmt.getInt32(iCol));
|
||||
|
@ -218,7 +218,7 @@ function verifyQuery(aSQLString, aBind, aResults)
|
|||
do_check_eq(expectedVal, stmt.getDouble(iCol));
|
||||
}
|
||||
}
|
||||
else if (typeof(expectedVal) == "string") {
|
||||
else if (typeof expectedVal == "string") {
|
||||
do_check_eq(stmt.VALUE_TYPE_TEXT, valType);
|
||||
do_check_eq(expectedVal, stmt.getUTF8String(iCol));
|
||||
}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/ */
|
||||
|
||||
// Testcase for bug 365166 - crash [@ strlen] calling
|
||||
// mozIStorageStatement::getColumnName of a statement created with
|
||||
// "PRAGMA user_version" or "PRAGMA schema_version"
|
||||
|
@ -16,7 +13,7 @@ function run_test() {
|
|||
var file = getTestDB();
|
||||
var storageService = Components.classes["@mozilla.org/storage/service;1"].
|
||||
getService(Components.interfaces.mozIStorageService);
|
||||
var conn = storageService.openDatabase(file);
|
||||
var conn = storageService.openDatabase(file);
|
||||
var statement = conn.createStatement(sql);
|
||||
try {
|
||||
// This shouldn't crash:
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Testcase for bug 393952: crash when I try to VACUUM and one of the tables
|
||||
// has a UNIQUE text column. StorageUnicodeFunctions::likeFunction()
|
||||
// has a UNIQUE text column. StorageUnicodeFunctions::likeFunction()
|
||||
// needs to handle null aArgv[0] and aArgv[1]
|
||||
|
||||
function setup()
|
||||
|
@ -32,7 +32,7 @@ function run_test()
|
|||
|
||||
for (var i = 0; i < tests.length; i++)
|
||||
tests[i]();
|
||||
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
|
|
|
@ -2,48 +2,45 @@
|
|||
* 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/. */
|
||||
|
||||
function setup()
|
||||
{
|
||||
getOpenedDatabase().createTable("t1", "x TEXT");
|
||||
function setup() {
|
||||
getOpenedDatabase().createTable("t1", "x TEXT");
|
||||
|
||||
var stmt = createStatement("INSERT INTO t1 (x) VALUES ('/mozilla.org/20070129_1/Europe/Berlin')");
|
||||
stmt.execute();
|
||||
stmt.finalize();
|
||||
var stmt = createStatement("INSERT INTO t1 (x) VALUES ('/mozilla.org/20070129_1/Europe/Berlin')");
|
||||
stmt.execute();
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
function test_bug429521()
|
||||
{
|
||||
var stmt = createStatement(
|
||||
"SELECT DISTINCT(zone) FROM ("+
|
||||
"SELECT x AS zone FROM t1 WHERE x LIKE '/mozilla.org%'" +
|
||||
");");
|
||||
function test_bug429521() {
|
||||
var stmt = createStatement(
|
||||
"SELECT DISTINCT(zone) FROM (" +
|
||||
"SELECT x AS zone FROM t1 WHERE x LIKE '/mozilla.org%'" +
|
||||
");");
|
||||
|
||||
print("*** test_bug429521: started");
|
||||
print("*** test_bug429521: started");
|
||||
|
||||
try {
|
||||
while (stmt.executeStep()) {
|
||||
print("*** test_bug429521: step() Read wrapper.row.zone");
|
||||
try {
|
||||
while (stmt.executeStep()) {
|
||||
print("*** test_bug429521: step() Read wrapper.row.zone");
|
||||
|
||||
// BUG: the print commands after the following statement
|
||||
// are never executed. Script stops immediately.
|
||||
var tzId = stmt.row.zone;
|
||||
// BUG: the print commands after the following statement
|
||||
// are never executed. Script stops immediately.
|
||||
var tzId = stmt.row.zone;
|
||||
|
||||
print("*** test_bug429521: step() Read wrapper.row.zone finished");
|
||||
}
|
||||
} catch (e) {
|
||||
print("*** test_bug429521: " + e);
|
||||
print("*** test_bug429521: step() Read wrapper.row.zone finished");
|
||||
}
|
||||
} catch (e) {
|
||||
print("*** test_bug429521: " + e);
|
||||
}
|
||||
|
||||
print("*** test_bug429521: finished");
|
||||
print("*** test_bug429521: finished");
|
||||
|
||||
stmt.finalize();
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
function run_test()
|
||||
{
|
||||
function run_test() {
|
||||
setup();
|
||||
|
||||
test_bug429521();
|
||||
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
|
|
@ -3,49 +3,49 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function setup() {
|
||||
// Create the table
|
||||
getOpenedDatabase().createTable("test_bug444233",
|
||||
"id INTEGER PRIMARY KEY, value TEXT");
|
||||
// Create the table
|
||||
getOpenedDatabase().createTable("test_bug444233",
|
||||
"id INTEGER PRIMARY KEY, value TEXT");
|
||||
|
||||
// Insert dummy data, using wrapper methods
|
||||
var stmt = createStatement("INSERT INTO test_bug444233 (value) VALUES (:value)");
|
||||
stmt.params.value = "value1"
|
||||
stmt.execute();
|
||||
stmt.finalize();
|
||||
|
||||
stmt = createStatement("INSERT INTO test_bug444233 (value) VALUES (:value)");
|
||||
stmt.params.value = "value2"
|
||||
stmt.execute();
|
||||
stmt.finalize();
|
||||
// Insert dummy data, using wrapper methods
|
||||
var stmt = createStatement("INSERT INTO test_bug444233 (value) VALUES (:value)");
|
||||
stmt.params.value = "value1";
|
||||
stmt.execute();
|
||||
stmt.finalize();
|
||||
|
||||
stmt = createStatement("INSERT INTO test_bug444233 (value) VALUES (:value)");
|
||||
stmt.params.value = "value2";
|
||||
stmt.execute();
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
function test_bug444233() {
|
||||
print("*** test_bug444233: started");
|
||||
|
||||
// Check that there are 2 results
|
||||
var stmt = createStatement("SELECT COUNT(*) AS number FROM test_bug444233");
|
||||
do_check_true(stmt.executeStep());
|
||||
do_check_eq(2, stmt.row.number);
|
||||
stmt.reset();
|
||||
stmt.finalize();
|
||||
print("*** test_bug444233: started");
|
||||
|
||||
print("*** test_bug444233: doing delete");
|
||||
|
||||
// Now try to delete using IN
|
||||
// Cheating since we know ids are 1,2
|
||||
try {
|
||||
var ids = [1, 2];
|
||||
stmt = createStatement("DELETE FROM test_bug444233 WHERE id IN (:ids)");
|
||||
stmt.params.ids = ids;
|
||||
} catch (e) {
|
||||
print("*** test_bug444233: successfully caught exception");
|
||||
}
|
||||
stmt.finalize();
|
||||
// Check that there are 2 results
|
||||
var stmt = createStatement("SELECT COUNT(*) AS number FROM test_bug444233");
|
||||
do_check_true(stmt.executeStep());
|
||||
do_check_eq(2, stmt.row.number);
|
||||
stmt.reset();
|
||||
stmt.finalize();
|
||||
|
||||
print("*** test_bug444233: doing delete");
|
||||
|
||||
// Now try to delete using IN
|
||||
// Cheating since we know ids are 1,2
|
||||
try {
|
||||
var ids = [1, 2];
|
||||
stmt = createStatement("DELETE FROM test_bug444233 WHERE id IN (:ids)");
|
||||
stmt.params.ids = ids;
|
||||
} catch (e) {
|
||||
print("*** test_bug444233: successfully caught exception");
|
||||
}
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
setup();
|
||||
test_bug444233();
|
||||
cleanup();
|
||||
setup();
|
||||
test_bug444233();
|
||||
cleanup();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,34 +1,31 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// This file tests SQLITE_FCNTL_CHUNK_SIZE behaves as expected
|
||||
|
||||
function run_sql(d, sql) {
|
||||
var stmt = d.createStatement(sql)
|
||||
stmt.execute()
|
||||
var stmt = d.createStatement(sql);
|
||||
stmt.execute();
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
function new_file(name)
|
||||
{
|
||||
function new_file(name) {
|
||||
var file = dirSvc.get("ProfD", Ci.nsIFile);
|
||||
file.append(name);
|
||||
return file;
|
||||
}
|
||||
|
||||
function get_size(name) {
|
||||
return new_file(name).fileSize
|
||||
return new_file(name).fileSize;
|
||||
}
|
||||
|
||||
function run_test()
|
||||
{
|
||||
function run_test() {
|
||||
const filename = "chunked.sqlite";
|
||||
const CHUNK_SIZE = 512 * 1024;
|
||||
var d = getDatabase(new_file(filename));
|
||||
try {
|
||||
d.setGrowthIncrement(CHUNK_SIZE, "");
|
||||
} catch (e if e.result == Cr.NS_ERROR_FILE_TOO_BIG) {
|
||||
} catch (e) {
|
||||
if (e.result != Cr.NS_ERROR_FILE_TOO_BIG) {
|
||||
throw e;
|
||||
}
|
||||
print("Too little free space to set CHUNK_SIZE!");
|
||||
return;
|
||||
}
|
||||
|
@ -39,17 +36,17 @@ function run_test()
|
|||
* While writing ensure that the file size growth in chunksize set above.
|
||||
*/
|
||||
const str1024 = new Array(1024).join("T");
|
||||
for(var i = 0; i < 32; i++) {
|
||||
for (var i = 0; i < 32; i++) {
|
||||
run_sql(d, "INSERT INTO bloat VALUES('" + str1024 + "')");
|
||||
var size = get_size(filename)
|
||||
var size = get_size(filename);
|
||||
// Must not grow in small increments.
|
||||
do_check_true(size == orig_size || size >= CHUNK_SIZE);
|
||||
}
|
||||
/* In addition to growing in chunk-size increments, the db
|
||||
* should shrink in chunk-size increments too.
|
||||
*/
|
||||
run_sql(d, "DELETE FROM bloat")
|
||||
run_sql(d, "VACUUM")
|
||||
do_check_true(get_size(filename) >= CHUNK_SIZE)
|
||||
run_sql(d, "DELETE FROM bloat");
|
||||
run_sql(d, "VACUUM");
|
||||
do_check_true(get_size(filename) >= CHUNK_SIZE);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,7 @@ const TEXT = "this is test text";
|
|||
const REAL = 3.23;
|
||||
const BLOB = [1, 2];
|
||||
|
||||
function test_create_and_add()
|
||||
{
|
||||
add_test(function test_create_and_add() {
|
||||
getOpenedDatabase().executeSimpleSQL(
|
||||
"CREATE TABLE test (" +
|
||||
"id INTEGER, " +
|
||||
|
@ -42,19 +41,17 @@ function test_create_and_add()
|
|||
stmts[1].bindBlobByIndex(3, BLOB, BLOB.length);
|
||||
|
||||
getOpenedDatabase().executeAsync(stmts, stmts.length, {
|
||||
handleResult: function(aResultSet)
|
||||
{
|
||||
dump("handleResult("+aResultSet+")\n");
|
||||
handleResult: function (aResultSet) {
|
||||
dump("handleResult(" + aResultSet + ")\n");
|
||||
do_throw("unexpected results obtained!");
|
||||
},
|
||||
handleError: function(aError)
|
||||
handleError: function (aError)
|
||||
{
|
||||
dump("handleError("+aError.result+")\n");
|
||||
dump("handleError(" + aError.result + ")\n");
|
||||
do_throw("unexpected error!");
|
||||
},
|
||||
handleCompletion: function(aReason)
|
||||
{
|
||||
dump("handleCompletion("+aReason+")\n");
|
||||
handleCompletion: function (aReason) {
|
||||
dump("handleCompletion(" + aReason + ")\n");
|
||||
do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason);
|
||||
|
||||
// Check that the result is in the table
|
||||
|
@ -96,10 +93,9 @@ function test_create_and_add()
|
|||
});
|
||||
stmts[0].finalize();
|
||||
stmts[1].finalize();
|
||||
}
|
||||
});
|
||||
|
||||
function test_multiple_bindings_on_statements()
|
||||
{
|
||||
add_test(function test_multiple_bindings_on_statements() {
|
||||
// This tests to make sure that we pass all the statements multiply bound
|
||||
// parameters when we call executeAsync.
|
||||
const AMOUNT_TO_ADD = 5;
|
||||
|
@ -145,18 +141,15 @@ function test_multiple_bindings_on_statements()
|
|||
|
||||
// Execute asynchronously.
|
||||
getOpenedDatabase().executeAsync(stmts, stmts.length, {
|
||||
handleResult: function(aResultSet)
|
||||
{
|
||||
handleResult: function (aResultSet) {
|
||||
do_throw("Unexpected call to handleResult!");
|
||||
},
|
||||
handleError: function(aError)
|
||||
{
|
||||
handleError: function (aError) {
|
||||
print("Error code " + aError.result + " with message '" +
|
||||
aError.message + "' returned.");
|
||||
do_throw("Unexpected error!");
|
||||
},
|
||||
handleCompletion: function(aReason)
|
||||
{
|
||||
handleCompletion: function (aReason) {
|
||||
print("handleCompletion(" + aReason +
|
||||
") for test_multiple_bindings_on_statements");
|
||||
do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason);
|
||||
|
@ -176,24 +169,19 @@ function test_multiple_bindings_on_statements()
|
|||
}
|
||||
});
|
||||
stmts.forEach(stmt => stmt.finalize());
|
||||
}
|
||||
});
|
||||
|
||||
function test_asyncClose_does_not_complete_before_statements()
|
||||
{
|
||||
add_test(function test_asyncClose_does_not_complete_before_statements() {
|
||||
let stmt = createStatement("SELECT * FROM sqlite_master");
|
||||
let executed = false;
|
||||
stmt.executeAsync({
|
||||
handleResult: function(aResultSet)
|
||||
{
|
||||
},
|
||||
handleError: function(aError)
|
||||
{
|
||||
handleResult(aResultSet) {},
|
||||
handleError(aError) {
|
||||
print("Error code " + aError.result + " with message '" +
|
||||
aError.message + "' returned.");
|
||||
do_throw("Unexpected error!");
|
||||
},
|
||||
handleCompletion: function(aReason)
|
||||
{
|
||||
handleCompletion(aReason) {
|
||||
print("handleCompletion(" + aReason +
|
||||
") for test_asyncClose_does_not_complete_before_statements");
|
||||
do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason);
|
||||
|
@ -202,7 +190,7 @@ function test_asyncClose_does_not_complete_before_statements()
|
|||
});
|
||||
stmt.finalize();
|
||||
|
||||
getOpenedDatabase().asyncClose(function() {
|
||||
getOpenedDatabase().asyncClose(function () {
|
||||
// Ensure that the statement executed to completion.
|
||||
do_check_true(executed);
|
||||
|
||||
|
@ -210,19 +198,17 @@ function test_asyncClose_does_not_complete_before_statements()
|
|||
gDBConn = null;
|
||||
run_next_test();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function test_asyncClose_does_not_throw_no_callback()
|
||||
{
|
||||
add_test(function test_asyncClose_does_not_throw_no_callback() {
|
||||
getOpenedDatabase().asyncClose();
|
||||
|
||||
// Reset gDBConn so that later tests will get a new connection object.
|
||||
gDBConn = null;
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
|
||||
function test_double_asyncClose_throws()
|
||||
{
|
||||
add_test(function test_double_asyncClose_throws() {
|
||||
let conn = getOpenedDatabase();
|
||||
conn.asyncClose();
|
||||
try {
|
||||
|
@ -230,31 +216,20 @@ function test_double_asyncClose_throws()
|
|||
do_throw("should have thrown");
|
||||
// There is a small race condition here, which can cause either of
|
||||
// Cr.NS_ERROR_NOT_INITIALIZED or Cr.NS_ERROR_UNEXPECTED to be thrown.
|
||||
} catch (e if "result" in e && e.result == Cr.NS_ERROR_NOT_INITIALIZED) {
|
||||
do_print("NS_ERROR_NOT_INITIALIZED");
|
||||
} catch (e if "result" in e && e.result == Cr.NS_ERROR_UNEXPECTED) {
|
||||
do_print("NS_ERROR_UNEXPECTED");
|
||||
} catch (e) {
|
||||
if ("result" in e && e.result == Cr.NS_ERROR_NOT_INITIALIZED) {
|
||||
do_print("NS_ERROR_NOT_INITIALIZED");
|
||||
} else if ("result" in e && e.result == Cr.NS_ERROR_UNEXPECTED) {
|
||||
do_print("NS_ERROR_UNEXPECTED");
|
||||
}
|
||||
}
|
||||
|
||||
// Reset gDBConn so that later tests will get a new connection object.
|
||||
gDBConn = null;
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Test Runner
|
||||
|
||||
[
|
||||
test_create_and_add,
|
||||
test_multiple_bindings_on_statements,
|
||||
test_asyncClose_does_not_complete_before_statements,
|
||||
test_asyncClose_does_not_throw_no_callback,
|
||||
test_double_asyncClose_throws,
|
||||
].forEach(add_test);
|
||||
|
||||
function run_test()
|
||||
{
|
||||
function run_test() {
|
||||
cleanup();
|
||||
run_next_test();
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ const REAL = 3.23;
|
|||
|
||||
function asyncClose(db) {
|
||||
let deferred = Promise.defer();
|
||||
db.asyncClose(function(status) {
|
||||
db.asyncClose(function (status) {
|
||||
if (Components.isSuccessCode(status)) {
|
||||
deferred.resolve();
|
||||
} else {
|
||||
|
@ -25,7 +25,7 @@ function asyncClose(db) {
|
|||
|
||||
function openAsyncDatabase(file) {
|
||||
let deferred = Promise.defer();
|
||||
getService().openAsyncDatabase(file, null, function(status, db) {
|
||||
getService().openAsyncDatabase(file, null, function (status, db) {
|
||||
if (Components.isSuccessCode(status)) {
|
||||
deferred.resolve(db.QueryInterface(Ci.mozIStorageAsyncConnection));
|
||||
} else {
|
||||
|
@ -38,24 +38,24 @@ function openAsyncDatabase(file) {
|
|||
function executeSimpleSQLAsync(db, query, onResult) {
|
||||
let deferred = Promise.defer();
|
||||
db.executeSimpleSQLAsync(query, {
|
||||
handleError: function(error) {
|
||||
handleError(error) {
|
||||
deferred.reject(error);
|
||||
},
|
||||
handleResult: function(result) {
|
||||
handleResult(result) {
|
||||
if (onResult) {
|
||||
onResult(result);
|
||||
} else {
|
||||
do_throw("No results were expected");
|
||||
}
|
||||
},
|
||||
handleCompletion: function(result) {
|
||||
handleCompletion(result) {
|
||||
deferred.resolve(result);
|
||||
}
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
add_task(function test_create_and_add() {
|
||||
add_task(function* test_create_and_add() {
|
||||
let adb = yield openAsyncDatabase(getTestDB());
|
||||
|
||||
let completion = yield executeSimpleSQLAsync(adb,
|
||||
|
@ -73,7 +73,7 @@ add_task(function test_create_and_add() {
|
|||
|
||||
completion = yield executeSimpleSQLAsync(adb,
|
||||
"SELECT string, number FROM test WHERE id = 1",
|
||||
function(aResultSet) {
|
||||
function (aResultSet) {
|
||||
result = aResultSet.getNextRow();
|
||||
do_check_eq(2, result.numEntries);
|
||||
do_check_eq(TEXT, result.getString(0));
|
||||
|
@ -86,7 +86,7 @@ add_task(function test_create_and_add() {
|
|||
result = null;
|
||||
|
||||
yield executeSimpleSQLAsync(adb, "SELECT COUNT(0) FROM test",
|
||||
function(aResultSet) {
|
||||
function (aResultSet) {
|
||||
result = aResultSet.getNextRow();
|
||||
do_check_eq(1, result.getInt32(0));
|
||||
});
|
||||
|
@ -97,12 +97,12 @@ add_task(function test_create_and_add() {
|
|||
});
|
||||
|
||||
|
||||
add_task(function test_asyncClose_does_not_complete_before_statement() {
|
||||
add_task(function* test_asyncClose_does_not_complete_before_statement() {
|
||||
let adb = yield openAsyncDatabase(getTestDB());
|
||||
let executed = false;
|
||||
|
||||
let reason = yield executeSimpleSQLAsync(adb, "SELECT * FROM test",
|
||||
function(aResultSet) {
|
||||
function (aResultSet) {
|
||||
let result = aResultSet.getNextRow();
|
||||
|
||||
do_check_neq(result, null);
|
||||
|
@ -121,11 +121,3 @@ add_task(function test_asyncClose_does_not_complete_before_statement() {
|
|||
|
||||
yield asyncClose(adb);
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Test Runner
|
||||
|
||||
function run_test()
|
||||
{
|
||||
run_next_test();
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ function test_params_enumerate()
|
|||
let index = 0;
|
||||
for (let name in stmt.params) {
|
||||
if (name == "QueryInterface")
|
||||
continue;
|
||||
continue;
|
||||
do_check_eq(name, expected[index++]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,8 +30,7 @@ function check_levenshtein(db, s, t, expectedDistance)
|
|||
try {
|
||||
do_check_true(stmt.executeStep());
|
||||
do_check_eq(expectedDistance, stmt.row.result);
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
stmt.reset();
|
||||
stmt.finalize();
|
||||
}
|
||||
|
@ -56,7 +55,7 @@ function testLevenshtein(db)
|
|||
check_levenshtein(db, "foo", null, null);
|
||||
check_levenshtein(db, null, "bar", null);
|
||||
check_levenshtein(db, null, null, null);
|
||||
|
||||
|
||||
// The levenshteinDistance function allocates temporary memory on the stack
|
||||
// if it can. Test some strings long enough to force a heap allocation.
|
||||
var dots1000 = Array(1001).join(".");
|
||||
|
|
|
@ -93,7 +93,7 @@ function test_like_2()
|
|||
stmt.reset();
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
|
||||
function test_like_3()
|
||||
{
|
||||
var stmt = createStatement("SELECT x FROM t1 WHERE x LIKE ?;");
|
||||
|
@ -107,7 +107,7 @@ function test_like_3()
|
|||
stmt.reset();
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
|
||||
function test_like_4()
|
||||
{
|
||||
var stmt = createStatement("SELECT x FROM t1 WHERE x LIKE ?;");
|
||||
|
@ -153,7 +153,7 @@ function test_like_6()
|
|||
stmt.reset();
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
|
||||
function test_like_7()
|
||||
{
|
||||
var stmt = createStatement("SELECT x FROM t1 WHERE x LIKE ?;");
|
||||
|
@ -185,17 +185,18 @@ function test_like_8()
|
|||
stmt.reset();
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
var tests = [test_count, test_like_1, test_like_2, test_like_3, test_like_4,
|
||||
|
||||
var tests = [test_count, test_like_1, test_like_2, test_like_3, test_like_4,
|
||||
test_like_5, test_like_6, test_like_7, test_like_8];
|
||||
|
||||
function run_test()
|
||||
{
|
||||
setup();
|
||||
|
||||
for (var i = 0; i < tests.length; i++)
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
tests[i]();
|
||||
|
||||
}
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const LATIN1_AE = "\xc6";
|
||||
const LATIN1_ae = "\xe6";
|
||||
const LATIN1_ae = "\xe6";
|
||||
|
||||
function setup()
|
||||
{
|
||||
|
@ -19,7 +19,7 @@ function setup()
|
|||
stmt.execute();
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
|
||||
function test_escape_for_like_ascii()
|
||||
{
|
||||
var stmt = createStatement("SELECT x FROM t1 WHERE x LIKE ?1 ESCAPE '/'");
|
||||
|
@ -27,7 +27,7 @@ function test_escape_for_like_ascii()
|
|||
// verify that we escaped / _ and %
|
||||
do_check_eq(paramForLike, "oo//bar/_baz/%20chees");
|
||||
// prepend and append with % for "contains"
|
||||
stmt.bindByIndex(0, "%" + paramForLike + "%");
|
||||
stmt.bindByIndex(0, "%" + paramForLike + "%");
|
||||
stmt.executeStep();
|
||||
do_check_eq("foo/bar_baz%20cheese", stmt.getString(0));
|
||||
stmt.finalize();
|
||||
|
@ -52,8 +52,9 @@ function run_test()
|
|||
{
|
||||
setup();
|
||||
|
||||
for (var i = 0; i < tests.length; i++)
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
tests[i]();
|
||||
|
||||
}
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
|
|
@ -140,21 +140,21 @@ function localeCompare(aCollation)
|
|||
var strength;
|
||||
|
||||
switch (aCollation) {
|
||||
case "locale":
|
||||
strength = Ci.nsICollation.kCollationCaseInSensitive;
|
||||
break;
|
||||
case "locale_case_sensitive":
|
||||
strength = Ci.nsICollation.kCollationAccentInsenstive;
|
||||
break;
|
||||
case "locale_accent_sensitive":
|
||||
strength = Ci.nsICollation.kCollationCaseInsensitiveAscii;
|
||||
break;
|
||||
case "locale_case_accent_sensitive":
|
||||
strength = Ci.nsICollation.kCollationCaseSensitive;
|
||||
break;
|
||||
default:
|
||||
do_throw("Error in test: unknown collation '" + aCollation + "'");
|
||||
break;
|
||||
case "locale":
|
||||
strength = Ci.nsICollation.kCollationCaseInSensitive;
|
||||
break;
|
||||
case "locale_case_sensitive":
|
||||
strength = Ci.nsICollation.kCollationAccentInsenstive;
|
||||
break;
|
||||
case "locale_accent_sensitive":
|
||||
strength = Ci.nsICollation.kCollationCaseInsensitiveAscii;
|
||||
break;
|
||||
case "locale_case_accent_sensitive":
|
||||
strength = Ci.nsICollation.kCollationCaseSensitive;
|
||||
break;
|
||||
default:
|
||||
do_throw("Error in test: unknown collation '" + aCollation + "'");
|
||||
break;
|
||||
}
|
||||
return function (aStr1, aStr2) {
|
||||
return gLocaleCollation.compareString(strength, aStr1, aStr2);
|
||||
|
@ -180,8 +180,9 @@ function readTestData()
|
|||
|
||||
let line = {};
|
||||
let lines = [];
|
||||
while (istream.readLine(line))
|
||||
lines.push(line.value);
|
||||
while (istream.readLine(line)) {
|
||||
lines.push(line.value);
|
||||
}
|
||||
istream.close();
|
||||
|
||||
return lines;
|
||||
|
|
|
@ -34,8 +34,7 @@ function getFileContents(aFile)
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Tests
|
||||
|
||||
function test_delete_removes_data()
|
||||
{
|
||||
add_test(function test_delete_removes_data() {
|
||||
const TEST_STRING = "SomeRandomStringToFind";
|
||||
|
||||
let file = getTestDB();
|
||||
|
@ -74,14 +73,7 @@ function test_delete_removes_data()
|
|||
do_check_eq(-1, contents.indexOf(TEST_STRING));
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Test Runner
|
||||
|
||||
[
|
||||
test_delete_removes_data,
|
||||
].forEach(add_test);
|
||||
});
|
||||
|
||||
function run_test()
|
||||
{
|
||||
|
|
|
@ -53,15 +53,15 @@ function execAsync(aStmt, aOptions, aResults)
|
|||
if (aResults == null) {
|
||||
resultsExpected = 0;
|
||||
}
|
||||
else if (typeof(aResults) == "number") {
|
||||
else if (typeof aResults == "number") {
|
||||
resultsExpected = aResults;
|
||||
}
|
||||
else if (typeof(aResults) == "function") {
|
||||
else if (typeof aResults == "function") {
|
||||
resultsChecker = aResults;
|
||||
}
|
||||
else { // array
|
||||
resultsExpected = aResults.length;
|
||||
resultsChecker = function(aResultNum, aTup, aCaller) {
|
||||
resultsChecker = function (aResultNum, aTup, aCaller) {
|
||||
aResults[aResultNum](aTup, aCaller);
|
||||
};
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ function execAsync(aStmt, aOptions, aResults)
|
|||
let completed = false;
|
||||
|
||||
let listener = {
|
||||
handleResult: function(aResultSet)
|
||||
handleResult(aResultSet)
|
||||
{
|
||||
let row, resultsSeenThisCall = 0;
|
||||
while ((row = aResultSet.getNextRow()) != null) {
|
||||
|
@ -96,13 +96,13 @@ function execAsync(aStmt, aOptions, aResults)
|
|||
if (!resultsSeenThisCall)
|
||||
do_throw("handleResult invoked with 0 result rows!");
|
||||
},
|
||||
handleError: function(aError)
|
||||
handleError(aError)
|
||||
{
|
||||
if (errorCodeSeen != false)
|
||||
do_throw("handleError called when we already had an error!");
|
||||
errorCodeSeen = aError.result;
|
||||
},
|
||||
handleCompletion: function(aReason)
|
||||
handleCompletion(aReason)
|
||||
{
|
||||
if (completed) // paranoia check
|
||||
do_throw("Received a second handleCompletion notification!", caller);
|
||||
|
@ -226,8 +226,7 @@ function test_get_data()
|
|||
);
|
||||
stmt.bindByIndex(0, INTEGER);
|
||||
execAsync(stmt, {}, [
|
||||
function(tuple)
|
||||
{
|
||||
function (tuple) {
|
||||
do_check_neq(null, tuple);
|
||||
|
||||
// Check that it's what we expect
|
||||
|
@ -254,7 +253,7 @@ function test_get_data()
|
|||
do_check_eq(BLOB.length, blobByName.length);
|
||||
var blobByIndex = tuple.getResultByIndex(3);
|
||||
do_check_eq(BLOB.length, blobByIndex.length);
|
||||
for (var i = 0; i < BLOB.length; i++) {
|
||||
for (let i = 0; i < BLOB.length; i++) {
|
||||
do_check_eq(BLOB[i], blobByName[i]);
|
||||
do_check_eq(BLOB[i], blobByIndex[i]);
|
||||
}
|
||||
|
@ -262,7 +261,7 @@ function test_get_data()
|
|||
var blob = { value: null };
|
||||
tuple.getBlob(3, count, blob);
|
||||
do_check_eq(BLOB.length, count.value);
|
||||
for (var i = 0; i < BLOB.length; i++)
|
||||
for (let i = 0; i < BLOB.length; i++)
|
||||
do_check_eq(BLOB[i], blob.value[i]);
|
||||
do_check_eq(Ci.mozIStorageValueArray.VALUE_TYPE_BLOB,
|
||||
tuple.getTypeOfIndex(3));
|
||||
|
@ -283,7 +282,7 @@ function test_tuple_out_of_bounds()
|
|||
"SELECT string FROM test"
|
||||
);
|
||||
execAsync(stmt, {}, [
|
||||
function(tuple) {
|
||||
function (tuple) {
|
||||
do_check_neq(null, tuple);
|
||||
|
||||
// Check all out of bounds - should throw
|
||||
|
@ -367,19 +366,13 @@ function test_partial_listener_works()
|
|||
);
|
||||
stmt.bindByIndex(0, 0);
|
||||
stmt.executeAsync({
|
||||
handleResult: function(aResultSet)
|
||||
{
|
||||
}
|
||||
handleResult(aResultSet) {}
|
||||
});
|
||||
stmt.executeAsync({
|
||||
handleError: function(aError)
|
||||
{
|
||||
}
|
||||
handleError(aError) {}
|
||||
});
|
||||
stmt.executeAsync({
|
||||
handleCompletion: function(aReason)
|
||||
{
|
||||
}
|
||||
handleCompletion(aReason) {}
|
||||
});
|
||||
stmt.finalize();
|
||||
|
||||
|
@ -467,8 +460,9 @@ function test_finalized_statement_does_not_crash()
|
|||
// we are concerned about a crash here; an error is fine.
|
||||
try {
|
||||
stmt.executeAsync();
|
||||
} catch (ex) {
|
||||
// Do nothing.
|
||||
}
|
||||
catch (ex) {}
|
||||
|
||||
// Run the next test.
|
||||
run_next_test();
|
||||
|
@ -905,14 +899,13 @@ var testPass = TEST_PASS_SYNC;
|
|||
* @return a statement of the type under test per testPass.
|
||||
*/
|
||||
function makeTestStatement(aSQL) {
|
||||
if (testPass == TEST_PASS_SYNC)
|
||||
if (testPass == TEST_PASS_SYNC) {
|
||||
return getOpenedDatabase().createStatement(aSQL);
|
||||
else
|
||||
return getOpenedDatabase().createAsyncStatement(aSQL);
|
||||
}
|
||||
return getOpenedDatabase().createAsyncStatement(aSQL);
|
||||
}
|
||||
|
||||
var tests =
|
||||
[
|
||||
var tests = [
|
||||
test_illegal_sql_async_deferred,
|
||||
test_create_table,
|
||||
test_add_data,
|
||||
|
|
|
@ -129,12 +129,9 @@ function insertAndCheckMultipleParams(aVal)
|
|||
*/
|
||||
function printValDesc(aVal)
|
||||
{
|
||||
try
|
||||
{
|
||||
try {
|
||||
var toSource = aVal.toSource();
|
||||
}
|
||||
catch (exc)
|
||||
{
|
||||
} catch (ex) {
|
||||
toSource = "";
|
||||
}
|
||||
print("Testing value: toString=" + aVal +
|
||||
|
@ -163,7 +160,7 @@ function run_test()
|
|||
print("Single parameter");
|
||||
insertAndCheckSingleParam(val);
|
||||
print("Multiple parameters");
|
||||
insertAndCheckMultipleParams(val)
|
||||
insertAndCheckMultipleParams(val);
|
||||
});
|
||||
|
||||
cleanup();
|
||||
|
|
|
@ -11,7 +11,7 @@ function setup()
|
|||
getOpenedDatabase().createTable("function_tests", "id INTEGER PRIMARY KEY");
|
||||
|
||||
var stmt = createStatement("INSERT INTO function_tests (id) VALUES(?1)");
|
||||
for(var i = 0; i < testNums.length; ++i) {
|
||||
for (let i = 0; i < testNums.length; ++i) {
|
||||
stmt.bindByIndex(0, testNums[i]);
|
||||
stmt.execute();
|
||||
}
|
||||
|
@ -23,17 +23,17 @@ var testSquareAndSumFunction = {
|
|||
calls: 0,
|
||||
_sas: 0,
|
||||
|
||||
reset: function() {
|
||||
reset() {
|
||||
this.calls = 0;
|
||||
this._sas = 0;
|
||||
this._sas = 0;
|
||||
},
|
||||
|
||||
onStep: function(val) {
|
||||
onStep(val) {
|
||||
++this.calls;
|
||||
this._sas += val.getInt32(0) * val.getInt32(0);
|
||||
},
|
||||
|
||||
onFinal: function() {
|
||||
onFinal() {
|
||||
var retval = this._sas;
|
||||
this._sas = 0; // Prepare for next group
|
||||
return retval;
|
||||
|
@ -79,7 +79,9 @@ function test_aggregate_no_aliases()
|
|||
function test_aggregate_call()
|
||||
{
|
||||
var stmt = createStatement("SELECT test_sas_aggr(id) FROM function_tests");
|
||||
while(stmt.executeStep());
|
||||
while (stmt.executeStep()) {
|
||||
// Do nothing.
|
||||
}
|
||||
do_check_eq(testNums.length, testSquareAndSumFunction.calls);
|
||||
testSquareAndSumFunction.reset();
|
||||
stmt.finalize();
|
||||
|
@ -88,7 +90,7 @@ function test_aggregate_call()
|
|||
function test_aggregate_result()
|
||||
{
|
||||
var sas = 0;
|
||||
for(var i = 0; i < testNums.length; ++i) {
|
||||
for (var i = 0; i < testNums.length; ++i) {
|
||||
sas += testNums[i] * testNums[i];
|
||||
}
|
||||
var stmt = createStatement("SELECT test_sas_aggr(id) FROM function_tests");
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
function asyncClone(db, readOnly) {
|
||||
let deferred = Promise.defer();
|
||||
db.asyncClone(readOnly, function(status, db2) {
|
||||
db.asyncClone(readOnly, function (status, db2) {
|
||||
if (Components.isSuccessCode(status)) {
|
||||
deferred.resolve(db2);
|
||||
} else {
|
||||
|
@ -21,7 +21,7 @@ function asyncClone(db, readOnly) {
|
|||
|
||||
function asyncClose(db) {
|
||||
let deferred = Promise.defer();
|
||||
db.asyncClose(function(status) {
|
||||
db.asyncClose(function (status) {
|
||||
if (Components.isSuccessCode(status)) {
|
||||
deferred.resolve();
|
||||
} else {
|
||||
|
@ -41,7 +41,7 @@ function openAsyncDatabase(file, options) {
|
|||
properties.setProperty(k, options[k]);
|
||||
}
|
||||
}
|
||||
getService().openAsyncDatabase(file, properties, function(status, db) {
|
||||
getService().openAsyncDatabase(file, properties, function (status, db) {
|
||||
if (Components.isSuccessCode(status)) {
|
||||
deferred.resolve(db.QueryInterface(Ci.mozIStorageAsyncConnection));
|
||||
} else {
|
||||
|
@ -54,23 +54,22 @@ function openAsyncDatabase(file, options) {
|
|||
function executeAsync(statement, onResult) {
|
||||
let deferred = Promise.defer();
|
||||
statement.executeAsync({
|
||||
handleError: function(error) {
|
||||
handleError: function (error) {
|
||||
deferred.reject(error);
|
||||
},
|
||||
handleResult: function(result) {
|
||||
handleResult: function (result) {
|
||||
if (onResult) {
|
||||
onResult(result);
|
||||
}
|
||||
},
|
||||
handleCompletion: function(result) {
|
||||
handleCompletion: function (result) {
|
||||
deferred.resolve(result);
|
||||
}
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
add_task(function test_connectionReady_open()
|
||||
{
|
||||
add_task(function* test_connectionReady_open() {
|
||||
// there doesn't seem to be a way for the connection to not be ready (unless
|
||||
// we close it with mozIStorageConnection::Close(), but we don't for this).
|
||||
// It can only fail if GetPath fails on the database file, or if we run out
|
||||
|
@ -80,8 +79,7 @@ add_task(function test_connectionReady_open()
|
|||
do_check_true(msc.connectionReady);
|
||||
});
|
||||
|
||||
add_task(function test_connectionReady_closed()
|
||||
{
|
||||
add_task(function* test_connectionReady_closed() {
|
||||
// This also tests mozIStorageConnection::Close()
|
||||
|
||||
var msc = getOpenedDatabase();
|
||||
|
@ -90,26 +88,22 @@ add_task(function test_connectionReady_closed()
|
|||
gDBConn = null; // this is so later tests don't start to fail.
|
||||
});
|
||||
|
||||
add_task(function test_databaseFile()
|
||||
{
|
||||
add_task(function* test_databaseFile() {
|
||||
var msc = getOpenedDatabase();
|
||||
do_check_true(getTestDB().equals(msc.databaseFile));
|
||||
});
|
||||
|
||||
add_task(function test_tableExists_not_created()
|
||||
{
|
||||
add_task(function* test_tableExists_not_created() {
|
||||
var msc = getOpenedDatabase();
|
||||
do_check_false(msc.tableExists("foo"));
|
||||
});
|
||||
|
||||
add_task(function test_indexExists_not_created()
|
||||
{
|
||||
add_task(function* test_indexExists_not_created() {
|
||||
var msc = getOpenedDatabase();
|
||||
do_check_false(msc.indexExists("foo"));
|
||||
});
|
||||
|
||||
add_task(function test_temp_tableExists_and_indexExists()
|
||||
{
|
||||
add_task(function* test_temp_tableExists_and_indexExists() {
|
||||
var msc = getOpenedDatabase();
|
||||
msc.executeSimpleSQL("CREATE TEMP TABLE test_temp(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)");
|
||||
do_check_true(msc.tableExists("test_temp"));
|
||||
|
@ -121,22 +115,19 @@ add_task(function test_temp_tableExists_and_indexExists()
|
|||
msc.executeSimpleSQL("DROP TABLE test_temp");
|
||||
});
|
||||
|
||||
add_task(function test_createTable_not_created()
|
||||
{
|
||||
add_task(function* test_createTable_not_created() {
|
||||
var msc = getOpenedDatabase();
|
||||
msc.createTable("test", "id INTEGER PRIMARY KEY, name TEXT");
|
||||
do_check_true(msc.tableExists("test"));
|
||||
});
|
||||
|
||||
add_task(function test_indexExists_created()
|
||||
{
|
||||
add_task(function* test_indexExists_created() {
|
||||
var msc = getOpenedDatabase();
|
||||
msc.executeSimpleSQL("CREATE INDEX name_ind ON test (name)");
|
||||
do_check_true(msc.indexExists("name_ind"));
|
||||
});
|
||||
|
||||
add_task(function test_createTable_already_created()
|
||||
{
|
||||
add_task(function* test_createTable_already_created() {
|
||||
var msc = getOpenedDatabase();
|
||||
do_check_true(msc.tableExists("test"));
|
||||
try {
|
||||
|
@ -147,8 +138,7 @@ add_task(function test_createTable_already_created()
|
|||
}
|
||||
});
|
||||
|
||||
add_task(function test_attach_createTable_tableExists_indexExists()
|
||||
{
|
||||
add_task(function* test_attach_createTable_tableExists_indexExists() {
|
||||
var msc = getOpenedDatabase();
|
||||
var file = do_get_file("storage_attach.sqlite", true);
|
||||
var msc2 = getDatabase(file);
|
||||
|
@ -160,7 +150,10 @@ add_task(function test_attach_createTable_tableExists_indexExists()
|
|||
try {
|
||||
msc.createTable("sample.test", "id INTEGER PRIMARY KEY, name TEXT");
|
||||
do_throw("We shouldn't get here!");
|
||||
} catch (e if e.result == Components.results.NS_ERROR_FAILURE) {
|
||||
} catch (e) {
|
||||
if (e.result != Components.results.NS_ERROR_FAILURE) {
|
||||
throw e;
|
||||
}
|
||||
// we expect to fail because this table should exist already.
|
||||
}
|
||||
|
||||
|
@ -170,24 +163,25 @@ add_task(function test_attach_createTable_tableExists_indexExists()
|
|||
|
||||
msc.executeSimpleSQL("DETACH DATABASE sample");
|
||||
msc2.close();
|
||||
try { file.remove(false); } catch(e) { }
|
||||
try {
|
||||
file.remove(false);
|
||||
} catch (e) {
|
||||
// Do nothing.
|
||||
}
|
||||
});
|
||||
|
||||
add_task(function test_lastInsertRowID()
|
||||
{
|
||||
add_task(function* test_lastInsertRowID() {
|
||||
var msc = getOpenedDatabase();
|
||||
msc.executeSimpleSQL("INSERT INTO test (name) VALUES ('foo')");
|
||||
do_check_eq(1, msc.lastInsertRowID);
|
||||
});
|
||||
|
||||
add_task(function test_transactionInProgress_no()
|
||||
{
|
||||
add_task(function* test_transactionInProgress_no() {
|
||||
var msc = getOpenedDatabase();
|
||||
do_check_false(msc.transactionInProgress);
|
||||
});
|
||||
|
||||
add_task(function test_transactionInProgress_yes()
|
||||
{
|
||||
add_task(function* test_transactionInProgress_yes() {
|
||||
var msc = getOpenedDatabase();
|
||||
msc.beginTransaction();
|
||||
do_check_true(msc.transactionInProgress);
|
||||
|
@ -200,8 +194,7 @@ add_task(function test_transactionInProgress_yes()
|
|||
do_check_false(msc.transactionInProgress);
|
||||
});
|
||||
|
||||
add_task(function test_commitTransaction_no_transaction()
|
||||
{
|
||||
add_task(function* test_commitTransaction_no_transaction() {
|
||||
var msc = getOpenedDatabase();
|
||||
do_check_false(msc.transactionInProgress);
|
||||
try {
|
||||
|
@ -212,8 +205,7 @@ add_task(function test_commitTransaction_no_transaction()
|
|||
}
|
||||
});
|
||||
|
||||
add_task(function test_rollbackTransaction_no_transaction()
|
||||
{
|
||||
add_task(function* test_rollbackTransaction_no_transaction() {
|
||||
var msc = getOpenedDatabase();
|
||||
do_check_false(msc.transactionInProgress);
|
||||
try {
|
||||
|
@ -224,47 +216,47 @@ add_task(function test_rollbackTransaction_no_transaction()
|
|||
}
|
||||
});
|
||||
|
||||
add_task(function test_get_schemaVersion_not_set()
|
||||
{
|
||||
add_task(function* test_get_schemaVersion_not_set() {
|
||||
do_check_eq(0, getOpenedDatabase().schemaVersion);
|
||||
});
|
||||
|
||||
add_task(function test_set_schemaVersion()
|
||||
{
|
||||
add_task(function* test_set_schemaVersion() {
|
||||
var msc = getOpenedDatabase();
|
||||
const version = 1;
|
||||
msc.schemaVersion = version;
|
||||
do_check_eq(version, msc.schemaVersion);
|
||||
});
|
||||
|
||||
add_task(function test_set_schemaVersion_same()
|
||||
{
|
||||
add_task(function* test_set_schemaVersion_same() {
|
||||
var msc = getOpenedDatabase();
|
||||
const version = 1;
|
||||
msc.schemaVersion = version; // should still work ok
|
||||
do_check_eq(version, msc.schemaVersion);
|
||||
});
|
||||
|
||||
add_task(function test_set_schemaVersion_negative()
|
||||
{
|
||||
add_task(function* test_set_schemaVersion_negative() {
|
||||
var msc = getOpenedDatabase();
|
||||
const version = -1;
|
||||
msc.schemaVersion = version;
|
||||
do_check_eq(version, msc.schemaVersion);
|
||||
});
|
||||
|
||||
add_task(function test_createTable(){
|
||||
add_task(function* test_createTable() {
|
||||
var temp = getTestDB().parent;
|
||||
temp.append("test_db_table");
|
||||
try {
|
||||
var con = getService().openDatabase(temp);
|
||||
con.createTable("a","");
|
||||
con.createTable("a", "");
|
||||
} catch (e) {
|
||||
if (temp.exists()) try {
|
||||
temp.remove(false);
|
||||
} catch (e2) {}
|
||||
do_check_true(e.result==Cr.NS_ERROR_NOT_INITIALIZED ||
|
||||
e.result==Cr.NS_ERROR_FAILURE);
|
||||
if (temp.exists()) {
|
||||
try {
|
||||
temp.remove(false);
|
||||
} catch (e2) {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
do_check_true(e.result == Cr.NS_ERROR_NOT_INITIALIZED ||
|
||||
e.result == Cr.NS_ERROR_FAILURE);
|
||||
} finally {
|
||||
if (con) {
|
||||
con.close();
|
||||
|
@ -272,8 +264,7 @@ add_task(function test_createTable(){
|
|||
}
|
||||
});
|
||||
|
||||
add_task(function test_defaultSynchronousAtNormal()
|
||||
{
|
||||
add_task(function* test_defaultSynchronousAtNormal() {
|
||||
var msc = getOpenedDatabase();
|
||||
var stmt = createStatement("PRAGMA synchronous;");
|
||||
try {
|
||||
|
@ -287,14 +278,12 @@ add_task(function test_defaultSynchronousAtNormal()
|
|||
});
|
||||
|
||||
// must be ran before executeAsync tests
|
||||
add_task(function test_close_does_not_spin_event_loop()
|
||||
{
|
||||
add_task(function* test_close_does_not_spin_event_loop() {
|
||||
// We want to make sure that the event loop on the calling thread does not
|
||||
// spin when close is called.
|
||||
let event = {
|
||||
ran: false,
|
||||
run: function()
|
||||
{
|
||||
run() {
|
||||
this.ran = true;
|
||||
},
|
||||
};
|
||||
|
@ -315,8 +304,7 @@ add_task(function test_close_does_not_spin_event_loop()
|
|||
gDBConn = null;
|
||||
});
|
||||
|
||||
add_task(function test_asyncClose_succeeds_with_finalized_async_statement()
|
||||
{
|
||||
add_task(function* test_asyncClose_succeeds_with_finalized_async_statement() {
|
||||
// XXX this test isn't perfect since we can't totally control when events will
|
||||
// run. If this paticular function fails randomly, it means we have a
|
||||
// real bug.
|
||||
|
@ -333,7 +321,7 @@ add_task(function test_asyncClose_succeeds_with_finalized_async_statement()
|
|||
gDBConn = null;
|
||||
});
|
||||
|
||||
add_task(function test_close_then_release_statement() {
|
||||
add_task(function* test_close_then_release_statement() {
|
||||
// Testing the behavior in presence of a bad client that finalizes
|
||||
// statements after the database has been closed (typically by
|
||||
// letting the gc finalize the statement).
|
||||
|
@ -346,7 +334,7 @@ add_task(function test_close_then_release_statement() {
|
|||
gDBConn = null;
|
||||
});
|
||||
|
||||
add_task(function test_asyncClose_then_release_statement() {
|
||||
add_task(function* test_asyncClose_then_release_statement() {
|
||||
// Testing the behavior in presence of a bad client that finalizes
|
||||
// statements after the database has been async closed (typically by
|
||||
// letting the gc finalize the statement).
|
||||
|
@ -359,8 +347,7 @@ add_task(function test_asyncClose_then_release_statement() {
|
|||
gDBConn = null;
|
||||
});
|
||||
|
||||
add_task(function test_close_fails_with_async_statement_ran()
|
||||
{
|
||||
add_task(function* test_close_fails_with_async_statement_ran() {
|
||||
let deferred = Promise.defer();
|
||||
let stmt = createStatement("SELECT * FROM test");
|
||||
stmt.executeAsync();
|
||||
|
@ -376,7 +363,7 @@ add_task(function test_close_fails_with_async_statement_ran()
|
|||
}
|
||||
finally {
|
||||
// Clean up after ourselves.
|
||||
db.asyncClose(function() {
|
||||
db.asyncClose(function () {
|
||||
// Reset gDBConn so that later tests will get a new connection object.
|
||||
gDBConn = null;
|
||||
deferred.resolve();
|
||||
|
@ -385,8 +372,7 @@ add_task(function test_close_fails_with_async_statement_ran()
|
|||
yield deferred.promise;
|
||||
});
|
||||
|
||||
add_task(function test_clone_optional_param()
|
||||
{
|
||||
add_task(function* test_clone_optional_param() {
|
||||
let db1 = getService().openUnsharedDatabase(getTestDB());
|
||||
let db2 = db1.clone();
|
||||
do_check_true(db2.connectionReady);
|
||||
|
@ -409,7 +395,7 @@ add_task(function test_clone_optional_param()
|
|||
db2.close();
|
||||
});
|
||||
|
||||
function standardAsyncTest(promisedDB, name, shouldInit = false) {
|
||||
function* standardAsyncTest(promisedDB, name, shouldInit = false) {
|
||||
do_print("Performing standard async test " + name);
|
||||
|
||||
let adb = yield promisedDB;
|
||||
|
@ -434,13 +420,12 @@ function standardAsyncTest(promisedDB, name, shouldInit = false) {
|
|||
do_print("Extracting data");
|
||||
stmt = adb.createAsyncStatement("SELECT * FROM test");
|
||||
let found = false;
|
||||
yield executeAsync(stmt, function(result) {
|
||||
yield executeAsync(stmt, function (results) {
|
||||
do_print("Data has been extracted");
|
||||
|
||||
for (let row = result.getNextRow(); row != null; row = result.getNextRow()) {
|
||||
for (let row = results.getNextRow(); row != null; row = results.getNextRow()) {
|
||||
if (row.getResultByName("name") == name) {
|
||||
found = true;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -451,7 +436,7 @@ function standardAsyncTest(promisedDB, name, shouldInit = false) {
|
|||
do_print("Standard async test " + name + " complete");
|
||||
}
|
||||
|
||||
add_task(function test_open_async() {
|
||||
add_task(function* test_open_async() {
|
||||
yield standardAsyncTest(openAsyncDatabase(getTestDB(), null), "default");
|
||||
yield standardAsyncTest(openAsyncDatabase(getTestDB()), "no optional arg");
|
||||
yield standardAsyncTest(openAsyncDatabase(getTestDB(),
|
||||
|
@ -492,7 +477,7 @@ add_task(function test_open_async() {
|
|||
});
|
||||
|
||||
|
||||
add_task(function test_async_open_with_shared_cache() {
|
||||
add_task(function* test_async_open_with_shared_cache() {
|
||||
do_print("Testing that opening with a shared cache doesn't break stuff");
|
||||
let adb = yield openAsyncDatabase(getTestDB(), {shared: true});
|
||||
|
||||
|
@ -505,13 +490,12 @@ add_task(function test_async_open_with_shared_cache() {
|
|||
do_print("Extracting data");
|
||||
stmt = adb.createAsyncStatement("SELECT * FROM test");
|
||||
let found = false;
|
||||
yield executeAsync(stmt, function(result) {
|
||||
yield executeAsync(stmt, function (results) {
|
||||
do_print("Data has been extracted");
|
||||
|
||||
for (let row = result.getNextRow(); row != null; row = result.getNextRow()) {
|
||||
for (let row = results.getNextRow(); row != null; row = results.getNextRow()) {
|
||||
if (row.getResultByName("name") == "clockworker") {
|
||||
found = true;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -520,8 +504,7 @@ add_task(function test_async_open_with_shared_cache() {
|
|||
yield asyncClose(adb);
|
||||
});
|
||||
|
||||
add_task(function test_clone_trivial_async()
|
||||
{
|
||||
add_task(function* test_clone_trivial_async() {
|
||||
let db1 = getService().openDatabase(getTestDB());
|
||||
do_print("Opened adb1");
|
||||
do_check_true(db1 instanceof Ci.mozIStorageAsyncConnection);
|
||||
|
@ -533,8 +516,7 @@ add_task(function test_clone_trivial_async()
|
|||
yield asyncClose(adb2);
|
||||
});
|
||||
|
||||
add_task(function test_clone_no_optional_param_async()
|
||||
{
|
||||
add_task(function* test_clone_no_optional_param_async() {
|
||||
"use strict";
|
||||
do_print("Testing async cloning");
|
||||
let adb1 = yield openAsyncDatabase(getTestDB(), null);
|
||||
|
@ -560,13 +542,12 @@ add_task(function test_clone_no_optional_param_async()
|
|||
do_print("Extracting data from clone db");
|
||||
stmt = adb2.createAsyncStatement("SELECT * FROM test");
|
||||
let found = false;
|
||||
yield executeAsync(stmt, function(result) {
|
||||
yield executeAsync(stmt, function (results) {
|
||||
do_print("Data has been extracted");
|
||||
|
||||
for (let row = result.getNextRow(); row != null; row = result.getNextRow()) {
|
||||
for (let row = results.getNextRow(); row != null; row = results.getNextRow()) {
|
||||
if (row.getResultByName("name") == "yoric") {
|
||||
found = true;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -580,8 +561,7 @@ add_task(function test_clone_no_optional_param_async()
|
|||
do_print("Second db closed");
|
||||
});
|
||||
|
||||
add_task(function test_clone_readonly()
|
||||
{
|
||||
add_task(function* test_clone_readonly() {
|
||||
let db1 = getService().openUnsharedDatabase(getTestDB());
|
||||
let db2 = db1.clone(true);
|
||||
do_check_true(db2.connectionReady);
|
||||
|
@ -601,8 +581,7 @@ add_task(function test_clone_readonly()
|
|||
db2.close();
|
||||
});
|
||||
|
||||
add_task(function test_clone_shared_readonly()
|
||||
{
|
||||
add_task(function* test_clone_shared_readonly() {
|
||||
let db1 = getService().openDatabase(getTestDB());
|
||||
let db2 = db1.clone(true);
|
||||
do_check_true(db2.connectionReady);
|
||||
|
@ -626,28 +605,25 @@ add_task(function test_clone_shared_readonly()
|
|||
db2.close();
|
||||
});
|
||||
|
||||
add_task(function test_close_clone_fails()
|
||||
{
|
||||
add_task(function* test_close_clone_fails() {
|
||||
let calls = [
|
||||
"openDatabase",
|
||||
"openUnsharedDatabase",
|
||||
];
|
||||
calls.forEach(function(methodName) {
|
||||
calls.forEach(function (methodName) {
|
||||
let db = getService()[methodName](getTestDB());
|
||||
db.close();
|
||||
expectError(Cr.NS_ERROR_NOT_INITIALIZED, () => db.clone());
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function test_memory_clone_fails()
|
||||
{
|
||||
add_task(function* test_memory_clone_fails() {
|
||||
let db = getService().openSpecialDatabase("memory");
|
||||
db.close();
|
||||
expectError(Cr.NS_ERROR_NOT_INITIALIZED, () => db.clone());
|
||||
});
|
||||
|
||||
add_task(function test_clone_copies_functions()
|
||||
{
|
||||
add_task(function* test_clone_copies_functions() {
|
||||
const FUNC_NAME = "test_func";
|
||||
let calls = [
|
||||
"openDatabase",
|
||||
|
@ -657,9 +633,9 @@ add_task(function test_clone_copies_functions()
|
|||
"createFunction",
|
||||
"createAggregateFunction",
|
||||
];
|
||||
calls.forEach(function(methodName) {
|
||||
[true, false].forEach(function(readOnly) {
|
||||
functionMethods.forEach(function(functionMethod) {
|
||||
calls.forEach(function (methodName) {
|
||||
[true, false].forEach(function (readOnly) {
|
||||
functionMethods.forEach(function (functionMethod) {
|
||||
let db1 = getService()[methodName](getTestDB());
|
||||
// Create a function for db1.
|
||||
db1[functionMethod](FUNC_NAME, 1, {
|
||||
|
@ -680,17 +656,16 @@ add_task(function test_clone_copies_functions()
|
|||
});
|
||||
});
|
||||
|
||||
add_task(function test_clone_copies_overridden_functions()
|
||||
{
|
||||
add_task(function* test_clone_copies_overridden_functions() {
|
||||
const FUNC_NAME = "lower";
|
||||
function test_func() {
|
||||
this.called = false;
|
||||
}
|
||||
test_func.prototype = {
|
||||
onFunctionCall: function() {
|
||||
onFunctionCall() {
|
||||
this.called = true;
|
||||
},
|
||||
onStep: function() {
|
||||
onStep() {
|
||||
this.called = true;
|
||||
},
|
||||
onFinal: () => 0,
|
||||
|
@ -704,9 +679,9 @@ add_task(function test_clone_copies_overridden_functions()
|
|||
"createFunction",
|
||||
"createAggregateFunction",
|
||||
];
|
||||
calls.forEach(function(methodName) {
|
||||
[true, false].forEach(function(readOnly) {
|
||||
functionMethods.forEach(function(functionMethod) {
|
||||
calls.forEach(function (methodName) {
|
||||
[true, false].forEach(function (readOnly) {
|
||||
functionMethods.forEach(function (functionMethod) {
|
||||
let db1 = getService()[methodName](getTestDB());
|
||||
// Create a function for db1.
|
||||
let func = new test_func();
|
||||
|
@ -726,8 +701,7 @@ add_task(function test_clone_copies_overridden_functions()
|
|||
});
|
||||
});
|
||||
|
||||
add_task(function test_clone_copies_pragmas()
|
||||
{
|
||||
add_task(function* test_clone_copies_pragmas() {
|
||||
const PRAGMAS = [
|
||||
{ name: "cache_size", value: 500, copied: true },
|
||||
{ name: "temp_store", value: 2, copied: true },
|
||||
|
@ -769,8 +743,7 @@ add_task(function test_clone_copies_pragmas()
|
|||
db2.close();
|
||||
});
|
||||
|
||||
add_task(function test_readonly_clone_copies_pragmas()
|
||||
{
|
||||
add_task(function* test_readonly_clone_copies_pragmas() {
|
||||
const PRAGMAS = [
|
||||
{ name: "cache_size", value: 500, copied: true },
|
||||
{ name: "temp_store", value: 2, copied: true },
|
||||
|
@ -812,8 +785,7 @@ add_task(function test_readonly_clone_copies_pragmas()
|
|||
db2.close();
|
||||
});
|
||||
|
||||
add_task(function test_getInterface()
|
||||
{
|
||||
add_task(function* test_getInterface() {
|
||||
let db = getOpenedDatabase();
|
||||
let target = db.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIEventTarget);
|
||||
|
@ -826,7 +798,6 @@ add_task(function test_getInterface()
|
|||
});
|
||||
|
||||
|
||||
function run_test()
|
||||
{
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ function setup()
|
|||
getOpenedDatabase().createTable("function_tests", "id INTEGER PRIMARY KEY");
|
||||
|
||||
var stmt = createStatement("INSERT INTO function_tests (id) VALUES(?1)");
|
||||
for(var i = 0; i < testNums.length; ++i) {
|
||||
for (let i = 0; i < testNums.length; ++i) {
|
||||
stmt.bindByIndex(0, testNums[i]);
|
||||
stmt.execute();
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ function setup()
|
|||
var testSquareFunction = {
|
||||
calls: 0,
|
||||
|
||||
onFunctionCall: function(val) {
|
||||
onFunctionCall(val) {
|
||||
++this.calls;
|
||||
return val.getInt32(0) * val.getInt32(0);
|
||||
}
|
||||
|
@ -62,7 +62,9 @@ function test_function_aliases()
|
|||
function test_function_call()
|
||||
{
|
||||
var stmt = createStatement("SELECT test_square(id) FROM function_tests");
|
||||
while(stmt.executeStep());
|
||||
while (stmt.executeStep()) {
|
||||
// Do nothing.
|
||||
}
|
||||
do_check_eq(testNums.length, testSquareFunction.calls);
|
||||
testSquareFunction.calls = 0;
|
||||
stmt.finalize();
|
||||
|
@ -72,7 +74,7 @@ function test_function_result()
|
|||
{
|
||||
var stmt = createStatement("SELECT test_square(42) FROM function_tests");
|
||||
stmt.executeStep();
|
||||
do_check_eq(42*42, stmt.getInt32(0));
|
||||
do_check_eq(42 * 42, stmt.getInt32(0));
|
||||
testSquareFunction.calls = 0;
|
||||
stmt.finalize();
|
||||
}
|
||||
|
|
|
@ -11,9 +11,9 @@ function setup()
|
|||
msc.beginTransaction();
|
||||
|
||||
var stmt = createStatement("INSERT INTO handler_tests (id, num) VALUES(?1, ?2)");
|
||||
for(var i = 0; i < 100; ++i) {
|
||||
for (let i = 0; i < 100; ++i) {
|
||||
stmt.bindByIndex(0, i);
|
||||
stmt.bindByIndex(1, Math.floor(Math.random()*1000));
|
||||
stmt.bindByIndex(1, Math.floor(Math.random() * 1000));
|
||||
stmt.execute();
|
||||
}
|
||||
stmt.reset();
|
||||
|
@ -25,7 +25,7 @@ var testProgressHandler = {
|
|||
calls: 0,
|
||||
abort: false,
|
||||
|
||||
onProgress: function(comm) {
|
||||
onProgress(comm) {
|
||||
++this.calls;
|
||||
return this.abort;
|
||||
}
|
||||
|
@ -59,7 +59,9 @@ function test_handler_call()
|
|||
// Some long-executing request
|
||||
var stmt = createStatement(
|
||||
"SELECT SUM(t1.num * t2.num) FROM handler_tests AS t1, handler_tests AS t2");
|
||||
while(stmt.executeStep());
|
||||
while (stmt.executeStep()) {
|
||||
// Do nothing.
|
||||
}
|
||||
do_check_true(testProgressHandler.calls > 0);
|
||||
stmt.finalize();
|
||||
}
|
||||
|
@ -75,7 +77,9 @@ function test_handler_abort()
|
|||
|
||||
const SQLITE_INTERRUPT = 9;
|
||||
try {
|
||||
while(stmt.executeStep());
|
||||
while (stmt.executeStep()) {
|
||||
// Do nothing.
|
||||
}
|
||||
do_throw("We shouldn't get here!");
|
||||
} catch (e) {
|
||||
do_check_eq(Cr.NS_ERROR_ABORT, e.result);
|
||||
|
|
|
@ -97,7 +97,7 @@ function test_backup_new_filename()
|
|||
{
|
||||
var backup = getService().backupDatabaseFile(getTestDB(), BACKUP_FILE_NAME);
|
||||
do_check_eq(BACKUP_FILE_NAME, backup.leafName);
|
||||
|
||||
|
||||
backup.remove(false);
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,7 @@ function test_backup_new_folder()
|
|||
parentDir.append("test_storage_temp");
|
||||
if (parentDir.exists())
|
||||
parentDir.remove(true);
|
||||
parentDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
|
||||
parentDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
|
||||
do_check_true(parentDir.exists());
|
||||
|
||||
var backup = getService().backupDatabaseFile(getTestDB(), BACKUP_FILE_NAME,
|
||||
|
@ -133,9 +133,10 @@ var tests = [
|
|||
|
||||
function run_test()
|
||||
{
|
||||
for (var i = 0; i < tests.length; i++)
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
tests[i]();
|
||||
|
||||
}
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ function run_test()
|
|||
{
|
||||
for (var i = 0; i < tests.length; i++)
|
||||
tests[i]();
|
||||
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ function test_getColumnIndex_different_case()
|
|||
do_check_eq(Cr.NS_ERROR_INVALID_ARG, e.result);
|
||||
}
|
||||
try {
|
||||
do_check_eq(1, stmt.getColumnIndex("Id"));
|
||||
do_check_eq(1, stmt.getColumnIndex("Id"));
|
||||
do_throw("should not get here");
|
||||
} catch (e) {
|
||||
do_check_eq(Cr.NS_ERROR_INVALID_ARG, e.result);
|
||||
|
@ -179,9 +179,10 @@ function run_test()
|
|||
{
|
||||
setup();
|
||||
|
||||
for (var i = 0; i < tests.length; i++)
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
tests[i]();
|
||||
|
||||
}
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
|
|
|
@ -8,14 +8,14 @@ function setup()
|
|||
{
|
||||
getOpenedDatabase().createTable("test", "id INTEGER PRIMARY KEY, name TEXT," +
|
||||
"number REAL, nuller NULL, blobber BLOB");
|
||||
|
||||
|
||||
var stmt = createStatement("INSERT INTO test (name, number, blobber) " +
|
||||
"VALUES (?1, ?2, ?3)");
|
||||
stmt.bindByIndex(0, "foo");
|
||||
stmt.bindByIndex(1, 2.34);
|
||||
stmt.bindBlobByIndex(2, [], 0);
|
||||
stmt.execute();
|
||||
|
||||
|
||||
stmt.bindByIndex(0, "");
|
||||
stmt.bindByIndex(1, 1.23);
|
||||
stmt.bindBlobByIndex(2, [1, 2], 2);
|
||||
|
@ -30,7 +30,7 @@ function test_getIsNull_for_null()
|
|||
var stmt = createStatement("SELECT nuller, blobber FROM test WHERE id = ?1");
|
||||
stmt.bindByIndex(0, 1);
|
||||
do_check_true(stmt.executeStep());
|
||||
|
||||
|
||||
do_check_true(stmt.getIsNull(0)); // null field
|
||||
do_check_true(stmt.getIsNull(1)); // data is null if size is 0
|
||||
stmt.reset();
|
||||
|
@ -202,9 +202,10 @@ function run_test()
|
|||
{
|
||||
setup();
|
||||
|
||||
for (var i = 0; i < tests.length; i++)
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
tests[i]();
|
||||
|
||||
}
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
// Make sure that there are telemetry entries created by sqlite io
|
||||
|
||||
function run_sql(d, sql) {
|
||||
var stmt = d.createStatement(sql)
|
||||
stmt.execute()
|
||||
var stmt = d.createStatement(sql);
|
||||
stmt.execute();
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ function run_test()
|
|||
const file = new_file("telemetry.sqlite");
|
||||
var d = getDatabase(file);
|
||||
run_sql(d, "CREATE TABLE bloat(data varchar)");
|
||||
run_sql(d, "DROP TABLE bloat")
|
||||
do_check_true(read_hgram.snapshot().sum > old_sum)
|
||||
run_sql(d, "DROP TABLE bloat");
|
||||
do_check_true(read_hgram.snapshot().sum > old_sum);
|
||||
}
|
||||
|
||||
|
|
|
@ -95,9 +95,10 @@ function run_test()
|
|||
{
|
||||
setup();
|
||||
|
||||
for (var i = 0; i < tests.length; i++)
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
tests[i]();
|
||||
|
||||
}
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
|
|
|
@ -87,6 +87,239 @@ function run_test()
|
|||
run_next_test();
|
||||
}
|
||||
|
||||
const TESTS = [
|
||||
|
||||
function test_common_vacuum()
|
||||
{
|
||||
print("\n*** Test that a VACUUM correctly happens and all notifications are fired.");
|
||||
// Wait for VACUUM begin.
|
||||
let beginVacuumReceived = false;
|
||||
Services.obs.addObserver(function onVacuum(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(onVacuum, aTopic);
|
||||
beginVacuumReceived = true;
|
||||
}, "test-begin-vacuum", false);
|
||||
|
||||
// Wait for heavy IO notifications.
|
||||
let heavyIOTaskBeginReceived = false;
|
||||
let heavyIOTaskEndReceived = false;
|
||||
Services.obs.addObserver(function onVacuum(aSubject, aTopic, aData) {
|
||||
if (heavyIOTaskBeginReceived && heavyIOTaskEndReceived) {
|
||||
Services.obs.removeObserver(onVacuum, aTopic);
|
||||
}
|
||||
|
||||
if (aData == "vacuum-begin") {
|
||||
heavyIOTaskBeginReceived = true;
|
||||
}
|
||||
else if (aData == "vacuum-end") {
|
||||
heavyIOTaskEndReceived = true;
|
||||
}
|
||||
}, "heavy-io-task", false);
|
||||
|
||||
// Wait for VACUUM end.
|
||||
Services.obs.addObserver(function onVacuum(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(onVacuum, aTopic);
|
||||
print("Check we received onBeginVacuum");
|
||||
do_check_true(beginVacuumReceived);
|
||||
print("Check we received heavy-io-task notifications");
|
||||
do_check_true(heavyIOTaskBeginReceived);
|
||||
do_check_true(heavyIOTaskEndReceived);
|
||||
print("Received onEndVacuum");
|
||||
run_next_test();
|
||||
}, "test-end-vacuum", false);
|
||||
|
||||
synthesize_idle_daily();
|
||||
},
|
||||
|
||||
function test_skipped_if_recent_vacuum()
|
||||
{
|
||||
print("\n*** Test that a VACUUM is skipped if it was run recently.");
|
||||
Services.prefs.setIntPref("storage.vacuum.last.testVacuum.sqlite",
|
||||
parseInt(Date.now() / 1000));
|
||||
|
||||
// Wait for VACUUM begin.
|
||||
let vacuumObserver = {
|
||||
gotNotification: false,
|
||||
observe: function VO_observe(aSubject, aTopic, aData) {
|
||||
this.gotNotification = true;
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
|
||||
};
|
||||
Services.obs.addObserver(vacuumObserver, "test-begin-vacuum", false);
|
||||
|
||||
// Check after a couple seconds that no VACUUM has been run.
|
||||
do_timeout(2000, function () {
|
||||
print("Check VACUUM did not run.");
|
||||
do_check_false(vacuumObserver.gotNotification);
|
||||
Services.obs.removeObserver(vacuumObserver, "test-begin-vacuum");
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
synthesize_idle_daily();
|
||||
},
|
||||
|
||||
function test_page_size_change()
|
||||
{
|
||||
print("\n*** Test that a VACUUM changes page_size");
|
||||
|
||||
// We did setup the database with a small page size, the previous vacuum
|
||||
// should have updated it.
|
||||
print("Check that page size was updated.");
|
||||
let conn = getDatabase(new_db_file("testVacuum"));
|
||||
let stmt = conn.createStatement("PRAGMA page_size");
|
||||
try {
|
||||
while (stmt.executeStep()) {
|
||||
do_check_eq(stmt.row.page_size, conn.defaultPageSize);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
},
|
||||
|
||||
function test_skipped_optout_vacuum()
|
||||
{
|
||||
print("\n*** Test that a VACUUM is skipped if the participant wants to opt-out.");
|
||||
Services.obs.notifyObservers(null, "test-options", "opt-out");
|
||||
|
||||
// Wait for VACUUM begin.
|
||||
let vacuumObserver = {
|
||||
gotNotification: false,
|
||||
observe: function VO_observe(aSubject, aTopic, aData) {
|
||||
this.gotNotification = true;
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
|
||||
};
|
||||
Services.obs.addObserver(vacuumObserver, "test-begin-vacuum", false);
|
||||
|
||||
// Check after a couple seconds that no VACUUM has been run.
|
||||
do_timeout(2000, function () {
|
||||
print("Check VACUUM did not run.");
|
||||
do_check_false(vacuumObserver.gotNotification);
|
||||
Services.obs.removeObserver(vacuumObserver, "test-begin-vacuum");
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
synthesize_idle_daily();
|
||||
},
|
||||
|
||||
/* Changing page size on WAL is not supported till Bug 634374 is properly fixed.
|
||||
function test_page_size_change_with_wal()
|
||||
{
|
||||
print("\n*** Test that a VACUUM changes page_size with WAL mode");
|
||||
Services.obs.notifyObservers(null, "test-options", "wal");
|
||||
|
||||
// Set a small page size.
|
||||
let conn = getDatabase(new_db_file("testVacuum2"));
|
||||
conn.executeSimpleSQL("PRAGMA page_size = 1024");
|
||||
let stmt = conn.createStatement("PRAGMA page_size");
|
||||
try {
|
||||
while (stmt.executeStep()) {
|
||||
do_check_eq(stmt.row.page_size, 1024);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
// Use WAL journal mode.
|
||||
conn.executeSimpleSQL("PRAGMA journal_mode = WAL");
|
||||
stmt = conn.createStatement("PRAGMA journal_mode");
|
||||
try {
|
||||
while (stmt.executeStep()) {
|
||||
do_check_eq(stmt.row.journal_mode, "wal");
|
||||
}
|
||||
}
|
||||
finally {
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
// Wait for VACUUM end.
|
||||
let vacuumObserver = {
|
||||
observe: function VO_observe(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(this, aTopic);
|
||||
print("Check page size has been updated.");
|
||||
let stmt = conn.createStatement("PRAGMA page_size");
|
||||
try {
|
||||
while (stmt.executeStep()) {
|
||||
do_check_eq(stmt.row.page_size, Ci.mozIStorageConnection.DEFAULT_PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
print("Check journal mode has been restored.");
|
||||
stmt = conn.createStatement("PRAGMA journal_mode");
|
||||
try {
|
||||
while (stmt.executeStep()) {
|
||||
do_check_eq(stmt.row.journal_mode, "wal");
|
||||
}
|
||||
}
|
||||
finally {
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
|
||||
}
|
||||
Services.obs.addObserver(vacuumObserver, "test-end-vacuum", false);
|
||||
|
||||
synthesize_idle_daily();
|
||||
},
|
||||
*/
|
||||
|
||||
function test_memory_database_crash()
|
||||
{
|
||||
print("\n*** Test that we don't crash trying to vacuum a memory database");
|
||||
Services.obs.notifyObservers(null, "test-options", "memory");
|
||||
|
||||
// Wait for VACUUM begin.
|
||||
let vacuumObserver = {
|
||||
gotNotification: false,
|
||||
observe: function VO_observe(aSubject, aTopic, aData) {
|
||||
this.gotNotification = true;
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
|
||||
};
|
||||
Services.obs.addObserver(vacuumObserver, "test-begin-vacuum", false);
|
||||
|
||||
// Check after a couple seconds that no VACUUM has been run.
|
||||
do_timeout(2000, function () {
|
||||
print("Check VACUUM did not run.");
|
||||
do_check_false(vacuumObserver.gotNotification);
|
||||
Services.obs.removeObserver(vacuumObserver, "test-begin-vacuum");
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
synthesize_idle_daily();
|
||||
},
|
||||
|
||||
/* Changing page size on WAL is not supported till Bug 634374 is properly fixed.
|
||||
function test_wal_restore_fail()
|
||||
{
|
||||
print("\n*** Test that a failing WAL restoration notifies failure");
|
||||
Services.obs.notifyObservers(null, "test-options", "wal-fail");
|
||||
|
||||
// Wait for VACUUM end.
|
||||
let vacuumObserver = {
|
||||
observe: function VO_observe(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(vacuumObserver, "test-end-vacuum");
|
||||
print("Check WAL restoration failed.");
|
||||
do_check_false(aData);
|
||||
run_next_test();
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
|
||||
}
|
||||
Services.obs.addObserver(vacuumObserver, "test-end-vacuum", false);
|
||||
|
||||
synthesize_idle_daily();
|
||||
},
|
||||
*/
|
||||
];
|
||||
|
||||
function run_next_test()
|
||||
{
|
||||
if (TESTS.length == 0) {
|
||||
|
@ -100,236 +333,3 @@ function run_next_test()
|
|||
do_execute_soon(TESTS.shift());
|
||||
}
|
||||
}
|
||||
|
||||
const TESTS = [
|
||||
|
||||
function test_common_vacuum()
|
||||
{
|
||||
print("\n*** Test that a VACUUM correctly happens and all notifications are fired.");
|
||||
// Wait for VACUUM begin.
|
||||
let beginVacuumReceived = false;
|
||||
Services.obs.addObserver(function onVacuum(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(onVacuum, aTopic);
|
||||
beginVacuumReceived = true;
|
||||
}, "test-begin-vacuum", false);
|
||||
|
||||
// Wait for heavy IO notifications.
|
||||
let heavyIOTaskBeginReceived = false;
|
||||
let heavyIOTaskEndReceived = false;
|
||||
Services.obs.addObserver(function onVacuum(aSubject, aTopic, aData) {
|
||||
if (heavyIOTaskBeginReceived && heavyIOTaskEndReceived) {
|
||||
Services.obs.removeObserver(onVacuum, aTopic);
|
||||
}
|
||||
|
||||
if (aData == "vacuum-begin") {
|
||||
heavyIOTaskBeginReceived = true;
|
||||
}
|
||||
else if (aData == "vacuum-end") {
|
||||
heavyIOTaskEndReceived = true;
|
||||
}
|
||||
}, "heavy-io-task", false);
|
||||
|
||||
// Wait for VACUUM end.
|
||||
Services.obs.addObserver(function onVacuum(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(onVacuum, aTopic);
|
||||
print("Check we received onBeginVacuum");
|
||||
do_check_true(beginVacuumReceived);
|
||||
print("Check we received heavy-io-task notifications");
|
||||
do_check_true(heavyIOTaskBeginReceived);
|
||||
do_check_true(heavyIOTaskEndReceived);
|
||||
print("Received onEndVacuum");
|
||||
run_next_test();
|
||||
}, "test-end-vacuum", false);
|
||||
|
||||
synthesize_idle_daily();
|
||||
},
|
||||
|
||||
function test_skipped_if_recent_vacuum()
|
||||
{
|
||||
print("\n*** Test that a VACUUM is skipped if it was run recently.");
|
||||
Services.prefs.setIntPref("storage.vacuum.last.testVacuum.sqlite",
|
||||
parseInt(Date.now() / 1000));
|
||||
|
||||
// Wait for VACUUM begin.
|
||||
let vacuumObserver = {
|
||||
gotNotification: false,
|
||||
observe: function VO_observe(aSubject, aTopic, aData) {
|
||||
this.gotNotification = true;
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
|
||||
}
|
||||
Services.obs.addObserver(vacuumObserver, "test-begin-vacuum", false);
|
||||
|
||||
// Check after a couple seconds that no VACUUM has been run.
|
||||
do_timeout(2000, function () {
|
||||
print("Check VACUUM did not run.");
|
||||
do_check_false(vacuumObserver.gotNotification);
|
||||
Services.obs.removeObserver(vacuumObserver, "test-begin-vacuum");
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
synthesize_idle_daily();
|
||||
},
|
||||
|
||||
function test_page_size_change()
|
||||
{
|
||||
print("\n*** Test that a VACUUM changes page_size");
|
||||
|
||||
// We did setup the database with a small page size, the previous vacuum
|
||||
// should have updated it.
|
||||
print("Check that page size was updated.");
|
||||
let conn = getDatabase(new_db_file("testVacuum"));
|
||||
let stmt = conn.createStatement("PRAGMA page_size");
|
||||
try {
|
||||
while (stmt.executeStep()) {
|
||||
do_check_eq(stmt.row.page_size, conn.defaultPageSize);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
},
|
||||
|
||||
function test_skipped_optout_vacuum()
|
||||
{
|
||||
print("\n*** Test that a VACUUM is skipped if the participant wants to opt-out.");
|
||||
Services.obs.notifyObservers(null, "test-options", "opt-out");
|
||||
|
||||
// Wait for VACUUM begin.
|
||||
let vacuumObserver = {
|
||||
gotNotification: false,
|
||||
observe: function VO_observe(aSubject, aTopic, aData) {
|
||||
this.gotNotification = true;
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
|
||||
}
|
||||
Services.obs.addObserver(vacuumObserver, "test-begin-vacuum", false);
|
||||
|
||||
// Check after a couple seconds that no VACUUM has been run.
|
||||
do_timeout(2000, function () {
|
||||
print("Check VACUUM did not run.");
|
||||
do_check_false(vacuumObserver.gotNotification);
|
||||
Services.obs.removeObserver(vacuumObserver, "test-begin-vacuum");
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
synthesize_idle_daily();
|
||||
},
|
||||
|
||||
/* Changing page size on WAL is not supported till Bug 634374 is properly fixed.
|
||||
function test_page_size_change_with_wal()
|
||||
{
|
||||
print("\n*** Test that a VACUUM changes page_size with WAL mode");
|
||||
Services.obs.notifyObservers(null, "test-options", "wal");
|
||||
|
||||
// Set a small page size.
|
||||
let conn = getDatabase(new_db_file("testVacuum2"));
|
||||
conn.executeSimpleSQL("PRAGMA page_size = 1024");
|
||||
let stmt = conn.createStatement("PRAGMA page_size");
|
||||
try {
|
||||
while (stmt.executeStep()) {
|
||||
do_check_eq(stmt.row.page_size, 1024);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
// Use WAL journal mode.
|
||||
conn.executeSimpleSQL("PRAGMA journal_mode = WAL");
|
||||
stmt = conn.createStatement("PRAGMA journal_mode");
|
||||
try {
|
||||
while (stmt.executeStep()) {
|
||||
do_check_eq(stmt.row.journal_mode, "wal");
|
||||
}
|
||||
}
|
||||
finally {
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
// Wait for VACUUM end.
|
||||
let vacuumObserver = {
|
||||
observe: function VO_observe(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(this, aTopic);
|
||||
print("Check page size has been updated.");
|
||||
let stmt = conn.createStatement("PRAGMA page_size");
|
||||
try {
|
||||
while (stmt.executeStep()) {
|
||||
do_check_eq(stmt.row.page_size, Ci.mozIStorageConnection.DEFAULT_PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
print("Check journal mode has been restored.");
|
||||
stmt = conn.createStatement("PRAGMA journal_mode");
|
||||
try {
|
||||
while (stmt.executeStep()) {
|
||||
do_check_eq(stmt.row.journal_mode, "wal");
|
||||
}
|
||||
}
|
||||
finally {
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
|
||||
}
|
||||
Services.obs.addObserver(vacuumObserver, "test-end-vacuum", false);
|
||||
|
||||
synthesize_idle_daily();
|
||||
},
|
||||
*/
|
||||
|
||||
function test_memory_database_crash()
|
||||
{
|
||||
print("\n*** Test that we don't crash trying to vacuum a memory database");
|
||||
Services.obs.notifyObservers(null, "test-options", "memory");
|
||||
|
||||
// Wait for VACUUM begin.
|
||||
let vacuumObserver = {
|
||||
gotNotification: false,
|
||||
observe: function VO_observe(aSubject, aTopic, aData) {
|
||||
this.gotNotification = true;
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
|
||||
}
|
||||
Services.obs.addObserver(vacuumObserver, "test-begin-vacuum", false);
|
||||
|
||||
// Check after a couple seconds that no VACUUM has been run.
|
||||
do_timeout(2000, function () {
|
||||
print("Check VACUUM did not run.");
|
||||
do_check_false(vacuumObserver.gotNotification);
|
||||
Services.obs.removeObserver(vacuumObserver, "test-begin-vacuum");
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
synthesize_idle_daily();
|
||||
},
|
||||
|
||||
/* Changing page size on WAL is not supported till Bug 634374 is properly fixed.
|
||||
function test_wal_restore_fail()
|
||||
{
|
||||
print("\n*** Test that a failing WAL restoration notifies failure");
|
||||
Services.obs.notifyObservers(null, "test-options", "wal-fail");
|
||||
|
||||
// Wait for VACUUM end.
|
||||
let vacuumObserver = {
|
||||
observe: function VO_observe(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(vacuumObserver, "test-end-vacuum");
|
||||
print("Check WAL restoration failed.");
|
||||
do_check_false(aData);
|
||||
run_next_test();
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
|
||||
}
|
||||
Services.obs.addObserver(vacuumObserver, "test-end-vacuum", false);
|
||||
|
||||
synthesize_idle_daily();
|
||||
},
|
||||
*/
|
||||
];
|
||||
|
|
|
@ -76,15 +76,17 @@ vacuumParticipant.prototype =
|
|||
else if (aData == "wal") {
|
||||
try {
|
||||
this._dbConn.close();
|
||||
} catch (e) {
|
||||
// Do nothing.
|
||||
}
|
||||
catch(e) {}
|
||||
this._dbConn = getDatabase(new_db_file("testVacuum2"));
|
||||
}
|
||||
else if (aData == "wal-fail") {
|
||||
try {
|
||||
this._dbConn.close();
|
||||
} catch (e) {
|
||||
// Do nothing.
|
||||
}
|
||||
catch(e) {}
|
||||
this._dbConn = getDatabase(new_db_file("testVacuum3"));
|
||||
// Use WAL journal mode.
|
||||
this._dbConn.executeSimpleSQL("PRAGMA journal_mode = WAL");
|
||||
|
@ -96,8 +98,9 @@ vacuumParticipant.prototype =
|
|||
else if (aData == "memory") {
|
||||
try {
|
||||
this._dbConn.asyncClose();
|
||||
} catch (e) {
|
||||
// Do nothing.
|
||||
}
|
||||
catch(e) {}
|
||||
this._dbConn = Cc["@mozilla.org/storage/service;1"].
|
||||
getService(Ci.mozIStorageService).
|
||||
openSpecialDatabase("memory");
|
||||
|
@ -106,14 +109,15 @@ vacuumParticipant.prototype =
|
|||
Services.obs.removeObserver(this, "test-options");
|
||||
try {
|
||||
this._dbConn.asyncClose();
|
||||
} catch (e) {
|
||||
// Do nothing.
|
||||
}
|
||||
catch(e) {}
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.mozIStorageVacuumParticipant
|
||||
, Ci.nsIObserver
|
||||
Ci.mozIStorageVacuumParticipant,
|
||||
Ci.nsIObserver,
|
||||
])
|
||||
};
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@
|
|||
// "no-unused-vars": [2, {"vars": "all", "args": "none"}],
|
||||
|
||||
// No using variables before defined
|
||||
// "no-use-before-define": 2,
|
||||
// "no-use-before-define": [2, "nofunc"],
|
||||
|
||||
// No using with
|
||||
// "no-with": 2,
|
||||
|
|
|
@ -561,7 +561,7 @@ var View = {
|
|||
cachedElements.eltName.textContent = `Full name: ${delta.fullName}.`;
|
||||
cachedElements.eltLoaded.textContent = `Measure start: ${Math.round(delta.age/1000)} seconds ago.`
|
||||
|
||||
let processes = [for (proc of delta.diff.processes) `${proc.processId} (${proc.isChildProcess?"child":"parent"})`];
|
||||
let processes = delta.diff.processes.map(proc => `${proc.processId} (${proc.isChildProcess?"child":"parent"})`);
|
||||
cachedElements.eltProcess.textContent = `Processes: ${processes.join(", ")}`;
|
||||
let jankSuffix = "";
|
||||
let cpowSuffix = "";
|
||||
|
|
|
@ -164,8 +164,8 @@ function frameScript() {
|
|||
return;
|
||||
}
|
||||
|
||||
let addonTitles = [for (eltContent of eltAddons.querySelectorAll("span.title")) eltContent.textContent];
|
||||
let webTitles = [for (eltContent of eltWeb.querySelectorAll("span.title")) eltContent.textContent];
|
||||
let addonTitles = Array.from(eltAddons.querySelectorAll("span.title"), elt => elt.textContent);
|
||||
let webTitles = Array.from(eltWeb.querySelectorAll("span.title"), elt => elt.textContent);
|
||||
|
||||
hasTitleInAddons = addonTitles.includes(title);
|
||||
hasTitleInWebpages = webTitles.includes(title);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
|
||||
#
|
||||
# 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/.
|
||||
/* 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/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/AppConstants.jsm");
|
||||
|
||||
function AppPicker() {};
|
||||
|
||||
|
@ -117,20 +117,19 @@ AppPicker.prototype =
|
|||
* Retrieve the pretty description from the file
|
||||
*/
|
||||
getFileDisplayName: function getFileDisplayName(file) {
|
||||
#ifdef XP_WIN
|
||||
if (file instanceof Components.interfaces.nsILocalFileWin) {
|
||||
try {
|
||||
return file.getVersionInfoField("FileDescription");
|
||||
} catch (e) {}
|
||||
if (AppConstants.platform == "win") {
|
||||
if (file instanceof Components.interfaces.nsILocalFileWin) {
|
||||
try {
|
||||
return file.getVersionInfoField("FileDescription");
|
||||
} catch (e) {}
|
||||
}
|
||||
} else if (AppConstants.platform == "macosx") {
|
||||
if (file instanceof Components.interfaces.nsILocalFileMac) {
|
||||
try {
|
||||
return file.bundleDisplayName;
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef XP_MACOSX
|
||||
if (file instanceof Components.interfaces.nsILocalFileMac) {
|
||||
try {
|
||||
return file.bundleDisplayName;
|
||||
} catch (e) {}
|
||||
}
|
||||
#endif
|
||||
return file.leafName;
|
||||
},
|
||||
|
||||
|
@ -186,15 +185,13 @@ AppPicker.prototype =
|
|||
var fileLoc = Components.classes["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Components.interfaces.nsIProperties);
|
||||
var startLocation;
|
||||
#ifdef XP_WIN
|
||||
startLocation = "ProgF"; // Program Files
|
||||
#else
|
||||
#ifdef XP_MACOSX
|
||||
startLocation = "LocApp"; // Local Applications
|
||||
#else
|
||||
startLocation = "Home";
|
||||
#endif
|
||||
#endif
|
||||
if (AppConstants.platform == "win") {
|
||||
startLocation = "ProgF"; // Program Files
|
||||
} else if (AppConstants.platform == "macosx") {
|
||||
startLocation = "LocApp"; // Local Applications
|
||||
} else {
|
||||
startLocation = "Home";
|
||||
}
|
||||
fp.displayDirectory =
|
||||
fileLoc.get(startLocation, Components.interfaces.nsILocalFile);
|
||||
|
||||
|
|
|
@ -4,5 +4,5 @@
|
|||
|
||||
toolkit.jar:
|
||||
content/global/appPicker.xul (content/appPicker.xul)
|
||||
* content/global/appPicker.js (content/appPicker.js)
|
||||
content/global/appPicker.js (content/appPicker.js)
|
||||
|
||||
|
|
|
@ -0,0 +1,499 @@
|
|||
{
|
||||
"extends": "../../.eslintrc",
|
||||
|
||||
"globals": {
|
||||
"Cc": true,
|
||||
"Ci": true,
|
||||
"Components": true,
|
||||
"Cr": true,
|
||||
"Cu": true,
|
||||
"dump": true,
|
||||
"TextDecoder": false,
|
||||
"TextEncoder": false,
|
||||
// Specific to WebExtensions:
|
||||
"extensions": true,
|
||||
"global": true,
|
||||
"Extension": true,
|
||||
"ExtensionManagement": true,
|
||||
"ExtensionPage": true,
|
||||
"GlobalManager": true,
|
||||
"runSafe": true,
|
||||
"runSafeSync": true,
|
||||
"runSafeSyncWithoutClone": true,
|
||||
"Services": true,
|
||||
"TabManager": true,
|
||||
"XPCOMUtils": true,
|
||||
},
|
||||
|
||||
"rules": {
|
||||
// Rules from the mozilla plugin
|
||||
"mozilla/balanced-listeners": 2,
|
||||
"mozilla/components-imports": 1,
|
||||
"mozilla/import-headjs-globals": 1,
|
||||
"mozilla/mark-test-function-used": 1,
|
||||
"mozilla/no-aArgs": 1,
|
||||
"mozilla/no-cpows-in-tests": 1,
|
||||
"mozilla/var-only-at-top-level": 1,
|
||||
|
||||
// Braces only needed for multi-line arrow function blocks
|
||||
// "arrow-body-style": [2, "as-needed"],
|
||||
|
||||
// Require spacing around =>
|
||||
"arrow-spacing": 2,
|
||||
|
||||
// Always require spacing around a single line block
|
||||
"block-spacing": 1,
|
||||
|
||||
// Enforce one true brace style (opening brace on the same line) and avoid
|
||||
// start and end braces on the same line.
|
||||
"brace-style": [2, "1tbs", { "allowSingleLine": true }],
|
||||
|
||||
// No space before always a space after a comma
|
||||
"comma-spacing": [2, {"before": false, "after": true}],
|
||||
|
||||
// Commas at the end of the line not the start
|
||||
"comma-style": 2,
|
||||
|
||||
// Don't require spaces around computed properties
|
||||
"computed-property-spacing": [1, "never"],
|
||||
|
||||
// Functions are not required to consistently return something or nothing
|
||||
"consistent-return": 0,
|
||||
|
||||
// Require braces around blocks that start a new line
|
||||
"curly": [2, "multi-line"],
|
||||
|
||||
// Always require a trailing EOL
|
||||
"eol-last": 2,
|
||||
|
||||
// Require function* name()
|
||||
"generator-star-spacing": [2, {"before": false, "after": true}],
|
||||
|
||||
// Two space indent
|
||||
"indent": [2, 2, { "SwitchCase": 1 }],
|
||||
|
||||
// Space after colon not before in property declarations
|
||||
"key-spacing": [2, { "beforeColon": false, "afterColon": true, "mode": "minimum" }],
|
||||
|
||||
// Unix linebreaks
|
||||
"linebreak-style": [2, "unix"],
|
||||
|
||||
// Always require parenthesis for new calls
|
||||
"new-parens": 2,
|
||||
|
||||
// Use [] instead of Array()
|
||||
"no-array-constructor": 2,
|
||||
|
||||
// No duplicate arguments in function declarations
|
||||
"no-dupe-args": 2,
|
||||
|
||||
// No duplicate keys in object declarations
|
||||
"no-dupe-keys": 2,
|
||||
|
||||
// No duplicate cases in switch statements
|
||||
"no-duplicate-case": 2,
|
||||
|
||||
// No labels
|
||||
// "no-labels": 2,
|
||||
|
||||
// If an if block ends with a return no need for an else block
|
||||
// "no-else-return": 2,
|
||||
|
||||
// Disallow empty statements. This will report an error for:
|
||||
// try { something(); } catch (e) {}
|
||||
// but will not report it for:
|
||||
// try { something(); } catch (e) { /* Silencing the error because ...*/ }
|
||||
// which is a valid use case.
|
||||
"no-empty": 2,
|
||||
|
||||
// No empty character classes in regex
|
||||
"no-empty-character-class": 2,
|
||||
|
||||
// Disallow empty destructuring
|
||||
"no-empty-pattern": 2,
|
||||
|
||||
// No assiging to exception variable
|
||||
"no-ex-assign": 2,
|
||||
|
||||
// No using !! where casting to boolean is already happening
|
||||
"no-extra-boolean-cast": 1,
|
||||
|
||||
// No double semicolon
|
||||
"no-extra-semi": 2,
|
||||
|
||||
// No overwriting defined functions
|
||||
"no-func-assign": 2,
|
||||
|
||||
// No invalid regular expresions
|
||||
"no-invalid-regexp": 2,
|
||||
|
||||
// No odd whitespace characters
|
||||
"no-irregular-whitespace": 2,
|
||||
|
||||
// No single if block inside an else block
|
||||
"no-lonely-if": 1,
|
||||
|
||||
// No mixing spaces and tabs in indent
|
||||
"no-mixed-spaces-and-tabs": [2, "smart-tabs"],
|
||||
|
||||
// Disallow use of multiple spaces (sometimes used to align const values,
|
||||
// array or object items, etc.). It's hard to maintain and doesn't add that
|
||||
// much benefit.
|
||||
"no-multi-spaces": 1,
|
||||
|
||||
// No reassigning native JS objects
|
||||
"no-native-reassign": 2,
|
||||
|
||||
// No (!foo in bar)
|
||||
"no-negated-in-lhs": 2,
|
||||
|
||||
// Nested ternary statements are confusing
|
||||
"no-nested-ternary": 2,
|
||||
|
||||
// Use {} instead of new Object()
|
||||
"no-new-object": 2,
|
||||
|
||||
// No Math() or JSON()
|
||||
"no-obj-calls": 2,
|
||||
|
||||
// No octal literals
|
||||
"no-octal": 2,
|
||||
|
||||
// No redeclaring variables
|
||||
"no-redeclare": 2,
|
||||
|
||||
// No unnecessary comparisons
|
||||
"no-self-compare": 2,
|
||||
|
||||
// No declaring variables from an outer scope
|
||||
"no-shadow": 1,
|
||||
|
||||
// No declaring variables that hide things like arguments
|
||||
"no-shadow-restricted-names": 2,
|
||||
|
||||
// No spaces between function name and parentheses
|
||||
"no-spaced-func": 1,
|
||||
|
||||
// No trailing whitespace
|
||||
"no-trailing-spaces": 2,
|
||||
|
||||
// No using undeclared variables
|
||||
"no-undef": 2,
|
||||
|
||||
// Error on newline where a semicolon is needed
|
||||
"no-unexpected-multiline": 2,
|
||||
|
||||
// No unreachable statements
|
||||
"no-unreachable": 2,
|
||||
|
||||
// No expressions where a statement is expected
|
||||
"no-unused-expressions": 2,
|
||||
|
||||
// No declaring variables that are never used
|
||||
"no-unused-vars": [2, { "args": "none", "varsIgnorePattern": "^(Cc|Ci|Cr|Cu|EXPORTED_SYMBOLS)$" }],
|
||||
|
||||
// No using variables before defined
|
||||
"no-use-before-define": 2,
|
||||
|
||||
// No using with
|
||||
"no-with": 2,
|
||||
|
||||
// Always require semicolon at end of statement
|
||||
"semi": [2, "always"],
|
||||
|
||||
// Require space after keywords
|
||||
"space-after-keywords": 2,
|
||||
|
||||
// Require space before blocks
|
||||
"space-before-blocks": 2,
|
||||
|
||||
// Never use spaces before function parentheses
|
||||
"space-before-function-paren": [2, { "anonymous": "never", "named": "never" }],
|
||||
|
||||
// Require spaces before finally, catch, etc.
|
||||
"space-before-keywords": [2, "always"],
|
||||
|
||||
// No space padding in parentheses
|
||||
"space-in-parens": [2, "never"],
|
||||
|
||||
// Require spaces around operators, except for a|0.
|
||||
"space-infix-ops": [2, {"int32Hint": true}],
|
||||
|
||||
|
||||
// Require spaces after return, throw and case
|
||||
"space-return-throw-case": 2,
|
||||
|
||||
// ++ and -- should not need spacing
|
||||
"space-unary-ops": [1, { "nonwords": false }],
|
||||
|
||||
// No comparisons to NaN
|
||||
"use-isnan": 2,
|
||||
|
||||
// Only check typeof against valid results
|
||||
"valid-typeof": 2,
|
||||
|
||||
// Disallow using variables outside the blocks they are defined (especially
|
||||
// since only let and const are used, see "no-var").
|
||||
"block-scoped-var": 2,
|
||||
|
||||
// Allow trailing commas for easy list extension. Having them does not
|
||||
// impair readability, but also not required either.
|
||||
"comma-dangle": [1, "always-multiline"],
|
||||
|
||||
// Warn about cyclomatic complexity in functions.
|
||||
"complexity": 1,
|
||||
|
||||
// Don't warn for inconsistent naming when capturing this (not so important
|
||||
// with auto-binding fat arrow functions).
|
||||
// "consistent-this": [2, "self"],
|
||||
|
||||
// Don't require a default case in switch statements. Avoid being forced to
|
||||
// add a bogus default when you know all possible cases are handled.
|
||||
"default-case": 0,
|
||||
|
||||
// Enforce dots on the next line with property name.
|
||||
"dot-location": [1, "property"],
|
||||
|
||||
// Encourage the use of dot notation whenever possible.
|
||||
"dot-notation": 2,
|
||||
|
||||
// Allow using == instead of ===, in the interest of landing something since
|
||||
// the devtools codebase is split on convention here.
|
||||
"eqeqeq": 0,
|
||||
|
||||
// Don't require function expressions to have a name.
|
||||
// This makes the code more verbose and hard to read. Our engine already
|
||||
// does a fantastic job assigning a name to the function, which includes
|
||||
// the enclosing function name, and worst case you have a line number that
|
||||
// you can just look up.
|
||||
"func-names": 0,
|
||||
|
||||
// Allow use of function declarations and expressions.
|
||||
"func-style": 0,
|
||||
|
||||
// Don't enforce the maximum depth that blocks can be nested. The complexity
|
||||
// rule is a better rule to check this.
|
||||
"max-depth": 0,
|
||||
|
||||
// Maximum length of a line.
|
||||
// Disabled because we exceed this in too many places.
|
||||
"max-len": [0, 80],
|
||||
|
||||
// Maximum depth callbacks can be nested.
|
||||
"max-nested-callbacks": [2, 4],
|
||||
|
||||
// Don't limit the number of parameters that can be used in a function.
|
||||
"max-params": 0,
|
||||
|
||||
// Don't limit the maximum number of statement allowed in a function. We
|
||||
// already have the complexity rule that's a better measurement.
|
||||
"max-statements": 0,
|
||||
|
||||
// Don't require a capital letter for constructors, only check if all new
|
||||
// operators are followed by a capital letter. Don't warn when capitalized
|
||||
// functions are used without the new operator.
|
||||
"new-cap": [0, {"capIsNew": false}],
|
||||
|
||||
// Allow use of bitwise operators.
|
||||
"no-bitwise": 0,
|
||||
|
||||
// Disallow use of arguments.caller or arguments.callee.
|
||||
"no-caller": 2,
|
||||
|
||||
// Disallow the catch clause parameter name being the same as a variable in
|
||||
// the outer scope, to avoid confusion.
|
||||
"no-catch-shadow": 0,
|
||||
|
||||
// Disallow assignment in conditional expressions.
|
||||
"no-cond-assign": 2,
|
||||
|
||||
// Disallow using the console API.
|
||||
"no-console": 2,
|
||||
|
||||
// Allow using constant expressions in conditions like while (true)
|
||||
"no-constant-condition": 0,
|
||||
|
||||
// Allow use of the continue statement.
|
||||
"no-continue": 0,
|
||||
|
||||
// Disallow control characters in regular expressions.
|
||||
"no-control-regex": 2,
|
||||
|
||||
// Disallow use of debugger.
|
||||
"no-debugger": 2,
|
||||
|
||||
// Disallow deletion of variables (deleting properties is fine).
|
||||
"no-delete-var": 2,
|
||||
|
||||
// Allow division operators explicitly at beginning of regular expression.
|
||||
"no-div-regex": 0,
|
||||
|
||||
// Disallow use of labels for anything other then loops and switches.
|
||||
"no-empty-label": 2,
|
||||
|
||||
// Disallow use of eval(). We have other APIs to evaluate code in content.
|
||||
"no-eval": 2,
|
||||
|
||||
// Disallow adding to native types
|
||||
"no-extend-native": 2,
|
||||
|
||||
// Disallow unnecessary function binding.
|
||||
"no-extra-bind": 2,
|
||||
|
||||
// Allow unnecessary parentheses, as they may make the code more readable.
|
||||
"no-extra-parens": 0,
|
||||
|
||||
// Disallow fallthrough of case statements, except if there is a comment.
|
||||
"no-fallthrough": 2,
|
||||
|
||||
// Allow the use of leading or trailing decimal points in numeric literals.
|
||||
"no-floating-decimal": 0,
|
||||
|
||||
// Allow comments inline after code.
|
||||
"no-inline-comments": 0,
|
||||
|
||||
// Disallow use of multiline strings (use template strings instead).
|
||||
"no-multi-str": 1,
|
||||
|
||||
// Disallow multiple empty lines.
|
||||
"no-multiple-empty-lines": [1, {"max": 2}],
|
||||
|
||||
// Allow reassignment of function parameters.
|
||||
"no-param-reassign": 0,
|
||||
|
||||
// Allow string concatenation with __dirname and __filename (not a node env).
|
||||
"no-path-concat": 0,
|
||||
|
||||
// Allow use of unary operators, ++ and --.
|
||||
"no-plusplus": 0,
|
||||
|
||||
// Allow using process.env (not a node environment).
|
||||
"no-process-env": 0,
|
||||
|
||||
// Allow using process.exit (not a node environment).
|
||||
"no-process-exit": 0,
|
||||
|
||||
// Disallow usage of __proto__ property.
|
||||
"no-proto": 2,
|
||||
|
||||
// Disallow multiple spaces in a regular expression literal.
|
||||
"no-regex-spaces": 2,
|
||||
|
||||
// Allow reserved words being used as object literal keys.
|
||||
"no-reserved-keys": 0,
|
||||
|
||||
// Don't restrict usage of specified node modules (not a node environment).
|
||||
"no-restricted-modules": 0,
|
||||
|
||||
// Disallow use of assignment in return statement. It is preferable for a
|
||||
// single line of code to have only one easily predictable effect.
|
||||
"no-return-assign": 2,
|
||||
|
||||
// Don't warn about declaration of variables already declared in the outer scope.
|
||||
"no-shadow": 0,
|
||||
|
||||
// Disallow shadowing of names such as arguments.
|
||||
"no-shadow-restricted-names": 2,
|
||||
|
||||
// Allow use of synchronous methods (not a node environment).
|
||||
"no-sync": 0,
|
||||
|
||||
// Allow the use of ternary operators.
|
||||
"no-ternary": 0,
|
||||
|
||||
// Disallow throwing literals (eg. throw "error" instead of
|
||||
// throw new Error("error")).
|
||||
"no-throw-literal": 2,
|
||||
|
||||
// Disallow use of undeclared variables unless mentioned in a /* global */
|
||||
// block. Note that globals from head.js are automatically imported in tests
|
||||
// by the import-headjs-globals rule form the mozilla eslint plugin.
|
||||
"no-undef": 2,
|
||||
|
||||
// Allow dangling underscores in identifiers (for privates).
|
||||
"no-underscore-dangle": 0,
|
||||
|
||||
// Allow use of undefined variable.
|
||||
"no-undefined": 0,
|
||||
|
||||
// Disallow the use of Boolean literals in conditional expressions.
|
||||
"no-unneeded-ternary": 2,
|
||||
|
||||
// We use var-only-at-top-level instead of no-var as we allow top level
|
||||
// vars.
|
||||
"no-var": 0,
|
||||
|
||||
// Allow using TODO/FIXME comments.
|
||||
"no-warning-comments": 0,
|
||||
|
||||
// Don't require method and property shorthand syntax for object literals.
|
||||
// We use this in the code a lot, but not consistently, and this seems more
|
||||
// like something to check at code review time.
|
||||
"object-shorthand": 0,
|
||||
|
||||
// Allow more than one variable declaration per function.
|
||||
"one-var": 0,
|
||||
|
||||
// Disallow padding within blocks.
|
||||
"padded-blocks": [1, "never"],
|
||||
|
||||
// Don't require quotes around object literal property names.
|
||||
"quote-props": 0,
|
||||
|
||||
// Double quotes should be used.
|
||||
"quotes": [1, "double", "avoid-escape"],
|
||||
|
||||
// Require use of the second argument for parseInt().
|
||||
"radix": 2,
|
||||
|
||||
// Enforce spacing after semicolons.
|
||||
"semi-spacing": [2, {"before": false, "after": true}],
|
||||
|
||||
// Don't require to sort variables within the same declaration block.
|
||||
// Anyway, one-var is disabled.
|
||||
"sort-vars": 0,
|
||||
|
||||
// Require a space after keywords.
|
||||
"space-after-keywords": [1, "always"],
|
||||
|
||||
// Require a space immediately following the // in a line comment.
|
||||
"spaced-comment": [2, "always"],
|
||||
|
||||
// Require "use strict" to be defined globally in the script.
|
||||
"strict": [2, "global"],
|
||||
|
||||
// Warn about invalid JSDoc comments.
|
||||
"valid-jsdoc": 0,
|
||||
|
||||
// Allow vars to be declared anywhere in the scope.
|
||||
"vars-on-top": 0,
|
||||
|
||||
// Don't require immediate function invocation to be wrapped in parentheses.
|
||||
"wrap-iife": 0,
|
||||
|
||||
// Don't require regex literals to be wrapped in parentheses (which
|
||||
// supposedly prevent them from being mistaken for division operators).
|
||||
"wrap-regex": 0,
|
||||
|
||||
// Disallow Yoda conditions (where literal value comes first).
|
||||
"yoda": 2,
|
||||
|
||||
// disallow use of eval()-like methods
|
||||
"no-implied-eval": 2,
|
||||
|
||||
// Disallow function or variable declarations in nested blocks
|
||||
"no-inner-declarations": 2,
|
||||
|
||||
// Disallow usage of __iterator__ property
|
||||
"no-iterator": 2,
|
||||
|
||||
// Disallow labels that share a name with a variable
|
||||
"no-label-var": 2,
|
||||
|
||||
// Disallow negation of the left operand of an in expression
|
||||
"no-negated-in-lhs": 2,
|
||||
|
||||
// Disallow creating new instances of String, Number, and Boolean
|
||||
"no-new-wrappers": 2,
|
||||
}
|
||||
}
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
this.EXPORTED_SYMBOLS = ["Extension", "ExtensionData"];
|
||||
|
||||
/* globals Extension ExtensionData */
|
||||
|
||||
/*
|
||||
* This file is the main entry point for extensions. When an extension
|
||||
* loads, its bootstrap.js file creates a Extension instance
|
||||
|
@ -21,8 +23,9 @@ const Cr = Components.results;
|
|||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://devtools/shared/event-emitter.js");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "EventEmitter",
|
||||
"resource://devtools/shared/event-emitter.js");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Locale",
|
||||
"resource://gre/modules/Locale.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Log",
|
||||
|
@ -67,13 +70,14 @@ var {
|
|||
injectAPI,
|
||||
extend,
|
||||
flushJarCache,
|
||||
instanceOf,
|
||||
} = ExtensionUtils;
|
||||
|
||||
const LOGGER_ID_BASE = "addons.webextension.";
|
||||
|
||||
var scriptScope = this;
|
||||
|
||||
var ExtensionPage, GlobalManager;
|
||||
|
||||
// This object loads the ext-*.js scripts that define the extension API.
|
||||
var Management = {
|
||||
initialized: false,
|
||||
|
@ -165,7 +169,7 @@ var Management = {
|
|||
|
||||
off(hook, callback) {
|
||||
this.emitter.off(hook, callback);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// A MessageBroker that's used to send and receive messages for
|
||||
|
@ -183,9 +187,8 @@ var globalBroker = new MessageBroker([Services.mm, Services.ppmm]);
|
|||
// |uri| is the URI of the content (optional).
|
||||
// |docShell| is the docshell the content runs in (optional).
|
||||
// |incognito| is the content running in a private context (default: false).
|
||||
function ExtensionPage(extension, params)
|
||||
{
|
||||
let {type, contentWindow, uri, docShell} = params;
|
||||
ExtensionPage = function(extension, params) {
|
||||
let {type, contentWindow, uri} = params;
|
||||
this.extension = extension;
|
||||
this.type = type;
|
||||
this.contentWindow = contentWindow || null;
|
||||
|
@ -206,7 +209,7 @@ function ExtensionPage(extension, params)
|
|||
this.messenger = new Messenger(this, globalBroker, sender, filter, delegate);
|
||||
|
||||
this.extension.views.add(this);
|
||||
}
|
||||
};
|
||||
|
||||
ExtensionPage.prototype = {
|
||||
get cloneScope() {
|
||||
|
@ -264,7 +267,7 @@ ExtensionPage.prototype = {
|
|||
};
|
||||
|
||||
// Responsible for loading extension APIs into the right globals.
|
||||
var GlobalManager = {
|
||||
GlobalManager = {
|
||||
// Number of extensions currently enabled.
|
||||
count: 0,
|
||||
|
||||
|
@ -365,8 +368,7 @@ var GlobalManager = {
|
|||
//
|
||||
// No functionality of this class is guaranteed to work before
|
||||
// |readManifest| has been called, and completed.
|
||||
this.ExtensionData = function(rootURI)
|
||||
{
|
||||
this.ExtensionData = function(rootURI) {
|
||||
this.rootURI = rootURI;
|
||||
|
||||
this.manifest = null;
|
||||
|
@ -375,7 +377,7 @@ this.ExtensionData = function(rootURI)
|
|||
this._promiseLocales = null;
|
||||
|
||||
this.errors = [];
|
||||
}
|
||||
};
|
||||
|
||||
ExtensionData.prototype = {
|
||||
get logger() {
|
||||
|
@ -406,11 +408,12 @@ ExtensionData.prototype = {
|
|||
yield iter.forEach(entry => {
|
||||
results.push(entry);
|
||||
});
|
||||
} catch (e) {}
|
||||
} catch (e) {
|
||||
// Always return a list, even if the directory does not exist (or is
|
||||
// not a directory) for symmetry with the ZipReader behavior.
|
||||
}
|
||||
iter.close();
|
||||
|
||||
// Always return a list, even if the directory does not exist (or is
|
||||
// not a directory) for symmetry with the ZipReader behavior.
|
||||
return results;
|
||||
}
|
||||
|
||||
|
@ -488,7 +491,9 @@ ExtensionData.prototype = {
|
|||
|
||||
try {
|
||||
this.id = this.manifest.applications.gecko.id;
|
||||
} catch (e) {}
|
||||
} catch (e) {
|
||||
// Errors are handled by the type check below.
|
||||
}
|
||||
|
||||
if (typeof this.id != "string") {
|
||||
this.manifestError("Missing required `applications.gecko.id` property");
|
||||
|
@ -626,8 +631,7 @@ ExtensionData.prototype = {
|
|||
// installed (by trying to load a moz-extension URI referring to a
|
||||
// web_accessible_resource from the extension). getExtensionUUID
|
||||
// returns the UUID for a given add-on ID.
|
||||
function getExtensionUUID(id)
|
||||
{
|
||||
function getExtensionUUID(id) {
|
||||
const PREF_NAME = "extensions.webextensions.uuids";
|
||||
|
||||
let pref = Preferences.get(PREF_NAME, "{}");
|
||||
|
@ -653,8 +657,7 @@ function getExtensionUUID(id)
|
|||
|
||||
// We create one instance of this class per extension. |addonData|
|
||||
// comes directly from bootstrap.js when initializing.
|
||||
this.Extension = function(addonData)
|
||||
{
|
||||
this.Extension = function(addonData) {
|
||||
ExtensionData.call(this, addonData.resourceURI);
|
||||
|
||||
this.uuid = getExtensionUUID(addonData.id);
|
||||
|
@ -683,7 +686,7 @@ this.Extension = function(addonData)
|
|||
this.webAccessibleResources = new Set();
|
||||
|
||||
this.emitter = new EventEmitter();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This code is designed to make it easy to test a WebExtension
|
||||
|
@ -710,8 +713,7 @@ this.Extension = function(addonData)
|
|||
* The generated extension is stored in the system temporary directory,
|
||||
* and an nsIFile object pointing to it is returned.
|
||||
*/
|
||||
this.Extension.generateXPI = function(id, data)
|
||||
{
|
||||
this.Extension.generateXPI = function(id, data) {
|
||||
let manifest = data.manifest;
|
||||
if (!manifest) {
|
||||
manifest = {};
|
||||
|
@ -799,8 +801,7 @@ this.Extension.generateXPI = function(id, data)
|
|||
* Generates a new extension using |Extension.generateXPI|, and initializes a
|
||||
* new |Extension| instance which will execute it.
|
||||
*/
|
||||
this.Extension.generate = function(id, data)
|
||||
{
|
||||
this.Extension.generate = function(id, data) {
|
||||
let file = this.generateXPI(id, data);
|
||||
|
||||
flushJarCache(file);
|
||||
|
@ -812,7 +813,7 @@ this.Extension.generate = function(id, data)
|
|||
return new Extension({
|
||||
id,
|
||||
resourceURI: jarURI,
|
||||
cleanupFile: file
|
||||
cleanupFile: file,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -856,7 +857,7 @@ Extension.prototype = extend(Object.create(ExtensionData.prototype), {
|
|||
manifest: this.manifest,
|
||||
resourceURL: this.addonData.resourceURI.spec,
|
||||
baseURL: this.baseURI.spec,
|
||||
content_scripts: this.manifest.content_scripts || [],
|
||||
content_scripts: this.manifest.content_scripts || [], // eslint-disable-line camelcase
|
||||
webAccessibleResources: this.webAccessibleResources,
|
||||
whiteListedHosts: this.whiteListedHosts.serialize(),
|
||||
localeData: this.localeData.serialize(),
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
this.EXPORTED_SYMBOLS = ["ExtensionContent"];
|
||||
|
||||
/* globals ExtensionContent */
|
||||
|
||||
/*
|
||||
* This file handles the content process side of extensions. It mainly
|
||||
* takes care of content script injection, content script APIs, and
|
||||
|
@ -38,8 +40,7 @@ var {
|
|||
flushJarCache,
|
||||
} = ExtensionUtils;
|
||||
|
||||
function isWhenBeforeOrSame(when1, when2)
|
||||
{
|
||||
function isWhenBeforeOrSame(when1, when2) {
|
||||
let table = {"document_start": 0,
|
||||
"document_end": 1,
|
||||
"document_idle": 2};
|
||||
|
@ -48,63 +49,65 @@ function isWhenBeforeOrSame(when1, when2)
|
|||
|
||||
// This is the fairly simple API that we inject into content
|
||||
// scripts.
|
||||
var api = context => { return {
|
||||
runtime: {
|
||||
connect: function(extensionId, connectInfo) {
|
||||
if (!connectInfo) {
|
||||
connectInfo = extensionId;
|
||||
extensionId = null;
|
||||
}
|
||||
let name = connectInfo && connectInfo.name || "";
|
||||
let recipient = extensionId ? {extensionId} : {extensionId: context.extensionId};
|
||||
return context.messenger.connect(context.messageManager, name, recipient);
|
||||
var api = context => {
|
||||
return {
|
||||
runtime: {
|
||||
connect: function(extensionId, connectInfo) {
|
||||
if (!connectInfo) {
|
||||
connectInfo = extensionId;
|
||||
extensionId = null;
|
||||
}
|
||||
let name = connectInfo && connectInfo.name || "";
|
||||
let recipient = extensionId ? {extensionId} : {extensionId: context.extensionId};
|
||||
return context.messenger.connect(context.messageManager, name, recipient);
|
||||
},
|
||||
|
||||
getManifest: function() {
|
||||
return Cu.cloneInto(context.extension.manifest, context.cloneScope);
|
||||
},
|
||||
|
||||
getURL: function(url) {
|
||||
return context.extension.baseURI.resolve(url);
|
||||
},
|
||||
|
||||
onConnect: context.messenger.onConnect("runtime.onConnect"),
|
||||
|
||||
onMessage: context.messenger.onMessage("runtime.onMessage"),
|
||||
|
||||
sendMessage: function(...args) {
|
||||
let options; // eslint-disable-line no-unused-vars
|
||||
let extensionId, message, responseCallback;
|
||||
if (args.length == 1) {
|
||||
message = args[0];
|
||||
} else if (args.length == 2) {
|
||||
[message, responseCallback] = args;
|
||||
} else {
|
||||
[extensionId, message, options, responseCallback] = args;
|
||||
}
|
||||
|
||||
let recipient = extensionId ? {extensionId} : {extensionId: context.extensionId};
|
||||
context.messenger.sendMessage(context.messageManager, message, recipient, responseCallback);
|
||||
},
|
||||
},
|
||||
|
||||
getManifest: function() {
|
||||
return Cu.cloneInto(context.extension.manifest, context.cloneScope);
|
||||
extension: {
|
||||
getURL: function(url) {
|
||||
return context.extension.baseURI.resolve(url);
|
||||
},
|
||||
|
||||
inIncognitoContext: PrivateBrowsingUtils.isContentWindowPrivate(context.contentWindow),
|
||||
},
|
||||
|
||||
getURL: function(url) {
|
||||
return context.extension.baseURI.resolve(url);
|
||||
i18n: {
|
||||
getMessage: function(messageName, substitutions) {
|
||||
return context.extension.localizeMessage(messageName, substitutions);
|
||||
},
|
||||
},
|
||||
|
||||
onConnect: context.messenger.onConnect("runtime.onConnect"),
|
||||
|
||||
onMessage: context.messenger.onMessage("runtime.onMessage"),
|
||||
|
||||
sendMessage: function(...args) {
|
||||
let extensionId, message, options, responseCallback;
|
||||
if (args.length == 1) {
|
||||
message = args[0];
|
||||
} else if (args.length == 2) {
|
||||
[message, responseCallback] = args;
|
||||
} else {
|
||||
[extensionId, message, options, responseCallback] = args;
|
||||
}
|
||||
|
||||
let recipient = extensionId ? {extensionId} : {extensionId: context.extensionId};
|
||||
context.messenger.sendMessage(context.messageManager, message, recipient, responseCallback);
|
||||
},
|
||||
},
|
||||
|
||||
extension: {
|
||||
getURL: function(url) {
|
||||
return context.extension.baseURI.resolve(url);
|
||||
},
|
||||
|
||||
inIncognitoContext: PrivateBrowsingUtils.isContentWindowPrivate(context.contentWindow),
|
||||
},
|
||||
|
||||
i18n: {
|
||||
getMessage: function(messageName, substitutions) {
|
||||
return context.extension.localizeMessage(messageName, substitutions);
|
||||
},
|
||||
},
|
||||
}};
|
||||
};
|
||||
};
|
||||
|
||||
// Represents a content script.
|
||||
function Script(options)
|
||||
{
|
||||
function Script(options) {
|
||||
this.options = options;
|
||||
this.run_at = this.options.run_at;
|
||||
this.js = this.options.js || [];
|
||||
|
@ -155,8 +158,8 @@ Script.prototype = {
|
|||
}
|
||||
|
||||
if (shouldRun("document_start")) {
|
||||
let winUtils = window.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIDOMWindowUtils);
|
||||
let winUtils = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
for (let url of this.css) {
|
||||
url = extension.baseURI.resolve(url);
|
||||
|
@ -183,8 +186,8 @@ Script.prototype = {
|
|||
let options = {
|
||||
target: sandbox,
|
||||
charset: "UTF-8",
|
||||
async: AppConstants.platform == "gonk"
|
||||
}
|
||||
async: AppConstants.platform == "gonk",
|
||||
};
|
||||
runSafeSyncWithoutClone(Services.scriptloader.loadSubScriptWithOptions, url, options);
|
||||
}
|
||||
|
||||
|
@ -195,8 +198,7 @@ Script.prototype = {
|
|||
},
|
||||
};
|
||||
|
||||
function getWindowMessageManager(contentWindow)
|
||||
{
|
||||
function getWindowMessageManager(contentWindow) {
|
||||
let ir = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDocShell)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor);
|
||||
|
@ -208,11 +210,12 @@ function getWindowMessageManager(contentWindow)
|
|||
}
|
||||
}
|
||||
|
||||
var ExtensionManager;
|
||||
|
||||
// Scope in which extension content script code can run. It uses
|
||||
// Cu.Sandbox to run the code. There is a separate scope for each
|
||||
// frame.
|
||||
function ExtensionContext(extensionId, contentWindow)
|
||||
{
|
||||
function ExtensionContext(extensionId, contentWindow) {
|
||||
this.extension = ExtensionManager.get(extensionId);
|
||||
this.extensionId = extensionId;
|
||||
this.contentWindow = contentWindow;
|
||||
|
@ -239,7 +242,7 @@ function ExtensionContext(extensionId, contentWindow)
|
|||
let delegate = {
|
||||
getSender(context, target, sender) {
|
||||
// Nothing to do here.
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let url = contentWindow.location.href;
|
||||
|
@ -280,8 +283,7 @@ ExtensionContext.prototype = {
|
|||
},
|
||||
};
|
||||
|
||||
function windowId(window)
|
||||
{
|
||||
function windowId(window) {
|
||||
return window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.currentInnerWindowID;
|
||||
|
@ -332,8 +334,10 @@ var DocumentManager = {
|
|||
}
|
||||
|
||||
this.trigger("document_start", window);
|
||||
/* eslint-disable mozilla/balanced-listeners */
|
||||
window.addEventListener("DOMContentLoaded", this, true);
|
||||
window.addEventListener("load", this, true);
|
||||
/* eslint-enable mozilla/balanced-listeners */
|
||||
} else if (topic == "inner-window-destroyed") {
|
||||
let id = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
if (!this.windows.has(id)) {
|
||||
|
@ -341,7 +345,7 @@ var DocumentManager = {
|
|||
}
|
||||
|
||||
let extensions = this.windows.get(id);
|
||||
for (let [extensionId, context] of extensions) {
|
||||
for (let [, context] of extensions) {
|
||||
context.close();
|
||||
}
|
||||
|
||||
|
@ -385,7 +389,7 @@ var DocumentManager = {
|
|||
|
||||
enumerateWindows: function*(docShell) {
|
||||
let window = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindow)
|
||||
.getInterface(Ci.nsIDOMWindow);
|
||||
yield [window, this.getWindowState(window)];
|
||||
|
||||
for (let i = 0; i < docShell.childCount; i++) {
|
||||
|
@ -430,7 +434,7 @@ var DocumentManager = {
|
|||
},
|
||||
|
||||
shutdownExtension(extensionId) {
|
||||
for (let [windowId, extensions] of this.windows) {
|
||||
for (let [, extensions] of this.windows) {
|
||||
let context = extensions.get(extensionId);
|
||||
if (context) {
|
||||
context.close();
|
||||
|
@ -458,8 +462,7 @@ var DocumentManager = {
|
|||
};
|
||||
|
||||
// Represents a browser extension in the content process.
|
||||
function BrowserExtensionContent(data)
|
||||
{
|
||||
function BrowserExtensionContent(data) {
|
||||
this.id = data.id;
|
||||
this.uuid = data.uuid;
|
||||
this.data = data;
|
||||
|
@ -478,7 +481,7 @@ function BrowserExtensionContent(data)
|
|||
// Extension.jsm takes care of this in the parent.
|
||||
ExtensionManagement.startupExtension(this.uuid, uri, this);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
BrowserExtensionContent.prototype = {
|
||||
shutdown() {
|
||||
|
@ -496,7 +499,7 @@ BrowserExtensionContent.prototype = {
|
|||
},
|
||||
};
|
||||
|
||||
var ExtensionManager = {
|
||||
ExtensionManager = {
|
||||
// Map[extensionId, BrowserExtensionContent]
|
||||
extensions: new Map(),
|
||||
|
||||
|
@ -546,7 +549,7 @@ var ExtensionManager = {
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
this.ExtensionContent = {
|
||||
|
@ -581,11 +584,11 @@ this.ExtensionContent = {
|
|||
|
||||
receiveMessage({target, name, data}) {
|
||||
switch (name) {
|
||||
case "Extension:Execute":
|
||||
let script = new Script(data.options);
|
||||
let {extensionId} = data;
|
||||
DocumentManager.executeScript(target, extensionId, script);
|
||||
break;
|
||||
case "Extension:Execute":
|
||||
let script = new Script(data.options);
|
||||
let {extensionId} = data;
|
||||
DocumentManager.executeScript(target, extensionId, script);
|
||||
break;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче