Merge m-c to b2g-inbound. a=merge
|
@ -978,8 +978,7 @@ pref("apz.subframe.enabled", true);
|
|||
pref("apz.overscroll.enabled", true);
|
||||
pref("apz.overscroll.fling_friction", "0.02");
|
||||
pref("apz.overscroll.fling_stopped_threshold", "0.4");
|
||||
pref("apz.overscroll.clamping", "0.5");
|
||||
pref("apz.overscroll.z_effect", "0.5");
|
||||
pref("apz.overscroll.stretch_factor", "0.5");
|
||||
pref("apz.overscroll.snap_back.spring_stiffness", "0.6");
|
||||
pref("apz.overscroll.snap_back.spring_friction", "0.1");
|
||||
pref("apz.overscroll.snap_back.mass", "1200");
|
||||
|
|
|
@ -1395,6 +1395,9 @@ pref("devtools.scratchpad.showTrailingSpace", false);
|
|||
pref("devtools.scratchpad.enableCodeFolding", true);
|
||||
pref("devtools.scratchpad.enableAutocompletion", true);
|
||||
|
||||
// Enable the Storage Inspector
|
||||
pref("devtools.storage.enabled", false);
|
||||
|
||||
// Enable the Style Editor.
|
||||
pref("devtools.styleeditor.enabled", true);
|
||||
pref("devtools.styleeditor.source-maps-enabled", false);
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
var gSafeBrowsing = {
|
||||
|
||||
setReportPhishingMenu: function() {
|
||||
|
||||
// A phishing page will have a specific about:blocked content documentURI
|
||||
var isPhishingPage = content.document.documentURI.startsWith("about:blocked?e=phishingBlocked");
|
||||
var uri = getBrowser().currentURI;
|
||||
var isPhishingPage = uri && uri.spec.startsWith("about:blocked?e=phishingBlocked");
|
||||
|
||||
// Show/hide the appropriate menu item.
|
||||
document.getElementById("menu_HelpPopup_reportPhishingtoolmenu")
|
||||
|
@ -24,7 +24,6 @@ var gSafeBrowsing = {
|
|||
if (!broadcaster)
|
||||
return;
|
||||
|
||||
var uri = getBrowser().currentURI;
|
||||
if (uri && (uri.schemeIs("http") || uri.schemeIs("https")))
|
||||
broadcaster.removeAttribute("disabled");
|
||||
else
|
||||
|
|
|
@ -0,0 +1,463 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/Log.jsm");
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["CardDavImporter"];
|
||||
|
||||
let log = Log.repository.getLogger("Loop.Importer.CardDAV");
|
||||
log.level = Log.Level.Debug;
|
||||
log.addAppender(new Log.ConsoleAppender(new Log.BasicFormatter()));
|
||||
|
||||
const DEPTH_RESOURCE_ONLY = "0";
|
||||
const DEPTH_RESOURCE_AND_CHILDREN = "1";
|
||||
const DEPTH_RESOURCE_AND_ALL_DESCENDENTS = "infinity";
|
||||
|
||||
this.CardDavImporter = function() {
|
||||
};
|
||||
|
||||
/**
|
||||
* CardDAV Address Book importer for Loop.
|
||||
*
|
||||
* The model for address book importers is to have a single public method,
|
||||
* "startImport." When the import is done (or upon a fatal error), the
|
||||
* caller's callback method is called.
|
||||
*
|
||||
* The current model for this importer is based on the subset of CardDAV
|
||||
* implemented by Google. In theory, it should work with other CardDAV
|
||||
* sources, but it has only been tested against Google at the moment.
|
||||
*
|
||||
* At the moment, this importer assumes that no local changes will be made
|
||||
* to data retreived from a remote source: when performing a re-import,
|
||||
* any records that have been previously imported will be completely
|
||||
* removed and replaced with the data received from the CardDAV server.
|
||||
* Witout this behavior, it would be impossible for users to take any
|
||||
* actions to remove fields that are no longer valid.
|
||||
*/
|
||||
|
||||
this.CardDavImporter.prototype = {
|
||||
/**
|
||||
* Begin import of an address book from a CardDAV server.
|
||||
*
|
||||
* @param {Object} options Information needed to perform the address
|
||||
* book import. The following fields are currently
|
||||
* defined:
|
||||
* - "host": CardDAV server base address
|
||||
* (e.g., "google.com")
|
||||
* - "auth": Authentication mechanism to use.
|
||||
* Currently, only "basic" is implemented.
|
||||
* - "user": Username to use for basic auth
|
||||
* - "password": Password to use for basic auth
|
||||
* @param {Function} callback Callback function that will be invoked once the
|
||||
* import operation is complete. The first argument
|
||||
* passed to the callback will be an 'Error' object
|
||||
* or 'null'. If the import operation was
|
||||
* successful, then the second parameter will be a
|
||||
* count of the number of contacts that were
|
||||
* successfully imported.
|
||||
* @param {Object} db Database to add imported contacts into.
|
||||
* Nominally, this is the LoopContacts API. In
|
||||
* practice, anything with the same interface
|
||||
* should work here.
|
||||
*/
|
||||
|
||||
startImport: function(options, callback, db) {
|
||||
let auth;
|
||||
if (!("auth" in options)) {
|
||||
callback(new Error("No authentication specified"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.auth === "basic") {
|
||||
if (!("user" in options) || !("password" in options)) {
|
||||
callback(new Error("Missing user or password for basic authentication"));
|
||||
return;
|
||||
}
|
||||
auth = { method: "basic",
|
||||
user: options.user,
|
||||
password: options.password };
|
||||
} else {
|
||||
callback(new Error("Unknown authentication method"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!("host" in options)){
|
||||
callback(new Error("Missing host for CardDav import"));
|
||||
return;
|
||||
}
|
||||
let host = options.host;
|
||||
|
||||
Task.spawn(function* () {
|
||||
log.info("Starting CardDAV import from " + host);
|
||||
let baseURL = "https://" + host;
|
||||
let startURL = baseURL + "/.well-known/carddav";
|
||||
let abookURL;
|
||||
|
||||
// Get list of contact URLs
|
||||
let body = "<d:propfind xmlns:d='DAV:'><d:prop><d:getetag />" +
|
||||
"</d:prop></d:propfind>";
|
||||
let abook = yield this._davPromise("PROPFIND", startURL, auth,
|
||||
DEPTH_RESOURCE_AND_CHILDREN, body);
|
||||
|
||||
// Build multiget REPORT body from URLs in PROPFIND result
|
||||
let contactElements = abook.responseXML.
|
||||
getElementsByTagNameNS("DAV:", "href");
|
||||
|
||||
body = "<c:addressbook-multiget xmlns:d='DAV:' " +
|
||||
"xmlns:c='urn:ietf:params:xml:ns:carddav'>" +
|
||||
"<d:prop><d:getetag /> <c:address-data /></d:prop>\n";
|
||||
|
||||
for (let element of contactElements) {
|
||||
let href = element.textContent;
|
||||
if (href.substr(-1) == "/") {
|
||||
abookURL = baseURL + href;
|
||||
} else {
|
||||
body += "<d:href>" + href + "</d:href>\n";
|
||||
}
|
||||
}
|
||||
body += "</c:addressbook-multiget>";
|
||||
|
||||
// Retreive contact URL contents
|
||||
let allEntries = yield this._davPromise("REPORT", abookURL, auth,
|
||||
DEPTH_RESOURCE_AND_CHILDREN,
|
||||
body);
|
||||
|
||||
// Parse multiget entites and add to DB
|
||||
let addressData = allEntries.responseXML.getElementsByTagNameNS(
|
||||
"urn:ietf:params:xml:ns:carddav", "address-data");
|
||||
|
||||
log.info("Retreived " + addressData.length + " contacts from " +
|
||||
host + "; importing into database");
|
||||
|
||||
let importCount = 0;
|
||||
for (let i = 0; i < addressData.length; i++) {
|
||||
let vcard = addressData.item(i).textContent;
|
||||
let contact = this._convertVcard(vcard);
|
||||
contact.id += "@" + host;
|
||||
contact.category = ["carddav@" + host];
|
||||
|
||||
let existing = yield this._dbPromise(db, "getByServiceId", contact.id);
|
||||
if (existing) {
|
||||
yield this._dbPromise(db, "remove", existing._guid);
|
||||
}
|
||||
|
||||
// If the contact contains neither email nor phone number, then it
|
||||
// is not useful in the Loop address book: do not add.
|
||||
if (!("tel" in contact) && !("email" in contact)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
yield this._dbPromise(db, "add", contact);
|
||||
importCount++;
|
||||
}
|
||||
|
||||
return importCount;
|
||||
}.bind(this)).then(
|
||||
(result) => {
|
||||
log.info("Import complete: " + result + " contacts imported.");
|
||||
callback(null, result);
|
||||
},
|
||||
(error) => {
|
||||
log.error("Aborting import: " + error.fileName + ":" +
|
||||
error.lineNumber + ": " + error.message);
|
||||
callback(error);
|
||||
}).then(null,
|
||||
(error) => {
|
||||
log.error("Error in callback: " + error.fileName +
|
||||
":" + error.lineNumber + ": " + error.message);
|
||||
callback(error);
|
||||
}).then(null,
|
||||
(error) => {
|
||||
log.error("Error calling failure callback, giving up: " +
|
||||
error.fileName + ":" + error.lineNumber + ": " +
|
||||
error.message);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Wrap a LoopContacts-style operation in a promise. The operation is run
|
||||
* immediately, and a corresponding Promise is returned. Error callbacks
|
||||
* cause the promise to be rejected, and success cause it to be resolved.
|
||||
*
|
||||
* @param {Object} db Object the operation is to be performed on
|
||||
* @param {String} method Name of operation being wrapped
|
||||
* @param {Object} param Parameter to be passed to the operation
|
||||
*
|
||||
* @return {Object} Promise corresponding to the result of the operation.
|
||||
*/
|
||||
|
||||
_dbPromise: function(db, method, param) {
|
||||
return new Promise((resolve, reject) => {
|
||||
db[method](param, (error, result) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a contact in VCard format (see RFC 6350) to the format used
|
||||
* by the LoopContacts class.
|
||||
*
|
||||
* @param {String} vcard The contact to convert, in vcard format
|
||||
* @return {Object} a LoopContacts-style contact object containing
|
||||
* the relevant fields from the vcard.
|
||||
*/
|
||||
|
||||
_convertVcard: function(vcard) {
|
||||
let contact = {};
|
||||
let nickname;
|
||||
vcard.split(/[\r\n]+(?! )/).forEach(
|
||||
function (contentline) {
|
||||
contentline = contentline.replace(/[\r\n]+ /g, "");
|
||||
let match = /^(.*?[^\\]):(.*)$/.exec(contentline);
|
||||
if (match) {
|
||||
let nameparam = match[1];
|
||||
let value = match[2];
|
||||
|
||||
// Poor-man's unescaping
|
||||
value = value.replace(/\\:/g, ":");
|
||||
value = value.replace(/\\,/g, ",");
|
||||
value = value.replace(/\\n/gi, "\n");
|
||||
value = value.replace(/\\\\/g, "\\");
|
||||
|
||||
let param = nameparam.split(/;/);
|
||||
let name = param[0];
|
||||
let pref = false;
|
||||
let type = [];
|
||||
|
||||
for (let i = 1; i < param.length; i++) {
|
||||
if (/^PREF/.exec(param[i]) || /^TYPE=PREF/.exec(param[i])) {
|
||||
pref = true;
|
||||
}
|
||||
let typeMatch = /^TYPE=(.*)/.exec(param[i]);
|
||||
if (typeMatch) {
|
||||
type.push(typeMatch[1].toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
if (!type.length) {
|
||||
type.push("other");
|
||||
}
|
||||
|
||||
if (name === "FN") {
|
||||
value = value.replace(/\\;/g, ";");
|
||||
contact.name = [value];
|
||||
}
|
||||
|
||||
if (name === "N") {
|
||||
// Because we don't have lookbehinds, matching unescaped
|
||||
// semicolons is a pain. Luckily, we know that \r and \n
|
||||
// cannot appear in the strings, so we use them to swap
|
||||
// unescaped semicolons for \n.
|
||||
value = value.replace(/\\;/g, "\r");
|
||||
value = value.replace(/;/g, "\n");
|
||||
value = value.replace(/\r/g, ";");
|
||||
|
||||
let family, given, additional, prefix, suffix;
|
||||
let values = value.split(/\n/);
|
||||
if (values.length >= 5) {
|
||||
[family, given, additional, prefix, suffix] = values;
|
||||
if (prefix.length) {
|
||||
contact.honorificPrefix = [prefix];
|
||||
}
|
||||
if (given.length) {
|
||||
contact.givenName = [given];
|
||||
}
|
||||
if (additional.length) {
|
||||
contact.additionalName = [additional];
|
||||
}
|
||||
if (family.length) {
|
||||
contact.familyName = [family];
|
||||
}
|
||||
if (suffix.length) {
|
||||
contact.honorificSuffix = [suffix];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (name === "EMAIL") {
|
||||
value = value.replace(/\\;/g, ";");
|
||||
if (!("email" in contact)) {
|
||||
contact.email = [];
|
||||
}
|
||||
contact.email.push({
|
||||
pref: pref,
|
||||
type: type,
|
||||
value: value
|
||||
});
|
||||
}
|
||||
|
||||
if (name === "NICKNAME") {
|
||||
value = value.replace(/\\;/g, ";");
|
||||
// We don't store nickname in contact because it's not
|
||||
// a supported field. We're saving it off here in case we
|
||||
// need to use it if the fullname is blank.
|
||||
nickname = value;
|
||||
};
|
||||
|
||||
if (name === "ADR") {
|
||||
value = value.replace(/\\;/g, "\r");
|
||||
value = value.replace(/;/g, "\n");
|
||||
value = value.replace(/\r/g, ";");
|
||||
let pobox, extra, street, locality, region, code, country;
|
||||
let values = value.split(/\n/);
|
||||
if (values.length >= 7) {
|
||||
[pobox, extra, street, locality, region, code, country] = values;
|
||||
if (!("adr" in contact)) {
|
||||
contact.adr = [];
|
||||
}
|
||||
contact.adr.push({
|
||||
pref: pref,
|
||||
type: type,
|
||||
streetAddress: (street || pobox) + (extra ? (" " + extra) : ""),
|
||||
locality: locality,
|
||||
region: region,
|
||||
postalCode: code,
|
||||
countryName: country
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (name === "TEL") {
|
||||
value = value.replace(/\\;/g, ";");
|
||||
if (!("tel" in contact)) {
|
||||
contact.tel = [];
|
||||
}
|
||||
contact.tel.push({
|
||||
pref: pref,
|
||||
type: type,
|
||||
value: value
|
||||
});
|
||||
}
|
||||
|
||||
if (name === "ORG") {
|
||||
value = value.replace(/\\;/g, "\r");
|
||||
value = value.replace(/;/g, "\n");
|
||||
value = value.replace(/\r/g, ";");
|
||||
if (!("org" in contact)) {
|
||||
contact.org = [];
|
||||
}
|
||||
contact.org.push(value.replace(/\n.*/, ""));
|
||||
}
|
||||
|
||||
if (name === "TITLE") {
|
||||
value = value.replace(/\\;/g, ";");
|
||||
if (!("jobTitle" in contact)) {
|
||||
contact.jobTitle = [];
|
||||
}
|
||||
contact.jobTitle.push(value);
|
||||
}
|
||||
|
||||
if (name === "BDAY") {
|
||||
value = value.replace(/\\;/g, ";");
|
||||
contact.bday = Date.parse(value);
|
||||
}
|
||||
|
||||
if (name === "UID") {
|
||||
contact.id = value;
|
||||
}
|
||||
|
||||
if (name === "NOTE") {
|
||||
value = value.replace(/\\;/g, ";");
|
||||
if (!("note" in contact)) {
|
||||
contact.note = [];
|
||||
}
|
||||
contact.note.push(value);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Basic sanity checking: make sure the name field isn't empty
|
||||
if (!("name" in contact) || contact.name[0].length == 0) {
|
||||
if (("familyName" in contact) && ("givenName" in contact)) {
|
||||
// First, try to synthesize a full name from the name fields.
|
||||
// Ordering is culturally sensitive, but we don't have
|
||||
// cultural origin information available here. The best we
|
||||
// can really do is "family, given additional"
|
||||
contact.name = [contact.familyName[0] + ", " + contact.givenName[0]];
|
||||
if (("additionalName" in contact)) {
|
||||
contact.name[0] += " " + contact.additionalName[0];
|
||||
}
|
||||
} else {
|
||||
if (nickname) {
|
||||
contact.name = [nickname];
|
||||
} else if ("familyName" in contact) {
|
||||
contact.name = [contact.familyName[0]];
|
||||
} else if ("givenName" in contact) {
|
||||
contact.name = [contact.givenName[0]];
|
||||
} else if ("org" in contact) {
|
||||
contact.name = [contact.org[0]];
|
||||
} else if ("email" in contact) {
|
||||
contact.name = [contact.email[0].value];
|
||||
} else if ("tel" in contact) {
|
||||
contact.name = [contact.tel[0].value];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return contact;
|
||||
},
|
||||
|
||||
/**
|
||||
* Issues a CardDAV request (see RFC 6352) and returns a Promise to represent
|
||||
* the success or failure state of the request.
|
||||
*
|
||||
* @param {String} method WebDAV method to use (e.g., "PROPFIND")
|
||||
* @param {String} url HTTP URL to use for the request
|
||||
* @param {Object} auth Object with authentication-related configuration.
|
||||
* See documentation for startImport for details.
|
||||
* @param {Number} depth Value to use for the WebDAV (HTTP) "Depth" header
|
||||
* @param {String} body Body to include in the WebDAV (HTTP) request
|
||||
*
|
||||
* @return {Object} Promise representing the request operation outcome.
|
||||
* If resolved, the resolution value is the XMLHttpRequest
|
||||
* that was used to perform the request.
|
||||
*/
|
||||
_davPromise: function(method, url, auth, depth, body) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
|
||||
createInstance(Ci.nsIXMLHttpRequest);
|
||||
let user = "";
|
||||
let password = "";
|
||||
|
||||
if (auth.method == "basic") {
|
||||
user = auth.user;
|
||||
password = auth.password;
|
||||
}
|
||||
|
||||
req.open(method, url, true, user, password);
|
||||
|
||||
req.setRequestHeader("Depth", depth);
|
||||
req.setRequestHeader("Content-Type", "application/xml; charset=utf-8");
|
||||
|
||||
req.onload = function() {
|
||||
if (req.status < 400) {
|
||||
resolve(req);
|
||||
} else {
|
||||
reject(new Error(req.status + " " + req.statusText));
|
||||
}
|
||||
};
|
||||
|
||||
req.onerror = function(error) {
|
||||
reject(error);
|
||||
}
|
||||
|
||||
req.send(body);
|
||||
});
|
||||
}
|
||||
};
|
|
@ -10,6 +10,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "console",
|
|||
"resource://gre/modules/devtools/Console.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "LoopStorage",
|
||||
"resource:///modules/loop/LoopStorage.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "CardDavImporter",
|
||||
"resource:///modules/loop/CardDavImporter.jsm");
|
||||
XPCOMUtils.defineLazyGetter(this, "eventEmitter", function() {
|
||||
const {EventEmitter} = Cu.import("resource://gre/modules/devtools/event-emitter.js", {});
|
||||
return new EventEmitter();
|
||||
|
@ -318,6 +320,13 @@ LoopStorage.on("upgrade", function(e, db) {
|
|||
* violated. You'll notice this as well in the documentation for each method.
|
||||
*/
|
||||
let LoopContactsInternal = Object.freeze({
|
||||
/**
|
||||
* Map of contact importer names to instances
|
||||
*/
|
||||
_importServices: {
|
||||
"carddav": new CardDavImporter()
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a contact to the data store.
|
||||
*
|
||||
|
@ -757,8 +766,15 @@ let LoopContactsInternal = Object.freeze({
|
|||
* be the result of the operation, if successfull.
|
||||
*/
|
||||
startImport: function(options, callback) {
|
||||
//TODO in bug 972000.
|
||||
callback(new Error("Not implemented yet!"));
|
||||
if (!("service" in options)) {
|
||||
callback(new Error("No import service specified in options"));
|
||||
return;
|
||||
}
|
||||
if (!(options.service in this._importServices)) {
|
||||
callback(new Error("Unknown import service specified: " + options.service));
|
||||
return;
|
||||
}
|
||||
this._importServices[options.service].startImport(options, callback, this);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -543,7 +543,7 @@ loop.shared.views = (function(_, OT, l10n) {
|
|||
return (
|
||||
FeedbackLayout({title: l10n.get("feedback_thank_you_heading")},
|
||||
React.DOM.p({className: "info thank-you"},
|
||||
l10n.get("feedback_window_will_close_in", {
|
||||
l10n.get("feedback_window_will_close_in2", {
|
||||
countdown: this.state.countdown,
|
||||
num: this.state.countdown
|
||||
}))
|
||||
|
|
|
@ -543,7 +543,7 @@ loop.shared.views = (function(_, OT, l10n) {
|
|||
return (
|
||||
<FeedbackLayout title={l10n.get("feedback_thank_you_heading")}>
|
||||
<p className="info thank-you">{
|
||||
l10n.get("feedback_window_will_close_in", {
|
||||
l10n.get("feedback_window_will_close_in2", {
|
||||
countdown: this.state.countdown,
|
||||
num: this.state.countdown
|
||||
})}</p>
|
||||
|
|
|
@ -13,6 +13,7 @@ BROWSER_CHROME_MANIFESTS += [
|
|||
]
|
||||
|
||||
EXTRA_JS_MODULES.loop += [
|
||||
'CardDavImporter.jsm',
|
||||
'LoopContacts.jsm',
|
||||
'LoopStorage.jsm',
|
||||
'MozLoopAPI.jsm',
|
||||
|
|
|
@ -4,6 +4,7 @@ support-files =
|
|||
loop_fxa.sjs
|
||||
../../../../base/content/test/general/browser_fxa_oauth.html
|
||||
|
||||
[browser_CardDavImporter.js]
|
||||
[browser_fxa_login.js]
|
||||
skip-if = !debug
|
||||
[browser_loop_fxa_server.js]
|
||||
|
|
|
@ -0,0 +1,364 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const {CardDavImporter} = Cu.import("resource:///modules/loop/CardDavImporter.jsm", {});
|
||||
|
||||
const mockDb = {
|
||||
_store: { },
|
||||
_next_guid: 1,
|
||||
|
||||
add: function(details, callback) {
|
||||
if (!("id" in details)) {
|
||||
callback(new Error("No 'id' field present"));
|
||||
return;
|
||||
}
|
||||
details._guid = this._next_guid++;
|
||||
this._store[details._guid] = details;
|
||||
callback(null, details);
|
||||
},
|
||||
remove: function(guid, callback) {
|
||||
if (!guid in this._store) {
|
||||
callback(new Error("Could not find _guid '" + guid + "' in database"));
|
||||
return;
|
||||
}
|
||||
delete this._store[guid];
|
||||
callback(null);
|
||||
},
|
||||
get: function(guid, callback) {
|
||||
callback(null, this._store[guid]);
|
||||
},
|
||||
getByServiceId: function(serviceId, callback) {
|
||||
for (let guid in this._store) {
|
||||
if (serviceId === this._store[guid].id) {
|
||||
callback(null, this._store[guid]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
callback(null, null);
|
||||
},
|
||||
removeAll: function(callback) {
|
||||
this._store = {};
|
||||
this._next_guid = 1;
|
||||
callback(null);
|
||||
}
|
||||
};
|
||||
|
||||
const kAuth = {
|
||||
"method": "basic",
|
||||
"user": "username",
|
||||
"password": "p455w0rd"
|
||||
}
|
||||
|
||||
|
||||
// "pid" for "provider ID"
|
||||
let vcards = [
|
||||
"VERSION:3.0\n" +
|
||||
"N:Smith;John;;;\n" +
|
||||
"FN:John Smith\n" +
|
||||
"EMAIL;TYPE=work:john.smith@example.com\n" +
|
||||
"REV:2011-07-12T14:43:20Z\n" +
|
||||
"UID:pid1\n" +
|
||||
"END:VCARD\n",
|
||||
|
||||
"VERSION:3.0\n" +
|
||||
"N:Smith;Jane;;;\n" +
|
||||
"FN:Jane Smith\n" +
|
||||
"EMAIL:jane.smith@example.com\n" +
|
||||
"REV:2011-07-12T14:43:20Z\n" +
|
||||
"UID:pid2\n" +
|
||||
"END:VCARD\n",
|
||||
|
||||
"VERSION:3.0\n" +
|
||||
"N:García Fernández;Miguel Angel;José Antonio;Mr.;Jr.\n" +
|
||||
"FN:Mr. Miguel Angel José Antonio\n García Fernández, Jr.\n" +
|
||||
"EMAIL:mike@example.org\n" +
|
||||
"EMAIL;PREF=1;TYPE=work:miguel.angel@example.net\n" +
|
||||
"EMAIL;TYPE=home;UNKNOWNPARAMETER=frotz:majacf@example.com\n" +
|
||||
"TEL:+3455555555\n" +
|
||||
"TEL;PREF=1;TYPE=work:+3455556666\n" +
|
||||
"TEL;TYPE=home;UNKNOWNPARAMETER=frotz:+3455557777\n" +
|
||||
"ADR:;Suite 123;Calle Aduana\\, 29;MADRID;;28070;SPAIN\n" +
|
||||
"ADR;TYPE=work:P.O. BOX 555;;;Washington;DC;20024-00555;USA\n" +
|
||||
"ORG:Acme España SL\n" +
|
||||
"TITLE:President\n" +
|
||||
"BDAY:1965-05-05\n" +
|
||||
"NOTE:Likes tulips\n" +
|
||||
"REV:2011-07-12T14:43:20Z\n" +
|
||||
"UID:pid3\n" +
|
||||
"END:VCARD\n",
|
||||
|
||||
"VERSION:3.0\n" +
|
||||
"N:Jones;Bob;;;\n" +
|
||||
"EMAIL:bob.jones@example.com\n" +
|
||||
"REV:2011-07-12T14:43:20Z\n" +
|
||||
"UID:pid4\n" +
|
||||
"END:VCARD\n",
|
||||
|
||||
"VERSION:3.0\n" +
|
||||
"N:Jones;Davy;Randall;;\n" +
|
||||
"EMAIL:davy.jones@example.com\n" +
|
||||
"REV:2011-07-12T14:43:20Z\n" +
|
||||
"UID:pid5\n" +
|
||||
"END:VCARD\n",
|
||||
|
||||
"VERSION:3.0\n" +
|
||||
"EMAIL:trip@example.com\n" +
|
||||
"NICKNAME:Trip\n" +
|
||||
"REV:2011-07-12T14:43:20Z\n" +
|
||||
"UID:pid6\n" +
|
||||
"END:VCARD\n",
|
||||
|
||||
"VERSION:3.0\n" +
|
||||
"EMAIL:acme@example.com\n" +
|
||||
"ORG:Acme, Inc.\n" +
|
||||
"REV:2011-07-12T14:43:20Z\n" +
|
||||
"UID:pid7\n" +
|
||||
"END:VCARD\n",
|
||||
|
||||
"VERSION:3.0\n" +
|
||||
"EMAIL:anyone@example.com\n" +
|
||||
"REV:2011-07-12T14:43:20Z\n" +
|
||||
"UID:pid8\n" +
|
||||
"END:VCARD\n",
|
||||
];
|
||||
|
||||
|
||||
const monkeyPatchImporter = function(importer) {
|
||||
// Set up the response bodies
|
||||
let listPropfind =
|
||||
'<?xml version="1.0" encoding="UTF-8"?>\n' +
|
||||
'<d:multistatus xmlns:card="urn:ietf:params:xml:ns:carddav"\n' +
|
||||
' xmlns:d="DAV:">\n' +
|
||||
' <d:response>\n' +
|
||||
' <d:href>/carddav/abook/</d:href>\n' +
|
||||
' <d:propstat>\n' +
|
||||
' <d:status>HTTP/1.1 200 OK</d:status>\n' +
|
||||
' </d:propstat>\n' +
|
||||
' <d:propstat>\n' +
|
||||
' <d:status>HTTP/1.1 404 Not Found</d:status>\n' +
|
||||
' <d:prop>\n' +
|
||||
' <d:getetag/>\n' +
|
||||
' </d:prop>\n' +
|
||||
' </d:propstat>\n' +
|
||||
' </d:response>\n';
|
||||
|
||||
let listReportMultiget =
|
||||
'<?xml version="1.0" encoding="UTF-8"?>\n' +
|
||||
'<d:multistatus xmlns:card="urn:ietf:params:xml:ns:carddav"\n' +
|
||||
' xmlns:d="DAV:">\n';
|
||||
|
||||
vcards.forEach(vcard => {
|
||||
let uid = /\nUID:(.*?)\n/.exec(vcard);
|
||||
listPropfind +=
|
||||
' <d:response>\n' +
|
||||
' <d:href>/carddav/abook/' + uid + '</d:href>\n' +
|
||||
' <d:propstat>\n' +
|
||||
' <d:status>HTTP/1.1 200 OK</d:status>\n' +
|
||||
' <d:prop>\n' +
|
||||
' <d:getetag>"2011-07-12T07:43:20.855-07:00"</d:getetag>\n' +
|
||||
' </d:prop>\n' +
|
||||
' </d:propstat>\n' +
|
||||
' </d:response>\n';
|
||||
|
||||
listReportMultiget +=
|
||||
' <d:response>\n' +
|
||||
' <d:href>/carddav/abook/' + uid + '</d:href>\n' +
|
||||
' <d:propstat>\n' +
|
||||
' <d:status>HTTP/1.1 200 OK</d:status>\n' +
|
||||
' <d:prop>\n' +
|
||||
' <d:getetag>"2011-07-12T07:43:20.855-07:00"</d:getetag>\n' +
|
||||
' <card:address-data>' + vcard + '</card:address-data>\n' +
|
||||
' </d:prop>\n' +
|
||||
' </d:propstat>\n' +
|
||||
' </d:response>\n';
|
||||
});
|
||||
|
||||
listPropfind += "</d:multistatus>\n";
|
||||
listReportMultiget += "</d:multistatus>\n";
|
||||
|
||||
importer._davPromise = function(method, url, auth, depth, body) {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
if (auth.method != "basic" ||
|
||||
auth.user != kAuth.user ||
|
||||
auth.password != kAuth.password) {
|
||||
reject(new Error("401 Auth Failure"));
|
||||
return;
|
||||
}
|
||||
|
||||
let request = method + " " + url + " " + depth;
|
||||
let xmlParser = new DOMParser();
|
||||
let responseXML;
|
||||
switch (request) {
|
||||
case "PROPFIND https://example.com/.well-known/carddav 1":
|
||||
responseXML = xmlParser.parseFromString(listPropfind, "text/xml");
|
||||
break;
|
||||
case "REPORT https://example.com/carddav/abook/ 1":
|
||||
responseXML = xmlParser.parseFromString(listReportMultiget, "text/xml");
|
||||
break;
|
||||
default:
|
||||
reject(new Error("404 Not Found"));
|
||||
return;
|
||||
}
|
||||
resolve({"responseXML": responseXML});
|
||||
});
|
||||
}.bind(importer);
|
||||
return importer;
|
||||
}
|
||||
|
||||
add_task(function* test_CardDavImport() {
|
||||
let importer = monkeyPatchImporter(new CardDavImporter());
|
||||
yield new Promise ((resolve, reject) => {
|
||||
info("Initiating import");
|
||||
importer.startImport({
|
||||
"host": "example.com",
|
||||
"auth": kAuth.method,
|
||||
"user": kAuth.user,
|
||||
"password": kAuth.password
|
||||
}, (err, result) => { err ? reject(err) : resolve(result); }, mockDb);
|
||||
});
|
||||
info("Import succeeded");
|
||||
|
||||
Assert.equal(vcards.length, Object.keys(mockDb._store).length,
|
||||
"Should import all VCards into database");
|
||||
|
||||
// Basic checks
|
||||
let c = mockDb._store[1];
|
||||
Assert.equal(c.name[0], "John Smith", "Full name should match");
|
||||
Assert.equal(c.givenName[0], "John", "Given name should match");
|
||||
Assert.equal(c.familyName[0], "Smith", "Family name should match");
|
||||
Assert.equal(c.email[0].type, "work", "Email type should match");
|
||||
Assert.equal(c.email[0].value, "john.smith@example.com", "Email should match");
|
||||
Assert.equal(c.email[0].pref, false, "Pref should match");
|
||||
Assert.equal(c.id, "pid1@example.com", "UID should match and be scoped to provider");
|
||||
|
||||
c = mockDb._store[2];
|
||||
Assert.equal(c.name[0], "Jane Smith", "Full name should match");
|
||||
Assert.equal(c.givenName[0], "Jane", "Given name should match");
|
||||
Assert.equal(c.familyName[0], "Smith", "Family name should match");
|
||||
Assert.equal(c.email[0].type, "other", "Email type should match");
|
||||
Assert.equal(c.email[0].value, "jane.smith@example.com", "Email should match");
|
||||
Assert.equal(c.email[0].pref, false, "Pref should match");
|
||||
Assert.equal(c.id, "pid2@example.com", "UID should match and be scoped to provider");
|
||||
|
||||
// Check every field
|
||||
c = mockDb._store[3];
|
||||
Assert.equal(c.name[0], "Mr. Miguel Angel José Antonio García Fernández, Jr.", "Full name should match");
|
||||
Assert.equal(c.givenName[0], "Miguel Angel", "Given name should match");
|
||||
Assert.equal(c.additionalName[0], "José Antonio", "Other name should match");
|
||||
Assert.equal(c.familyName[0], "García Fernández", "Family name should match");
|
||||
Assert.equal(c.email.length, 3, "Email count should match");
|
||||
Assert.equal(c.email[0].type, "other", "Email type should match");
|
||||
Assert.equal(c.email[0].value, "mike@example.org", "Email should match");
|
||||
Assert.equal(c.email[0].pref, false, "Pref should match");
|
||||
Assert.equal(c.email[1].type, "work", "Email type should match");
|
||||
Assert.equal(c.email[1].value, "miguel.angel@example.net", "Email should match");
|
||||
Assert.equal(c.email[1].pref, true, "Pref should match");
|
||||
Assert.equal(c.email[2].type, "home", "Email type should match");
|
||||
Assert.equal(c.email[2].value, "majacf@example.com", "Email should match");
|
||||
Assert.equal(c.email[2].pref, false, "Pref should match");
|
||||
Assert.equal(c.tel.length, 3, "Phone number count should match");
|
||||
Assert.equal(c.tel[0].type, "other", "Phone type should match");
|
||||
Assert.equal(c.tel[0].value, "+3455555555", "Phone number should match");
|
||||
Assert.equal(c.tel[0].pref, false, "Pref should match");
|
||||
Assert.equal(c.tel[1].type, "work", "Phone type should match");
|
||||
Assert.equal(c.tel[1].value, "+3455556666", "Phone number should match");
|
||||
Assert.equal(c.tel[1].pref, true, "Pref should match");
|
||||
Assert.equal(c.tel[2].type, "home", "Phone type should match");
|
||||
Assert.equal(c.tel[2].value, "+3455557777", "Phone number should match");
|
||||
Assert.equal(c.tel[2].pref, false, "Pref should match");
|
||||
Assert.equal(c.adr.length, 2, "Address count should match");
|
||||
Assert.equal(c.adr[0].pref, false, "Pref should match");
|
||||
Assert.equal(c.adr[0].type, "other", "Type should match");
|
||||
Assert.equal(c.adr[0].streetAddress, "Calle Aduana, 29 Suite 123", "Street address should match");
|
||||
Assert.equal(c.adr[0].locality, "MADRID", "Locality should match");
|
||||
Assert.equal(c.adr[0].postalCode, "28070", "Post code should match");
|
||||
Assert.equal(c.adr[0].countryName, "SPAIN", "Country should match");
|
||||
Assert.equal(c.adr[1].pref, false, "Pref should match");
|
||||
Assert.equal(c.adr[1].type, "work", "Type should match");
|
||||
Assert.equal(c.adr[1].streetAddress, "P.O. BOX 555", "Street address should match");
|
||||
Assert.equal(c.adr[1].locality, "Washington", "Locality should match");
|
||||
Assert.equal(c.adr[1].region, "DC", "Region should match");
|
||||
Assert.equal(c.adr[1].postalCode, "20024-00555", "Post code should match");
|
||||
Assert.equal(c.adr[1].countryName, "USA", "Country should match");
|
||||
Assert.equal(c.org[0], "Acme España SL", "Org should match");
|
||||
Assert.equal(c.jobTitle[0], "President", "Title should match");
|
||||
Assert.equal(c.note[0], "Likes tulips", "Note should match");
|
||||
let bday = new Date(c.bday);
|
||||
Assert.equal(bday.getUTCFullYear(), 1965, "Birthday year should match");
|
||||
Assert.equal(bday.getUTCMonth(), 4, "Birthday month should match");
|
||||
Assert.equal(bday.getUTCDate(), 5, "Birthday day should match");
|
||||
Assert.equal(c.id, "pid3@example.com", "UID should match and be scoped to provider");
|
||||
|
||||
// Check name synthesis
|
||||
c = mockDb._store[4];
|
||||
Assert.equal(c.name[0], "Jones, Bob", "Full name should be synthesized correctly");
|
||||
c = mockDb._store[5];
|
||||
Assert.equal(c.name[0], "Jones, Davy Randall", "Full name should be synthesized correctly");
|
||||
c = mockDb._store[6];
|
||||
Assert.equal(c.name[0], "Trip", "Full name should be synthesized correctly");
|
||||
c = mockDb._store[7];
|
||||
Assert.equal(c.name[0], "Acme, Inc.", "Full name should be synthesized correctly");
|
||||
c = mockDb._store[8];
|
||||
Assert.equal(c.name[0], "anyone@example.com", "Full name should be synthesized correctly");
|
||||
|
||||
// Check that a re-import doesn't cause contact duplication.
|
||||
yield new Promise ((resolve, reject) => {
|
||||
info("Initiating import");
|
||||
importer.startImport({
|
||||
"host": "example.com",
|
||||
"auth": kAuth.method,
|
||||
"user": kAuth.user,
|
||||
"password": kAuth.password
|
||||
}, (err, result) => { err ? reject(err) : resolve(result); }, mockDb);
|
||||
});
|
||||
Assert.equal(vcards.length, Object.keys(mockDb._store).length,
|
||||
"Second import shouldn't increase DB size");
|
||||
|
||||
// Check that errors are propagated back to caller
|
||||
let error = yield new Promise ((resolve, reject) => {
|
||||
info("Initiating import");
|
||||
importer.startImport({
|
||||
"host": "example.com",
|
||||
"auth": kAuth.method,
|
||||
"user": kAuth.user,
|
||||
"password": "invalidpassword"
|
||||
}, (err, result) => { err ? resolve(err) : reject(new Error("Should have failed")); }, mockDb);
|
||||
});
|
||||
Assert.equal(error.message, "401 Auth Failure", "Auth error should propagate");
|
||||
|
||||
let error = yield new Promise ((resolve, reject) => {
|
||||
info("Initiating import");
|
||||
importer.startImport({
|
||||
"host": "example.invalid",
|
||||
"auth": kAuth.method,
|
||||
"user": kAuth.user,
|
||||
"password": kAuth.password
|
||||
}, (err, result) => { err ? resolve(err) : reject(new Error("Should have failed")); }, mockDb);
|
||||
});
|
||||
Assert.equal(error.message, "404 Not Found", "Not found error should propagate");
|
||||
|
||||
let tmp = mockDb.getByServiceId;
|
||||
mockDb.getByServiceId = function(serviceId, callback) {
|
||||
callback(new Error("getByServiceId failed"));
|
||||
};
|
||||
let error = yield new Promise ((resolve, reject) => {
|
||||
info("Initiating import");
|
||||
importer.startImport({
|
||||
"host": "example.com",
|
||||
"auth": kAuth.method,
|
||||
"user": kAuth.user,
|
||||
"password": kAuth.password
|
||||
}, (err, result) => { err ? resolve(err) : reject(new Error("Should have failed")); }, mockDb);
|
||||
});
|
||||
Assert.equal(error.message, "getByServiceId failed", "Database error should propagate");
|
||||
mockDb.getByServiceId = tmp;
|
||||
|
||||
let error = yield new Promise ((resolve, reject) => {
|
||||
info("Initiating import");
|
||||
importer.startImport({
|
||||
"host": "example.com",
|
||||
}, (err, result) => { err ? resolve(err) : reject(new Error("Should have failed")); }, mockDb);
|
||||
});
|
||||
Assert.equal(error.message, "No authentication specified", "Missing parameters should generate error");
|
||||
})
|
|
@ -11,7 +11,7 @@ add_task(loadLoopPanel);
|
|||
add_task(function* test_mozLoop_pluralStrings() {
|
||||
Assert.ok(gMozLoopAPI, "mozLoop should exist");
|
||||
|
||||
var strings = JSON.parse(gMozLoopAPI.getStrings("feedback_window_will_close_in"));
|
||||
var strings = JSON.parse(gMozLoopAPI.getStrings("feedback_window_will_close_in2"));
|
||||
Assert.equal(gMozLoopAPI.getPluralForm(0, strings.textContent),
|
||||
"This window will close in {{countdown}} seconds");
|
||||
Assert.equal(gMozLoopAPI.getPluralForm(1, strings.textContent),
|
||||
|
|
|
@ -29,7 +29,6 @@ const MAX_ORDINAL = 99;
|
|||
this.DevTools = function DevTools() {
|
||||
this._tools = new Map(); // Map<toolId, tool>
|
||||
this._themes = new Map(); // Map<themeId, theme>
|
||||
this._eventParsers = new Map(); // Map<parserID, [handlers]>
|
||||
this._toolboxes = new Map(); // Map<target, toolbox>
|
||||
|
||||
// destroy() is an observer's handler so we need to preserve context.
|
||||
|
@ -42,7 +41,7 @@ this.DevTools = function DevTools() {
|
|||
|
||||
Services.obs.addObserver(this._teardown, "devtools-unloaded", false);
|
||||
Services.obs.addObserver(this.destroy, "quit-application", false);
|
||||
}
|
||||
};
|
||||
|
||||
DevTools.prototype = {
|
||||
/**
|
||||
|
@ -66,10 +65,6 @@ DevTools.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
get eventParsers() {
|
||||
return this._eventParsers;
|
||||
},
|
||||
|
||||
/**
|
||||
* Register a new developer tool.
|
||||
*
|
||||
|
@ -145,85 +140,6 @@ DevTools.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Register a new event parser to be used in the processing of event info.
|
||||
*
|
||||
* @param {Object} parserObj
|
||||
* Each parser must contain the following properties:
|
||||
* - parser, which must take the following form:
|
||||
* {
|
||||
* id {String}: "jQuery events", // Unique id.
|
||||
* getListeners: function(node) { }, // Function that takes a node and
|
||||
* // returns an array of eventInfo
|
||||
* // objects (see below).
|
||||
*
|
||||
* hasListeners: function(node) { }, // Optional function that takes a
|
||||
* // node and returns a boolean
|
||||
* // indicating whether a node has
|
||||
* // listeners attached.
|
||||
*
|
||||
* normalizeHandler: function(fnDO) { }, // Optional function that takes a
|
||||
* // Debugger.Object instance and
|
||||
* // climbs the scope chain to get
|
||||
* // the function that should be
|
||||
* // displayed in the event bubble
|
||||
* // see the following url for
|
||||
* // details:
|
||||
* // https://developer.mozilla.org/
|
||||
* // docs/Tools/Debugger-API/
|
||||
* // Debugger.Object
|
||||
* }
|
||||
*
|
||||
* An eventInfo object should take the following form:
|
||||
* {
|
||||
* type {String}: "click",
|
||||
* handler {Function}: event handler,
|
||||
* tags {String}: "jQuery,Live", // These tags will be displayed as
|
||||
* // attributes in the events popup.
|
||||
* hide: { // Hide or show fields:
|
||||
* debugger: false, // Debugger icon
|
||||
* type: false, // Event type e.g. click
|
||||
* filename: false, // Filename
|
||||
* capturing: false, // Capturing
|
||||
* dom0: false // DOM 0
|
||||
* },
|
||||
*
|
||||
* override: { // The following can be overridden:
|
||||
* type: "click",
|
||||
* origin: "http://www.mozilla.com",
|
||||
* searchString: 'onclick="doSomething()"',
|
||||
* DOM0: true,
|
||||
* capturing: true
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
registerEventParser: function(parserObj) {
|
||||
let parserId = parserObj.id;
|
||||
|
||||
if (!parserId) {
|
||||
throw new Error("Cannot register new event parser with id " + parserId);
|
||||
}
|
||||
if (this._eventParsers.has(parserId)) {
|
||||
throw new Error("Duplicate event parser id " + parserId);
|
||||
}
|
||||
|
||||
this._eventParsers.set(parserId, {
|
||||
getListeners: parserObj.getListeners,
|
||||
hasListeners: parserObj.hasListeners,
|
||||
normalizeHandler: parserObj.normalizeHandler
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes parser that matches a given parserId.
|
||||
*
|
||||
* @param {String} parserId
|
||||
* id of the event parser to unregister.
|
||||
*/
|
||||
unregisterEventParser: function(parserId) {
|
||||
this._eventParsers.delete(parserId);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sorting function used for sorting tools based on their ordinals.
|
||||
*/
|
||||
|
@ -555,10 +471,6 @@ DevTools.prototype = {
|
|||
this.unregisterTool(key, true);
|
||||
}
|
||||
|
||||
for (let [id] of this._eventParsers) {
|
||||
this.unregisterEventParser(id, true);
|
||||
}
|
||||
|
||||
// Cleaning down the toolboxes: i.e.
|
||||
// for (let [target, toolbox] of this._toolboxes) toolbox.destroy();
|
||||
// Is taken care of by the gDevToolsBrowser.forgetBrowserWindow
|
||||
|
|
|
@ -26,6 +26,7 @@ browser.jar:
|
|||
content/browser/devtools/frame-script-utils.js (shared/frame-script-utils.js)
|
||||
content/browser/devtools/styleeditor.xul (styleeditor/styleeditor.xul)
|
||||
content/browser/devtools/styleeditor.css (styleeditor/styleeditor.css)
|
||||
content/browser/devtools/storage.xul (storage/storage.xul)
|
||||
content/browser/devtools/computedview.xhtml (styleinspector/computedview.xhtml)
|
||||
content/browser/devtools/cssruleview.xhtml (styleinspector/cssruleview.xhtml)
|
||||
content/browser/devtools/ruleview.css (styleinspector/ruleview.css)
|
||||
|
|
|
@ -21,8 +21,6 @@ loader.lazyGetter(this, "osString", () => Cc["@mozilla.org/xre/app-info;1"].getS
|
|||
|
||||
let events = require("sdk/system/events");
|
||||
|
||||
require("devtools/toolkit/event-parsers");
|
||||
|
||||
// Panels
|
||||
loader.lazyGetter(this, "OptionsPanel", () => require("devtools/framework/toolbox-options").OptionsPanel);
|
||||
loader.lazyGetter(this, "InspectorPanel", () => require("devtools/inspector/inspector-panel").InspectorPanel);
|
||||
|
@ -35,6 +33,7 @@ loader.lazyGetter(this, "WebAudioEditorPanel", () => require("devtools/webaudioe
|
|||
loader.lazyGetter(this, "ProfilerPanel", () => require("devtools/profiler/panel").ProfilerPanel);
|
||||
loader.lazyGetter(this, "NetMonitorPanel", () => require("devtools/netmonitor/panel").NetMonitorPanel);
|
||||
loader.lazyGetter(this, "ScratchpadPanel", () => require("devtools/scratchpad/scratchpad-panel").ScratchpadPanel);
|
||||
loader.lazyGetter(this, "StoragePanel", () => require("devtools/storage/panel").StoragePanel);
|
||||
|
||||
// Strings
|
||||
const toolboxProps = "chrome://browser/locale/devtools/toolbox.properties";
|
||||
|
@ -44,11 +43,12 @@ const styleEditorProps = "chrome://browser/locale/devtools/styleeditor.propertie
|
|||
const shaderEditorProps = "chrome://browser/locale/devtools/shadereditor.properties";
|
||||
const canvasDebuggerProps = "chrome://browser/locale/devtools/canvasdebugger.properties";
|
||||
const webAudioEditorProps = "chrome://browser/locale/devtools/webaudioeditor.properties";
|
||||
|
||||
const webConsoleProps = "chrome://browser/locale/devtools/webconsole.properties";
|
||||
const profilerProps = "chrome://browser/locale/devtools/profiler.properties";
|
||||
const netMonitorProps = "chrome://browser/locale/devtools/netmonitor.properties";
|
||||
const scratchpadProps = "chrome://browser/locale/devtools/scratchpad.properties";
|
||||
const storageProps = "chrome://browser/locale/devtools/storage.properties";
|
||||
|
||||
loader.lazyGetter(this, "toolboxStrings", () => Services.strings.createBundle(toolboxProps));
|
||||
loader.lazyGetter(this, "webConsoleStrings", () => Services.strings.createBundle(webConsoleProps));
|
||||
loader.lazyGetter(this, "debuggerStrings", () => Services.strings.createBundle(debuggerProps));
|
||||
|
@ -60,6 +60,7 @@ loader.lazyGetter(this, "inspectorStrings", () => Services.strings.createBundle(
|
|||
loader.lazyGetter(this, "profilerStrings",() => Services.strings.createBundle(profilerProps));
|
||||
loader.lazyGetter(this, "netMonitorStrings", () => Services.strings.createBundle(netMonitorProps));
|
||||
loader.lazyGetter(this, "scratchpadStrings", () => Services.strings.createBundle(scratchpadProps));
|
||||
loader.lazyGetter(this, "storageStrings", () => Services.strings.createBundle(storageProps));
|
||||
|
||||
let Tools = {};
|
||||
exports.Tools = Tools;
|
||||
|
@ -318,9 +319,34 @@ Tools.netMonitor = {
|
|||
}
|
||||
};
|
||||
|
||||
Tools.storage = {
|
||||
id: "storage",
|
||||
key: l10n("open.commandkey", storageStrings),
|
||||
ordinal: 9,
|
||||
accesskey: l10n("open.accesskey", storageStrings),
|
||||
modifiers: "shift",
|
||||
visibilityswitch: "devtools.storage.enabled",
|
||||
icon: "chrome://browser/skin/devtools/tool-storage.svg",
|
||||
invertIconForLightTheme: true,
|
||||
url: "chrome://browser/content/devtools/storage.xul",
|
||||
label: l10n("storage.label", storageStrings),
|
||||
tooltip: l10n("storage.tooltip", storageStrings),
|
||||
inMenu: true,
|
||||
|
||||
isTargetSupported: function(target) {
|
||||
return target.isLocalTab ||
|
||||
(target.client.traits.storageInspector && !target.isAddon);
|
||||
},
|
||||
|
||||
build: function(iframeWindow, toolbox) {
|
||||
let panel = new StoragePanel(iframeWindow, toolbox);
|
||||
return panel.open();
|
||||
}
|
||||
};
|
||||
|
||||
Tools.scratchpad = {
|
||||
id: "scratchpad",
|
||||
ordinal: 9,
|
||||
ordinal: 10,
|
||||
visibilityswitch: "devtools.scratchpad.enabled",
|
||||
icon: "chrome://browser/skin/devtools/tool-scratchpad.svg",
|
||||
invertIconForLightTheme: true,
|
||||
|
@ -352,6 +378,7 @@ let defaultTools = [
|
|||
Tools.webAudioEditor,
|
||||
Tools.jsprofiler,
|
||||
Tools.netMonitor,
|
||||
Tools.storage,
|
||||
Tools.scratchpad
|
||||
];
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ DIRS += [
|
|||
'shadereditor',
|
||||
'shared',
|
||||
'sourceeditor',
|
||||
'storage',
|
||||
'styleeditor',
|
||||
'styleinspector',
|
||||
'tilt',
|
||||
|
|
|
@ -16,7 +16,7 @@ function test() {
|
|||
"-H 'User-Agent: " + aDebuggee.navigator.userAgent + "'",
|
||||
"-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'",
|
||||
"-H 'Accept-Language: " + aDebuggee.navigator.language + "'",
|
||||
"-H 'Accept-Encoding: gzip, deflate'",
|
||||
"--compressed",
|
||||
"-H 'X-Custom-Header-1: Custom value'",
|
||||
"-H 'X-Custom-Header-2: 8.8.8.8'",
|
||||
"-H 'X-Custom-Header-3: Mon, 3 Mar 2014 11:11:11 GMT'",
|
||||
|
@ -31,7 +31,7 @@ function test() {
|
|||
'-H "User-Agent: ' + aDebuggee.navigator.userAgent + '"',
|
||||
'-H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"',
|
||||
'-H "Accept-Language: ' + aDebuggee.navigator.language + '"',
|
||||
'-H "Accept-Encoding: gzip, deflate"',
|
||||
"--compressed",
|
||||
'-H "X-Custom-Header-1: Custom value"',
|
||||
'-H "X-Custom-Header-2: 8.8.8.8"',
|
||||
'-H "X-Custom-Header-3: Mon, 3 Mar 2014 11:11:11 GMT"',
|
||||
|
|
|
@ -57,6 +57,13 @@ var Resource = Class({
|
|||
*/
|
||||
get hasChildren() { return this.children && this.children.size > 0; },
|
||||
|
||||
/**
|
||||
* Is this Resource the root (top level for the store)?
|
||||
*/
|
||||
get isRoot() {
|
||||
return !this.parent
|
||||
},
|
||||
|
||||
/**
|
||||
* Sorted array of children for display
|
||||
*/
|
||||
|
|
|
@ -84,6 +84,9 @@ var ResourceContainer = Class({
|
|||
evt.stopPropagation();
|
||||
}, true);
|
||||
|
||||
if (!this.resource.isRoot) {
|
||||
this.expanded = false;
|
||||
}
|
||||
this.update();
|
||||
},
|
||||
|
||||
|
|
|
@ -35,8 +35,14 @@ let test = asyncTest(function*() {
|
|||
function selectFileFirstLoad(projecteditor, resource) {
|
||||
ok (resource && resource.path, "A valid resource has been passed in for selection " + (resource && resource.path));
|
||||
projecteditor.projectTree.selectResource(resource);
|
||||
let container = projecteditor.projectTree.getViewContainer(resource);
|
||||
|
||||
if (resource.isRoot) {
|
||||
ok (container.expanded, "The root directory is expanded by default.");
|
||||
return;
|
||||
}
|
||||
if (resource.isDir) {
|
||||
ok (!container.expanded, "A directory is not expanded by default.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -120,6 +120,10 @@ this.Curl = {
|
|||
}
|
||||
for (let i = 0; i < headers.length; i++) {
|
||||
let header = headers[i];
|
||||
if (header.name === "Accept-Encoding"){
|
||||
command.push("--compressed");
|
||||
continue;
|
||||
}
|
||||
if (ignoredHeaders.has(header.name)) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ const MAX_VISIBLE_STRING_SIZE = 100;
|
|||
* entry in the table. Default: name.
|
||||
* - emptyText: text to display when no entries in the table to display.
|
||||
* - highlightUpdated: true to highlight the changed/added row.
|
||||
* - removableColumns: Whether columns are removeable. If set to true,
|
||||
* - removableColumns: Whether columns are removeable. If set to false,
|
||||
* the context menu in the headers will not appear.
|
||||
* - firstColumn: key of the first column that should appear.
|
||||
*/
|
||||
|
@ -55,7 +55,7 @@ function TableWidget(node, options={}) {
|
|||
this.uniqueId = uniqueId || "name";
|
||||
this.firstColumn = firstColumn || "";
|
||||
this.highlightUpdated = highlightUpdated || false;
|
||||
this.removableColumns = removableColumns || false;
|
||||
this.removableColumns = removableColumns !== false;
|
||||
|
||||
this.tbody = this.document.createElementNS(XUL_NS, "hbox");
|
||||
this.tbody.className = "table-widget-body theme-body";
|
||||
|
@ -276,7 +276,7 @@ TableWidget.prototype = {
|
|||
item = item[this.uniqueId];
|
||||
}
|
||||
|
||||
return item == this.selectedRow[this.uniqueId];
|
||||
return this.selectedRow && item == this.selectedRow[this.uniqueId];
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -687,6 +687,8 @@ Column.prototype = {
|
|||
/**
|
||||
* Event handler for the command event coming from the header context menu.
|
||||
* Toggles the column if it was requested by the user.
|
||||
* When called explicitly without parameters, it toggles the corresponding
|
||||
* column.
|
||||
*
|
||||
* @param {string} event
|
||||
* The name of the event. i.e. EVENTS.HEADER_CONTEXT_MENU
|
||||
|
@ -696,6 +698,11 @@ Column.prototype = {
|
|||
* true if the column is visible
|
||||
*/
|
||||
toggleColumn: function(event, id, checked) {
|
||||
if (arguments.length == 0) {
|
||||
// Act like a toggling method when called with no params
|
||||
id = this.id;
|
||||
checked = this.wrapper.hasAttribute("hidden");
|
||||
}
|
||||
if (id != this.id) {
|
||||
return;
|
||||
}
|
||||
|
@ -960,6 +967,8 @@ Cell.prototype = {
|
|||
*/
|
||||
flash: function() {
|
||||
this.label.classList.remove("flash-out");
|
||||
// Cause a reflow so that the animation retriggers on adding back the class
|
||||
let a = this.label.parentNode.offsetWidth;
|
||||
this.label.classList.add("flash-out");
|
||||
},
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ TreeWidget.prototype = {
|
|||
this._selectedLabel = this._selectedItem = null;
|
||||
return;
|
||||
}
|
||||
if (!typeof id == "array") {
|
||||
if (!Array.isArray(id)) {
|
||||
return;
|
||||
}
|
||||
this._selectedLabel = this.root.setSelectedItem(id);
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
|
||||
|
||||
EXTRA_JS_MODULES.devtools.storage += [
|
||||
'panel.js',
|
||||
'ui.js'
|
||||
]
|
|
@ -0,0 +1,83 @@
|
|||
/* -*- Mode: Javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
const {Cc, Ci, Cu, Cr} = require("chrome");
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
|
||||
let EventEmitter = require("devtools/toolkit/event-emitter");
|
||||
|
||||
loader.lazyGetter(this, "StorageFront",
|
||||
() => require("devtools/server/actors/storage").StorageFront);
|
||||
|
||||
loader.lazyGetter(this, "StorageUI",
|
||||
() => require("devtools/storage/ui").StorageUI);
|
||||
|
||||
this.StoragePanel = function StoragePanel(panelWin, toolbox) {
|
||||
EventEmitter.decorate(this);
|
||||
|
||||
this._toolbox = toolbox;
|
||||
this._target = toolbox.target;
|
||||
this._panelWin = panelWin;
|
||||
|
||||
this.destroy = this.destroy.bind(this);
|
||||
}
|
||||
|
||||
exports.StoragePanel = StoragePanel;
|
||||
|
||||
StoragePanel.prototype = {
|
||||
get target() this._toolbox.target,
|
||||
|
||||
get panelWindow() this._panelWin,
|
||||
|
||||
/**
|
||||
* open is effectively an asynchronous constructor
|
||||
*/
|
||||
open: function() {
|
||||
let targetPromise;
|
||||
// We always interact with the target as if it were remote
|
||||
if (!this.target.isRemote) {
|
||||
targetPromise = this.target.makeRemote();
|
||||
} else {
|
||||
targetPromise = Promise.resolve(this.target);
|
||||
}
|
||||
|
||||
return targetPromise.then(() => {
|
||||
this.target.on("close", this.destroy);
|
||||
this._front = new StorageFront(this.target.client, this.target.form);
|
||||
|
||||
this.UI = new StorageUI(this._front, this._target, this._panelWin);
|
||||
this.isReady = true;
|
||||
this.emit("ready");
|
||||
return this;
|
||||
}, console.error);
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroy the style editor.
|
||||
*/
|
||||
destroy: function() {
|
||||
if (!this._destroyed) {
|
||||
this.UI.destroy();
|
||||
this._destroyed = true;
|
||||
|
||||
this._target.off("close", this.destroy);
|
||||
this._target = null;
|
||||
this._toolbox = null;
|
||||
this._panelDoc = null;
|
||||
}
|
||||
|
||||
return Promise.resolve(null);
|
||||
},
|
||||
}
|
||||
|
||||
XPCOMUtils.defineLazyGetter(StoragePanel.prototype, "strings",
|
||||
function () {
|
||||
return Services.strings.createBundle(
|
||||
"chrome://browser/locale/devtools/storage.properties");
|
||||
});
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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/. -->
|
||||
<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/devtools/widgets.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/devtools/common.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/devtools/widgets.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/devtools/storage.css" type="text/css"?>
|
||||
|
||||
<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script type="application/javascript;version=1.8"
|
||||
src="chrome://browser/content/devtools/theme-switching.js"/>
|
||||
<script type="text/javascript" src="chrome://global/content/globalOverlay.js"/>
|
||||
|
||||
<commandset id="editMenuCommands"/>
|
||||
|
||||
<box flex="1" class="devtools-responsive-container theme-body">
|
||||
<vbox id="storage-tree"/>
|
||||
<splitter class="devtools-side-splitter"/>
|
||||
<vbox id="storage-table" class="theme-sidebar" flex="1"/>
|
||||
<splitter class="devtools-side-splitter"/>
|
||||
<vbox id="storage-sidebar" class="devtools-sidebar-tabs" hidden="true">
|
||||
<vbox flex="1"/>
|
||||
</vbox>
|
||||
</box>
|
||||
|
||||
</window>
|
|
@ -0,0 +1,15 @@
|
|||
[DEFAULT]
|
||||
skip-if = e10s # Bug 1049888 - storage actors do not work in e10s for now
|
||||
subsuite = devtools
|
||||
support-files =
|
||||
storage-complex-values.html
|
||||
storage-listings.html
|
||||
storage-secured-iframe.html
|
||||
storage-unsecured-iframe.html
|
||||
storage-updates.html
|
||||
head.js
|
||||
|
||||
[browser_storage_basic.js]
|
||||
[browser_storage_dynamic_updates.js]
|
||||
[browser_storage_sidebar.js]
|
||||
[browser_storage_values.js]
|
|
@ -0,0 +1,114 @@
|
|||
/* 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/. */
|
||||
|
||||
// Basic test to assert that the storage tree and table corresponding to each
|
||||
// item in the storage tree is correctly displayed
|
||||
|
||||
// Entries that should be present in the tree for this test
|
||||
// Format for each entry in the array :
|
||||
// [
|
||||
// ["path", "to", "tree", "item"], - The path to the tree item to click formed
|
||||
// by id of each item
|
||||
// ["key_value1", "key_value2", ...] - The value of the first (unique) column
|
||||
// for each row in the table corresponding
|
||||
// to the tree item selected.
|
||||
// ]
|
||||
// These entries are formed by the cookies, local storage, session storage and
|
||||
// indexedDB entries created in storage-listings.html,
|
||||
// storage-secured-iframe.html and storage-unsecured-iframe.html
|
||||
const storeItems = [
|
||||
[["cookies", "test1.example.org"],
|
||||
["c1", "cs2", "c3", "uc1"]],
|
||||
[["cookies", "sectest1.example.org"],
|
||||
["uc1", "cs2", "sc1"]],
|
||||
[["localStorage", "http://test1.example.org"],
|
||||
["ls1", "ls2"]],
|
||||
[["localStorage", "http://sectest1.example.org"],
|
||||
["iframe-u-ls1"]],
|
||||
[["localStorage", "https://sectest1.example.org"],
|
||||
["iframe-s-ls1"]],
|
||||
[["sessionStorage", "http://test1.example.org"],
|
||||
["ss1"]],
|
||||
[["sessionStorage", "http://sectest1.example.org"],
|
||||
["iframe-u-ss1", "iframe-u-ss2"]],
|
||||
[["sessionStorage", "https://sectest1.example.org"],
|
||||
["iframe-s-ss1"]],
|
||||
[["indexedDB", "http://test1.example.org"],
|
||||
["idb1", "idb2"]],
|
||||
[["indexedDB", "http://test1.example.org", "idb1"],
|
||||
["obj1", "obj2"]],
|
||||
[["indexedDB", "http://test1.example.org", "idb2"],
|
||||
["obj3"]],
|
||||
[["indexedDB", "http://test1.example.org", "idb1", "obj1"],
|
||||
[1, 2, 3]],
|
||||
[["indexedDB", "http://test1.example.org", "idb1", "obj2"],
|
||||
[1]],
|
||||
[["indexedDB", "http://test1.example.org", "idb2", "obj3"],
|
||||
[]],
|
||||
[["indexedDB", "http://sectest1.example.org"],
|
||||
[]],
|
||||
[["indexedDB", "https://sectest1.example.org"],
|
||||
["idb-s1", "idb-s2"]],
|
||||
[["indexedDB", "https://sectest1.example.org", "idb-s1"],
|
||||
["obj-s1"]],
|
||||
[["indexedDB", "https://sectest1.example.org", "idb-s2"],
|
||||
["obj-s2"]],
|
||||
[["indexedDB", "https://sectest1.example.org", "idb-s1", "obj-s1"],
|
||||
[6, 7]],
|
||||
[["indexedDB", "https://sectest1.example.org", "idb-s2", "obj-s2"],
|
||||
[16]],
|
||||
];
|
||||
|
||||
/**
|
||||
* Test that the desired number of tree items are present
|
||||
*/
|
||||
function testTree() {
|
||||
let doc = gPanelWindow.document;
|
||||
for (let item of storeItems) {
|
||||
ok(doc.querySelector("[data-id='" + JSON.stringify(item[0]) + "']"),
|
||||
"Tree item " + item[0] + " should be present in the storage tree");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that correct table entries are shown for each of the tree item
|
||||
*/
|
||||
let testTables = Task.async(function*() {
|
||||
let doc = gPanelWindow.document;
|
||||
// Expand all nodes so that the synthesized click event actually works
|
||||
gUI.tree.expandAll();
|
||||
|
||||
// First tree item is already selected so no clicking and waiting for update
|
||||
for (let id of storeItems[0][1]) {
|
||||
ok(doc.querySelector(".table-widget-cell[data-id='" + id + "']"),
|
||||
"Table item " + id + " should be present");
|
||||
}
|
||||
|
||||
// Click rest of the tree items and wait for the table to be updated
|
||||
for (let item of storeItems.slice(1)) {
|
||||
selectTreeItem(item[0]);
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
// Check whether correct number of items are present in the table
|
||||
is(doc.querySelectorAll(
|
||||
".table-widget-wrapper:first-of-type .table-widget-cell"
|
||||
).length, item[1].length, "Number of items in table is correct");
|
||||
|
||||
// Check if all the desired items are present in the table
|
||||
for (let id of item[1]) {
|
||||
ok(doc.querySelector(".table-widget-cell[data-id='" + id + "']"),
|
||||
"Table item " + id + " should be present");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let startTest = Task.async(function*() {
|
||||
testTree();
|
||||
yield testTables();
|
||||
finishTests();
|
||||
});
|
||||
|
||||
function test() {
|
||||
openTabAndSetupStorage(MAIN_DOMAIN + "storage-listings.html").then(startTest);
|
||||
}
|
|
@ -0,0 +1,211 @@
|
|||
/* 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/. */
|
||||
|
||||
let testUpdates = Task.async(function*() {
|
||||
|
||||
let $ = id => gPanelWindow.document.querySelector(id);
|
||||
let $$ = sel => gPanelWindow.document.querySelectorAll(sel);
|
||||
|
||||
gUI.tree.expandAll();
|
||||
|
||||
ok(gUI.sidebar.hidden, "Sidebar is initially hidden");
|
||||
selectTableItem("c1");
|
||||
yield gUI.once("sidebar-updated");
|
||||
|
||||
// test that value is something initially
|
||||
let initialValue = [[
|
||||
{name: "c1", value: "1.2.3.4.5.6.7"},
|
||||
{name: "c1.path", value: "/browser"}
|
||||
],[
|
||||
{name: "c1", value: "Array"},
|
||||
{name: "c1.0", value: "1"},
|
||||
{name: "c1.6", value: "7"}
|
||||
]];
|
||||
|
||||
// test that value is something initially
|
||||
let finalValue = [[
|
||||
{name: "c1", value: '{"foo": 4,"bar":6}'},
|
||||
{name: "c1.path", value: "/browser"}
|
||||
],[
|
||||
{name: "c1", value: "Object"},
|
||||
{name: "c1.foo", value: "4"},
|
||||
{name: "c1.bar", value: "6"}
|
||||
]];
|
||||
// Check that sidebar shows correct initial value
|
||||
yield findVariableViewProperties(initialValue[0], false);
|
||||
yield findVariableViewProperties(initialValue[1], true);
|
||||
// Check if table shows correct initial value
|
||||
ok($("#value [data-id='c1'].table-widget-cell"), "cell is present");
|
||||
is($("#value [data-id='c1'].table-widget-cell").value, "1.2.3.4.5.6.7",
|
||||
"correct initial value in table");
|
||||
gWindow.addCookie("c1", '{"foo": 4,"bar":6}', "/browser");
|
||||
yield gUI.once("sidebar-updated");
|
||||
|
||||
yield findVariableViewProperties(finalValue[0], false);
|
||||
yield findVariableViewProperties(finalValue[1], true);
|
||||
ok($("#value [data-id='c1'].table-widget-cell"), "cell is present after update");
|
||||
is($("#value [data-id='c1'].table-widget-cell").value, '{"foo": 4,"bar":6}',
|
||||
"correct final value in table");
|
||||
|
||||
// Add a new entry
|
||||
is($$("#value .table-widget-cell").length, 2,
|
||||
"Correct number of rows before update 0");
|
||||
|
||||
gWindow.addCookie("c3", "booyeah");
|
||||
|
||||
// Wait once for update and another time for value fetching
|
||||
yield gUI.once("store-objects-updated");
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
is($$("#value .table-widget-cell").length, 3,
|
||||
"Correct number of rows after update 1");
|
||||
|
||||
// Add another
|
||||
gWindow.addCookie("c4", "booyeah");
|
||||
|
||||
// Wait once for update and another time for value fetching
|
||||
yield gUI.once("store-objects-updated");
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
is($$("#value .table-widget-cell").length, 4,
|
||||
"Correct number of rows after update 2");
|
||||
|
||||
// Removing cookies
|
||||
gWindow.removeCookie("c1", "/browser");
|
||||
|
||||
yield gUI.once("sidebar-updated");
|
||||
|
||||
is($$("#value .table-widget-cell").length, 3,
|
||||
"Correct number of rows after delete update 3");
|
||||
|
||||
ok(!$("#c1"), "Correct row got deleted");
|
||||
|
||||
ok(!gUI.sidebar.hidden, "Sidebar still visible for next row");
|
||||
|
||||
// Check if next element's value is visible in sidebar
|
||||
yield findVariableViewProperties([{name: "c2", value: "foobar"}]);
|
||||
|
||||
// Keep deleting till no rows
|
||||
|
||||
gWindow.removeCookie("c3");
|
||||
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
is($$("#value .table-widget-cell").length, 2,
|
||||
"Correct number of rows after delete update 4");
|
||||
|
||||
// Check if next element's value is visible in sidebar
|
||||
yield findVariableViewProperties([{name: "c2", value: "foobar"}]);
|
||||
|
||||
gWindow.removeCookie("c2", "/browser");
|
||||
|
||||
yield gUI.once("sidebar-updated");
|
||||
|
||||
yield findVariableViewProperties([{name: "c4", value: "booyeah"}]);
|
||||
|
||||
is($$("#value .table-widget-cell").length, 1,
|
||||
"Correct number of rows after delete update 5");
|
||||
|
||||
gWindow.removeCookie("c4");
|
||||
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
is($$("#value .table-widget-cell").length, 0,
|
||||
"Correct number of rows after delete update 6");
|
||||
ok(gUI.sidebar.hidden, "Sidebar is hidden when no rows");
|
||||
|
||||
// Testing in local storage
|
||||
selectTreeItem(["localStorage", "http://test1.example.org"]);
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
is($$("#value .table-widget-cell").length, 7,
|
||||
"Correct number of rows after delete update 7");
|
||||
|
||||
ok($(".table-widget-cell[data-id='ls4']"), "ls4 exists before deleting");
|
||||
|
||||
gWindow.localStorage.removeItem("ls4");
|
||||
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
is($$("#value .table-widget-cell").length, 6,
|
||||
"Correct number of rows after delete update 8");
|
||||
ok(!$(".table-widget-cell[data-id='ls4']"),
|
||||
"ls4 does not exists after deleting");
|
||||
|
||||
gWindow.localStorage.setItem("ls4", "again");
|
||||
|
||||
yield gUI.once("store-objects-updated");
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
is($$("#value .table-widget-cell").length, 7,
|
||||
"Correct number of rows after delete update 9");
|
||||
ok($(".table-widget-cell[data-id='ls4']"),
|
||||
"ls4 came back after adding it again");
|
||||
|
||||
// Updating a row
|
||||
gWindow.localStorage.setItem("ls2", "ls2-changed");
|
||||
|
||||
yield gUI.once("store-objects-updated");
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
is($("#value [data-id='ls2']").value, "ls2-changed",
|
||||
"Value got updated for local storage");
|
||||
|
||||
// Testing in session storage
|
||||
selectTreeItem(["sessionStorage", "http://test1.example.org"]);
|
||||
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
is($$("#value .table-widget-cell").length, 3,
|
||||
"Correct number of rows for session storage");
|
||||
|
||||
gWindow.sessionStorage.setItem("ss4", "new-item");
|
||||
|
||||
yield gUI.once("store-objects-updated");
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
is($$("#value .table-widget-cell").length, 4,
|
||||
"Correct number of rows after session storage update");
|
||||
|
||||
// deleting item
|
||||
|
||||
gWindow.sessionStorage.removeItem("ss3");
|
||||
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
gWindow.sessionStorage.removeItem("ss1");
|
||||
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
is($$("#value .table-widget-cell").length, 2,
|
||||
"Correct number of rows after removing items from session storage");
|
||||
|
||||
selectTableItem("ss2");
|
||||
|
||||
yield gUI.once("sidebar-updated");
|
||||
|
||||
ok(!gUI.sidebar.hidden, "sidebar is visible");
|
||||
|
||||
// Checking for correct value in sidebar before update
|
||||
yield findVariableViewProperties([{name: "ss2", value: "foobar"}]);
|
||||
|
||||
gWindow.sessionStorage.setItem("ss2", "changed=ss2");
|
||||
|
||||
yield gUI.once("sidebar-updated");
|
||||
|
||||
is($("#value [data-id='ss2']").value, "changed=ss2",
|
||||
"Value got updated for session storage in the table");
|
||||
|
||||
yield findVariableViewProperties([{name: "ss2", value: "changed=ss2"}]);
|
||||
|
||||
});
|
||||
|
||||
let startTest = Task.async(function*() {
|
||||
yield testUpdates();
|
||||
finishTests();
|
||||
});
|
||||
|
||||
function test() {
|
||||
openTabAndSetupStorage(MAIN_DOMAIN + "storage-updates.html").then(startTest);
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/* 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/. */
|
||||
|
||||
// Test to verify that the sidebar opens, closes and updates
|
||||
// This test is not testing the values in the sidebar, being tested in _values
|
||||
|
||||
// Format: [
|
||||
// <id of the table item to click> or <id array for tree item to select> or
|
||||
// null to press Escape,
|
||||
// <do we wait for the async "sidebar-updated" event>,
|
||||
// <is the sidebar open>
|
||||
// ]
|
||||
const testCases = [
|
||||
[["cookies", "sectest1.example.org"], 0, 0],
|
||||
["cs2", 1, 1],
|
||||
[null, 0, 0],
|
||||
["cs2", 1, 1],
|
||||
["uc1", 1, 1],
|
||||
["uc1", 0, 1],
|
||||
[["localStorage", "http://sectest1.example.org"], 0, 0],
|
||||
["iframe-u-ls1", 1, 1],
|
||||
["iframe-u-ls1", 0, 1],
|
||||
[null, 0, 0],
|
||||
[["sessionStorage", "http://test1.example.org"], 0, 0],
|
||||
["ss1", 1, 1],
|
||||
[null, 0, 0],
|
||||
[["indexedDB", "http://test1.example.org"], 0, 0],
|
||||
["idb2", 1, 1],
|
||||
[["indexedDB", "http://test1.example.org", "idb2", "obj3"], 0, 0],
|
||||
[["indexedDB", "https://sectest1.example.org", "idb-s2"], 0, 0],
|
||||
["obj-s2", 1, 1],
|
||||
[null, 0, 0],
|
||||
[null, 0, 0],
|
||||
["obj-s2", 1, 1],
|
||||
[null, 0, 0],
|
||||
];
|
||||
|
||||
let testSidebar = Task.async(function*() {
|
||||
let doc = gPanelWindow.document;
|
||||
for (let item of testCases) {
|
||||
info("clicking for item " + item);
|
||||
if (Array.isArray(item[0])) {
|
||||
selectTreeItem(item[0]);
|
||||
yield gUI.once("store-objects-updated");
|
||||
}
|
||||
else if (item[0]) {
|
||||
selectTableItem(item[0]);
|
||||
}
|
||||
else {
|
||||
EventUtils.sendKey("ESCAPE", gPanelWindow);
|
||||
}
|
||||
if (item[1]) {
|
||||
yield gUI.once("sidebar-updated");
|
||||
}
|
||||
is(!item[2], gUI.sidebar.hidden, "Correct visibility state of sidebar");
|
||||
}
|
||||
});
|
||||
|
||||
let startTest = Task.async(function*() {
|
||||
yield testSidebar();
|
||||
finishTests();
|
||||
});
|
||||
|
||||
function test() {
|
||||
openTabAndSetupStorage(MAIN_DOMAIN + "storage-listings.html").then(startTest);
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
/* 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/. */
|
||||
|
||||
// Test to verify that the values shown in sidebar are correct
|
||||
|
||||
// Format: [
|
||||
// <id of the table item to click> or <id array for tree item to select> or
|
||||
// null do click nothing,
|
||||
// null to skip checking value in variables view or a key value pair object
|
||||
// which will be asserted to exist in the storage sidebar,
|
||||
// true if the check is to be made in the parsed value section
|
||||
// ]
|
||||
const testCases = [
|
||||
["cs2", [
|
||||
{name: "cs2", value: "sessionCookie"},
|
||||
{name: "cs2.path", value: "/"},
|
||||
{name: "cs2.isDomain", value: "true"},
|
||||
{name: "cs2.isHttpOnly", value: "false"},
|
||||
{name: "cs2.host", value: ".example.org"},
|
||||
{name: "cs2.expires", value: "Session"},
|
||||
{name: "cs2.isSecure", value: "false"},
|
||||
]],
|
||||
["c1", [
|
||||
{name: "c1", value: JSON.stringify(["foo", "Bar", {foo: "Bar"}])},
|
||||
{name: "c1.path", value: "/browser"},
|
||||
{name: "c1.isDomain", value: "false"},
|
||||
{name: "c1.isHttpOnly", value: "false"},
|
||||
{name: "c1.host", value: "test1.example.org"},
|
||||
{name: "c1.expires", value: new Date(2000000000000).toLocaleString()},
|
||||
{name: "c1.isSecure", value: "false"},
|
||||
]],
|
||||
[/*"c1"*/, [
|
||||
{name: "c1", value: "Array"},
|
||||
{name: "c1.0", value: "foo"},
|
||||
{name: "c1.1", value: "Bar"},
|
||||
{name: "c1.2", value: "Object"},
|
||||
{name: "c1.2.foo", value: "Bar"},
|
||||
], true],
|
||||
[["localStorage", "http://test1.example.org"]],
|
||||
["ls2", [
|
||||
{name: "ls2", value: "foobar-2"}
|
||||
]],
|
||||
["ls1", [
|
||||
{name: "ls1", value: JSON.stringify({
|
||||
es6: "for", the: "win", baz: [0, 2, 3, {
|
||||
deep: "down",
|
||||
nobody: "cares"
|
||||
}]})}
|
||||
]],
|
||||
[/*ls1*/, [
|
||||
{name: "ls1", value: "Object"},
|
||||
{name: "ls1.es6", value: "for"},
|
||||
{name: "ls1.the", value: "win"},
|
||||
{name: "ls1.baz", value: "Array"},
|
||||
{name: "ls1.baz.0", value: "0"},
|
||||
{name: "ls1.baz.1", value: "2"},
|
||||
{name: "ls1.baz.2", value: "3"},
|
||||
{name: "ls1.baz.3", value: "Object"},
|
||||
{name: "ls1.baz.3.deep", value: "down"},
|
||||
{name: "ls1.baz.3.nobody", value: "cares"},
|
||||
], true],
|
||||
["ls3", [
|
||||
{name: "ls3", "value": "http://foobar.com/baz.php"}
|
||||
]],
|
||||
[/*ls3*/, [
|
||||
{name: "ls3", "value": "http://foobar.com/baz.php", dontMatch: true}
|
||||
], true],
|
||||
[["sessionStorage", "http://test1.example.org"]],
|
||||
["ss1", [
|
||||
{name: "ss1", value: "This#is#an#array"}
|
||||
]],
|
||||
[/*ss1*/, [
|
||||
{name: "ss1", value: "Array"},
|
||||
{name: "ss1.0", value: "This"},
|
||||
{name: "ss1.1", value: "is"},
|
||||
{name: "ss1.2", value: "an"},
|
||||
{name: "ss1.3", value: "array"},
|
||||
], true],
|
||||
["ss2", [
|
||||
{name: "ss2", value: "Array"},
|
||||
{name: "ss2.0", value: "This"},
|
||||
{name: "ss2.1", value: "is"},
|
||||
{name: "ss2.2", value: "another"},
|
||||
{name: "ss2.3", value: "array"},
|
||||
], true],
|
||||
["ss3", [
|
||||
{name: "ss3", value: "Object"},
|
||||
{name: "ss3.this", value: "is"},
|
||||
{name: "ss3.an", value: "object"},
|
||||
{name: "ss3.foo", value: "bar"},
|
||||
], true],
|
||||
[["indexedDB", "http://test1.example.org", "idb1", "obj1"]],
|
||||
[1, [
|
||||
{name: 1, value: JSON.stringify({id: 1, name: "foo", email: "foo@bar.com"})}
|
||||
]],
|
||||
[/*1*/, [
|
||||
{name: "1.id", value: "1"},
|
||||
{name: "1.name", value: "foo"},
|
||||
{name: "1.email", value: "foo@bar.com"},
|
||||
], true],
|
||||
[["indexedDB", "http://test1.example.org", "idb1", "obj2"]],
|
||||
[1, [
|
||||
{name: 1, value: JSON.stringify({
|
||||
id2: 1, name: "foo", email: "foo@bar.com", extra: "baz"
|
||||
})}
|
||||
]],
|
||||
[/*1*/, [
|
||||
{name: "1.id2", value: "1"},
|
||||
{name: "1.name", value: "foo"},
|
||||
{name: "1.email", value: "foo@bar.com"},
|
||||
{name: "1.extra", value: "baz"},
|
||||
], true]
|
||||
];
|
||||
|
||||
let testValues = Task.async(function*() {
|
||||
gUI.tree.expandAll();
|
||||
let doc = gPanelWindow.document;
|
||||
for (let item of testCases) {
|
||||
info("clicking for item " + item);
|
||||
if (Array.isArray(item[0])) {
|
||||
selectTreeItem(item[0]);
|
||||
yield gUI.once("store-objects-updated");
|
||||
continue;
|
||||
}
|
||||
else if (item[0]) {
|
||||
selectTableItem(item[0]);
|
||||
}
|
||||
if (item[0] && item[1]) {
|
||||
yield gUI.once("sidebar-updated");
|
||||
}
|
||||
yield findVariableViewProperties(item[1], item[2]);
|
||||
}
|
||||
});
|
||||
|
||||
let startTest = Task.async(function*() {
|
||||
yield testValues();
|
||||
finishTests();
|
||||
});
|
||||
|
||||
function test() {
|
||||
openTabAndSetupStorage(MAIN_DOMAIN + "storage-complex-values.html").then(startTest);
|
||||
}
|
|
@ -0,0 +1,499 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
let tempScope = {};
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm", tempScope);
|
||||
Cu.import("resource://gre/modules/devtools/Console.jsm", tempScope);
|
||||
const console = tempScope.console;
|
||||
const devtools = tempScope.devtools;
|
||||
tempScope = null;
|
||||
const require = devtools.require;
|
||||
const TargetFactory = devtools.TargetFactory;
|
||||
|
||||
const SPLIT_CONSOLE_PREF = "devtools.toolbox.splitconsoleEnabled";
|
||||
const STORAGE_PREF = "devtools.storage.enabled";
|
||||
const PATH = "browser/browser/devtools/storage/test/";
|
||||
const MAIN_DOMAIN = "http://test1.example.org/" + PATH;
|
||||
const ALT_DOMAIN = "http://sectest1.example.org/" + PATH;
|
||||
const ALT_DOMAIN_SECURED = "https://sectest1.example.org:443/" + PATH;
|
||||
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
let gToolbox, gPanelWindow, gWindow, gUI;
|
||||
|
||||
Services.prefs.setBoolPref(STORAGE_PREF, true);
|
||||
gDevTools.testing = true;
|
||||
registerCleanupFunction(() => {
|
||||
gToolbox = gPanelWindow = gWindow = gUI = null;
|
||||
Services.prefs.clearUserPref(STORAGE_PREF);
|
||||
Services.prefs.clearUserPref(SPLIT_CONSOLE_PREF);
|
||||
gDevTools.testing = false;
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Add a new test tab in the browser and load the given url.
|
||||
*
|
||||
* @param {String} url The url to be loaded in the new tab
|
||||
*
|
||||
* @return a promise that resolves to the content window when the url is loaded
|
||||
*/
|
||||
function addTab(url) {
|
||||
info("Adding a new tab with URL: '" + url + "'");
|
||||
let def = promise.defer();
|
||||
|
||||
// Bug 921935 should bring waitForFocus() support to e10s, which would
|
||||
// probably cover the case of the test losing focus when the page is loading.
|
||||
// For now, we just make sure the window is focused.
|
||||
window.focus();
|
||||
|
||||
let tab = window.gBrowser.selectedTab = window.gBrowser.addTab(url);
|
||||
let linkedBrowser = tab.linkedBrowser;
|
||||
|
||||
linkedBrowser.addEventListener("load", function onload(event) {
|
||||
if (event.originalTarget.location.href != url) {
|
||||
return;
|
||||
}
|
||||
linkedBrowser.removeEventListener("load", onload, true);
|
||||
info("URL '" + url + "' loading complete");
|
||||
def.resolve(tab.linkedBrowser.contentWindow);
|
||||
}, true);
|
||||
|
||||
return def.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the given url in a new tab, then sets up the page by waiting for
|
||||
* all cookies, indexedDB items etc. to be created; Then opens the storage
|
||||
* inspector and waits for the storage tree and table to be populated
|
||||
*
|
||||
* @param url {String} The url to be opened in the new tab
|
||||
*
|
||||
* @return {Promise} A promise that resolves after storage inspector is ready
|
||||
*/
|
||||
let openTabAndSetupStorage = Task.async(function*(url) {
|
||||
/**
|
||||
* This method iterates over iframes in a window and setups the indexed db
|
||||
* required for this test.
|
||||
*/
|
||||
let setupIDBInFrames = (w, i, c) => {
|
||||
if (w[i] && w[i].idbGenerator) {
|
||||
w[i].setupIDB = w[i].idbGenerator(() => setupIDBInFrames(w, i + 1, c));
|
||||
w[i].setupIDB.next();
|
||||
}
|
||||
else if (w[i] && w[i + 1]) {
|
||||
setupIDBInFrames(w, i + 1, c);
|
||||
}
|
||||
else {
|
||||
c();
|
||||
}
|
||||
};
|
||||
|
||||
let content = yield addTab(url);
|
||||
|
||||
let def = promise.defer();
|
||||
// Setup the indexed db in main window.
|
||||
gWindow = content.wrappedJSObject;
|
||||
if (gWindow.idbGenerator) {
|
||||
gWindow.setupIDB = gWindow.idbGenerator(() => {
|
||||
setupIDBInFrames(gWindow, 0, () => {
|
||||
def.resolve();
|
||||
});
|
||||
});
|
||||
gWindow.setupIDB.next();
|
||||
yield def.promise;
|
||||
}
|
||||
|
||||
// open storage inspector
|
||||
return yield openStoragePanel();
|
||||
});
|
||||
|
||||
/**
|
||||
* Open the toolbox, with the storage tool visible.
|
||||
*
|
||||
* @param cb {Function} Optional callback, if you don't want to use the returned
|
||||
* promise
|
||||
*
|
||||
* @return {Promise} a promise that resolves when the storage inspector is ready
|
||||
*/
|
||||
let openStoragePanel = Task.async(function*(cb) {
|
||||
info("Opening the storage inspector");
|
||||
let target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
|
||||
let storage, toolbox;
|
||||
|
||||
// Checking if the toolbox and the storage are already loaded
|
||||
// The storage-updated event should only be waited for if the storage
|
||||
// isn't loaded yet
|
||||
toolbox = gDevTools.getToolbox(target);
|
||||
if (toolbox) {
|
||||
storage = toolbox.getPanel("storage");
|
||||
if (storage) {
|
||||
gPanelWindow = storage.panelWindow;
|
||||
gUI = storage.UI;
|
||||
gToolbox = toolbox;
|
||||
info("Toolbox and storage already open");
|
||||
if (cb) {
|
||||
return cb(storage, toolbox);
|
||||
} else {
|
||||
return {
|
||||
toolbox: toolbox,
|
||||
storage: storage
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
info("Opening the toolbox");
|
||||
toolbox = yield gDevTools.showToolbox(target, "storage");
|
||||
storage = toolbox.getPanel("storage");
|
||||
gPanelWindow = storage.panelWindow;
|
||||
gUI = storage.UI;
|
||||
gToolbox = toolbox;
|
||||
|
||||
info("Waiting for the stores to update");
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
yield waitForToolboxFrameFocus(toolbox);
|
||||
|
||||
if (cb) {
|
||||
return cb(storage, toolbox);
|
||||
} else {
|
||||
return {
|
||||
toolbox: toolbox,
|
||||
storage: storage
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Wait for the toolbox frame to receive focus after it loads
|
||||
*
|
||||
* @param toolbox {Toolbox}
|
||||
*
|
||||
* @return a promise that resolves when focus has been received
|
||||
*/
|
||||
function waitForToolboxFrameFocus(toolbox) {
|
||||
info("Making sure that the toolbox's frame is focused");
|
||||
let def = promise.defer();
|
||||
let win = toolbox.frame.contentWindow;
|
||||
waitForFocus(def.resolve, win);
|
||||
return def.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces GC, CC and Shrinking GC to get rid of disconnected docshells and
|
||||
* windows.
|
||||
*/
|
||||
function forceCollections() {
|
||||
Cu.forceGC();
|
||||
Cu.forceCC();
|
||||
Cu.forceShrinkingGC();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up and finishes the test
|
||||
*/
|
||||
function finishTests() {
|
||||
// Cleanup so that indexed db created from this test do not interfere next ones
|
||||
|
||||
/**
|
||||
* This method iterates over iframes in a window and clears the indexed db
|
||||
* created by this test.
|
||||
*/
|
||||
let clearIDB = (w, i, c) => {
|
||||
if (w[i] && w[i].clear) {
|
||||
w[i].clearIterator = w[i].clear(() => clearIDB(w, i + 1, c));
|
||||
w[i].clearIterator.next();
|
||||
}
|
||||
else if (w[i] && w[i + 1]) {
|
||||
clearIDB(w, i + 1, c);
|
||||
}
|
||||
else {
|
||||
c();
|
||||
}
|
||||
};
|
||||
|
||||
gWindow.clearIterator = gWindow.clear(() => {
|
||||
clearIDB(gWindow, 0, () => {
|
||||
// Forcing GC/CC to get rid of docshells and windows created by this test.
|
||||
forceCollections();
|
||||
finish();
|
||||
});
|
||||
});
|
||||
gWindow.clearIterator.next();
|
||||
}
|
||||
|
||||
// Sends a click event on the passed DOM node in an async manner
|
||||
function click(node) {
|
||||
node.scrollIntoView()
|
||||
executeSoon(() => EventUtils.synthesizeMouseAtCenter(node, {}, gPanelWindow));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Recursively expand the variables view up to a given property.
|
||||
*
|
||||
* @param aOptions
|
||||
* Options for view expansion:
|
||||
* - rootVariable: start from the given scope/variable/property.
|
||||
* - expandTo: string made up of property names you want to expand.
|
||||
* For example: "body.firstChild.nextSibling" given |rootVariable:
|
||||
* document|.
|
||||
* @return object
|
||||
* A promise that is resolved only when the last property in |expandTo|
|
||||
* is found, and rejected otherwise. Resolution reason is always the
|
||||
* last property - |nextSibling| in the example above. Rejection is
|
||||
* always the last property that was found.
|
||||
*/
|
||||
function variablesViewExpandTo(aOptions) {
|
||||
let root = aOptions.rootVariable;
|
||||
let expandTo = aOptions.expandTo.split(".");
|
||||
let lastDeferred = promise.defer();
|
||||
|
||||
function getNext(aProp) {
|
||||
let name = expandTo.shift();
|
||||
let newProp = aProp.get(name);
|
||||
|
||||
if (expandTo.length > 0) {
|
||||
ok(newProp, "found property " + name);
|
||||
if (newProp && newProp.expand) {
|
||||
newProp.expand();
|
||||
getNext(newProp);
|
||||
}
|
||||
else {
|
||||
lastDeferred.reject(aProp);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (newProp) {
|
||||
lastDeferred.resolve(newProp);
|
||||
}
|
||||
else {
|
||||
lastDeferred.reject(aProp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function fetchError(aProp) {
|
||||
lastDeferred.reject(aProp);
|
||||
}
|
||||
|
||||
if (root && root.expand) {
|
||||
root.expand();
|
||||
getNext(root);
|
||||
}
|
||||
else {
|
||||
lastDeferred.resolve(root)
|
||||
}
|
||||
|
||||
return lastDeferred.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find variables or properties in a VariablesView instance.
|
||||
*
|
||||
* @param array aRules
|
||||
* The array of rules you want to match. Each rule is an object with:
|
||||
* - name (string|regexp): property name to match.
|
||||
* - value (string|regexp): property value to match.
|
||||
* - dontMatch (boolean): make sure the rule doesn't match any property.
|
||||
* @param boolean aParsed
|
||||
* true if we want to test the rules in the parse value section of the
|
||||
* storage sidebar
|
||||
* @return object
|
||||
* A promise object that is resolved when all the rules complete
|
||||
* matching. The resolved callback is given an array of all the rules
|
||||
* you wanted to check. Each rule has a new property: |matchedProp|
|
||||
* which holds a reference to the Property object instance from the
|
||||
* VariablesView. If the rule did not match, then |matchedProp| is
|
||||
* undefined.
|
||||
*/
|
||||
function findVariableViewProperties(aRules, aParsed) {
|
||||
// Initialize the search.
|
||||
function init() {
|
||||
// If aParsed is true, we are checking rules in the parsed value section of
|
||||
// the storage sidebar. That scope uses a blank variable as a placeholder
|
||||
// Thus, adding a blank parent to each name
|
||||
if (aParsed) {
|
||||
aRules = aRules.map(({name, value, dontMatch}) => {
|
||||
return {name: "." + name, value, dontMatch}
|
||||
});
|
||||
}
|
||||
// Separate out the rules that require expanding properties throughout the
|
||||
// view.
|
||||
let expandRules = [];
|
||||
let rules = aRules.filter((aRule) => {
|
||||
if (typeof aRule.name == "string" && aRule.name.indexOf(".") > -1) {
|
||||
expandRules.push(aRule);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
// Search through the view those rules that do not require any properties to
|
||||
// be expanded. Build the array of matchers, outstanding promises to be
|
||||
// resolved.
|
||||
let outstanding = [];
|
||||
|
||||
finder(rules, gUI.view, outstanding);
|
||||
|
||||
// Process the rules that need to expand properties.
|
||||
let lastStep = processExpandRules.bind(null, expandRules);
|
||||
|
||||
// Return the results - a promise resolved to hold the updated aRules array.
|
||||
let returnResults = onAllRulesMatched.bind(null, aRules);
|
||||
|
||||
return promise.all(outstanding).then(lastStep).then(returnResults);
|
||||
}
|
||||
|
||||
function onMatch(aProp, aRule, aMatched) {
|
||||
if (aMatched && !aRule.matchedProp) {
|
||||
aRule.matchedProp = aProp;
|
||||
}
|
||||
}
|
||||
|
||||
function finder(aRules, aView, aPromises) {
|
||||
for (let scope of aView) {
|
||||
for (let [id, prop] of scope) {
|
||||
for (let rule of aRules) {
|
||||
let matcher = matchVariablesViewProperty(prop, rule);
|
||||
aPromises.push(matcher.then(onMatch.bind(null, prop, rule)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function processExpandRules(aRules) {
|
||||
let rule = aRules.shift();
|
||||
if (!rule) {
|
||||
return promise.resolve(null);
|
||||
}
|
||||
|
||||
let deferred = promise.defer();
|
||||
let expandOptions = {
|
||||
rootVariable: gUI.view.getScopeAtIndex(aParsed ? 1: 0),
|
||||
expandTo: rule.name
|
||||
};
|
||||
|
||||
variablesViewExpandTo(expandOptions).then(function onSuccess(aProp) {
|
||||
let name = rule.name;
|
||||
let lastName = name.split(".").pop();
|
||||
rule.name = lastName;
|
||||
|
||||
let matched = matchVariablesViewProperty(aProp, rule);
|
||||
return matched.then(onMatch.bind(null, aProp, rule)).then(function() {
|
||||
rule.name = name;
|
||||
});
|
||||
}, function onFailure() {
|
||||
return promise.resolve(null);
|
||||
}).then(processExpandRules.bind(null, aRules)).then(function() {
|
||||
deferred.resolve(null);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function onAllRulesMatched(aRules) {
|
||||
for (let rule of aRules) {
|
||||
let matched = rule.matchedProp;
|
||||
if (matched && !rule.dontMatch) {
|
||||
ok(true, "rule " + rule.name + " matched for property " + matched.name);
|
||||
}
|
||||
else if (matched && rule.dontMatch) {
|
||||
ok(false, "rule " + rule.name + " should not match property " +
|
||||
matched.name);
|
||||
}
|
||||
else {
|
||||
ok(rule.dontMatch, "rule " + rule.name + " did not match any property");
|
||||
}
|
||||
}
|
||||
return aRules;
|
||||
}
|
||||
|
||||
return init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given Property object from the variables view matches the given
|
||||
* rule.
|
||||
*
|
||||
* @param object aProp
|
||||
* The variable's view Property instance.
|
||||
* @param object aRule
|
||||
* Rules for matching the property. See findVariableViewProperties() for
|
||||
* details.
|
||||
* @return object
|
||||
* A promise that is resolved when all the checks complete. Resolution
|
||||
* result is a boolean that tells your promise callback the match
|
||||
* result: true or false.
|
||||
*/
|
||||
function matchVariablesViewProperty(aProp, aRule) {
|
||||
function resolve(aResult) {
|
||||
return promise.resolve(aResult);
|
||||
}
|
||||
|
||||
if (!aProp) {
|
||||
return resolve(false);
|
||||
}
|
||||
|
||||
if (aRule.name) {
|
||||
let match = aRule.name instanceof RegExp ?
|
||||
aRule.name.test(aProp.name) :
|
||||
aProp.name == aRule.name;
|
||||
if (!match) {
|
||||
return resolve(false);
|
||||
}
|
||||
}
|
||||
|
||||
if ("value" in aRule) {
|
||||
let displayValue = aProp.displayValue;
|
||||
if (aProp.displayValueClassName == "token-string") {
|
||||
displayValue = displayValue.substring(1, displayValue.length - 1);
|
||||
}
|
||||
|
||||
let match = aRule.value instanceof RegExp ?
|
||||
aRule.value.test(displayValue) :
|
||||
displayValue == aRule.value;
|
||||
if (!match) {
|
||||
info("rule " + aRule.name + " did not match value, expected '" +
|
||||
aRule.value + "', found '" + displayValue + "'");
|
||||
return resolve(false);
|
||||
}
|
||||
}
|
||||
|
||||
return resolve(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Click selects a row in the table.
|
||||
*
|
||||
* @param {[String]} ids
|
||||
* The array id of the item in the tree
|
||||
*/
|
||||
function selectTreeItem(ids) {
|
||||
// Expand tree as some/all items could be collapsed leading to click on an
|
||||
// incorrect tree item
|
||||
gUI.tree.expandAll();
|
||||
click(gPanelWindow.document.querySelector("[data-id='" + JSON.stringify(ids) +
|
||||
"'] > .tree-widget-item"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Click selects a row in the table.
|
||||
*
|
||||
* @param {String} id
|
||||
* The id of the row in the table widget
|
||||
*/
|
||||
function selectTableItem(id) {
|
||||
click(gPanelWindow.document.querySelector(".table-widget-cell[data-id='" +
|
||||
id + "']"));
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['browser.ini']
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Bug 970517 - Storage inspector front end - tests
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Storage inspector test for correct values in the sidebar</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
let partialHostname = location.hostname.match(/^[^.]+(\..*)$/)[1];
|
||||
let cookieExpiresTime = 2000000000000;
|
||||
// Setting up some cookies to eat.
|
||||
document.cookie = "c1=" + JSON.stringify([
|
||||
"foo", "Bar", {
|
||||
foo: "Bar"
|
||||
}]) + "; expires=" + new Date(cookieExpiresTime).toGMTString() +
|
||||
"; path=/browser";
|
||||
document.cookie = "cs2=sessionCookie; path=/; domain=" + partialHostname;
|
||||
// ... and some local storage items ..
|
||||
var es6 = "for";
|
||||
localStorage.setItem("ls1", JSON.stringify({
|
||||
es6, the: "win", baz: [0, 2, 3, {
|
||||
deep: "down",
|
||||
nobody: "cares"
|
||||
}]}));
|
||||
localStorage.setItem("ls2", "foobar-2");
|
||||
localStorage.setItem("ls3", "http://foobar.com/baz.php");
|
||||
// ... and finally some session storage items too
|
||||
sessionStorage.setItem("ss1", "This#is#an#array");
|
||||
sessionStorage.setItem("ss2", "This~is~another~array");
|
||||
sessionStorage.setItem("ss3", "this#is~an#object~foo#bar");
|
||||
console.log("added cookies and stuff from main page");
|
||||
|
||||
function success(event) {
|
||||
setupIDB.next(event);
|
||||
}
|
||||
|
||||
window.idbGenerator = function*(callback) {
|
||||
let request = indexedDB.open("idb1", 1);
|
||||
request.onupgradeneeded = success;
|
||||
request.onerror = function(e) {
|
||||
throw new Error("error opening db connection");
|
||||
};
|
||||
let event = yield undefined;
|
||||
let db = event.target.result;
|
||||
let store1 = db.createObjectStore("obj1", { keyPath: "id" });
|
||||
store1.createIndex("name", "name", { unique: false });
|
||||
store1.createIndex("email", "email", { unique: true });
|
||||
let store2 = db.createObjectStore("obj2", { keyPath: "id2" });
|
||||
|
||||
store1.add({id: 1, name: "foo", email: "foo@bar.com"}).onsuccess = success;
|
||||
yield undefined;
|
||||
store1.add({id: 2, name: "foo2", email: "foo2@bar.com"}).onsuccess = success;
|
||||
yield undefined;
|
||||
store1.add({id: 3, name: "foo2", email: "foo3@bar.com"}).onsuccess = success;
|
||||
yield undefined;
|
||||
store2.add({id2: 1, name: "foo", email: "foo@bar.com", extra: "baz"}).onsuccess = success;
|
||||
yield undefined;
|
||||
|
||||
store1.transaction.oncomplete = success;
|
||||
yield undefined;
|
||||
db.close();
|
||||
|
||||
request = indexedDB.open("idb2", 1);
|
||||
request.onupgradeneeded = success;
|
||||
event = yield undefined;
|
||||
|
||||
let db2 = event.target.result;
|
||||
let store3 = db2.createObjectStore("obj3", { keyPath: "id3" });
|
||||
store3.createIndex("name2", "name2", { unique: true });
|
||||
store3.transaction.oncomplete = success;
|
||||
yield undefined;
|
||||
db2.close();
|
||||
console.log("added cookies and stuff from main page");
|
||||
callback();
|
||||
}
|
||||
|
||||
function successClear(event) {
|
||||
clearIterator.next(event);
|
||||
}
|
||||
|
||||
window.clear = function*(callback) {
|
||||
document.cookie = "c1=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/browser";
|
||||
document.cookie = "cs2=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
|
||||
localStorage.clear();
|
||||
sessionStorage.clear();
|
||||
indexedDB.deleteDatabase("idb1").onsuccess = successClear;
|
||||
yield undefined;
|
||||
indexedDB.deleteDatabase("idb2").onsuccess = successClear;
|
||||
yield undefined;
|
||||
console.log("removed cookies and stuff from main page");
|
||||
callback();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,94 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Bug 970517 - Storage inspector front end - tests
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Storage inspector test for listing hosts and storages</title>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="http://sectest1.example.org/browser/browser/devtools/storage/test/storage-unsecured-iframe.html"></iframe>
|
||||
<iframe src="https://sectest1.example.org:443/browser/browser/devtools/storage/test/storage-secured-iframe.html"></iframe>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
let partialHostname = location.hostname.match(/^[^.]+(\..*)$/)[1];
|
||||
let cookieExpiresTime1 = 2000000000000;
|
||||
let cookieExpiresTime2 = 2000000001000;
|
||||
// Setting up some cookies to eat.
|
||||
document.cookie = "c1=foobar; expires=" +
|
||||
new Date(cookieExpiresTime1).toGMTString() + "; path=/browser";
|
||||
document.cookie = "cs2=sessionCookie; path=/; domain=" + partialHostname;
|
||||
document.cookie = "c3=foobar-2; secure=true; expires=" +
|
||||
new Date(cookieExpiresTime2).toGMTString() + "; path=/";
|
||||
// ... and some local storage items ..
|
||||
localStorage.setItem("ls1", "foobar");
|
||||
localStorage.setItem("ls2", "foobar-2");
|
||||
// ... and finally some session storage items too
|
||||
sessionStorage.setItem("ss1", "foobar-3");
|
||||
console.log("added cookies and stuff from main page");
|
||||
|
||||
function success(event) {
|
||||
setupIDB.next(event);
|
||||
}
|
||||
|
||||
window.idbGenerator = function*(callback) {
|
||||
let request = indexedDB.open("idb1", 1);
|
||||
request.onupgradeneeded = success;
|
||||
request.onerror = function(e) {
|
||||
throw new Error("error opening db connection");
|
||||
};
|
||||
let event = yield undefined;
|
||||
let db = event.target.result;
|
||||
let store1 = db.createObjectStore("obj1", { keyPath: "id" });
|
||||
store1.createIndex("name", "name", { unique: false });
|
||||
store1.createIndex("email", "email", { unique: true });
|
||||
let store2 = db.createObjectStore("obj2", { keyPath: "id2" });
|
||||
|
||||
store1.add({id: 1, name: "foo", email: "foo@bar.com"}).onsuccess = success;
|
||||
yield undefined;
|
||||
store1.add({id: 2, name: "foo2", email: "foo2@bar.com"}).onsuccess = success;
|
||||
yield undefined;
|
||||
store1.add({id: 3, name: "foo2", email: "foo3@bar.com"}).onsuccess = success;
|
||||
yield undefined;
|
||||
store2.add({id2: 1, name: "foo", email: "foo@bar.com", extra: "baz"}).onsuccess = success;
|
||||
yield undefined;
|
||||
|
||||
store1.transaction.oncomplete = success;
|
||||
yield undefined;
|
||||
db.close();
|
||||
|
||||
request = indexedDB.open("idb2", 1);
|
||||
request.onupgradeneeded = success;
|
||||
event = yield undefined;
|
||||
|
||||
let db2 = event.target.result;
|
||||
let store3 = db2.createObjectStore("obj3", { keyPath: "id3" });
|
||||
store3.createIndex("name2", "name2", { unique: true });
|
||||
store3.transaction.oncomplete = success;
|
||||
yield undefined;
|
||||
db2.close();
|
||||
console.log("added cookies and stuff from main page");
|
||||
callback();
|
||||
}
|
||||
|
||||
function successClear(event) {
|
||||
clearIterator.next(event);
|
||||
}
|
||||
|
||||
window.clear = function*(callback) {
|
||||
document.cookie = "c1=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/browser";
|
||||
document.cookie = "c3=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; secure=true";
|
||||
document.cookie = "cs2=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=" + partialHostname;
|
||||
localStorage.clear();
|
||||
sessionStorage.clear();
|
||||
indexedDB.deleteDatabase("idb1").onsuccess = successClear;
|
||||
yield undefined;
|
||||
indexedDB.deleteDatabase("idb2").onsuccess = successClear;
|
||||
yield undefined;
|
||||
console.log("removed cookies and stuff from main page");
|
||||
callback();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,71 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Iframe for testing multiple host detetion in storage actor
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
document.cookie = "sc1=foobar;";
|
||||
localStorage.setItem("iframe-s-ls1", "foobar");
|
||||
sessionStorage.setItem("iframe-s-ss1", "foobar-2");
|
||||
|
||||
function success(event) {
|
||||
setupIDB.next(event);
|
||||
}
|
||||
|
||||
window.idbGenerator = function*(callback) {
|
||||
let request = indexedDB.open("idb-s1", 1);
|
||||
request.onupgradeneeded = success;
|
||||
request.onerror = function(e) {
|
||||
throw new Error("error opening db connection");
|
||||
};
|
||||
let event = yield undefined;
|
||||
let db = event.target.result;
|
||||
let store1 = db.createObjectStore("obj-s1", { keyPath: "id" });
|
||||
|
||||
store1.add({id: 6, name: "foo", email: "foo@bar.com"}).onsuccess = success;
|
||||
yield undefined;
|
||||
store1.add({id: 7, name: "foo2", email: "foo2@bar.com"}).onsuccess = success;
|
||||
yield undefined;
|
||||
store1.transaction.oncomplete = success;
|
||||
yield undefined;
|
||||
db.close();
|
||||
|
||||
request = indexedDB.open("idb-s2", 1);
|
||||
request.onupgradeneeded = success;
|
||||
event = yield undefined;
|
||||
|
||||
let db2 = event.target.result;
|
||||
let store3 = db2.createObjectStore("obj-s2", { keyPath: "id3", autoIncrement: true });
|
||||
store3.createIndex("name2", "name2", { unique: true });
|
||||
store3.add({id3: 16, name2: "foo", email: "foo@bar.com"}).onsuccess = success;
|
||||
yield undefined;
|
||||
store3.transaction.oncomplete = success;
|
||||
yield undefined;
|
||||
db2.close();
|
||||
console.log("added cookies and stuff from secured iframe");
|
||||
callback();
|
||||
}
|
||||
|
||||
function successClear(event) {
|
||||
clearIterator.next(event);
|
||||
}
|
||||
|
||||
window.clear = function*(callback) {
|
||||
document.cookie = "sc1=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
|
||||
localStorage.clear();
|
||||
sessionStorage.clear();
|
||||
indexedDB.deleteDatabase("idb-s1").onsuccess = successClear;
|
||||
yield undefined;
|
||||
indexedDB.deleteDatabase("idb-s2").onsuccess = successClear;
|
||||
yield undefined;
|
||||
console.log("removed cookies and stuff from secured iframe");
|
||||
callback();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Iframe for testing multiple host detetion in storage actor
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
document.cookie = "uc1=foobar; domain=.example.org; path=/; secure=true";
|
||||
localStorage.setItem("iframe-u-ls1", "foobar");
|
||||
sessionStorage.setItem("iframe-u-ss1", "foobar1");
|
||||
sessionStorage.setItem("iframe-u-ss2", "foobar2");
|
||||
console.log("added cookies and stuff from unsecured iframe");
|
||||
|
||||
window.clear = function*(callback) {
|
||||
document.cookie = "uc1=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=.example.org; secure=true";
|
||||
localStorage.clear();
|
||||
sessionStorage.clear();
|
||||
console.log("removed cookies and stuff from unsecured iframe");
|
||||
callback();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,63 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Bug 965872 - Storage inspector actor with cookies, local storage and session storage.
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Storage inspector blank html for tests</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
window.addCookie = function(name, value, path, domain, expires, secure) {
|
||||
var cookieString = name + "=" + value + ";";
|
||||
if (path) {
|
||||
cookieString += "path=" + path + ";";
|
||||
}
|
||||
if (domain) {
|
||||
cookieString += "domain=" + domain + ";";
|
||||
}
|
||||
if (expires) {
|
||||
cookieString += "expires=" + expires + ";";
|
||||
}
|
||||
if (secure) {
|
||||
cookieString += "secure=true;";
|
||||
}
|
||||
document.cookie = cookieString;
|
||||
};
|
||||
|
||||
window.removeCookie = function(name, path) {
|
||||
document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=" + path;
|
||||
}
|
||||
|
||||
window.clear = function*(callback) {
|
||||
var cookies = document.cookie;
|
||||
for (var cookie of cookies.split(";")) {
|
||||
removeCookie(cookie.split("=")[0]);
|
||||
removeCookie(cookie.split("=")[0], "/browser");
|
||||
}
|
||||
localStorage.clear();
|
||||
sessionStorage.clear();
|
||||
callback();
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
addCookie("c1", "1.2.3.4.5.6.7", "/browser");
|
||||
addCookie("c2", "foobar", "/browser");
|
||||
|
||||
localStorage.setItem("ls1", "testing");
|
||||
localStorage.setItem("ls2", "testing");
|
||||
localStorage.setItem("ls3", "testing");
|
||||
localStorage.setItem("ls4", "testing");
|
||||
localStorage.setItem("ls5", "testing");
|
||||
localStorage.setItem("ls6", "testing");
|
||||
localStorage.setItem("ls7", "testing");
|
||||
|
||||
sessionStorage.setItem("ss1", "foobar");
|
||||
sessionStorage.setItem("ss2", "foobar");
|
||||
sessionStorage.setItem("ss3", "foobar");
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,565 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {Cu} = require("chrome");
|
||||
const STORAGE_STRINGS = "chrome://browser/locale/devtools/storage.properties";
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
XPCOMUtils.defineLazyGetter(this, "TreeWidget",
|
||||
() => require("devtools/shared/widgets/TreeWidget").TreeWidget);
|
||||
XPCOMUtils.defineLazyGetter(this, "TableWidget",
|
||||
() => require("devtools/shared/widgets/TableWidget").TableWidget);
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "EventEmitter",
|
||||
"resource://gre/modules/devtools/event-emitter.js");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ViewHelpers",
|
||||
"resource:///modules/devtools/ViewHelpers.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "VariablesView",
|
||||
"resource:///modules/devtools/VariablesView.jsm");
|
||||
|
||||
/**
|
||||
* Localization convenience methods.
|
||||
*/
|
||||
let L10N = new ViewHelpers.L10N(STORAGE_STRINGS);
|
||||
|
||||
const GENERIC_VARIABLES_VIEW_SETTINGS = {
|
||||
lazyEmpty: true,
|
||||
lazyEmptyDelay: 10, // ms
|
||||
searchEnabled: true,
|
||||
searchPlaceholder: L10N.getStr("storage.search.placeholder"),
|
||||
preventDescriptorModifiers: true
|
||||
};
|
||||
|
||||
// Columns which are hidden by default in the storage table
|
||||
const HIDDEN_COLUMNS = [
|
||||
"creationTime",
|
||||
"isDomain",
|
||||
"isSecure"
|
||||
];
|
||||
|
||||
/**
|
||||
* StorageUI is controls and builds the UI of the Storage Inspector.
|
||||
*
|
||||
* @param {Front} front
|
||||
* Front for the storage actor
|
||||
* @param {Target} target
|
||||
* Interface for the page we're debugging
|
||||
* @param {Window} panelWin
|
||||
* Window of the toolbox panel to populate UI in.
|
||||
*/
|
||||
this.StorageUI = function StorageUI(front, target, panelWin) {
|
||||
EventEmitter.decorate(this);
|
||||
|
||||
this._target = target;
|
||||
this._window = panelWin;
|
||||
this._panelDoc = panelWin.document;
|
||||
this.front = front;
|
||||
|
||||
let treeNode = this._panelDoc.getElementById("storage-tree");
|
||||
this.tree = new TreeWidget(treeNode, {defaultType: "dir"});
|
||||
this.onHostSelect = this.onHostSelect.bind(this);
|
||||
this.tree.on("select", this.onHostSelect);
|
||||
|
||||
let tableNode = this._panelDoc.getElementById("storage-table");
|
||||
this.table = new TableWidget(tableNode, {
|
||||
emptyText: L10N.getStr("table.emptyText"),
|
||||
highlightUpdated: true,
|
||||
});
|
||||
this.displayObjectSidebar = this.displayObjectSidebar.bind(this);
|
||||
this.table.on(TableWidget.EVENTS.ROW_SELECTED, this.displayObjectSidebar)
|
||||
|
||||
this.sidebar = this._panelDoc.getElementById("storage-sidebar");
|
||||
this.sidebar.setAttribute("width", "300");
|
||||
this.view = new VariablesView(this.sidebar.firstChild,
|
||||
GENERIC_VARIABLES_VIEW_SETTINGS);
|
||||
|
||||
this.front.listStores().then(storageTypes => {
|
||||
this.populateStorageTree(storageTypes);
|
||||
});
|
||||
this.onUpdate = this.onUpdate.bind(this);
|
||||
this.front.on("stores-update", this.onUpdate);
|
||||
|
||||
this.handleKeypress = this.handleKeypress.bind(this);
|
||||
this._panelDoc.addEventListener("keypress", this.handleKeypress);
|
||||
}
|
||||
|
||||
exports.StorageUI = StorageUI;
|
||||
|
||||
StorageUI.prototype = {
|
||||
|
||||
storageTypes: null,
|
||||
shouldResetColumns: true,
|
||||
|
||||
destroy: function() {
|
||||
this.front.off("stores-update", this.onUpdate);
|
||||
this._panelDoc.removeEventListener("keypress", this.handleKeypress)
|
||||
},
|
||||
|
||||
/**
|
||||
* Empties and hides the object viewer sidebar
|
||||
*/
|
||||
hideSidebar: function() {
|
||||
this.view.empty();
|
||||
this.sidebar.hidden = true;
|
||||
this.table.clearSelection();
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes the given item from the storage table. Reselects the next item in
|
||||
* the table and repopulates the sidebar with that item's data if the item
|
||||
* being removed was selected.
|
||||
*/
|
||||
removeItemFromTable: function(name) {
|
||||
if (this.table.isSelected(name)) {
|
||||
if (this.table.selectedIndex == 0) {
|
||||
this.table.selectNextRow()
|
||||
}
|
||||
else {
|
||||
this.table.selectPreviousRow();
|
||||
}
|
||||
this.table.remove(name);
|
||||
this.displayObjectSidebar();
|
||||
}
|
||||
else {
|
||||
this.table.remove(name);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Event handler for "stores-update" event coming from the storage actor.
|
||||
*
|
||||
* @param {object} argument0
|
||||
* An object containing the details of the added, changed and deleted
|
||||
* storage objects.
|
||||
* Each of these 3 objects are of the following format:
|
||||
* {
|
||||
* <store_type1>: {
|
||||
* <host1>: [<store_names1>, <store_name2>...],
|
||||
* <host2>: [<store_names34>...], ...
|
||||
* },
|
||||
* <store_type2>: {
|
||||
* <host1>: [<store_names1>, <store_name2>...],
|
||||
* <host2>: [<store_names34>...], ...
|
||||
* }, ...
|
||||
* }
|
||||
* Where store_type1 and store_type2 is one of cookies, indexedDB,
|
||||
* sessionStorage and localStorage; host1, host2 are the host in which
|
||||
* this change happened; and [<store_namesX] is an array of the names
|
||||
* of the changed store objects. This array is empty for deleted object
|
||||
* if the host was completely removed.
|
||||
*/
|
||||
onUpdate: function({ changed, added, deleted }) {
|
||||
if (deleted) {
|
||||
for (let type in deleted) {
|
||||
for (let host in deleted[type]) {
|
||||
if (!deleted[type][host].length) {
|
||||
// This means that the whole host is deleted, thus the item should
|
||||
// be removed from the storage tree
|
||||
if (this.tree.isSelected([type, host])) {
|
||||
this.table.clear();
|
||||
this.hideSidebar();
|
||||
this.tree.selectPreviousItem();
|
||||
}
|
||||
|
||||
this.tree.remove([type, host]);
|
||||
}
|
||||
else if (this.tree.isSelected([type, host])) {
|
||||
for (let name of deleted[type][host]) {
|
||||
try {
|
||||
// trying to parse names in case its for indexedDB
|
||||
let names = JSON.parse(name);
|
||||
if (!names[2]) {
|
||||
if (this.tree.isSelected([type, host, names[0], names[1]])) {
|
||||
this.tree.selectPreviousItem();
|
||||
this.tree.remove([type, host, names[0], names[1]]);
|
||||
this.table.clear();
|
||||
this.hideSidebar();
|
||||
}
|
||||
}
|
||||
else if (this.tree.isSelected([type, host, names[0], names[1]])) {
|
||||
this.removeItemFromTable(names[2]);
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
this.removeItemFromTable(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (added) {
|
||||
for (let type in added) {
|
||||
for (let host in added[type]) {
|
||||
this.tree.add([type, {id: host, type: "url"}]);
|
||||
for (let name of added[type][host]) {
|
||||
try {
|
||||
name = JSON.parse(name);
|
||||
if (name.length == 3) {
|
||||
name.splice(2, 1);
|
||||
}
|
||||
this.tree.add([type, host, ...name]);
|
||||
if (!this.tree.selectedItem) {
|
||||
this.tree.selectedItem = [type, host, name[0], name[1]];
|
||||
this.fetchStorageObjects(type, host, [JSON.stringify(name)], 1);
|
||||
}
|
||||
} catch(ex) {}
|
||||
}
|
||||
|
||||
if (this.tree.isSelected([type, host])) {
|
||||
this.fetchStorageObjects(type, host, added[type][host], 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
let [type, host, db, objectStore] = this.tree.selectedItem;
|
||||
if (changed[type] && changed[type][host]) {
|
||||
if (changed[type][host].length) {
|
||||
try {
|
||||
let toUpdate = [];
|
||||
for (let name of changed[type][host]) {
|
||||
let names = JSON.parse(name);
|
||||
if (names[0] == db && names[1] == objectStore && names[2]) {
|
||||
toUpdate.push(name);
|
||||
}
|
||||
}
|
||||
this.fetchStorageObjects(type, host, toUpdate, 2);
|
||||
}
|
||||
catch (ex) {
|
||||
this.fetchStorageObjects(type, host, changed[type][host], 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (added || deleted || changed) {
|
||||
this.emit("store-objects-updated");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetches the storage objects from the storage actor and populates the
|
||||
* storage table with the returned data.
|
||||
*
|
||||
* @param {string} type
|
||||
* The type of storage. Ex. "cookies"
|
||||
* @param {string} host
|
||||
* Hostname
|
||||
* @param {array} names
|
||||
* Names of particular store objects. Empty if all are requested
|
||||
* @param {number} reason
|
||||
* 2 for update, 1 for new row in an existing table and 0 when
|
||||
* populating a table for the first time for the given host/type
|
||||
*/
|
||||
fetchStorageObjects: function(type, host, names, reason) {
|
||||
this.storageTypes[type].getStoreObjects(host, names).then(({data}) => {
|
||||
if (!data.length) {
|
||||
this.emit("store-objects-updated");
|
||||
return;
|
||||
}
|
||||
if (this.shouldResetColumns) {
|
||||
this.resetColumns(data[0], type);
|
||||
}
|
||||
this.populateTable(data, reason);
|
||||
this.emit("store-objects-updated");
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Populates the storage tree which displays the list of storages present for
|
||||
* the page.
|
||||
*
|
||||
* @param {object} storageTypes
|
||||
* List of storages and their corresponding hosts returned by the
|
||||
* StorageFront.listStores call.
|
||||
*/
|
||||
populateStorageTree: function(storageTypes) {
|
||||
this.storageTypes = {};
|
||||
for (let type in storageTypes) {
|
||||
let typeLabel = L10N.getStr("tree.labels." + type);
|
||||
this.tree.add([{id: type, label: typeLabel, type: "store"}]);
|
||||
if (storageTypes[type].hosts) {
|
||||
this.storageTypes[type] = storageTypes[type];
|
||||
for (let host in storageTypes[type].hosts) {
|
||||
this.tree.add([type, {id: host, type: "url"}]);
|
||||
for (let name of storageTypes[type].hosts[host]) {
|
||||
|
||||
try {
|
||||
let names = JSON.parse(name);
|
||||
this.tree.add([type, host, ...names]);
|
||||
if (!this.tree.selectedItem) {
|
||||
this.tree.selectedItem = [type, host, names[0], names[1]];
|
||||
this.fetchStorageObjects(type, host, [name], 0);
|
||||
}
|
||||
} catch(ex) {}
|
||||
}
|
||||
if (!this.tree.selectedItem) {
|
||||
this.tree.selectedItem = [type, host];
|
||||
this.fetchStorageObjects(type, host, null, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Populates the selected entry from teh table in the sidebar for a more
|
||||
* detailed view.
|
||||
*/
|
||||
displayObjectSidebar: function() {
|
||||
let item = this.table.selectedRow;
|
||||
if (!item) {
|
||||
// Make sure that sidebar is hidden and return
|
||||
this.sidebar.hidden = true;
|
||||
return;
|
||||
}
|
||||
this.sidebar.hidden = false;
|
||||
this.view.empty();
|
||||
let mainScope = this.view.addScope(L10N.getStr("storage.data.label"));
|
||||
mainScope.expanded = true;
|
||||
|
||||
if (item.name && item.valueActor) {
|
||||
let itemVar = mainScope.addItem(item.name + "", {}, true);
|
||||
|
||||
item.valueActor.string().then(value => {
|
||||
// The main area where the value will be displayed
|
||||
itemVar.setGrip(value);
|
||||
|
||||
// May be the item value is a json or a key value pair itself
|
||||
this.parseItemValue(item.name, value);
|
||||
|
||||
// By default the item name and value are shown. If this is the only
|
||||
// information available, then nothing else is to be displayed.
|
||||
let itemProps = Object.keys(item);
|
||||
if (itemProps.length == 3) {
|
||||
this.emit("sidebar-updated");
|
||||
return;
|
||||
}
|
||||
|
||||
// Display any other information other than the item name and value
|
||||
// which may be available.
|
||||
let rawObject = Object.create(null);
|
||||
let otherProps =
|
||||
itemProps.filter(e => e != "name" && e != "value" && e != "valueActor");
|
||||
for (let prop of otherProps) {
|
||||
rawObject[prop] = item[prop];
|
||||
}
|
||||
itemVar.populate(rawObject, {sorted: true});
|
||||
itemVar.twisty = true;
|
||||
itemVar.expanded = true;
|
||||
this.emit("sidebar-updated");
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Case when displaying IndexedDB db/object store properties.
|
||||
for (let key in item) {
|
||||
mainScope.addItem(key, {}, true).setGrip(item[key]);
|
||||
this.parseItemValue(key, item[key]);
|
||||
}
|
||||
this.emit("sidebar-updated");
|
||||
},
|
||||
|
||||
/**
|
||||
* Tries to parse a string value into either a json or a key-value separated
|
||||
* object and populates the sidebar with the parsed value. The value can also
|
||||
* be a key separated array.
|
||||
*
|
||||
* @param {string} name
|
||||
* The key corresponding to the `value` string in the object
|
||||
* @param {string} value
|
||||
* The string to be parsed into an object
|
||||
*/
|
||||
parseItemValue: function(name, value) {
|
||||
let json = null
|
||||
try {
|
||||
json = JSON.parse(value);
|
||||
}
|
||||
catch (ex) {
|
||||
json = null;
|
||||
}
|
||||
|
||||
if (!json && value) {
|
||||
json = this._extractKeyValPairs(value);
|
||||
}
|
||||
|
||||
// return if json is null, or same as value, or just a string.
|
||||
if (!json || json == value || typeof json == "string") {
|
||||
return;
|
||||
}
|
||||
|
||||
// One special case is a url which gets separated as key value pair on :
|
||||
if ((json.length == 2 || Object.keys(json).length == 1) &&
|
||||
((json[0] || Object.keys(json)[0]) + "").match(/^(http|file|ftp)/)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let jsonObject = Object.create(null);
|
||||
jsonObject[name] = json;
|
||||
let valueScope = this.view.getScopeAtIndex(1) ||
|
||||
this.view.addScope(L10N.getStr("storage.parsedValue.label"));
|
||||
valueScope.expanded = true;
|
||||
let jsonVar = valueScope.addItem("", Object.create(null), true);
|
||||
jsonVar.expanded = true;
|
||||
jsonVar.twisty = true;
|
||||
jsonVar.populate(jsonObject, {expanded: true});
|
||||
},
|
||||
|
||||
/**
|
||||
* Tries to parse a string into an object on the basis of key-value pairs,
|
||||
* separated by various separators. If failed, tries to parse for single
|
||||
* separator separated values to form an array.
|
||||
*
|
||||
* @param {string} value
|
||||
* The string to be parsed into an object or array
|
||||
*/
|
||||
_extractKeyValPairs: function(value) {
|
||||
let makeObject = (keySep, pairSep) => {
|
||||
let object = {};
|
||||
for (let pair of value.split(pairSep)) {
|
||||
let [key, val] = pair.split(keySep);
|
||||
object[key] = val;
|
||||
}
|
||||
return object;
|
||||
};
|
||||
|
||||
// Possible separators.
|
||||
const separators = ["=", ":", "~", "#", "&", "\\*", ",", "\\."];
|
||||
// Testing for object
|
||||
for (let i = 0; i < separators.length; i++) {
|
||||
let kv = separators[i];
|
||||
for (let j = 0; j < separators.length; j++) {
|
||||
if (i == j) {
|
||||
continue;
|
||||
}
|
||||
let p = separators[j];
|
||||
let regex = new RegExp("^([^" + kv + p + "]*" + kv + "+[^" + kv + p +
|
||||
"]*" + p + "*)+$", "g");
|
||||
if (value.match(regex) && value.contains(kv) &&
|
||||
(value.contains(p) || value.split(kv).length == 2)) {
|
||||
return makeObject(kv, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Testing for array
|
||||
for (let i = 0; i < separators.length; i++) {
|
||||
let p = separators[i];
|
||||
let regex = new RegExp("^[^" + p + "]+(" + p + "+[^" + p + "]*)+$", "g");
|
||||
if (value.match(regex)) {
|
||||
return value.split(p.replace(/\\*/g, ""));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Select handler for the storage tree. Fetches details of the selected item
|
||||
* from the storage details and populates the storage tree.
|
||||
*
|
||||
* @param {string} event
|
||||
* The name of the event fired
|
||||
* @param {array} item
|
||||
* An array of ids which represent the location of the selected item in
|
||||
* the storage tree
|
||||
*/
|
||||
onHostSelect: function(event, item) {
|
||||
this.table.clear();
|
||||
this.hideSidebar();
|
||||
|
||||
let [type, host] = item;
|
||||
let names = null;
|
||||
if (!host) {
|
||||
return;
|
||||
}
|
||||
if (item.length > 2) {
|
||||
names = [JSON.stringify(item.slice(2))];
|
||||
}
|
||||
this.shouldResetColumns = true;
|
||||
this.fetchStorageObjects(type, host, names, 0);
|
||||
},
|
||||
|
||||
/**
|
||||
* Resets the column headers in the storage table with the pased object `data`
|
||||
*
|
||||
* @param {object} data
|
||||
* The object from which key and values will be used for naming the
|
||||
* headers of the columns
|
||||
* @param {string} type
|
||||
* The type of storage corresponding to the after-reset columns in the
|
||||
* table.
|
||||
*/
|
||||
resetColumns: function(data, type) {
|
||||
let columns = {};
|
||||
let uniqueKey = null;
|
||||
for (let key in data) {
|
||||
if (!uniqueKey) {
|
||||
this.table.uniqueId = uniqueKey = key;
|
||||
}
|
||||
columns[key] = L10N.getStr("table.headers." + type + "." + key);
|
||||
}
|
||||
this.table.setColumns(columns, null, HIDDEN_COLUMNS);
|
||||
this.shouldResetColumns = false;
|
||||
this.hideSidebar();
|
||||
},
|
||||
|
||||
/**
|
||||
* Populates or updates the rows in the storage table.
|
||||
*
|
||||
* @param {array[object]} data
|
||||
* Array of objects to be populated in the storage table
|
||||
* @param {number} reason
|
||||
* The reason of this populateTable call. 2 for update, 1 for new row
|
||||
* in an existing table and 0 when populating a table for the first
|
||||
* time for the given host/type
|
||||
*/
|
||||
populateTable: function(data, reason) {
|
||||
for (let item of data) {
|
||||
if (item.value) {
|
||||
item.valueActor = item.value;
|
||||
item.value = item.value.initial || "";
|
||||
}
|
||||
if (item.expires != null) {
|
||||
item.expires = item.expires
|
||||
? new Date(item.expires).toLocaleString()
|
||||
: L10N.getStr("label.expires.session");
|
||||
}
|
||||
if (item.creationTime != null) {
|
||||
item.creationTime = new Date(item.creationTime).toLocaleString();
|
||||
}
|
||||
if (item.lastAccessed != null) {
|
||||
item.lastAccessed = new Date(item.lastAccessed).toLocaleString();
|
||||
}
|
||||
if (reason < 2) {
|
||||
this.table.push(item, reason == 0);
|
||||
}
|
||||
else {
|
||||
this.table.update(item);
|
||||
if (item == this.table.selectedRow && !this.sidebar.hidden) {
|
||||
this.displayObjectSidebar();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles keypress event on the body table to close the sidebar when open
|
||||
*
|
||||
* @param {DOMEvent} event
|
||||
* The event passed by the keypress event.
|
||||
*/
|
||||
handleKeypress: function(event) {
|
||||
if (event.keyCode == event.DOM_VK_ESCAPE && !this.sidebar.hidden) {
|
||||
// Stop Propagation to prevent opening up of split console
|
||||
this.hideSidebar();
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
# 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/.
|
||||
|
||||
# LOCALIZATION NOTE These strings are used inside the Storage Editor tool.
|
||||
# LOCALIZATION NOTE The correct localization of this file might be to keep it
|
||||
# in English, or another language commonly spoken among web developers.
|
||||
# You want to make that choice consistent across the developer tools.
|
||||
# A good criteria is the language in which you'd find the best documentation
|
||||
# on web development on the web.
|
||||
|
||||
# LOCALIZATION NOTE (chromeWindowTitle): This is the title of the Storage
|
||||
# 'chrome' window. That is, the main window with all the cookies, etc.
|
||||
# The argument is either the content document's title or its href if no title
|
||||
# is available.
|
||||
chromeWindowTitle=Storage [%S]
|
||||
|
||||
# LOCALIZATION NOTE (open.commandkey): This the key to use in
|
||||
# conjunction with shift to open the storage editor
|
||||
open.commandkey=VK_F9
|
||||
|
||||
# LOCALIZATION NOTE (open.accesskey): The access key used to open the storage
|
||||
# editor.
|
||||
open.accesskey=d
|
||||
|
||||
# LOCALIZATION NOTE (storage.label):
|
||||
# This string is displayed in the title of the tab when the storage editor is
|
||||
# displayed inside the developer tools window and in the Developer Tools Menu.
|
||||
storage.label=Storage
|
||||
|
||||
# LOCALIZATION NOTE (storage.tooltip):
|
||||
# This string is displayed in the tooltip of the tab when the storage editor is
|
||||
# displayed inside the developer tools window.
|
||||
storage.tooltip=Storage Inspector (Cookies, Local Storage ...)
|
||||
|
||||
# LOCALIZATION NOTE (tree.emptyText):
|
||||
# This string is displayed when the Storage Tree is empty. This can happen when
|
||||
# there are no websites on the current page (about:blank)
|
||||
tree.emptyText=No hosts on the page
|
||||
|
||||
# LOCALIZATION NOTE (table.emptyText):
|
||||
# This string is displayed when there are no rows in the Storage Table for the
|
||||
# selected host.
|
||||
table.emptyText=No data present for selected host
|
||||
|
||||
# LOCALIZATION NOTE (tree.labels.*):
|
||||
# These strings are the labels for Storage type groups present in the Storage
|
||||
# Tree, like cookies, local storage etc.
|
||||
tree.labels.cookies=Cookies
|
||||
tree.labels.localStorage=Local Storage
|
||||
tree.labels.sessionStorage=Session Storage
|
||||
tree.labels.indexedDB=Indexed DB
|
||||
|
||||
# LOCALIZATION NOTE (table.headers.*.*):
|
||||
# These strings are the header names of the columns in the Storage Table for
|
||||
# each type of storage available through the Storage Tree to the side.
|
||||
table.headers.cookies.name=Name
|
||||
table.headers.cookies.path=Path
|
||||
table.headers.cookies.host=Domain
|
||||
table.headers.cookies.expires=Expires on
|
||||
table.headers.cookies.value=Value
|
||||
table.headers.cookies.lastAccessed:Last accessed on
|
||||
table.headers.cookies.creationTime:Created on
|
||||
table.headers.cookies.isHttpOnly:isHttpOnly
|
||||
table.headers.cookies.isSecure:isSecure
|
||||
table.headers.cookies.isDomain:isDomain
|
||||
|
||||
table.headers.localStorage.name=Key
|
||||
table.headers.localStorage.value=Value
|
||||
|
||||
table.headers.sessionStorage.name=Key
|
||||
table.headers.sessionStorage.value=Value
|
||||
|
||||
table.headers.indexedDB.name=Key
|
||||
table.headers.indexedDB.db=Database Name
|
||||
table.headers.indexedDB.objectStore=Object Store Name
|
||||
table.headers.indexedDB.value=Value
|
||||
table.headers.indexedDB.origin=Origin
|
||||
table.headers.indexedDB.version=Version
|
||||
table.headers.indexedDB.objectStores=Object Stores
|
||||
table.headers.indexedDB.keyPath=Key
|
||||
table.headers.indexedDB.autoIncrement=Auto Increment
|
||||
table.headers.indexedDB.indexes=Indexes
|
||||
|
||||
# LOCALIZATION NOTE (label.expires.session):
|
||||
# This string is displayed in the expires column when the cookie is Session
|
||||
# Cookie
|
||||
label.expires.session=Session
|
||||
|
||||
# LOCALIZATION NOTE (storage.search.placeholder):
|
||||
# This is the placeholder text in the sidebar search box
|
||||
storage.search.placeholder=Filter values
|
||||
|
||||
# LOCALIZATION NOTE (storage.data.label):
|
||||
# This is the heading displayed over the item value in the sidebar
|
||||
storage.data.label=Data
|
||||
|
||||
# LOCALIZATION NOTE (storage.parsedValue.label):
|
||||
# This is the heading displayed over the item parsed value in the sidebar
|
||||
storage.parsedValue.label=Parsed Value
|
|
@ -55,11 +55,11 @@ feedback_category_other=Other:
|
|||
feedback_custom_category_text_placeholder=What went wrong?
|
||||
feedback_submit_button=Submit
|
||||
feedback_back_button=Back
|
||||
## LOCALIZATION NOTE (feedback_window_will_close_in):
|
||||
## LOCALIZATION NOTE (feedback_window_will_close_in2):
|
||||
## Semicolon-separated list of plural forms. See:
|
||||
## http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
## In this item, don't translate the part between {{..}}
|
||||
feedback_window_will_close_in=This window will close in {{countdown}} second;This window will close in {{countdown}} seconds
|
||||
feedback_window_will_close_in2=This window will close in {{countdown}} second;This window will close in {{countdown}} seconds
|
||||
|
||||
share_email_subject2=Invitation to chat
|
||||
## LOCALIZATION NOTE (share_email_body2): In this item, don't translate the
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
locale/browser/devtools/tilt.properties (%chrome/browser/devtools/tilt.properties)
|
||||
locale/browser/devtools/scratchpad.properties (%chrome/browser/devtools/scratchpad.properties)
|
||||
locale/browser/devtools/scratchpad.dtd (%chrome/browser/devtools/scratchpad.dtd)
|
||||
locale/browser/devtools/storage.properties (%chrome/browser/devtools/storage.properties)
|
||||
locale/browser/devtools/styleeditor.properties (%chrome/browser/devtools/styleeditor.properties)
|
||||
locale/browser/devtools/styleeditor.dtd (%chrome/browser/devtools/styleeditor.dtd)
|
||||
locale/browser/devtools/styleinspector.dtd (%chrome/browser/devtools/styleinspector.dtd)
|
||||
|
|
|
@ -203,6 +203,7 @@ browser.jar:
|
|||
skin/classic/browser/devtools/filetype-dir-close.svg (../shared/devtools/images/filetypes/dir-close.svg)
|
||||
skin/classic/browser/devtools/filetype-dir-open.svg (../shared/devtools/images/filetypes/dir-open.svg)
|
||||
skin/classic/browser/devtools/filetype-globe.svg (../shared/devtools/images/filetypes/globe.svg)
|
||||
skin/classic/browser/devtools/filetype-store.svg (../shared/devtools/images/filetypes/store.svg)
|
||||
skin/classic/browser/devtools/commandline-icon.png (../shared/devtools/images/commandline-icon.png)
|
||||
skin/classic/browser/devtools/commandline-icon@2x.png (../shared/devtools/images/commandline-icon@2x.png)
|
||||
skin/classic/browser/devtools/command-paintflashing.png (../shared/devtools/images/command-paintflashing.png)
|
||||
|
@ -248,6 +249,7 @@ browser.jar:
|
|||
* skin/classic/browser/devtools/shadereditor.css (devtools/shadereditor.css)
|
||||
* skin/classic/browser/devtools/splitview.css (../shared/devtools/splitview.css)
|
||||
skin/classic/browser/devtools/styleeditor.css (../shared/devtools/styleeditor.css)
|
||||
skin/classic/browser/devtools/storage.css (../shared/devtools/storage.css)
|
||||
* skin/classic/browser/devtools/webaudioeditor.css (devtools/webaudioeditor.css)
|
||||
skin/classic/browser/devtools/magnifying-glass.png (../shared/devtools/images/magnifying-glass.png)
|
||||
skin/classic/browser/devtools/magnifying-glass@2x.png (../shared/devtools/images/magnifying-glass@2x.png)
|
||||
|
@ -310,6 +312,7 @@ browser.jar:
|
|||
skin/classic/browser/devtools/tool-inspector.svg (../shared/devtools/images/tool-inspector.svg)
|
||||
skin/classic/browser/devtools/tool-inspector.svg (../shared/devtools/images/tool-inspector.svg)
|
||||
skin/classic/browser/devtools/tool-styleeditor.svg (../shared/devtools/images/tool-styleeditor.svg)
|
||||
skin/classic/browser/devtools/tool-storage.svg (../shared/devtools/images/tool-storage.svg)
|
||||
skin/classic/browser/devtools/tool-profiler.svg (../shared/devtools/images/tool-profiler.svg)
|
||||
skin/classic/browser/devtools/tool-network.svg (../shared/devtools/images/tool-network.svg)
|
||||
skin/classic/browser/devtools/tool-scratchpad.svg (../shared/devtools/images/tool-scratchpad.svg)
|
||||
|
|
После Ширина: | Высота: | Размер: 15 KiB |
После Ширина: | Высота: | Размер: 34 KiB |
|
@ -145,6 +145,10 @@ browser.jar:
|
|||
skin/classic/browser/loop/toolbar@2x.png (loop/toolbar@2x.png)
|
||||
skin/classic/browser/loop/toolbar-inverted.png (loop/toolbar-inverted.png)
|
||||
skin/classic/browser/loop/toolbar-inverted@2x.png (loop/toolbar-inverted@2x.png)
|
||||
skin/classic/browser/yosemite/loop/menuPanel.png (loop/menuPanel-yosemite.png)
|
||||
skin/classic/browser/yosemite/loop/menuPanel@2x.png (loop/menuPanel-yosemite@2x.png)
|
||||
skin/classic/browser/yosemite/loop/toolbar.png (loop/toolbar-yosemite.png)
|
||||
skin/classic/browser/yosemite/loop/toolbar@2x.png (loop/toolbar-yosemite@2x.png)
|
||||
skin/classic/browser/customizableui/background-noise-toolbar.png (customizableui/background-noise-toolbar.png)
|
||||
skin/classic/browser/customizableui/customize-titleBar-toggle.png (customizableui/customize-titleBar-toggle.png)
|
||||
skin/classic/browser/customizableui/customize-titleBar-toggle@2x.png (customizableui/customize-titleBar-toggle@2x.png)
|
||||
|
@ -326,6 +330,7 @@ browser.jar:
|
|||
skin/classic/browser/devtools/filetype-dir-close.svg (../shared/devtools/images/filetypes/dir-close.svg)
|
||||
skin/classic/browser/devtools/filetype-dir-open.svg (../shared/devtools/images/filetypes/dir-open.svg)
|
||||
skin/classic/browser/devtools/filetype-globe.svg (../shared/devtools/images/filetypes/globe.svg)
|
||||
skin/classic/browser/devtools/filetype-store.svg (../shared/devtools/images/filetypes/store.svg)
|
||||
skin/classic/browser/devtools/commandline-icon.png (../shared/devtools/images/commandline-icon.png)
|
||||
skin/classic/browser/devtools/commandline-icon@2x.png (../shared/devtools/images/commandline-icon@2x.png)
|
||||
skin/classic/browser/devtools/command-paintflashing.png (../shared/devtools/images/command-paintflashing.png)
|
||||
|
@ -372,6 +377,7 @@ browser.jar:
|
|||
* skin/classic/browser/devtools/shadereditor.css (devtools/shadereditor.css)
|
||||
* skin/classic/browser/devtools/splitview.css (../shared/devtools/splitview.css)
|
||||
skin/classic/browser/devtools/styleeditor.css (../shared/devtools/styleeditor.css)
|
||||
skin/classic/browser/devtools/storage.css (../shared/devtools/storage.css)
|
||||
* skin/classic/browser/devtools/webaudioeditor.css (devtools/webaudioeditor.css)
|
||||
skin/classic/browser/devtools/magnifying-glass.png (../shared/devtools/images/magnifying-glass.png)
|
||||
skin/classic/browser/devtools/magnifying-glass@2x.png (../shared/devtools/images/magnifying-glass@2x.png)
|
||||
|
@ -434,6 +440,7 @@ browser.jar:
|
|||
skin/classic/browser/devtools/tool-inspector.svg (../shared/devtools/images/tool-inspector.svg)
|
||||
skin/classic/browser/devtools/tool-inspector.svg (../shared/devtools/images/tool-inspector.svg)
|
||||
skin/classic/browser/devtools/tool-styleeditor.svg (../shared/devtools/images/tool-styleeditor.svg)
|
||||
skin/classic/browser/devtools/tool-storage.svg (../shared/devtools/images/tool-storage.svg)
|
||||
skin/classic/browser/devtools/tool-profiler.svg (../shared/devtools/images/tool-profiler.svg)
|
||||
skin/classic/browser/devtools/tool-network.svg (../shared/devtools/images/tool-network.svg)
|
||||
skin/classic/browser/devtools/tool-scratchpad.svg (../shared/devtools/images/tool-scratchpad.svg)
|
||||
|
@ -503,6 +510,22 @@ browser.jar:
|
|||
skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon@2x.png (tabbrowser/alltabs-box-bkgnd-icon-lion@2x.png)
|
||||
skin/classic/browser/lion/tabview/tabview.png (tabview/tabview-lion.png)
|
||||
skin/classic/browser/lion/places/toolbar.png (places/toolbar-lion.png)
|
||||
skin/classic/browser/yosemite/Toolbar.png (Toolbar-yosemite.png)
|
||||
skin/classic/browser/yosemite/Toolbar@2x.png (Toolbar-yosemite@2x.png)
|
||||
skin/classic/browser/yosemite/menuPanel.png (menuPanel-yosemite.png)
|
||||
skin/classic/browser/yosemite/menuPanel@2x.png (menuPanel-yosemite@2x.png)
|
||||
skin/classic/browser/yosemite/menuPanel-customize.png (menuPanel-customize-yosemite.png)
|
||||
skin/classic/browser/yosemite/menuPanel-customize@2x.png (menuPanel-customize-yosemite@2x.png)
|
||||
skin/classic/browser/yosemite/menuPanel-exit.png (menuPanel-exit-yosemite.png)
|
||||
skin/classic/browser/yosemite/menuPanel-exit@2x.png (menuPanel-exit-yosemite@2x.png)
|
||||
skin/classic/browser/yosemite/menuPanel-help.png (menuPanel-help-yosemite.png)
|
||||
skin/classic/browser/yosemite/menuPanel-help@2x.png (menuPanel-help-yosemite@2x.png)
|
||||
skin/classic/browser/yosemite/menuPanel-small.png (menuPanel-small-yosemite.png)
|
||||
skin/classic/browser/yosemite/menuPanel-small@2x.png (menuPanel-small-yosemite@2x.png)
|
||||
skin/classic/browser/yosemite/reload-stop-go.png (reload-stop-go-yosemite.png)
|
||||
skin/classic/browser/yosemite/reload-stop-go@2x.png (reload-stop-go-yosemite@2x.png)
|
||||
skin/classic/browser/yosemite/sync-horizontalbar.png (sync-horizontalbar-yosemite.png)
|
||||
skin/classic/browser/yosemite/sync-horizontalbar@2x.png (sync-horizontalbar-yosemite@2x.png)
|
||||
skin/classic/browser/notification-pluginNormal.png (../shared/plugins/notification-pluginNormal.png)
|
||||
skin/classic/browser/notification-pluginAlert.png (../shared/plugins/notification-pluginAlert.png)
|
||||
skin/classic/browser/notification-pluginBlocked.png (../shared/plugins/notification-pluginBlocked.png)
|
||||
|
@ -522,3 +545,23 @@ browser.jar:
|
|||
% override chrome://browser/skin/tabbrowser/alltabs-box-bkgnd-icon.png chrome://browser/skin/lion/tabbrowser/alltabs-box-bkgnd-icon.png os=Darwin osversion>=10.7
|
||||
% override chrome://browser/skin/tabview/tabview.png chrome://browser/skin/lion/tabview/tabview.png os=Darwin osversion>=10.7
|
||||
% override chrome://browser/skin/places/toolbar.png chrome://browser/skin/lion/places/toolbar.png os=Darwin osversion>=10.7
|
||||
% override chrome://browser/skin/Toolbar.png chrome://browser/skin/yosemite/Toolbar.png os=Darwin osversion>=10.10
|
||||
% override chrome://browser/skin/Toolbar@2x.png chrome://browser/skin/yosemite/Toolbar@2x.png os=Darwin osversion>=10.10
|
||||
% override chrome://browser/skin/menuPanel.png chrome://browser/skin/yosemite/menuPanel.png os=Darwin osversion>=10.10
|
||||
% override chrome://browser/skin/menuPanel@2x.png chrome://browser/skin/yosemite/menuPanel@2x.png os=Darwin osversion>=10.10
|
||||
% override chrome://browser/skin/loop/menuPanel.png chrome://browser/skin/yosemite/loop/menuPanel.png os=Darwin osversion>=10.10
|
||||
% override chrome://browser/skin/loop/menuPanel@2x.png chrome://browser/skin/yosemite/loop/menuPanel@2x.png os=Darwin osversion>=10.10
|
||||
% override chrome://browser/skin/loop/toolbar.png chrome://browser/skin/yosemite/loop/toolbar.png os=Darwin osversion>=10.10
|
||||
% override chrome://browser/skin/loop/toolbar@2x.png chrome://browser/skin/yosemite/loop/toolbar@2x.png os=Darwin osversion>=10.10
|
||||
% override chrome://browser/skin/menuPanel-customize.png chrome://browser/skin/yosemite/menuPanel-customize.png os=Darwin osversion>=10.10
|
||||
% override chrome://browser/skin/menuPanel-customize@2x.png chrome://browser/skin/yosemite/menuPanel-customize@2x.png os=Darwin osversion>=10.10
|
||||
% override chrome://browser/skin/menuPanel-exit.png chrome://browser/skin/yosemite/menuPanel-exit.png os=Darwin osversion>=10.10
|
||||
% override chrome://browser/skin/menuPanel-exit@2x.png chrome://browser/skin/yosemite/menuPanel-exit@2x.png os=Darwin osversion>=10.10
|
||||
% override chrome://browser/skin/menuPanel-help.png chrome://browser/skin/yosemite/menuPanel-help.png os=Darwin osversion>=10.10
|
||||
% override chrome://browser/skin/menuPanel-help@2x.png chrome://browser/skin/yosemite/menuPanel-help@2x.png os=Darwin osversion>=10.10
|
||||
% override chrome://browser/skin/menuPanel-small.png chrome://browser/skin/yosemite/menuPanel-small.png os=Darwin osversion>=10.10
|
||||
% override chrome://browser/skin/menuPanel-small@2x.png chrome://browser/skin/yosemite/menuPanel-small@2x.png os=Darwin osversion>=10.10
|
||||
% override chrome://browser/skin/reload-stop-go.png chrome://browser/skin/yosemite/reload-stop-go.png os=Darwin osversion>=10.10
|
||||
% override chrome://browser/skin/reload-stop-go@2x.png chrome://browser/skin/yosemite/reload-stop-go@2x.png os=Darwin osversion>=10.10
|
||||
% override chrome://browser/skin/sync-horizontalbar.png chrome://browser/skin/yosemite/sync-horizontalbar.png os=Darwin osversion>=10.10
|
||||
% override chrome://browser/skin/sync-horizontalbar@2x.png chrome://browser/skin/yosemite/sync-horizontalbar@2x.png os=Darwin osversion>=10.10
|
||||
|
|
После Ширина: | Высота: | Размер: 9.5 KiB |
После Ширина: | Высота: | Размер: 20 KiB |
После Ширина: | Высота: | Размер: 2.3 KiB |
После Ширина: | Высота: | Размер: 4.7 KiB |
После Ширина: | Высота: | Размер: 219 B |
После Ширина: | Высота: | Размер: 364 B |
После Ширина: | Высота: | Размер: 515 B |
После Ширина: | Высота: | Размер: 939 B |
После Ширина: | Высота: | Размер: 1.5 KiB |
После Ширина: | Высота: | Размер: 3.4 KiB |
После Ширина: | Высота: | Размер: 1.6 KiB |
После Ширина: | Высота: | Размер: 4.1 KiB |
После Ширина: | Высота: | Размер: 19 KiB |
После Ширина: | Высота: | Размер: 43 KiB |
После Ширина: | Высота: | Размер: 923 B |
После Ширина: | Высота: | Размер: 1.6 KiB |
После Ширина: | Высота: | Размер: 311 B |
После Ширина: | Высота: | Размер: 609 B |
|
@ -0,0 +1,7 @@
|
|||
<svg width="16" xmlns="http://www.w3.org/2000/svg" height="16" viewBox="0 0 16 16" xmlns:xlink="http://www.w3.org/1999/xlink" enable-background="new 0 0 16 16">
|
||||
<g>
|
||||
<path d="m1.3,12.5v-2.4c0,0 0,2.5 6.7,2.5 6.7,0 6.7-2.5 6.7-2.5v2.4c0,0 0,2.7-6.8,2.7-6.6,0-6.6-2.7-6.6-2.7z"/>
|
||||
<path d="m14.7,3.4c0-1.4-3-2.5-6.7-2.5s-6.7,1.1-6.7,2.5c0,.2 0,.3 .1,.5-.1-.3-.1-.4-.1-.4v1.5c0,0 0,2.7 6.7,2.7 6.7,0 6.8-2.7 6.8-2.7v-1.6c0,.1 0,.2-.1,.5-0-.2-0-.3-0-.5z"/>
|
||||
<path d="m1.3,8.7v-2.4c0,0 0,2.5 6.7,2.5 6.7,0 6.7-2.5 6.7-2.5v2.4c0,0 0,2.7-6.8,2.7-6.6-0-6.6-2.7-6.6-2.7z"/>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 574 B |
|
@ -0,0 +1,7 @@
|
|||
<svg width="16" xmlns="http://www.w3.org/2000/svg" height="16" viewBox="0 0 16 16" xmlns:xlink="http://www.w3.org/1999/xlink" enable-background="new 0 0 16 16">
|
||||
<g fill="#edf0f1">
|
||||
<path d="m1.3,12.5v-2.4c0,0 0,2.5 6.7,2.5 6.7,0 6.7-2.5 6.7-2.5v2.4c0,0 0,2.7-6.8,2.7-6.6,0-6.6-2.7-6.6-2.7z"/>
|
||||
<path d="m14.7,3.4c0-1.4-3-2.5-6.7-2.5s-6.7,1.1-6.7,2.5c0,.2 0,.3 .1,.5-.1-.3-.1-.4-.1-.4v1.5c0,0 0,2.7 6.7,2.7 6.7,0 6.8-2.7 6.8-2.7v-1.6c0,.1 0,.2-.1,.5-0-.2-0-.3-0-.5z"/>
|
||||
<path d="m1.3,8.7v-2.4c0,0 0,2.5 6.7,2.5 6.7,0 6.7-2.5 6.7-2.5v2.4c0,0 0,2.7-6.8,2.7-6.6-0-6.6-2.7-6.6-2.7z"/>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 589 B |
|
@ -0,0 +1,48 @@
|
|||
/* 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/. */
|
||||
|
||||
/* Storage Host Tree */
|
||||
|
||||
#storage-tree {
|
||||
min-width: 220px;
|
||||
max-width: 500px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.theme-dark #storage-tree {
|
||||
background: #343c45; /* Toolbars */
|
||||
}
|
||||
|
||||
#storage-tree .tree-widget-item[type="store"]:after {
|
||||
background-image: url(chrome://browser/skin/devtools/filetype-store.svg);
|
||||
background-size: 18px 18px;
|
||||
background-position: -1px 0;
|
||||
}
|
||||
|
||||
/* Columns with date should have a min width so that date is visible */
|
||||
#expires, #lastAccessed, #creationTime {
|
||||
min-width: 150px;
|
||||
}
|
||||
|
||||
/* Variables View Sidebar */
|
||||
|
||||
#storage-sidebar {
|
||||
max-width: 500px;
|
||||
min-width: 250px;
|
||||
}
|
||||
|
||||
/* Responsive sidebar */
|
||||
@media (max-width: 700px) {
|
||||
#storage-tree {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
#storage-table #path {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#storage-table .table-widget-cell {
|
||||
min-width: 100px;
|
||||
}
|
||||
}
|
|
@ -1430,6 +1430,7 @@
|
|||
padding: 10px 20px;
|
||||
font-size: medium;
|
||||
background: transparent;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Tree Item */
|
||||
|
|
|
@ -239,6 +239,7 @@ browser.jar:
|
|||
skin/classic/browser/devtools/filetype-dir-close.svg (../shared/devtools/images/filetypes/dir-close.svg)
|
||||
skin/classic/browser/devtools/filetype-dir-open.svg (../shared/devtools/images/filetypes/dir-open.svg)
|
||||
skin/classic/browser/devtools/filetype-globe.svg (../shared/devtools/images/filetypes/globe.svg)
|
||||
skin/classic/browser/devtools/filetype-store.svg (../shared/devtools/images/filetypes/store.svg)
|
||||
skin/classic/browser/devtools/commandline-icon.png (../shared/devtools/images/commandline-icon.png)
|
||||
skin/classic/browser/devtools/commandline-icon@2x.png (../shared/devtools/images/commandline-icon@2x.png)
|
||||
skin/classic/browser/devtools/alerticon-warning.png (../shared/devtools/images/alerticon-warning.png)
|
||||
|
@ -283,6 +284,7 @@ browser.jar:
|
|||
* skin/classic/browser/devtools/profiler.css (devtools/profiler.css)
|
||||
* skin/classic/browser/devtools/scratchpad.css (devtools/scratchpad.css)
|
||||
* skin/classic/browser/devtools/shadereditor.css (devtools/shadereditor.css)
|
||||
skin/classic/browser/devtools/storage.css (../shared/devtools/storage.css)
|
||||
* skin/classic/browser/devtools/splitview.css (../shared/devtools/splitview.css)
|
||||
skin/classic/browser/devtools/styleeditor.css (../shared/devtools/styleeditor.css)
|
||||
* skin/classic/browser/devtools/webaudioeditor.css (devtools/webaudioeditor.css)
|
||||
|
@ -346,6 +348,7 @@ browser.jar:
|
|||
skin/classic/browser/devtools/tool-debugger-paused.svg (../shared/devtools/images/tool-debugger-paused.svg)
|
||||
skin/classic/browser/devtools/tool-inspector.svg (../shared/devtools/images/tool-inspector.svg)
|
||||
skin/classic/browser/devtools/tool-styleeditor.svg (../shared/devtools/images/tool-styleeditor.svg)
|
||||
skin/classic/browser/devtools/tool-storage.svg (../shared/devtools/images/tool-storage.svg)
|
||||
skin/classic/browser/devtools/tool-profiler.svg (../shared/devtools/images/tool-profiler.svg)
|
||||
skin/classic/browser/devtools/tool-network.svg (../shared/devtools/images/tool-network.svg)
|
||||
skin/classic/browser/devtools/tool-scratchpad.svg (../shared/devtools/images/tool-scratchpad.svg)
|
||||
|
@ -654,6 +657,7 @@ browser.jar:
|
|||
skin/classic/aero/browser/devtools/filetype-dir-close.svg (../shared/devtools/images/filetypes/dir-close.svg)
|
||||
skin/classic/aero/browser/devtools/filetype-dir-open.svg (../shared/devtools/images/filetypes/dir-open.svg)
|
||||
skin/classic/aero/browser/devtools/filetype-globe.svg (../shared/devtools/images/filetypes/globe.svg)
|
||||
skin/classic/aero/browser/devtools/filetype-store.svg (../shared/devtools/images/filetypes/store.svg)
|
||||
skin/classic/aero/browser/devtools/commandline-icon.png (../shared/devtools/images/commandline-icon.png)
|
||||
skin/classic/aero/browser/devtools/commandline-icon@2x.png (../shared/devtools/images/commandline-icon@2x.png)
|
||||
skin/classic/aero/browser/devtools/command-paintflashing.png (../shared/devtools/images/command-paintflashing.png)
|
||||
|
@ -700,6 +704,7 @@ browser.jar:
|
|||
* skin/classic/aero/browser/devtools/shadereditor.css (devtools/shadereditor.css)
|
||||
* skin/classic/aero/browser/devtools/splitview.css (../shared/devtools/splitview.css)
|
||||
skin/classic/aero/browser/devtools/styleeditor.css (../shared/devtools/styleeditor.css)
|
||||
skin/classic/aero/browser/devtools/storage.css (../shared/devtools/storage.css)
|
||||
* skin/classic/aero/browser/devtools/webaudioeditor.css (devtools/webaudioeditor.css)
|
||||
skin/classic/aero/browser/devtools/magnifying-glass.png (../shared/devtools/images/magnifying-glass.png)
|
||||
skin/classic/aero/browser/devtools/magnifying-glass@2x.png (../shared/devtools/images/magnifying-glass@2x.png)
|
||||
|
@ -761,6 +766,7 @@ browser.jar:
|
|||
skin/classic/aero/browser/devtools/tool-debugger-paused.svg (../shared/devtools/images/tool-debugger-paused.svg)
|
||||
skin/classic/aero/browser/devtools/tool-inspector.svg (../shared/devtools/images/tool-inspector.svg)
|
||||
skin/classic/aero/browser/devtools/tool-styleeditor.svg (../shared/devtools/images/tool-styleeditor.svg)
|
||||
skin/classic/aero/browser/devtools/tool-storage.svg (../shared/devtools/images/tool-storage.svg)
|
||||
skin/classic/aero/browser/devtools/tool-profiler.svg (../shared/devtools/images/tool-profiler.svg)
|
||||
skin/classic/aero/browser/devtools/tool-network.svg (../shared/devtools/images/tool-network.svg)
|
||||
skin/classic/aero/browser/devtools/tool-scratchpad.svg (../shared/devtools/images/tool-scratchpad.svg)
|
||||
|
|
|
@ -1177,7 +1177,7 @@ nsContentSink::StartLayout(bool aIgnorePendingSheets)
|
|||
// If the document we are loading has a reference or it is a
|
||||
// frameset document, disable the scroll bars on the views.
|
||||
|
||||
mDocument->SetScrollToRef(mDocumentURI);
|
||||
mDocument->SetScrollToRef(mDocument->GetDocumentURI());
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -207,6 +207,8 @@ nsMixedContentBlocker::ShouldLoad(uint32_t aContentType,
|
|||
|
||||
// Assume active (high risk) content and blocked by default
|
||||
MixedContentTypes classification = eMixedScript;
|
||||
// Make decision to block/reject by default
|
||||
*aDecision = REJECT_REQUEST;
|
||||
|
||||
|
||||
// Notes on non-obvious decisions:
|
||||
|
@ -339,10 +341,12 @@ nsMixedContentBlocker::ShouldLoad(uint32_t aContentType,
|
|||
NS_FAILED(NS_URIChainHasFlags(aContentLocation, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA, &schemeNoReturnData)) ||
|
||||
NS_FAILED(NS_URIChainHasFlags(aContentLocation, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT, &schemeInherits)) ||
|
||||
NS_FAILED(NS_URIChainHasFlags(aContentLocation, nsIProtocolHandler::URI_SAFE_TO_LOAD_IN_SECURE_CONTEXT, &schemeSecure))) {
|
||||
*aDecision = REJECT_REQUEST;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (schemeLocal || schemeNoReturnData || schemeInherits || schemeSecure) {
|
||||
*aDecision = ACCEPT;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -441,6 +445,7 @@ nsMixedContentBlocker::ShouldLoad(uint32_t aContentType,
|
|||
bool isRootDocShell = false;
|
||||
rv = docShell->GetAllowMixedContentAndConnectionData(&rootHasSecureConnection, &allowMixedContent, &isRootDocShell);
|
||||
if (NS_FAILED(rv)) {
|
||||
*aDecision = REJECT_REQUEST;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -590,6 +595,7 @@ nsMixedContentBlocker::ShouldLoad(uint32_t aContentType,
|
|||
// from within ShouldLoad
|
||||
nsContentUtils::AddScriptRunner(
|
||||
new nsMixedContentEvent(aRequestingContext, classification));
|
||||
*aDecision = ACCEPT;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -610,8 +616,10 @@ nsMixedContentBlocker::ShouldProcess(uint32_t aContentType,
|
|||
if (!aContentLocation) {
|
||||
// aContentLocation may be null when a plugin is loading without an associated URI resource
|
||||
if (aContentType == TYPE_OBJECT) {
|
||||
*aDecision = ACCEPT;
|
||||
return NS_OK;
|
||||
} else {
|
||||
*aDecision = REJECT_REQUEST;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,12 @@
|
|||
#include "base/string_util.h"
|
||||
#include "base/process_util.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include <codecvt>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
|
||||
|
@ -43,6 +49,13 @@ GMPProcessParent::Launch(int32_t aTimeoutMs)
|
|||
{
|
||||
vector<string> args;
|
||||
args.push_back(mGMPPath);
|
||||
|
||||
#ifdef XP_WIN
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
|
||||
std::wstring wGMPPath = converter.from_bytes(mGMPPath.c_str());
|
||||
mAllowedFilesRead.push_back(wGMPPath + L"\\*");
|
||||
#endif
|
||||
|
||||
return SyncLaunch(args, aTimeoutMs, base::GetCurrentProcessArchitecture());
|
||||
}
|
||||
|
||||
|
|
|
@ -828,6 +828,7 @@ nsXULElement::BindToTree(nsIDocument* aDocument,
|
|||
{
|
||||
if (!aBindingParent &&
|
||||
aDocument &&
|
||||
!aDocument->IsLoadedAsInteractiveData() &&
|
||||
!aDocument->AllowXULXBL() &&
|
||||
!aDocument->HasWarnedAbout(nsIDocument::eImportXULIntoContent)) {
|
||||
nsContentUtils::AddScriptRunner(new XULInContentErrorReporter(aDocument));
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "AnimationPlayer.h"
|
||||
#include "AnimationUtils.h"
|
||||
#include "mozilla/dom/AnimationPlayerBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -20,34 +21,16 @@ AnimationPlayer::WrapObject(JSContext* aCx)
|
|||
return dom::AnimationPlayerBinding::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
double
|
||||
AnimationPlayer::StartTime() const
|
||||
Nullable<double>
|
||||
AnimationPlayer::GetStartTime() const
|
||||
{
|
||||
Nullable<double> startTime = mTimeline->ToTimelineTime(mStartTime);
|
||||
return startTime.IsNull() ? 0.0 : startTime.Value();
|
||||
return AnimationUtils::TimeDurationToDouble(mStartTime);
|
||||
}
|
||||
|
||||
double
|
||||
AnimationPlayer::CurrentTime() const
|
||||
Nullable<double>
|
||||
AnimationPlayer::GetCurrentTime() const
|
||||
{
|
||||
Nullable<TimeDuration> currentTime = GetCurrentTimeDuration();
|
||||
|
||||
// The current time is currently only going to be null when don't have a
|
||||
// refresh driver (e.g. because we are in a display:none iframe).
|
||||
//
|
||||
// Web Animations says that in this case we should use a timeline time of
|
||||
// 0 (the "effective timeline time") and calculate the current time from that.
|
||||
// Doing that, however, requires storing the start time as an offset rather
|
||||
// than a timestamp so for now we just return 0.
|
||||
//
|
||||
// FIXME: Store player start time and pause start as offsets rather than
|
||||
// timestamps and return the appropriate current time when the timeline time
|
||||
// is null.
|
||||
if (currentTime.IsNull()) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return currentTime.Value().ToMilliseconds();
|
||||
return AnimationUtils::TimeDurationToDouble(GetCurrentTimeDuration());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -87,5 +70,20 @@ AnimationPlayer::IsCurrent() const
|
|||
return GetSource() && GetSource()->IsCurrent();
|
||||
}
|
||||
|
||||
Nullable<TimeDuration>
|
||||
AnimationPlayer::GetCurrentTimeDuration() const
|
||||
{
|
||||
Nullable<TimeDuration> result;
|
||||
if (!mHoldTime.IsNull()) {
|
||||
result = mHoldTime;
|
||||
} else {
|
||||
Nullable<TimeDuration> timelineTime = mTimeline->GetCurrentTimeDuration();
|
||||
if (!timelineTime.IsNull() && !mStartTime.IsNull()) {
|
||||
result.SetValue(timelineTime.Value() - mStartTime.Value());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -48,8 +48,8 @@ public:
|
|||
// AnimationPlayer methods
|
||||
Animation* GetSource() const { return mSource; }
|
||||
AnimationTimeline* Timeline() const { return mTimeline; }
|
||||
double StartTime() const;
|
||||
double CurrentTime() const;
|
||||
Nullable<double> GetStartTime() const;
|
||||
Nullable<double> GetCurrentTime() const;
|
||||
bool IsRunningOnCompositor() const { return mIsRunningOnCompositor; }
|
||||
|
||||
void SetSource(Animation* aSource);
|
||||
|
@ -67,29 +67,12 @@ public:
|
|||
bool IsCurrent() const;
|
||||
|
||||
// Return the duration since the start time of the player, taking into
|
||||
// account the pause state. May be negative.
|
||||
// Returns a null value if the timeline associated with this object has a
|
||||
// current timestamp that is null or if the start time of this object is
|
||||
// null.
|
||||
Nullable<TimeDuration> GetCurrentTimeDuration() const {
|
||||
const TimeStamp& timelineTime = mTimeline->GetCurrentTimeStamp();
|
||||
// FIXME: In order to support arbitrary timelines we will need to fix
|
||||
// the pause logic to handle the timeline time going backwards.
|
||||
MOZ_ASSERT(timelineTime.IsNull() || !IsPaused() ||
|
||||
timelineTime >= mPauseStart,
|
||||
"if paused, any non-null value of aTime must be at least"
|
||||
" mPauseStart");
|
||||
|
||||
Nullable<TimeDuration> result; // Initializes to null
|
||||
if (!timelineTime.IsNull() && !mStartTime.IsNull()) {
|
||||
result.SetValue((IsPaused() ? mPauseStart : timelineTime) - mStartTime);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// account the pause state. May be negative or null.
|
||||
Nullable<TimeDuration> GetCurrentTimeDuration() const;
|
||||
|
||||
// The beginning of the delay period.
|
||||
TimeStamp mStartTime;
|
||||
TimeStamp mPauseStart;
|
||||
Nullable<TimeDuration> mStartTime;
|
||||
Nullable<TimeDuration> mHoldTime;
|
||||
uint8_t mPlayState;
|
||||
bool mIsRunningOnCompositor;
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "AnimationTimeline.h"
|
||||
#include "mozilla/dom/AnimationTimelineBinding.h"
|
||||
#include "AnimationUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsPresContext.h"
|
||||
|
@ -28,7 +29,7 @@ AnimationTimeline::WrapObject(JSContext* aCx)
|
|||
Nullable<double>
|
||||
AnimationTimeline::GetCurrentTime() const
|
||||
{
|
||||
return ToTimelineTime(GetCurrentTimeStamp());
|
||||
return AnimationUtils::TimeDurationToDouble(GetCurrentTimeDuration());
|
||||
}
|
||||
|
||||
TimeStamp
|
||||
|
@ -67,10 +68,16 @@ AnimationTimeline::GetCurrentTimeStamp() const
|
|||
return result;
|
||||
}
|
||||
|
||||
Nullable<double>
|
||||
AnimationTimeline::ToTimelineTime(const mozilla::TimeStamp& aTimeStamp) const
|
||||
Nullable<TimeDuration>
|
||||
AnimationTimeline::GetCurrentTimeDuration() const
|
||||
{
|
||||
Nullable<double> result; // Initializes to null
|
||||
return ToTimelineTime(GetCurrentTimeStamp());
|
||||
}
|
||||
|
||||
Nullable<TimeDuration>
|
||||
AnimationTimeline::ToTimelineTime(const TimeStamp& aTimeStamp) const
|
||||
{
|
||||
Nullable<TimeDuration> result; // Initializes to null
|
||||
if (aTimeStamp.IsNull()) {
|
||||
return result;
|
||||
}
|
||||
|
@ -80,7 +87,20 @@ AnimationTimeline::ToTimelineTime(const mozilla::TimeStamp& aTimeStamp) const
|
|||
return result;
|
||||
}
|
||||
|
||||
result.SetValue(timing->TimeStampToDOMHighRes(aTimeStamp));
|
||||
result.SetValue(aTimeStamp - timing->GetNavigationStartTimeStamp());
|
||||
return result;
|
||||
}
|
||||
|
||||
TimeStamp
|
||||
AnimationTimeline::ToTimeStamp(const TimeDuration& aTimeDuration) const
|
||||
{
|
||||
TimeStamp result;
|
||||
nsRefPtr<nsDOMNavigationTiming> timing = mDocument->GetNavigationTiming();
|
||||
if (MOZ_UNLIKELY(!timing)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = timing->GetNavigationStartTimeStamp() + aTimeDuration;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,12 +33,17 @@ public:
|
|||
nsISupports* GetParentObject() const { return mDocument; }
|
||||
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
// WebIDL API
|
||||
Nullable<double> GetCurrentTime() const;
|
||||
mozilla::TimeStamp GetCurrentTimeStamp() const;
|
||||
|
||||
Nullable<double> ToTimelineTime(const mozilla::TimeStamp& aTimeStamp) const;
|
||||
Nullable<TimeDuration> GetCurrentTimeDuration() const;
|
||||
|
||||
Nullable<TimeDuration> ToTimelineTime(const TimeStamp& aTimeStamp) const;
|
||||
TimeStamp ToTimeStamp(const TimeDuration& aTimelineTime) const;
|
||||
|
||||
protected:
|
||||
TimeStamp GetCurrentTimeStamp() const;
|
||||
|
||||
virtual ~AnimationTimeline() { }
|
||||
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
|
@ -46,7 +51,7 @@ protected:
|
|||
// Store the most recently returned value of current time. This is used
|
||||
// in cases where we don't have a refresh driver (e.g. because we are in
|
||||
// a display:none iframe).
|
||||
mutable mozilla::TimeStamp mLastCurrentTime;
|
||||
mutable TimeStamp mLastCurrentTime;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
|
||||
/* 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/. */
|
||||
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/dom/Nullable.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class AnimationUtils
|
||||
{
|
||||
public:
|
||||
static Nullable<double>
|
||||
TimeDurationToDouble(const Nullable<TimeDuration>& aTime)
|
||||
{
|
||||
Nullable<double> result;
|
||||
|
||||
if (!aTime.IsNull()) {
|
||||
result.SetValue(aTime.Value().ToMilliseconds());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -959,10 +959,15 @@ DOMInterfaces = {
|
|||
'wrapperCache': False
|
||||
},
|
||||
|
||||
'Performance': {
|
||||
'Performance': [{
|
||||
'nativeType': 'nsPerformance',
|
||||
'resultNotAddRefed': [ 'timing', 'navigation' ]
|
||||
},
|
||||
{
|
||||
'nativeType': 'mozilla::dom::workers::Performance',
|
||||
'headerFile': 'mozilla/dom/workers/bindings/Performance.h',
|
||||
'workers': True,
|
||||
}],
|
||||
|
||||
'PerformanceTiming': {
|
||||
'nativeType': 'nsPerformanceTiming',
|
||||
|
@ -1619,7 +1624,12 @@ DOMInterfaces = {
|
|||
'implicitJSContext': [
|
||||
'close', 'importScripts',
|
||||
],
|
||||
'binaryNames': { 'console': 'getConsole', },
|
||||
# Rename a few things so we don't have both classes and methods
|
||||
# with the same name
|
||||
'binaryNames': {
|
||||
'console': 'getConsole',
|
||||
'performance': 'getPerformance',
|
||||
},
|
||||
},
|
||||
|
||||
'WorkerLocation': {
|
||||
|
|
|
@ -2155,7 +2155,8 @@ class MethodDefiner(PropertyDefiner):
|
|||
if not static:
|
||||
stringifier = descriptor.operations['Stringifier']
|
||||
if (stringifier and
|
||||
unforgeable == MemberIsUnforgeable(stringifier, descriptor)):
|
||||
unforgeable == MemberIsUnforgeable(stringifier, descriptor) and
|
||||
isMaybeExposedIn(stringifier, descriptor)):
|
||||
toStringDesc = {
|
||||
"name": "toString",
|
||||
"nativeName": stringifier.identifier.name,
|
||||
|
@ -2168,7 +2169,9 @@ class MethodDefiner(PropertyDefiner):
|
|||
else:
|
||||
self.regular.append(toStringDesc)
|
||||
jsonifier = descriptor.operations['Jsonifier']
|
||||
if jsonifier:
|
||||
if (jsonifier and
|
||||
unforgeable == MemberIsUnforgeable(jsonifier, descriptor) and
|
||||
isMaybeExposedIn(jsonifier, descriptor)):
|
||||
toJSONDesc = {
|
||||
"name": "toJSON",
|
||||
"nativeName": jsonifier.identifier.name,
|
||||
|
|
|
@ -551,12 +551,7 @@ class Descriptor(DescriptorProvider):
|
|||
self.interface.isExposedOnlyInSomeWorkers()))
|
||||
|
||||
def isExposedConditionally(self):
|
||||
return (self.interface.getExtendedAttribute("Pref") or
|
||||
self.interface.getExtendedAttribute("ChromeOnly") or
|
||||
self.interface.getExtendedAttribute("Func") or
|
||||
self.interface.getExtendedAttribute("AvailableIn") or
|
||||
self.interface.getExtendedAttribute("CheckPermissions") or
|
||||
self.hasThreadChecks())
|
||||
return self.interface.isExposedConditionally() or self.hasThreadChecks()
|
||||
|
||||
def needsXrayResolveHooks(self):
|
||||
"""
|
||||
|
|
|
@ -1018,6 +1018,14 @@ class IDLInterface(IDLObjectWithScope):
|
|||
self.parentScope.primaryGlobalName,
|
||||
[self.location])
|
||||
|
||||
# Conditional exposure makes no sense for interfaces with no
|
||||
# interface object, unless they're navigator properties.
|
||||
if (self.isExposedConditionally() and
|
||||
not self.hasInterfaceObject() and
|
||||
not self.getNavigatorProperty()):
|
||||
raise WebIDLError("Interface with no interface object is "
|
||||
"exposed conditionally",
|
||||
[self.location])
|
||||
|
||||
def isInterface(self):
|
||||
return True
|
||||
|
@ -1356,6 +1364,13 @@ class IDLInterface(IDLObjectWithScope):
|
|||
def hasMembersInSlots(self):
|
||||
return self._ownMembersInSlots != 0
|
||||
|
||||
def isExposedConditionally(self):
|
||||
return (self.getExtendedAttribute("Pref") or
|
||||
self.getExtendedAttribute("ChromeOnly") or
|
||||
self.getExtendedAttribute("Func") or
|
||||
self.getExtendedAttribute("AvailableIn") or
|
||||
self.getExtendedAttribute("CheckPermissions"))
|
||||
|
||||
class IDLDictionary(IDLObjectWithScope):
|
||||
def __init__(self, location, parentScope, name, parent, members):
|
||||
assert isinstance(parentScope, IDLScope)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// files that end in .txt list other tests
|
||||
// other lines are assumed to be .html files
|
||||
|
||||
always-fail.html
|
||||
|
||||
conformance/00_test_list.txt
|
||||
conformance/more/00_test_list.txt
|
||||
|
||||
|
|
|
@ -0,0 +1,834 @@
|
|||
[DEFAULT]
|
||||
skip-if = e10s || os == 'b2g' || ((os == 'linux') && (buildapp == 'b2g'))
|
||||
|
||||
support-files = mochi-single.html
|
||||
mochi-wrapper.css
|
||||
always-fail.html
|
||||
conformance/00_readme.txt
|
||||
conformance/00_test_list.txt
|
||||
conformance/LICENSE_CHROMIUM
|
||||
conformance/attribs/00_test_list.txt
|
||||
conformance/attribs/gl-enable-vertex-attrib.html
|
||||
conformance/attribs/gl-vertex-attrib-zero-issues.html
|
||||
conformance/attribs/gl-vertex-attrib.html
|
||||
conformance/attribs/gl-vertexattribpointer-offsets.html
|
||||
conformance/attribs/gl-vertexattribpointer.html
|
||||
conformance/buffers/00_test_list.txt
|
||||
conformance/buffers/buffer-bind-test.html
|
||||
conformance/buffers/buffer-data-array-buffer.html
|
||||
conformance/buffers/index-validation-copies-indices.html
|
||||
conformance/buffers/index-validation-crash-with-buffer-sub-data.html
|
||||
conformance/buffers/index-validation-verifies-too-many-indices.html
|
||||
conformance/buffers/index-validation-with-resized-buffer.html
|
||||
conformance/buffers/index-validation.html
|
||||
conformance/canvas/00_test_list.txt
|
||||
conformance/canvas/buffer-offscreen-test.html
|
||||
conformance/canvas/buffer-preserve-test.html
|
||||
conformance/canvas/canvas-test.html
|
||||
conformance/canvas/canvas-zero-size.html
|
||||
conformance/canvas/drawingbuffer-static-canvas-test.html
|
||||
conformance/canvas/drawingbuffer-test.html
|
||||
conformance/canvas/viewport-unchanged-upon-resize.html
|
||||
conformance/context/00_test_list.txt
|
||||
conformance/context/constants.html
|
||||
conformance/context/context-attribute-preserve-drawing-buffer.html
|
||||
conformance/context/context-attributes-alpha-depth-stencil-antialias.html
|
||||
conformance/context/context-lost-restored.html
|
||||
conformance/context/context-lost.html
|
||||
conformance/context/context-type-test.html
|
||||
conformance/context/incorrect-context-object-behaviour.html
|
||||
conformance/context/methods.html
|
||||
conformance/context/premultiplyalpha-test.html
|
||||
conformance/context/resource-sharing-test.html
|
||||
conformance/extensions/00_test_list.txt
|
||||
conformance/extensions/ext-sRGB.html
|
||||
conformance/extensions/ext-shader-texture-lod.html
|
||||
conformance/extensions/ext-texture-filter-anisotropic.html
|
||||
conformance/extensions/oes-standard-derivatives.html
|
||||
conformance/extensions/oes-texture-float.html
|
||||
conformance/extensions/oes-vertex-array-object.html
|
||||
conformance/extensions/webgl-compressed-texture-etc1.html
|
||||
conformance/extensions/webgl-compressed-texture-s3tc.html
|
||||
conformance/extensions/webgl-debug-renderer-info.html
|
||||
conformance/extensions/webgl-debug-shaders.html
|
||||
conformance/extensions/webgl-depth-texture.html
|
||||
conformance/glsl/00_test_list.txt
|
||||
conformance/glsl/functions/00_test_list.txt
|
||||
conformance/glsl/functions/glsl-function-abs.html
|
||||
conformance/glsl/functions/glsl-function-acos.html
|
||||
conformance/glsl/functions/glsl-function-asin.html
|
||||
conformance/glsl/functions/glsl-function-atan-xy.html
|
||||
conformance/glsl/functions/glsl-function-atan.html
|
||||
conformance/glsl/functions/glsl-function-ceil.html
|
||||
conformance/glsl/functions/glsl-function-clamp-float.html
|
||||
conformance/glsl/functions/glsl-function-clamp-gentype.html
|
||||
conformance/glsl/functions/glsl-function-cos.html
|
||||
conformance/glsl/functions/glsl-function-cross.html
|
||||
conformance/glsl/functions/glsl-function-distance.html
|
||||
conformance/glsl/functions/glsl-function-dot.html
|
||||
conformance/glsl/functions/glsl-function-faceforward.html
|
||||
conformance/glsl/functions/glsl-function-floor.html
|
||||
conformance/glsl/functions/glsl-function-fract.html
|
||||
conformance/glsl/functions/glsl-function-length.html
|
||||
conformance/glsl/functions/glsl-function-lessThan.html
|
||||
conformance/glsl/functions/glsl-function-max-float.html
|
||||
conformance/glsl/functions/glsl-function-max-gentype.html
|
||||
conformance/glsl/functions/glsl-function-min-float.html
|
||||
conformance/glsl/functions/glsl-function-min-gentype.html
|
||||
conformance/glsl/functions/glsl-function-mix-float.html
|
||||
conformance/glsl/functions/glsl-function-mix-gentype.html
|
||||
conformance/glsl/functions/glsl-function-mod-float.html
|
||||
conformance/glsl/functions/glsl-function-mod-gentype.html
|
||||
conformance/glsl/functions/glsl-function-normalize.html
|
||||
conformance/glsl/functions/glsl-function-reflect.html
|
||||
conformance/glsl/functions/glsl-function-refract.html
|
||||
conformance/glsl/functions/glsl-function-sign.html
|
||||
conformance/glsl/functions/glsl-function-sin.html
|
||||
conformance/glsl/functions/glsl-function-smoothstep-float.html
|
||||
conformance/glsl/functions/glsl-function-smoothstep-gentype.html
|
||||
conformance/glsl/functions/glsl-function-step-float.html
|
||||
conformance/glsl/functions/glsl-function-step-gentype.html
|
||||
conformance/glsl/functions/glsl-function.html
|
||||
conformance/glsl/implicit/00_test_list.txt
|
||||
conformance/glsl/implicit/add_int_float.vert.html
|
||||
conformance/glsl/implicit/add_int_mat2.vert.html
|
||||
conformance/glsl/implicit/add_int_mat3.vert.html
|
||||
conformance/glsl/implicit/add_int_mat4.vert.html
|
||||
conformance/glsl/implicit/add_int_vec2.vert.html
|
||||
conformance/glsl/implicit/add_int_vec3.vert.html
|
||||
conformance/glsl/implicit/add_int_vec4.vert.html
|
||||
conformance/glsl/implicit/add_ivec2_vec2.vert.html
|
||||
conformance/glsl/implicit/add_ivec3_vec3.vert.html
|
||||
conformance/glsl/implicit/add_ivec4_vec4.vert.html
|
||||
conformance/glsl/implicit/assign_int_to_float.vert.html
|
||||
conformance/glsl/implicit/assign_ivec2_to_vec2.vert.html
|
||||
conformance/glsl/implicit/assign_ivec3_to_vec3.vert.html
|
||||
conformance/glsl/implicit/assign_ivec4_to_vec4.vert.html
|
||||
conformance/glsl/implicit/construct_struct.vert.html
|
||||
conformance/glsl/implicit/divide_int_float.vert.html
|
||||
conformance/glsl/implicit/divide_int_mat2.vert.html
|
||||
conformance/glsl/implicit/divide_int_mat3.vert.html
|
||||
conformance/glsl/implicit/divide_int_mat4.vert.html
|
||||
conformance/glsl/implicit/divide_int_vec2.vert.html
|
||||
conformance/glsl/implicit/divide_int_vec3.vert.html
|
||||
conformance/glsl/implicit/divide_int_vec4.vert.html
|
||||
conformance/glsl/implicit/divide_ivec2_vec2.vert.html
|
||||
conformance/glsl/implicit/divide_ivec3_vec3.vert.html
|
||||
conformance/glsl/implicit/divide_ivec4_vec4.vert.html
|
||||
conformance/glsl/implicit/equal_int_float.vert.html
|
||||
conformance/glsl/implicit/equal_ivec2_vec2.vert.html
|
||||
conformance/glsl/implicit/equal_ivec3_vec3.vert.html
|
||||
conformance/glsl/implicit/equal_ivec4_vec4.vert.html
|
||||
conformance/glsl/implicit/function_int_float.vert.html
|
||||
conformance/glsl/implicit/function_ivec2_vec2.vert.html
|
||||
conformance/glsl/implicit/function_ivec3_vec3.vert.html
|
||||
conformance/glsl/implicit/function_ivec4_vec4.vert.html
|
||||
conformance/glsl/implicit/greater_than.vert.html
|
||||
conformance/glsl/implicit/greater_than_equal.vert.html
|
||||
conformance/glsl/implicit/less_than.vert.html
|
||||
conformance/glsl/implicit/less_than_equal.vert.html
|
||||
conformance/glsl/implicit/multiply_int_float.vert.html
|
||||
conformance/glsl/implicit/multiply_int_mat2.vert.html
|
||||
conformance/glsl/implicit/multiply_int_mat3.vert.html
|
||||
conformance/glsl/implicit/multiply_int_mat4.vert.html
|
||||
conformance/glsl/implicit/multiply_int_vec2.vert.html
|
||||
conformance/glsl/implicit/multiply_int_vec3.vert.html
|
||||
conformance/glsl/implicit/multiply_int_vec4.vert.html
|
||||
conformance/glsl/implicit/multiply_ivec2_vec2.vert.html
|
||||
conformance/glsl/implicit/multiply_ivec3_vec3.vert.html
|
||||
conformance/glsl/implicit/multiply_ivec4_vec4.vert.html
|
||||
conformance/glsl/implicit/not_equal_int_float.vert.html
|
||||
conformance/glsl/implicit/not_equal_ivec2_vec2.vert.html
|
||||
conformance/glsl/implicit/not_equal_ivec3_vec3.vert.html
|
||||
conformance/glsl/implicit/not_equal_ivec4_vec4.vert.html
|
||||
conformance/glsl/implicit/subtract_int_float.vert.html
|
||||
conformance/glsl/implicit/subtract_int_mat2.vert.html
|
||||
conformance/glsl/implicit/subtract_int_mat3.vert.html
|
||||
conformance/glsl/implicit/subtract_int_mat4.vert.html
|
||||
conformance/glsl/implicit/subtract_int_vec2.vert.html
|
||||
conformance/glsl/implicit/subtract_int_vec3.vert.html
|
||||
conformance/glsl/implicit/subtract_int_vec4.vert.html
|
||||
conformance/glsl/implicit/subtract_ivec2_vec2.vert.html
|
||||
conformance/glsl/implicit/subtract_ivec3_vec3.vert.html
|
||||
conformance/glsl/implicit/subtract_ivec4_vec4.vert.html
|
||||
conformance/glsl/implicit/ternary_int_float.vert.html
|
||||
conformance/glsl/implicit/ternary_ivec2_vec2.vert.html
|
||||
conformance/glsl/implicit/ternary_ivec3_vec3.vert.html
|
||||
conformance/glsl/implicit/ternary_ivec4_vec4.vert.html
|
||||
conformance/glsl/matrices/00_test_list.txt
|
||||
conformance/glsl/matrices/glsl-mat4-to-mat3.html
|
||||
conformance/glsl/misc/00_test_list.txt
|
||||
conformance/glsl/misc/attrib-location-length-limits.html
|
||||
conformance/glsl/misc/embedded-struct-definitions-forbidden.html
|
||||
conformance/glsl/misc/glsl-2types-of-textures-on-same-unit.html
|
||||
conformance/glsl/misc/glsl-function-nodes.html
|
||||
conformance/glsl/misc/glsl-long-variable-names.html
|
||||
conformance/glsl/misc/glsl-vertex-branch.html
|
||||
conformance/glsl/misc/include.vs
|
||||
conformance/glsl/misc/non-ascii-comments.vert.html
|
||||
conformance/glsl/misc/non-ascii.vert.html
|
||||
conformance/glsl/misc/re-compile-re-link.html
|
||||
conformance/glsl/misc/shader-with-256-character-identifier.frag.html
|
||||
conformance/glsl/misc/shader-with-257-character-identifier.frag.html
|
||||
conformance/glsl/misc/shader-with-_webgl-identifier.vert.html
|
||||
conformance/glsl/misc/shader-with-arbitrary-indexing.frag.html
|
||||
conformance/glsl/misc/shader-with-arbitrary-indexing.vert.html
|
||||
conformance/glsl/misc/shader-with-attrib-array.vert.html
|
||||
conformance/glsl/misc/shader-with-attrib-struct.vert.html
|
||||
conformance/glsl/misc/shader-with-clipvertex.vert.html
|
||||
conformance/glsl/misc/shader-with-comma-assignment.html
|
||||
conformance/glsl/misc/shader-with-comma-conditional-assignment.html
|
||||
conformance/glsl/misc/shader-with-conditional-scoping.html
|
||||
conformance/glsl/misc/shader-with-default-precision.frag.html
|
||||
conformance/glsl/misc/shader-with-default-precision.vert.html
|
||||
conformance/glsl/misc/shader-with-define-line-continuation.frag.html
|
||||
conformance/glsl/misc/shader-with-dfdx-no-ext.frag.html
|
||||
conformance/glsl/misc/shader-with-dfdx.frag.html
|
||||
conformance/glsl/misc/shader-with-do-scoping.html
|
||||
conformance/glsl/misc/shader-with-error-directive.html
|
||||
conformance/glsl/misc/shader-with-explicit-int-cast.vert.html
|
||||
conformance/glsl/misc/shader-with-float-return-value.frag.html
|
||||
conformance/glsl/misc/shader-with-for-loop.html
|
||||
conformance/glsl/misc/shader-with-for-scoping.html
|
||||
conformance/glsl/misc/shader-with-frag-depth.frag.html
|
||||
conformance/glsl/misc/shader-with-function-recursion.frag.html
|
||||
conformance/glsl/misc/shader-with-function-scoped-struct.html
|
||||
conformance/glsl/misc/shader-with-functional-scoping.html
|
||||
conformance/glsl/misc/shader-with-glcolor.vert.html
|
||||
conformance/glsl/misc/shader-with-gles-1.frag.html
|
||||
conformance/glsl/misc/shader-with-gles-symbol.frag.html
|
||||
conformance/glsl/misc/shader-with-glprojectionmatrix.vert.html
|
||||
conformance/glsl/misc/shader-with-hex-int-constant-macro.html
|
||||
conformance/glsl/misc/shader-with-implicit-vec3-to-vec4-cast.vert.html
|
||||
conformance/glsl/misc/shader-with-include.vert.html
|
||||
conformance/glsl/misc/shader-with-int-return-value.frag.html
|
||||
conformance/glsl/misc/shader-with-invalid-identifier.frag.html
|
||||
conformance/glsl/misc/shader-with-ivec2-return-value.frag.html
|
||||
conformance/glsl/misc/shader-with-ivec3-return-value.frag.html
|
||||
conformance/glsl/misc/shader-with-ivec4-return-value.frag.html
|
||||
conformance/glsl/misc/shader-with-limited-indexing.frag.html
|
||||
conformance/glsl/misc/shader-with-line-directive.html
|
||||
conformance/glsl/misc/shader-with-long-line.html
|
||||
conformance/glsl/misc/shader-with-non-ascii-error.frag.html
|
||||
conformance/glsl/misc/shader-with-precision.frag.html
|
||||
conformance/glsl/misc/shader-with-quoted-error.frag.html
|
||||
conformance/glsl/misc/shader-with-undefined-preprocessor-symbol.frag.html
|
||||
conformance/glsl/misc/shader-with-uniform-in-loop-condition.vert.html
|
||||
conformance/glsl/misc/shader-with-vec2-return-value.frag.html
|
||||
conformance/glsl/misc/shader-with-vec3-return-value.frag.html
|
||||
conformance/glsl/misc/shader-with-vec4-return-value.frag.html
|
||||
conformance/glsl/misc/shader-with-vec4-vec3-vec4-conditional.html
|
||||
conformance/glsl/misc/shader-with-version-100.frag.html
|
||||
conformance/glsl/misc/shader-with-version-100.vert.html
|
||||
conformance/glsl/misc/shader-with-version-120.vert.html
|
||||
conformance/glsl/misc/shader-with-version-130.vert.html
|
||||
conformance/glsl/misc/shader-with-webgl-identifier.vert.html
|
||||
conformance/glsl/misc/shader-without-precision.frag.html
|
||||
conformance/glsl/misc/shared.html
|
||||
conformance/glsl/misc/struct-nesting-exceeds-maximum.html
|
||||
conformance/glsl/misc/struct-nesting-under-maximum.html
|
||||
conformance/glsl/misc/uniform-location-length-limits.html
|
||||
conformance/glsl/reserved/00_test_list.txt
|
||||
conformance/glsl/reserved/_webgl_field.vert.html
|
||||
conformance/glsl/reserved/_webgl_function.vert.html
|
||||
conformance/glsl/reserved/_webgl_struct.vert.html
|
||||
conformance/glsl/reserved/_webgl_variable.vert.html
|
||||
conformance/glsl/reserved/webgl_field.vert.html
|
||||
conformance/glsl/reserved/webgl_function.vert.html
|
||||
conformance/glsl/reserved/webgl_struct.vert.html
|
||||
conformance/glsl/reserved/webgl_variable.vert.html
|
||||
conformance/glsl/samplers/00_test_list.txt
|
||||
conformance/glsl/samplers/glsl-function-texture2d-bias.html
|
||||
conformance/glsl/samplers/glsl-function-texture2dlod.html
|
||||
conformance/glsl/samplers/glsl-function-texture2dproj.html
|
||||
conformance/glsl/variables/00_test_list.txt
|
||||
conformance/glsl/variables/gl-fragcoord.html
|
||||
conformance/glsl/variables/gl-frontfacing.html
|
||||
conformance/glsl/variables/gl-pointcoord.html
|
||||
conformance/limits/00_test_list.txt
|
||||
conformance/limits/gl-max-texture-dimensions.html
|
||||
conformance/limits/gl-min-attribs.html
|
||||
conformance/limits/gl-min-textures.html
|
||||
conformance/limits/gl-min-uniforms.html
|
||||
conformance/misc/00_test_list.txt
|
||||
conformance/misc/bad-arguments-test.html
|
||||
conformance/misc/delayed-drawing.html
|
||||
conformance/misc/error-reporting.html
|
||||
conformance/misc/functions-returning-strings.html
|
||||
conformance/misc/instanceof-test.html
|
||||
conformance/misc/invalid-passed-params.html
|
||||
conformance/misc/is-object.html
|
||||
conformance/misc/null-object-behaviour.html
|
||||
conformance/misc/object-deletion-behaviour.html
|
||||
conformance/misc/shader-precision-format.html
|
||||
conformance/misc/type-conversion-test.html
|
||||
conformance/misc/uninitialized-test.html
|
||||
conformance/misc/webgl-specific.html
|
||||
conformance/more/00_test_list.txt
|
||||
conformance/more/README.md
|
||||
conformance/more/all_tests.html
|
||||
conformance/more/all_tests_linkonly.html
|
||||
conformance/more/all_tests_sequential.html
|
||||
conformance/more/conformance/argGenerators-A.js
|
||||
conformance/more/conformance/argGenerators-B1.js
|
||||
conformance/more/conformance/argGenerators-B2.js
|
||||
conformance/more/conformance/argGenerators-B3.js
|
||||
conformance/more/conformance/argGenerators-B4.js
|
||||
conformance/more/conformance/argGenerators-C.js
|
||||
conformance/more/conformance/argGenerators-D_G.js
|
||||
conformance/more/conformance/argGenerators-G_I.js
|
||||
conformance/more/conformance/argGenerators-L_S.js
|
||||
conformance/more/conformance/argGenerators-S_V.js
|
||||
conformance/more/conformance/badArgsArityLessThanArgc.html
|
||||
conformance/more/conformance/constants.html
|
||||
conformance/more/conformance/fuzzTheAPI.html
|
||||
conformance/more/conformance/getContext.html
|
||||
conformance/more/conformance/methods.html
|
||||
conformance/more/conformance/quickCheckAPI-A.html
|
||||
conformance/more/conformance/quickCheckAPI-B1.html
|
||||
conformance/more/conformance/quickCheckAPI-B2.html
|
||||
conformance/more/conformance/quickCheckAPI-B3.html
|
||||
conformance/more/conformance/quickCheckAPI-B4.html
|
||||
conformance/more/conformance/quickCheckAPI-C.html
|
||||
conformance/more/conformance/quickCheckAPI-D_G.html
|
||||
conformance/more/conformance/quickCheckAPI-G_I.html
|
||||
conformance/more/conformance/quickCheckAPI-L_S.html
|
||||
conformance/more/conformance/quickCheckAPI-S_V.html
|
||||
conformance/more/conformance/quickCheckAPI.js
|
||||
conformance/more/conformance/quickCheckAPIBadArgs.html
|
||||
conformance/more/conformance/webGLArrays.html
|
||||
conformance/more/demos/opengl_web.html
|
||||
conformance/more/demos/video.html
|
||||
conformance/more/functions/bindBuffer.html
|
||||
conformance/more/functions/bindBufferBadArgs.html
|
||||
conformance/more/functions/bindFramebufferLeaveNonZero.html
|
||||
conformance/more/functions/bufferData.html
|
||||
conformance/more/functions/bufferDataBadArgs.html
|
||||
conformance/more/functions/bufferSubData.html
|
||||
conformance/more/functions/bufferSubDataBadArgs.html
|
||||
conformance/more/functions/copyTexImage2D.html
|
||||
conformance/more/functions/copyTexImage2DBadArgs.html
|
||||
conformance/more/functions/copyTexSubImage2D.html
|
||||
conformance/more/functions/copyTexSubImage2DBadArgs.html
|
||||
conformance/more/functions/deleteBufferBadArgs.html
|
||||
conformance/more/functions/drawArrays.html
|
||||
conformance/more/functions/drawArraysOutOfBounds.html
|
||||
conformance/more/functions/drawElements.html
|
||||
conformance/more/functions/drawElementsBadArgs.html
|
||||
conformance/more/functions/isTests.html
|
||||
conformance/more/functions/readPixels.html
|
||||
conformance/more/functions/readPixelsBadArgs.html
|
||||
conformance/more/functions/texImage2D.html
|
||||
conformance/more/functions/texImage2DBadArgs.html
|
||||
conformance/more/functions/texImage2DHTML.html
|
||||
conformance/more/functions/texImage2DHTMLBadArgs.html
|
||||
conformance/more/functions/texSubImage2D.html
|
||||
conformance/more/functions/texSubImage2DBadArgs.html
|
||||
conformance/more/functions/texSubImage2DHTML.html
|
||||
conformance/more/functions/texSubImage2DHTMLBadArgs.html
|
||||
conformance/more/functions/uniformMatrix.html
|
||||
conformance/more/functions/uniformMatrixBadArgs.html
|
||||
conformance/more/functions/uniformf.html
|
||||
conformance/more/functions/uniformfArrayLen1.html
|
||||
conformance/more/functions/uniformfBadArgs.html
|
||||
conformance/more/functions/uniformi.html
|
||||
conformance/more/functions/uniformiBadArgs.html
|
||||
conformance/more/functions/vertexAttrib.html
|
||||
conformance/more/functions/vertexAttribBadArgs.html
|
||||
conformance/more/functions/vertexAttribPointer.html
|
||||
conformance/more/functions/vertexAttribPointerBadArgs.html
|
||||
conformance/more/glsl/arrayOutOfBounds.html
|
||||
conformance/more/glsl/longLoops.html
|
||||
conformance/more/glsl/uniformOutOfBounds.html
|
||||
conformance/more/glsl/unusedAttribsUniforms.html
|
||||
conformance/more/index.html
|
||||
conformance/more/performance/CPUvsGPU.html
|
||||
conformance/more/performance/bandwidth.html
|
||||
conformance/more/performance/jsGCPause.html
|
||||
conformance/more/performance/jsMatrixMult.html
|
||||
conformance/more/performance/jsToGLOverhead.html
|
||||
conformance/more/unit.css
|
||||
conformance/more/unit.js
|
||||
conformance/more/util.js
|
||||
conformance/programs/00_test_list.txt
|
||||
conformance/programs/get-active-test.html
|
||||
conformance/programs/gl-bind-attrib-location-test.html
|
||||
conformance/programs/gl-get-active-attribute.html
|
||||
conformance/programs/gl-get-active-uniform.html
|
||||
conformance/programs/gl-getshadersource.html
|
||||
conformance/programs/gl-shader-test.html
|
||||
conformance/programs/invalid-UTF-16.html
|
||||
conformance/programs/program-test.html
|
||||
conformance/reading/00_test_list.txt
|
||||
conformance/reading/read-pixels-pack-alignment.html
|
||||
conformance/reading/read-pixels-test.html
|
||||
conformance/renderbuffers/00_test_list.txt
|
||||
conformance/renderbuffers/framebuffer-object-attachment.html
|
||||
conformance/renderbuffers/framebuffer-test.html
|
||||
conformance/renderbuffers/renderbuffer-initialization.html
|
||||
conformance/rendering/00_test_list.txt
|
||||
conformance/rendering/draw-arrays-out-of-bounds.html
|
||||
conformance/rendering/draw-elements-out-of-bounds.html
|
||||
conformance/rendering/gl-clear.html
|
||||
conformance/rendering/gl-drawelements.html
|
||||
conformance/rendering/gl-scissor-test.html
|
||||
conformance/rendering/line-loop-tri-fan.html
|
||||
conformance/rendering/more-than-65536-indices.html
|
||||
conformance/rendering/point-size.html
|
||||
conformance/rendering/triangle.html
|
||||
conformance/resources/3x3.png
|
||||
conformance/resources/blue-1x1.jpg
|
||||
conformance/resources/boolUniformShader.vert
|
||||
conformance/resources/bug-32888-texture.png
|
||||
conformance/resources/floatUniformShader.vert
|
||||
conformance/resources/fragmentShader.frag
|
||||
conformance/resources/glsl-conformance-test.js
|
||||
conformance/resources/glsl-feature-tests.css
|
||||
conformance/resources/glsl-generator.js
|
||||
conformance/resources/gray-ramp-256-with-128-alpha.png
|
||||
conformance/resources/gray-ramp-256.png
|
||||
conformance/resources/gray-ramp-default-gamma.png
|
||||
conformance/resources/gray-ramp-gamma0.1.png
|
||||
conformance/resources/gray-ramp-gamma1.0.png
|
||||
conformance/resources/gray-ramp-gamma2.0.png
|
||||
conformance/resources/gray-ramp-gamma4.0.png
|
||||
conformance/resources/gray-ramp-gamma9.0.png
|
||||
conformance/resources/gray-ramp.png
|
||||
conformance/resources/green-2x2-16bit.png
|
||||
conformance/resources/intArrayUniformShader.vert
|
||||
conformance/resources/intUniformShader.vert
|
||||
conformance/resources/matUniformShader.vert
|
||||
conformance/resources/noopUniformShader.frag
|
||||
conformance/resources/noopUniformShader.vert
|
||||
conformance/resources/npot-video.mp4
|
||||
conformance/resources/npot-video.theora.ogv
|
||||
conformance/resources/npot-video.webmvp8.webm
|
||||
conformance/resources/pnglib.js
|
||||
conformance/resources/red-green.mp4
|
||||
conformance/resources/red-green.png
|
||||
conformance/resources/red-green.theora.ogv
|
||||
conformance/resources/red-green.webmvp8.webm
|
||||
conformance/resources/red-indexed.png
|
||||
conformance/resources/samplerUniformShader.frag
|
||||
conformance/resources/small-square-with-cie-rgb-profile.png
|
||||
conformance/resources/small-square-with-colormatch-profile.png
|
||||
conformance/resources/small-square-with-colorspin-profile.jpg
|
||||
conformance/resources/small-square-with-colorspin-profile.png
|
||||
conformance/resources/small-square-with-e-srgb-profile.png
|
||||
conformance/resources/small-square-with-smpte-c-profile.png
|
||||
conformance/resources/small-square-with-srgb-iec61966-2.1-profile.png
|
||||
conformance/resources/structUniformShader.vert
|
||||
conformance/resources/vertexShader.vert
|
||||
conformance/resources/webgl-test-utils.js
|
||||
conformance/resources/webgl-test.js
|
||||
conformance/resources/zero-alpha.png
|
||||
conformance/state/00_test_list.txt
|
||||
conformance/state/gl-enable-enum-test.html
|
||||
conformance/state/gl-enum-tests.html
|
||||
conformance/state/gl-get-calls.html
|
||||
conformance/state/gl-geterror.html
|
||||
conformance/state/gl-getstring.html
|
||||
conformance/state/gl-object-get-calls.html
|
||||
conformance/textures/00_test_list.txt
|
||||
conformance/textures/compressed-tex-image.html
|
||||
conformance/textures/copy-tex-image-and-sub-image-2d.html
|
||||
conformance/textures/gl-pixelstorei.html
|
||||
conformance/textures/gl-teximage.html
|
||||
conformance/textures/origin-clean-conformance.html
|
||||
conformance/textures/tex-image-and-sub-image-2d-with-array-buffer-view.html
|
||||
conformance/textures/tex-image-and-sub-image-2d-with-canvas.html
|
||||
conformance/textures/tex-image-and-sub-image-2d-with-image-data.html
|
||||
conformance/textures/tex-image-and-sub-image-2d-with-image.html
|
||||
conformance/textures/tex-image-and-sub-image-2d-with-video.html
|
||||
conformance/textures/tex-image-and-uniform-binding-bugs.html
|
||||
conformance/textures/tex-image-with-format-and-type.html
|
||||
conformance/textures/tex-image-with-invalid-data.html
|
||||
conformance/textures/tex-input-validation.html
|
||||
conformance/textures/tex-sub-image-2d-bad-args.html
|
||||
conformance/textures/tex-sub-image-2d.html
|
||||
conformance/textures/texparameter-test.html
|
||||
conformance/textures/texture-active-bind-2.html
|
||||
conformance/textures/texture-active-bind.html
|
||||
conformance/textures/texture-clear.html
|
||||
conformance/textures/texture-complete.html
|
||||
conformance/textures/texture-formats-test.html
|
||||
conformance/textures/texture-mips.html
|
||||
conformance/textures/texture-npot-video.html
|
||||
conformance/textures/texture-npot.html
|
||||
conformance/textures/texture-size-cube-maps.html
|
||||
conformance/textures/texture-size.html
|
||||
conformance/textures/texture-transparent-pixels-initialized.html
|
||||
conformance/typedarrays/00_test_list.txt
|
||||
conformance/typedarrays/array-buffer-crash.html
|
||||
conformance/typedarrays/array-buffer-view-crash.html
|
||||
conformance/typedarrays/array-unit-tests.html
|
||||
conformance/uniforms/00_test_list.txt
|
||||
conformance/uniforms/gl-uniform-arrays.html
|
||||
conformance/uniforms/gl-uniform-bool.html
|
||||
conformance/uniforms/gl-uniformmatrix4fv.html
|
||||
conformance/uniforms/gl-unknown-uniform.html
|
||||
conformance/uniforms/null-uniform-location.html
|
||||
conformance/uniforms/uniform-location.html
|
||||
conformance/uniforms/uniform-samplers-test.html
|
||||
resources/cors-util.js
|
||||
resources/desktop-gl-constants.js
|
||||
resources/js-test-pre.js
|
||||
resources/js-test-style.css
|
||||
resources/opengl_logo.jpg
|
||||
resources/thunderbird-logo-64x64.png
|
||||
resources/webgl-logo.png
|
||||
resources/webgl-test-harness.js
|
||||
|
||||
[_wrappers/test_always-fail.html]
|
||||
[_wrappers/test_conformance__attribs__gl-enable-vertex-attrib.html]
|
||||
[_wrappers/test_conformance__attribs__gl-vertex-attrib-zero-issues.html]
|
||||
[_wrappers/test_conformance__attribs__gl-vertex-attrib.html]
|
||||
[_wrappers/test_conformance__attribs__gl-vertexattribpointer-offsets.html]
|
||||
[_wrappers/test_conformance__attribs__gl-vertexattribpointer.html]
|
||||
[_wrappers/test_conformance__buffers__buffer-bind-test.html]
|
||||
[_wrappers/test_conformance__buffers__buffer-data-array-buffer.html]
|
||||
[_wrappers/test_conformance__buffers__index-validation-copies-indices.html]
|
||||
[_wrappers/test_conformance__buffers__index-validation-crash-with-buffer-sub-data.html]
|
||||
[_wrappers/test_conformance__buffers__index-validation-verifies-too-many-indices.html]
|
||||
[_wrappers/test_conformance__buffers__index-validation-with-resized-buffer.html]
|
||||
[_wrappers/test_conformance__buffers__index-validation.html]
|
||||
[_wrappers/test_conformance__canvas__buffer-offscreen-test.html]
|
||||
[_wrappers/test_conformance__canvas__buffer-preserve-test.html]
|
||||
[_wrappers/test_conformance__canvas__canvas-test.html]
|
||||
[_wrappers/test_conformance__canvas__canvas-zero-size.html]
|
||||
[_wrappers/test_conformance__canvas__drawingbuffer-static-canvas-test.html]
|
||||
skip-if = os == 'mac'
|
||||
[_wrappers/test_conformance__canvas__drawingbuffer-test.html]
|
||||
[_wrappers/test_conformance__canvas__viewport-unchanged-upon-resize.html]
|
||||
[_wrappers/test_conformance__context__constants.html]
|
||||
[_wrappers/test_conformance__context__context-attributes-alpha-depth-stencil-antialias.html]
|
||||
skip-if = (os == 'b2g')
|
||||
[_wrappers/test_conformance__context__context-lost-restored.html]
|
||||
[_wrappers/test_conformance__context__context-lost.html]
|
||||
[_wrappers/test_conformance__context__context-type-test.html]
|
||||
[_wrappers/test_conformance__context__incorrect-context-object-behaviour.html]
|
||||
[_wrappers/test_conformance__context__methods.html]
|
||||
[_wrappers/test_conformance__context__premultiplyalpha-test.html]
|
||||
[_wrappers/test_conformance__context__resource-sharing-test.html]
|
||||
[_wrappers/test_conformance__extensions__oes-standard-derivatives.html]
|
||||
[_wrappers/test_conformance__extensions__ext-texture-filter-anisotropic.html]
|
||||
[_wrappers/test_conformance__extensions__oes-texture-float.html]
|
||||
[_wrappers/test_conformance__extensions__oes-vertex-array-object.html]
|
||||
[_wrappers/test_conformance__extensions__webgl-debug-renderer-info.html]
|
||||
[_wrappers/test_conformance__extensions__webgl-debug-shaders.html]
|
||||
[_wrappers/test_conformance__extensions__webgl-compressed-texture-etc1.html]
|
||||
[_wrappers/test_conformance__extensions__webgl-compressed-texture-s3tc.html]
|
||||
[_wrappers/test_conformance__extensions__ext-sRGB.html]
|
||||
[_wrappers/test_conformance__extensions__ext-shader-texture-lod.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-abs.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-acos.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-asin.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-atan.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-atan-xy.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-ceil.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-clamp-float.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-clamp-gentype.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-cos.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-cross.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-distance.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-dot.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-faceforward.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-floor.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-fract.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-length.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-max-float.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-max-gentype.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-min-float.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-min-gentype.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-mix-float.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-mix-gentype.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-mod-float.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-mod-gentype.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-normalize.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-reflect.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-sign.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-sin.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-step-float.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-step-gentype.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-smoothstep-float.html]
|
||||
[_wrappers/test_conformance__glsl__functions__glsl-function-smoothstep-gentype.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__add_int_float.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__add_int_mat2.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__add_int_mat3.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__add_int_mat4.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__add_int_vec2.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__add_int_vec3.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__add_int_vec4.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__add_ivec2_vec2.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__add_ivec3_vec3.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__add_ivec4_vec4.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__assign_int_to_float.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__assign_ivec2_to_vec2.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__assign_ivec3_to_vec3.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__assign_ivec4_to_vec4.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__construct_struct.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__divide_int_float.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__divide_int_mat2.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__divide_int_mat3.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__divide_int_mat4.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__divide_int_vec2.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__divide_int_vec3.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__divide_int_vec4.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__divide_ivec2_vec2.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__divide_ivec3_vec3.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__divide_ivec4_vec4.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__equal_int_float.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__equal_ivec2_vec2.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__equal_ivec3_vec3.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__equal_ivec4_vec4.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__function_int_float.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__function_ivec2_vec2.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__function_ivec3_vec3.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__function_ivec4_vec4.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__greater_than.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__greater_than_equal.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__less_than.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__less_than_equal.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__multiply_int_float.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__multiply_int_mat2.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__multiply_int_mat3.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__multiply_int_mat4.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__multiply_int_vec2.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__multiply_int_vec3.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__multiply_int_vec4.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__multiply_ivec2_vec2.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__multiply_ivec3_vec3.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__multiply_ivec4_vec4.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__not_equal_int_float.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__not_equal_ivec2_vec2.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__not_equal_ivec3_vec3.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__not_equal_ivec4_vec4.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__subtract_int_float.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__subtract_int_mat2.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__subtract_int_mat3.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__subtract_int_mat4.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__subtract_int_vec2.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__subtract_int_vec3.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__subtract_int_vec4.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__subtract_ivec2_vec2.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__subtract_ivec3_vec3.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__subtract_ivec4_vec4.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__ternary_int_float.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__ternary_ivec2_vec2.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__ternary_ivec3_vec3.vert.html]
|
||||
[_wrappers/test_conformance__glsl__implicit__ternary_ivec4_vec4.vert.html]
|
||||
[_wrappers/test_conformance__glsl__misc__attrib-location-length-limits.html]
|
||||
[_wrappers/test_conformance__glsl__misc__embedded-struct-definitions-forbidden.html]
|
||||
[_wrappers/test_conformance__glsl__misc__glsl-function-nodes.html]
|
||||
[_wrappers/test_conformance__glsl__misc__glsl-long-variable-names.html]
|
||||
[_wrappers/test_conformance__glsl__misc__non-ascii-comments.vert.html]
|
||||
[_wrappers/test_conformance__glsl__misc__non-ascii.vert.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-256-character-identifier.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-257-character-identifier.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-_webgl-identifier.vert.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-arbitrary-indexing.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-arbitrary-indexing.vert.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-attrib-array.vert.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-attrib-struct.vert.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-clipvertex.vert.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-default-precision.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-default-precision.vert.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-define-line-continuation.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-dfdx-no-ext.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-dfdx.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-error-directive.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-explicit-int-cast.vert.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-float-return-value.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-frag-depth.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-function-recursion.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-glcolor.vert.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-gles-1.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-gles-symbol.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-glprojectionmatrix.vert.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-implicit-vec3-to-vec4-cast.vert.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-include.vert.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-int-return-value.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-invalid-identifier.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-ivec2-return-value.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-ivec3-return-value.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-ivec4-return-value.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-limited-indexing.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-long-line.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-non-ascii-error.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-precision.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-quoted-error.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-undefined-preprocessor-symbol.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-uniform-in-loop-condition.vert.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-vec2-return-value.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-vec3-return-value.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-vec4-return-value.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-version-100.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-version-100.vert.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-version-120.vert.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-version-130.vert.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-with-webgl-identifier.vert.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shader-without-precision.frag.html]
|
||||
[_wrappers/test_conformance__glsl__misc__shared.html]
|
||||
[_wrappers/test_conformance__glsl__misc__struct-nesting-exceeds-maximum.html]
|
||||
[_wrappers/test_conformance__glsl__misc__struct-nesting-under-maximum.html]
|
||||
[_wrappers/test_conformance__glsl__misc__uniform-location-length-limits.html]
|
||||
[_wrappers/test_conformance__glsl__reserved___webgl_field.vert.html]
|
||||
[_wrappers/test_conformance__glsl__reserved___webgl_function.vert.html]
|
||||
[_wrappers/test_conformance__glsl__reserved___webgl_struct.vert.html]
|
||||
[_wrappers/test_conformance__glsl__reserved___webgl_variable.vert.html]
|
||||
[_wrappers/test_conformance__glsl__reserved__webgl_field.vert.html]
|
||||
[_wrappers/test_conformance__glsl__reserved__webgl_function.vert.html]
|
||||
[_wrappers/test_conformance__glsl__reserved__webgl_struct.vert.html]
|
||||
[_wrappers/test_conformance__glsl__reserved__webgl_variable.vert.html]
|
||||
[_wrappers/test_conformance__glsl__variables__gl-fragcoord.html]
|
||||
[_wrappers/test_conformance__glsl__variables__gl-frontfacing.html]
|
||||
[_wrappers/test_conformance__glsl__variables__gl-pointcoord.html]
|
||||
[_wrappers/test_conformance__limits__gl-min-attribs.html]
|
||||
[_wrappers/test_conformance__limits__gl-max-texture-dimensions.html]
|
||||
[_wrappers/test_conformance__limits__gl-min-textures.html]
|
||||
[_wrappers/test_conformance__limits__gl-min-uniforms.html]
|
||||
[_wrappers/test_conformance__misc__bad-arguments-test.html]
|
||||
[_wrappers/test_conformance__misc__error-reporting.html]
|
||||
[_wrappers/test_conformance__misc__instanceof-test.html]
|
||||
[_wrappers/test_conformance__misc__invalid-passed-params.html]
|
||||
skip-if = (os == 'android') || (os == 'b2g') || (os == 'linux')
|
||||
[_wrappers/test_conformance__misc__is-object.html]
|
||||
[_wrappers/test_conformance__misc__null-object-behaviour.html]
|
||||
[_wrappers/test_conformance__misc__functions-returning-strings.html]
|
||||
[_wrappers/test_conformance__misc__object-deletion-behaviour.html]
|
||||
[_wrappers/test_conformance__misc__shader-precision-format.html]
|
||||
[_wrappers/test_conformance__misc__type-conversion-test.html]
|
||||
skip-if = (os == 'android') || (os == 'b2g') || (os == 'linux')
|
||||
[_wrappers/test_conformance__misc__uninitialized-test.html]
|
||||
skip-if = os == 'android'
|
||||
[_wrappers/test_conformance__misc__webgl-specific.html]
|
||||
[_wrappers/test_conformance__programs__get-active-test.html]
|
||||
[_wrappers/test_conformance__programs__gl-bind-attrib-location-test.html]
|
||||
[_wrappers/test_conformance__programs__gl-get-active-attribute.html]
|
||||
[_wrappers/test_conformance__programs__gl-get-active-uniform.html]
|
||||
[_wrappers/test_conformance__programs__gl-getshadersource.html]
|
||||
[_wrappers/test_conformance__programs__gl-shader-test.html]
|
||||
[_wrappers/test_conformance__programs__invalid-UTF-16.html]
|
||||
[_wrappers/test_conformance__programs__program-test.html]
|
||||
[_wrappers/test_conformance__reading__read-pixels-pack-alignment.html]
|
||||
[_wrappers/test_conformance__reading__read-pixels-test.html]
|
||||
skip-if = (os == 'android') || (os == 'b2g') || (os == 'linux')
|
||||
[_wrappers/test_conformance__renderbuffers__framebuffer-object-attachment.html]
|
||||
skip-if = os == 'android'
|
||||
[_wrappers/test_conformance__renderbuffers__framebuffer-test.html]
|
||||
[_wrappers/test_conformance__renderbuffers__renderbuffer-initialization.html]
|
||||
[_wrappers/test_conformance__rendering__draw-arrays-out-of-bounds.html]
|
||||
[_wrappers/test_conformance__rendering__draw-elements-out-of-bounds.html]
|
||||
[_wrappers/test_conformance__rendering__gl-clear.html]
|
||||
[_wrappers/test_conformance__rendering__gl-drawelements.html]
|
||||
[_wrappers/test_conformance__rendering__gl-scissor-test.html]
|
||||
[_wrappers/test_conformance__rendering__more-than-65536-indices.html]
|
||||
[_wrappers/test_conformance__rendering__point-size.html]
|
||||
[_wrappers/test_conformance__rendering__triangle.html]
|
||||
[_wrappers/test_conformance__rendering__line-loop-tri-fan.html]
|
||||
[_wrappers/test_conformance__state__gl-enable-enum-test.html]
|
||||
[_wrappers/test_conformance__state__gl-enum-tests.html]
|
||||
[_wrappers/test_conformance__state__gl-get-calls.html]
|
||||
[_wrappers/test_conformance__state__gl-geterror.html]
|
||||
[_wrappers/test_conformance__state__gl-getstring.html]
|
||||
[_wrappers/test_conformance__state__gl-object-get-calls.html]
|
||||
[_wrappers/test_conformance__textures__compressed-tex-image.html]
|
||||
[_wrappers/test_conformance__textures__copy-tex-image-and-sub-image-2d.html]
|
||||
[_wrappers/test_conformance__textures__gl-pixelstorei.html]
|
||||
[_wrappers/test_conformance__textures__gl-teximage.html]
|
||||
skip-if = (os == 'android') || (os == 'b2g') || (os == 'linux')
|
||||
[_wrappers/test_conformance__textures__origin-clean-conformance.html]
|
||||
[_wrappers/test_conformance__textures__tex-image-and-sub-image-2d-with-array-buffer-view.html]
|
||||
[_wrappers/test_conformance__textures__tex-image-and-sub-image-2d-with-canvas.html]
|
||||
[_wrappers/test_conformance__textures__tex-image-and-sub-image-2d-with-image-data.html]
|
||||
[_wrappers/test_conformance__textures__tex-image-and-sub-image-2d-with-image.html]
|
||||
[_wrappers/test_conformance__textures__tex-image-and-sub-image-2d-with-video.html]
|
||||
skip-if = (os == 'android') || (os == 'b2g') || (os == 'linux') || (os == 'win')
|
||||
[_wrappers/test_conformance__textures__tex-image-and-uniform-binding-bugs.html]
|
||||
skip-if = (os == 'b2g')
|
||||
[_wrappers/test_conformance__textures__tex-image-with-format-and-type.html]
|
||||
skip-if = (os == 'android') || (os == 'b2g') || (os == 'linux')
|
||||
[_wrappers/test_conformance__textures__tex-image-with-invalid-data.html]
|
||||
[_wrappers/test_conformance__textures__tex-input-validation.html]
|
||||
skip-if = (os == 'android') || (os == 'b2g') || (os == 'linux')
|
||||
[_wrappers/test_conformance__textures__tex-sub-image-2d-bad-args.html]
|
||||
[_wrappers/test_conformance__textures__tex-sub-image-2d.html]
|
||||
[_wrappers/test_conformance__textures__texparameter-test.html]
|
||||
[_wrappers/test_conformance__textures__texture-active-bind-2.html]
|
||||
[_wrappers/test_conformance__textures__texture-active-bind.html]
|
||||
[_wrappers/test_conformance__textures__texture-complete.html]
|
||||
[_wrappers/test_conformance__textures__texture-formats-test.html]
|
||||
[_wrappers/test_conformance__textures__texture-mips.html]
|
||||
[_wrappers/test_conformance__textures__texture-npot-video.html]
|
||||
skip-if = os == 'win'
|
||||
[_wrappers/test_conformance__textures__texture-npot.html]
|
||||
[_wrappers/test_conformance__textures__texture-size.html]
|
||||
skip-if = os == 'android'
|
||||
[_wrappers/test_conformance__textures__texture-size-cube-maps.html]
|
||||
skip-if = os == 'android'
|
||||
[_wrappers/test_conformance__textures__texture-transparent-pixels-initialized.html]
|
||||
[_wrappers/test_conformance__typedarrays__array-buffer-crash.html]
|
||||
[_wrappers/test_conformance__typedarrays__array-buffer-view-crash.html]
|
||||
[_wrappers/test_conformance__typedarrays__array-unit-tests.html]
|
||||
[_wrappers/test_conformance__uniforms__gl-uniform-arrays.html]
|
||||
[_wrappers/test_conformance__uniforms__gl-uniform-bool.html]
|
||||
[_wrappers/test_conformance__uniforms__gl-uniformmatrix4fv.html]
|
||||
[_wrappers/test_conformance__uniforms__gl-unknown-uniform.html]
|
||||
[_wrappers/test_conformance__uniforms__null-uniform-location.html]
|
||||
[_wrappers/test_conformance__uniforms__uniform-location.html]
|
||||
[_wrappers/test_conformance__uniforms__uniform-samplers-test.html]
|
||||
[_wrappers/test_conformance__more__conformance__constants.html]
|
||||
[_wrappers/test_conformance__more__conformance__getContext.html]
|
||||
[_wrappers/test_conformance__more__conformance__methods.html]
|
||||
[_wrappers/test_conformance__more__conformance__quickCheckAPI-A.html]
|
||||
[_wrappers/test_conformance__more__conformance__quickCheckAPI-B1.html]
|
||||
[_wrappers/test_conformance__more__conformance__quickCheckAPI-B2.html]
|
||||
[_wrappers/test_conformance__more__conformance__quickCheckAPI-B3.html]
|
||||
[_wrappers/test_conformance__more__conformance__quickCheckAPI-B4.html]
|
||||
[_wrappers/test_conformance__more__conformance__quickCheckAPI-C.html]
|
||||
[_wrappers/test_conformance__more__conformance__quickCheckAPI-D_G.html]
|
||||
[_wrappers/test_conformance__more__conformance__quickCheckAPI-G_I.html]
|
||||
[_wrappers/test_conformance__more__conformance__quickCheckAPI-L_S.html]
|
||||
[_wrappers/test_conformance__more__conformance__quickCheckAPI-S_V.html]
|
||||
[_wrappers/test_conformance__more__conformance__webGLArrays.html]
|
||||
[_wrappers/test_conformance__more__functions__bindBuffer.html]
|
||||
[_wrappers/test_conformance__more__functions__bindBufferBadArgs.html]
|
||||
[_wrappers/test_conformance__more__functions__bindFramebufferLeaveNonZero.html]
|
||||
[_wrappers/test_conformance__more__functions__bufferData.html]
|
||||
[_wrappers/test_conformance__more__functions__bufferDataBadArgs.html]
|
||||
[_wrappers/test_conformance__more__functions__bufferSubData.html]
|
||||
[_wrappers/test_conformance__more__functions__bufferSubDataBadArgs.html]
|
||||
[_wrappers/test_conformance__more__functions__copyTexImage2D.html]
|
||||
[_wrappers/test_conformance__more__functions__copyTexImage2DBadArgs.html]
|
||||
[_wrappers/test_conformance__more__functions__copyTexSubImage2D.html]
|
||||
[_wrappers/test_conformance__more__functions__copyTexSubImage2DBadArgs.html]
|
||||
[_wrappers/test_conformance__more__functions__deleteBufferBadArgs.html]
|
||||
[_wrappers/test_conformance__more__functions__drawArrays.html]
|
||||
[_wrappers/test_conformance__more__functions__drawArraysOutOfBounds.html]
|
||||
[_wrappers/test_conformance__more__functions__drawElements.html]
|
||||
[_wrappers/test_conformance__more__functions__drawElementsBadArgs.html]
|
||||
[_wrappers/test_conformance__more__functions__isTests.html]
|
||||
[_wrappers/test_conformance__more__functions__readPixels.html]
|
||||
[_wrappers/test_conformance__more__functions__readPixelsBadArgs.html]
|
||||
[_wrappers/test_conformance__more__functions__texImage2D.html]
|
||||
[_wrappers/test_conformance__more__functions__texImage2DBadArgs.html]
|
||||
[_wrappers/test_conformance__more__functions__texImage2DHTML.html]
|
||||
[_wrappers/test_conformance__more__functions__texImage2DHTMLBadArgs.html]
|
||||
[_wrappers/test_conformance__more__functions__texSubImage2D.html]
|
||||
[_wrappers/test_conformance__more__functions__texSubImage2DBadArgs.html]
|
||||
[_wrappers/test_conformance__more__functions__texSubImage2DHTML.html]
|
||||
[_wrappers/test_conformance__more__functions__texSubImage2DHTMLBadArgs.html]
|
||||
[_wrappers/test_conformance__more__functions__uniformf.html]
|
||||
[_wrappers/test_conformance__more__functions__uniformfBadArgs.html]
|
||||
[_wrappers/test_conformance__more__functions__uniformfArrayLen1.html]
|
||||
[_wrappers/test_conformance__more__functions__uniformi.html]
|
||||
[_wrappers/test_conformance__more__functions__uniformiBadArgs.html]
|
||||
[_wrappers/test_conformance__more__functions__uniformMatrix.html]
|
||||
[_wrappers/test_conformance__more__functions__uniformMatrixBadArgs.html]
|
||||
[_wrappers/test_conformance__more__functions__vertexAttrib.html]
|
||||
[_wrappers/test_conformance__more__functions__vertexAttribBadArgs.html]
|
||||
[_wrappers/test_conformance__more__functions__vertexAttribPointer.html]
|
||||
[_wrappers/test_conformance__more__functions__vertexAttribPointerBadArgs.html]
|
||||
[_wrappers/test_conformance__more__glsl__arrayOutOfBounds.html]
|
||||
[_wrappers/test_conformance__more__glsl__uniformOutOfBounds.html]
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE HTML>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Mochitest wrapper for WebGL Conformance Test Suite tests
|
||||
</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="../mochi-wrapper.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src='../mochi-single.html?always-fail.html'>
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE HTML>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Mochitest wrapper for WebGL Conformance Test Suite tests
|
||||
</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="../mochi-wrapper.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src='../mochi-single.html?conformance/attribs/gl-enable-vertex-attrib.html'>
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE HTML>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Mochitest wrapper for WebGL Conformance Test Suite tests
|
||||
</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="../mochi-wrapper.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src='../mochi-single.html?conformance/attribs/gl-vertex-attrib-zero-issues.html'>
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE HTML>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Mochitest wrapper for WebGL Conformance Test Suite tests
|
||||
</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="../mochi-wrapper.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src='../mochi-single.html?conformance/attribs/gl-vertex-attrib.html'>
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE HTML>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Mochitest wrapper for WebGL Conformance Test Suite tests
|
||||
</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="../mochi-wrapper.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src='../mochi-single.html?conformance/attribs/gl-vertexattribpointer-offsets.html'>
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE HTML>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Mochitest wrapper for WebGL Conformance Test Suite tests
|
||||
</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="../mochi-wrapper.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src='../mochi-single.html?conformance/attribs/gl-vertexattribpointer.html'>
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE HTML>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Mochitest wrapper for WebGL Conformance Test Suite tests
|
||||
</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="../mochi-wrapper.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src='../mochi-single.html?conformance/buffers/buffer-bind-test.html'>
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE HTML>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Mochitest wrapper for WebGL Conformance Test Suite tests
|
||||
</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="../mochi-wrapper.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src='../mochi-single.html?conformance/buffers/buffer-data-array-buffer.html'>
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE HTML>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Mochitest wrapper for WebGL Conformance Test Suite tests
|
||||
</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="../mochi-wrapper.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src='../mochi-single.html?conformance/buffers/index-validation-copies-indices.html'>
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE HTML>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Mochitest wrapper for WebGL Conformance Test Suite tests
|
||||
</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="../mochi-wrapper.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src='../mochi-single.html?conformance/buffers/index-validation-crash-with-buffer-sub-data.html'>
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE HTML>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Mochitest wrapper for WebGL Conformance Test Suite tests
|
||||
</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="../mochi-wrapper.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src='../mochi-single.html?conformance/buffers/index-validation-verifies-too-many-indices.html'>
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE HTML>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Mochitest wrapper for WebGL Conformance Test Suite tests
|
||||
</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="../mochi-wrapper.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src='../mochi-single.html?conformance/buffers/index-validation-with-resized-buffer.html'>
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE HTML>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Mochitest wrapper for WebGL Conformance Test Suite tests
|
||||
</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="../mochi-wrapper.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src='../mochi-single.html?conformance/buffers/index-validation.html'>
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE HTML>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Mochitest wrapper for WebGL Conformance Test Suite tests
|
||||
</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="../mochi-wrapper.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src='../mochi-single.html?conformance/canvas/buffer-offscreen-test.html'>
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE HTML>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Mochitest wrapper for WebGL Conformance Test Suite tests
|
||||
</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="../mochi-wrapper.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src='../mochi-single.html?conformance/canvas/buffer-preserve-test.html'>
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE HTML>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Mochitest wrapper for WebGL Conformance Test Suite tests
|
||||
</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="../mochi-wrapper.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src='../mochi-single.html?conformance/canvas/canvas-test.html'>
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|