mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-04 23:08:39 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
395
devtools/client/webconsole/utils.js
Normal file
395
devtools/client/webconsole/utils.js
Normal file
|
|
@ -0,0 +1,395 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {Cc, Ci, Cu, components} = require("chrome");
|
||||
const Services = require("Services");
|
||||
const {LocalizationHelper} = require("devtools/shared/l10n");
|
||||
|
||||
// Match the function name from the result of toString() or toSource().
|
||||
//
|
||||
// Examples:
|
||||
// (function foobar(a, b) { ...
|
||||
// function foobar2(a) { ...
|
||||
// function() { ...
|
||||
const REGEX_MATCH_FUNCTION_NAME = /^\(?function\s+([^(\s]+)\s*\(/;
|
||||
|
||||
// Number of terminal entries for the self-xss prevention to go away
|
||||
const CONSOLE_ENTRY_THRESHOLD = 5;
|
||||
|
||||
const CONSOLE_WORKER_IDS = exports.CONSOLE_WORKER_IDS = [
|
||||
"SharedWorker",
|
||||
"ServiceWorker",
|
||||
"Worker"
|
||||
];
|
||||
|
||||
var WebConsoleUtils = {
|
||||
|
||||
/**
|
||||
* Wrap a string in an nsISupportsString object.
|
||||
*
|
||||
* @param string string
|
||||
* @return nsISupportsString
|
||||
*/
|
||||
supportsString: function (string) {
|
||||
let str = Cc["@mozilla.org/supports-string;1"]
|
||||
.createInstance(Ci.nsISupportsString);
|
||||
str.data = string;
|
||||
return str;
|
||||
},
|
||||
|
||||
/**
|
||||
* Clone an object.
|
||||
*
|
||||
* @param object object
|
||||
* The object you want cloned.
|
||||
* @param boolean recursive
|
||||
* Tells if you want to dig deeper into the object, to clone
|
||||
* recursively.
|
||||
* @param function [filter]
|
||||
* Optional, filter function, called for every property. Three
|
||||
* arguments are passed: key, value and object. Return true if the
|
||||
* property should be added to the cloned object. Return false to skip
|
||||
* the property.
|
||||
* @return object
|
||||
* The cloned object.
|
||||
*/
|
||||
cloneObject: function (object, recursive, filter) {
|
||||
if (typeof object != "object") {
|
||||
return object;
|
||||
}
|
||||
|
||||
let temp;
|
||||
|
||||
if (Array.isArray(object)) {
|
||||
temp = [];
|
||||
Array.forEach(object, function (value, index) {
|
||||
if (!filter || filter(index, value, object)) {
|
||||
temp.push(recursive ? WebConsoleUtils.cloneObject(value) : value);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
temp = {};
|
||||
for (let key in object) {
|
||||
let value = object[key];
|
||||
if (object.hasOwnProperty(key) &&
|
||||
(!filter || filter(key, value, object))) {
|
||||
temp[key] = recursive ? WebConsoleUtils.cloneObject(value) : value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return temp;
|
||||
},
|
||||
|
||||
/**
|
||||
* Copies certain style attributes from one element to another.
|
||||
*
|
||||
* @param nsIDOMNode from
|
||||
* The target node.
|
||||
* @param nsIDOMNode to
|
||||
* The destination node.
|
||||
*/
|
||||
copyTextStyles: function (from, to) {
|
||||
let win = from.ownerDocument.defaultView;
|
||||
let style = win.getComputedStyle(from);
|
||||
to.style.fontFamily = style.getPropertyCSSValue("font-family").cssText;
|
||||
to.style.fontSize = style.getPropertyCSSValue("font-size").cssText;
|
||||
to.style.fontWeight = style.getPropertyCSSValue("font-weight").cssText;
|
||||
to.style.fontStyle = style.getPropertyCSSValue("font-style").cssText;
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a grip for the given value. If the value is an object,
|
||||
* an object wrapper will be created.
|
||||
*
|
||||
* @param mixed value
|
||||
* The value you want to create a grip for, before sending it to the
|
||||
* client.
|
||||
* @param function objectWrapper
|
||||
* If the value is an object then the objectWrapper function is
|
||||
* invoked to give us an object grip. See this.getObjectGrip().
|
||||
* @return mixed
|
||||
* The value grip.
|
||||
*/
|
||||
createValueGrip: function (value, objectWrapper) {
|
||||
switch (typeof value) {
|
||||
case "boolean":
|
||||
return value;
|
||||
case "string":
|
||||
return objectWrapper(value);
|
||||
case "number":
|
||||
if (value === Infinity) {
|
||||
return { type: "Infinity" };
|
||||
} else if (value === -Infinity) {
|
||||
return { type: "-Infinity" };
|
||||
} else if (Number.isNaN(value)) {
|
||||
return { type: "NaN" };
|
||||
} else if (!value && 1 / value === -Infinity) {
|
||||
return { type: "-0" };
|
||||
}
|
||||
return value;
|
||||
case "undefined":
|
||||
return { type: "undefined" };
|
||||
case "object":
|
||||
if (value === null) {
|
||||
return { type: "null" };
|
||||
}
|
||||
// Fall through.
|
||||
case "function":
|
||||
return objectWrapper(value);
|
||||
default:
|
||||
console.error("Failed to provide a grip for value of " + typeof value
|
||||
+ ": " + value);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Determine if the given request mixes HTTP with HTTPS content.
|
||||
*
|
||||
* @param string request
|
||||
* Location of the requested content.
|
||||
* @param string location
|
||||
* Location of the current page.
|
||||
* @return boolean
|
||||
* True if the content is mixed, false if not.
|
||||
*/
|
||||
isMixedHTTPSRequest: function (request, location) {
|
||||
try {
|
||||
let requestURI = Services.io.newURI(request, null, null);
|
||||
let contentURI = Services.io.newURI(location, null, null);
|
||||
return (contentURI.scheme == "https" && requestURI.scheme != "https");
|
||||
} catch (ex) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper function to deduce the name of the provided function.
|
||||
*
|
||||
* @param funtion function
|
||||
* The function whose name will be returned.
|
||||
* @return string
|
||||
* Function name.
|
||||
*/
|
||||
getFunctionName: function (func) {
|
||||
let name = null;
|
||||
if (func.name) {
|
||||
name = func.name;
|
||||
} else {
|
||||
let desc;
|
||||
try {
|
||||
desc = func.getOwnPropertyDescriptor("displayName");
|
||||
} catch (ex) {
|
||||
// Ignore.
|
||||
}
|
||||
if (desc && typeof desc.value == "string") {
|
||||
name = desc.value;
|
||||
}
|
||||
}
|
||||
if (!name) {
|
||||
try {
|
||||
let str = (func.toString() || func.toSource()) + "";
|
||||
name = (str.match(REGEX_MATCH_FUNCTION_NAME) || [])[1];
|
||||
} catch (ex) {
|
||||
// Ignore.
|
||||
}
|
||||
}
|
||||
return name;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the object class name. For example, the |window| object has the Window
|
||||
* class name (based on [object Window]).
|
||||
*
|
||||
* @param object object
|
||||
* The object you want to get the class name for.
|
||||
* @return string
|
||||
* The object class name.
|
||||
*/
|
||||
getObjectClassName: function (object) {
|
||||
if (object === null) {
|
||||
return "null";
|
||||
}
|
||||
if (object === undefined) {
|
||||
return "undefined";
|
||||
}
|
||||
|
||||
let type = typeof object;
|
||||
if (type != "object") {
|
||||
// Grip class names should start with an uppercase letter.
|
||||
return type.charAt(0).toUpperCase() + type.substr(1);
|
||||
}
|
||||
|
||||
let className;
|
||||
|
||||
try {
|
||||
className = ((object + "").match(/^\[object (\S+)\]$/) || [])[1];
|
||||
if (!className) {
|
||||
className = ((object.constructor + "")
|
||||
.match(/^\[object (\S+)\]$/) || [])[1];
|
||||
}
|
||||
if (!className && typeof object.constructor == "function") {
|
||||
className = this.getFunctionName(object.constructor);
|
||||
}
|
||||
} catch (ex) {
|
||||
// Ignore.
|
||||
}
|
||||
|
||||
return className;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if the given value is a grip with an actor.
|
||||
*
|
||||
* @param mixed grip
|
||||
* Value you want to check if it is a grip with an actor.
|
||||
* @return boolean
|
||||
* True if the given value is a grip with an actor.
|
||||
*/
|
||||
isActorGrip: function (grip) {
|
||||
return grip && typeof (grip) == "object" && grip.actor;
|
||||
},
|
||||
|
||||
/**
|
||||
* Value of devtools.selfxss.count preference
|
||||
*
|
||||
* @type number
|
||||
* @private
|
||||
*/
|
||||
_usageCount: 0,
|
||||
get usageCount() {
|
||||
if (WebConsoleUtils._usageCount < CONSOLE_ENTRY_THRESHOLD) {
|
||||
WebConsoleUtils._usageCount =
|
||||
Services.prefs.getIntPref("devtools.selfxss.count");
|
||||
if (Services.prefs.getBoolPref("devtools.chrome.enabled")) {
|
||||
WebConsoleUtils.usageCount = CONSOLE_ENTRY_THRESHOLD;
|
||||
}
|
||||
}
|
||||
return WebConsoleUtils._usageCount;
|
||||
},
|
||||
set usageCount(newUC) {
|
||||
if (newUC <= CONSOLE_ENTRY_THRESHOLD) {
|
||||
WebConsoleUtils._usageCount = newUC;
|
||||
Services.prefs.setIntPref("devtools.selfxss.count", newUC);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* The inputNode "paste" event handler generator. Helps prevent
|
||||
* self-xss attacks
|
||||
*
|
||||
* @param nsIDOMElement inputField
|
||||
* @param nsIDOMElement notificationBox
|
||||
* @returns A function to be added as a handler to 'paste' and
|
||||
*'drop' events on the input field
|
||||
*/
|
||||
pasteHandlerGen: function (inputField, notificationBox, msg, okstring) {
|
||||
let handler = function (event) {
|
||||
if (WebConsoleUtils.usageCount >= CONSOLE_ENTRY_THRESHOLD) {
|
||||
inputField.removeEventListener("paste", handler);
|
||||
inputField.removeEventListener("drop", handler);
|
||||
return true;
|
||||
}
|
||||
if (notificationBox.getNotificationWithValue("selfxss-notification")) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
|
||||
let notification = notificationBox.appendNotification(msg,
|
||||
"selfxss-notification", null,
|
||||
notificationBox.PRIORITY_WARNING_HIGH, null,
|
||||
function (eventType) {
|
||||
// Cleanup function if notification is dismissed
|
||||
if (eventType == "removed") {
|
||||
inputField.removeEventListener("keyup", pasteKeyUpHandler);
|
||||
}
|
||||
});
|
||||
|
||||
function pasteKeyUpHandler(event2) {
|
||||
let value = inputField.value || inputField.textContent;
|
||||
if (value.includes(okstring)) {
|
||||
notificationBox.removeNotification(notification);
|
||||
inputField.removeEventListener("keyup", pasteKeyUpHandler);
|
||||
WebConsoleUtils.usageCount = CONSOLE_ENTRY_THRESHOLD;
|
||||
}
|
||||
}
|
||||
inputField.addEventListener("keyup", pasteKeyUpHandler);
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
};
|
||||
return handler;
|
||||
},
|
||||
};
|
||||
|
||||
exports.Utils = WebConsoleUtils;
|
||||
|
||||
// Localization
|
||||
|
||||
WebConsoleUtils.L10n = function (bundleURI) {
|
||||
this._helper = new LocalizationHelper(bundleURI);
|
||||
};
|
||||
|
||||
WebConsoleUtils.L10n.prototype = {
|
||||
/**
|
||||
* Generates a formatted timestamp string for displaying in console messages.
|
||||
*
|
||||
* @param integer [milliseconds]
|
||||
* Optional, allows you to specify the timestamp in milliseconds since
|
||||
* the UNIX epoch.
|
||||
* @return string
|
||||
* The timestamp formatted for display.
|
||||
*/
|
||||
timestampString: function (milliseconds) {
|
||||
let d = new Date(milliseconds ? milliseconds : null);
|
||||
let hours = d.getHours(), minutes = d.getMinutes();
|
||||
let seconds = d.getSeconds();
|
||||
milliseconds = d.getMilliseconds();
|
||||
let parameters = [hours, minutes, seconds, milliseconds];
|
||||
return this.getFormatStr("timestampFormat", parameters);
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve a localized string.
|
||||
*
|
||||
* @param string name
|
||||
* The string name you want from the Web Console string bundle.
|
||||
* @return string
|
||||
* The localized string.
|
||||
*/
|
||||
getStr: function (name) {
|
||||
try {
|
||||
return this._helper.getStr(name);
|
||||
} catch (ex) {
|
||||
console.error("Failed to get string: " + name);
|
||||
throw ex;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve a localized string formatted with values coming from the given
|
||||
* array.
|
||||
*
|
||||
* @param string name
|
||||
* The string name you want from the Web Console string bundle.
|
||||
* @param array array
|
||||
* The array of values you want in the formatted string.
|
||||
* @return string
|
||||
* The formatted local string.
|
||||
*/
|
||||
getFormatStr: function (name, array) {
|
||||
try {
|
||||
return this._helper.getFormatStr(name, ...array);
|
||||
} catch (ex) {
|
||||
console.error("Failed to format string: " + name);
|
||||
throw ex;
|
||||
}
|
||||
},
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue