merge m-c to fx-team

This commit is contained in:
Tim Taubert 2012-07-11 08:44:05 +02:00
commit ac142b1a94
34 changed files with 2109 additions and 20 deletions

View File

@ -519,6 +519,7 @@
autocheck="false"
hidden="true"
label="&devToolbarMenu.label;"
accesskey="&devToolbarMenu.accesskey;"
key="key_devToolbar"
command="Tools:DevToolbar"/>
<menuitem id="webConsole"

View File

@ -89,6 +89,7 @@
<command id="Tools:Search" oncommand="BrowserSearch.webSearch();"/>
<command id="Tools:Downloads" oncommand="BrowserDownloadsUI();"/>
<command id="Tools:DevToolbar" oncommand="DeveloperToolbar.toggle();" disabled="true"/>
<command id="Tools:DevToolbarFocus" oncommand="DeveloperToolbar.focus();" disabled="true"/>
<command id="Tools:WebConsole" oncommand="HUDConsoleUI.toggleHUD();"/>
<command id="Tools:Inspect" oncommand="InspectorUI.toggleInspectorUI();" disabled="true"/>
<command id="Tools:Debugger" oncommand="DebuggerUI.toggleDebugger();" disabled="true"/>
@ -225,6 +226,8 @@
#endif
<key id="key_openAddons" key="&addons.commandkey;" command="Tools:Addons" modifiers="accel,shift"/>
<key id="key_errorConsole" key="&errorConsoleCmd.commandkey;" oncommand="toJavaScriptConsole();" modifiers="accel,shift" disabled="true"/>
<key id="key_devToolbar" keycode="&devToolbar.keycode;" modifiers="shift"
keytext="&devToolbar.keytext;" command="Tools:DevToolbarFocus"/>
<key id="key_webConsole" key="&webConsoleCmd.commandkey;" oncommand="HUDConsoleUI.toggleHUD();"
#ifdef XP_MACOSX
modifiers="accel,alt"

View File

@ -1394,6 +1394,7 @@ var gBrowserInit = {
if (devToolbarEnabled) {
document.getElementById("menu_devToolbar").hidden = false;
document.getElementById("Tools:DevToolbar").removeAttribute("disabled");
document.getElementById("Tools:DevToolbarFocus").removeAttribute("disabled");
#ifdef MENUBAR_CAN_AUTOHIDE
document.getElementById("appmenu_devToolbar").hidden = false;
#endif

View File

@ -148,6 +148,7 @@ _BROWSER_FILES = \
browser_bug664672.js \
browser_bug710878.js \
browser_bug719271.js \
browser_bug724239.js \
browser_bug735471.js \
browser_bug743421.js \
browser_bug749738.js \

View File

@ -0,0 +1,28 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
waitForExplicitFinish();
BrowserOpenTab();
let tab = gBrowser.selectedTab;
let browser = tab.linkedBrowser;
registerCleanupFunction(function () { gBrowser.removeTab(tab); });
whenBrowserLoaded(browser, function () {
browser.loadURI("http://example.com/");
whenBrowserLoaded(browser, function () {
ok(!gBrowser.canGoBack, "about:newtab wasn't added to the session history");
finish();
});
});
}
function whenBrowserLoaded(aBrowser, aCallback) {
aBrowser.addEventListener("load", function onLoad() {
aBrowser.removeEventListener("load", onLoad, true);
executeSoon(aCallback);
}, true);
}

View File

@ -23,6 +23,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "LayoutHelpers",
XPCOMUtils.defineLazyModuleGetter(this, "console",
"resource:///modules/devtools/Console.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
"resource://gre/modules/AddonManager.jsm");
let prefSvc = "@mozilla.org/preferences-service;1";
XPCOMUtils.defineLazyGetter(this, "prefBranch", function() {
let prefService = Cc[prefSvc].getService(Ci.nsIPrefService);
@ -30,6 +33,7 @@ XPCOMUtils.defineLazyGetter(this, "prefBranch", function() {
});
Cu.import("resource:///modules/devtools/GcliTiltCommands.jsm", {});
Cu.import("resource:///modules/devtools/GcliCookieCommands.jsm", {});
/**
* A place to store the names of the commands that we have added as a result of
@ -332,6 +336,51 @@ gcli.addCommand({
}
});
/**
* Restart command
*
* @param boolean nocache
* Disables loading content from cache upon restart.
*
* Examples :
* >> restart
* - restarts browser immediately
* >> restart --nocache
* - restarts immediately and starts Firefox without using cache
*/
gcli.addCommand({
name: "restart",
description: gcli.lookup("restartFirefoxDesc"),
params: [
{
name: "nocache",
type: "boolean",
defaultValue: false,
description: gcli.lookup("restartFirefoxNocacheDesc")
}
],
returnType: "string",
exec: function Restart(args, context) {
let canceled = Cc["@mozilla.org/supports-PRBool;1"]
.createInstance(Ci.nsISupportsPRBool);
Services.obs.notifyObservers(canceled, "quit-application-requested", "restart");
if (canceled.data) {
return gcli.lookup("restartFirefoxRequestCancelled");
}
// disable loading content from cache.
if (args.nocache) {
Services.appinfo.invalidateCachesOnRestart();
}
// restart
Cc['@mozilla.org/toolkit/app-startup;1']
.getService(Ci.nsIAppStartup)
.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
return gcli.lookup("restartFirefoxRestarting");
}
});
/**
* 'inspect' command
*/
@ -542,3 +591,615 @@ gcli.addCommand({
return promise;
}
});
/**
* 'export' command
*/
gcli.addCommand({
name: "export",
description: gcli.lookup("exportDesc"),
});
/**
* The 'export html' command. This command allows the user to export the page to
* HTML after they do DOM changes.
*/
gcli.addCommand({
name: "export html",
description: gcli.lookup("exportHtmlDesc"),
exec: function(args, context) {
let document = context.environment.contentDocument;
let window = document.defaultView;
let page = document.documentElement.outerHTML;
window.open('data:text/plain;charset=utf8,' + encodeURIComponent(page));
}
});
/**
* 'pagemod' command
*/
gcli.addCommand({
name: "pagemod",
description: gcli.lookup("pagemodDesc"),
});
/**
* The 'pagemod replace' command. This command allows the user to search and
* replace within text nodes and attributes.
*/
gcli.addCommand({
name: "pagemod replace",
description: gcli.lookup("pagemodReplaceDesc"),
params: [
{
name: "search",
type: "string",
description: gcli.lookup("pagemodReplaceSearchDesc"),
},
{
name: "replace",
type: "string",
description: gcli.lookup("pagemodReplaceReplaceDesc"),
},
{
name: "ignoreCase",
type: "boolean",
description: gcli.lookup("pagemodReplaceIgnoreCaseDesc"),
},
{
name: "selector",
type: "string",
description: gcli.lookup("pagemodReplaceSelectorDesc"),
defaultValue: "*:not(script):not(style):not(embed):not(object):not(frame):not(iframe):not(frameset)",
},
{
name: "root",
type: "node",
description: gcli.lookup("pagemodReplaceRootDesc"),
defaultValue: null,
},
{
name: "attrOnly",
type: "boolean",
description: gcli.lookup("pagemodReplaceAttrOnlyDesc"),
},
{
name: "contentOnly",
type: "boolean",
description: gcli.lookup("pagemodReplaceContentOnlyDesc"),
},
{
name: "attributes",
type: "string",
description: gcli.lookup("pagemodReplaceAttributesDesc"),
defaultValue: null,
},
],
exec: function(args, context) {
let document = context.environment.contentDocument;
let searchTextNodes = !args.attrOnly;
let searchAttributes = !args.contentOnly;
let regexOptions = args.ignoreCase ? 'ig' : 'g';
let search = new RegExp(escapeRegex(args.search), regexOptions);
let attributeRegex = null;
if (args.attributes) {
attributeRegex = new RegExp(args.attributes, regexOptions);
}
let root = args.root || document;
let elements = root.querySelectorAll(args.selector);
elements = Array.prototype.slice.call(elements);
let replacedTextNodes = 0;
let replacedAttributes = 0;
function replaceAttribute() {
replacedAttributes++;
return args.replace;
}
function replaceTextNode() {
replacedTextNodes++;
return args.replace;
}
for (let i = 0; i < elements.length; i++) {
let element = elements[i];
if (searchTextNodes) {
for (let y = 0; y < element.childNodes.length; y++) {
let node = element.childNodes[y];
if (node.nodeType == node.TEXT_NODE) {
node.textContent = node.textContent.replace(search, replaceTextNode);
}
}
}
if (searchAttributes) {
if (!element.attributes) {
continue;
}
for (let y = 0; y < element.attributes.length; y++) {
let attr = element.attributes[y];
if (!attributeRegex || attributeRegex.test(attr.name)) {
attr.value = attr.value.replace(search, replaceAttribute);
}
}
}
}
return gcli.lookupFormat("pagemodReplaceResult",
[elements.length, replacedTextNodes,
replacedAttributes]);
}
});
/**
* 'pagemod remove' command
*/
gcli.addCommand({
name: "pagemod remove",
description: gcli.lookup("pagemodRemoveDesc"),
});
/**
* The 'pagemod remove element' command.
*/
gcli.addCommand({
name: "pagemod remove element",
description: gcli.lookup("pagemodRemoveElementDesc"),
params: [
{
name: "search",
type: "string",
description: gcli.lookup("pagemodRemoveElementSearchDesc"),
},
{
name: "root",
type: "node",
description: gcli.lookup("pagemodRemoveElementRootDesc"),
defaultValue: null,
},
{
name: 'stripOnly',
type: 'boolean',
description: gcli.lookup("pagemodRemoveElementStripOnlyDesc"),
},
{
name: 'ifEmptyOnly',
type: 'boolean',
description: gcli.lookup("pagemodRemoveElementIfEmptyOnlyDesc"),
},
],
exec: function(args, context) {
let document = context.environment.contentDocument;
let root = args.root || document;
let elements = Array.prototype.slice.call(root.querySelectorAll(args.search));
let removed = 0;
for (let i = 0; i < elements.length; i++) {
let element = elements[i];
let parentNode = element.parentNode;
if (!parentNode || !element.removeChild) {
continue;
}
if (args.stripOnly) {
while (element.hasChildNodes()) {
parentNode.insertBefore(element.childNodes[0], element);
}
}
if (!args.ifEmptyOnly || !element.hasChildNodes()) {
element.parentNode.removeChild(element);
removed++;
}
}
return gcli.lookupFormat("pagemodRemoveElementResultMatchedAndRemovedElements",
[elements.length, removed]);
}
});
/**
* The 'pagemod remove attribute' command.
*/
gcli.addCommand({
name: "pagemod remove attribute",
description: gcli.lookup("pagemodRemoveAttributeDesc"),
params: [
{
name: "searchAttributes",
type: "string",
description: gcli.lookup("pagemodRemoveAttributeSearchAttributesDesc"),
},
{
name: "searchElements",
type: "string",
description: gcli.lookup("pagemodRemoveAttributeSearchElementsDesc"),
},
{
name: "root",
type: "node",
description: gcli.lookup("pagemodRemoveAttributeRootDesc"),
defaultValue: null,
},
{
name: "ignoreCase",
type: "boolean",
description: gcli.lookup("pagemodRemoveAttributeIgnoreCaseDesc"),
},
],
exec: function(args, context) {
let document = context.environment.contentDocument;
let root = args.root || document;
let regexOptions = args.ignoreCase ? 'ig' : 'g';
let attributeRegex = new RegExp(args.searchAttributes, regexOptions);
let elements = root.querySelectorAll(args.searchElements);
elements = Array.prototype.slice.call(elements);
let removed = 0;
for (let i = 0; i < elements.length; i++) {
let element = elements[i];
if (!element.attributes) {
continue;
}
var attrs = Array.prototype.slice.call(element.attributes);
for (let y = 0; y < attrs.length; y++) {
let attr = attrs[y];
if (attributeRegex.test(attr.name)) {
element.removeAttribute(attr.name);
removed++;
}
}
}
return gcli.lookupFormat("pagemodRemoveAttributeResult",
[elements.length, removed]);
}
});
/**
* Make a given string safe to use in a regular expression.
*
* @param string aString
* The string you want to use in a regex.
* @return string
* The equivalent of |aString| but safe to use in a regex.
*/
function escapeRegex(aString) {
return aString.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
}
/**
* 'addon' command.
*/
gcli.addCommand({
name: "addon",
description: gcli.lookup("addonDesc")
});
/**
* 'addon list' command.
*/
gcli.addCommand({
name: "addon list",
description: gcli.lookup("addonListDesc"),
params: [{
name: 'type',
type: {
name: 'selection',
data: ["dictionary", "extension", "locale", "plugin", "theme", "all"]
},
defaultValue: 'all',
description: gcli.lookup("addonListTypeDesc"),
}],
exec: function(aArgs, context) {
function representEnabledAddon(aAddon) {
return "<li><![CDATA[" + aAddon.name + "\u2002" + aAddon.version +
getAddonStatus(aAddon) + "]]></li>";
}
function representDisabledAddon(aAddon) {
return "<li class=\"gcli-addon-disabled\">" +
"<![CDATA[" + aAddon.name + "\u2002" + aAddon.version + aAddon.version +
"]]></li>";
}
function getAddonStatus(aAddon) {
let operations = [];
if (aAddon.pendingOperations & AddonManager.PENDING_ENABLE) {
operations.push("PENDING_ENABLE");
}
if (aAddon.pendingOperations & AddonManager.PENDING_DISABLE) {
operations.push("PENDING_DISABLE");
}
if (aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL) {
operations.push("PENDING_UNINSTALL");
}
if (aAddon.pendingOperations & AddonManager.PENDING_INSTALL) {
operations.push("PENDING_INSTALL");
}
if (aAddon.pendingOperations & AddonManager.PENDING_UPGRADE) {
operations.push("PENDING_UPGRADE");
}
if (operations.length) {
return " (" + operations.join(", ") + ")";
}
return "";
}
/**
* Compares two addons by their name. Used in sorting.
*/
function compareAddonNames(aNameA, aNameB) {
return String.localeCompare(aNameA.name, aNameB.name);
}
/**
* Resolves the promise which is the scope (this) of this function, filling
* it with an HTML representation of the passed add-ons.
*/
function list(aType, aAddons) {
if (!aAddons.length) {
this.resolve(gcli.lookup("addonNoneOfType"));
}
// Separate the enabled add-ons from the disabled ones.
let enabledAddons = [];
let disabledAddons = [];
aAddons.forEach(function(aAddon) {
if (aAddon.isActive) {
enabledAddons.push(aAddon);
} else {
disabledAddons.push(aAddon);
}
});
let header;
switch(aType) {
case "dictionary":
header = gcli.lookup("addonListDictionaryHeading");
break;
case "extension":
header = gcli.lookup("addonListExtensionHeading");
break;
case "locale":
header = gcli.lookup("addonListLocaleHeading");
break;
case "plugin":
header = gcli.lookup("addonListPluginHeading");
break;
case "theme":
header = gcli.lookup("addonListThemeHeading");
case "all":
header = gcli.lookup("addonListAllHeading");
break;
default:
header = gcli.lookup("addonListUnknownHeading");
}
// Map and sort the add-ons, and create an HTML list.
this.resolve(header +
"<ol>" +
enabledAddons.sort(compareAddonNames).map(representEnabledAddon).join("") +
disabledAddons.sort(compareAddonNames).map(representDisabledAddon).join("") +
"</ol>");
}
// Create the promise that will be resolved when the add-on listing has
// been finished.
let promise = context.createPromise();
let types = aArgs.type == "all" ? null : [aArgs.type];
AddonManager.getAddonsByTypes(types, list.bind(promise, aArgs.type));
return promise;
}
});
// We need a list of addon names for the enable and disable commands. Because
// getting the name list is async we do not add the commands until we have the
// list.
AddonManager.getAllAddons(function addonAsync(aAddons) {
// We listen for installs to keep our addon list up to date. There is no need
// to listen for uninstalls because uninstalled addons are simply disabled
// until restart (to enable undo functionality).
AddonManager.addAddonListener({
onInstalled: function(aAddon) {
addonNameCache.push({
name: representAddon(aAddon).replace(/\s/g, "_"),
value: aAddon.name
});
},
onUninstalled: function(aAddon) {
let name = representAddon(aAddon).replace(/\s/g, "_");
for (let i = 0; i < addonNameCache.length; i++) {
if(addonNameCache[i].name == name) {
addonNameCache.splice(i, 1);
break;
}
}
},
});
/**
* Returns a string that represents the passed add-on.
*/
function representAddon(aAddon) {
let name = aAddon.name + " " + aAddon.version;
return name.trim();
}
let addonNameCache = [];
// The name parameter, used in "addon enable" and "addon disable."
let nameParameter = {
name: "name",
type: {
name: "selection",
lookup: addonNameCache
},
description: gcli.lookup("addonNameDesc")
};
for (let addon of aAddons) {
addonNameCache.push({
name: representAddon(addon).replace(/\s/g, "_"),
value: addon.name
});
}
/**
* 'addon enable' command.
*/
gcli.addCommand({
name: "addon enable",
description: gcli.lookup("addonEnableDesc"),
params: [nameParameter],
exec: function(aArgs, context) {
/**
* Enables the addon in the passed list which has a name that matches
* according to the passed name comparer, and resolves the promise which
* is the scope (this) of this function to display the result of this
* enable attempt.
*/
function enable(aName, addons) {
// Find the add-on.
let addon = null;
addons.some(function(candidate) {
if (candidate.name == aName) {
addon = candidate;
return true;
} else {
return false;
}
});
let name = representAddon(addon);
if (!addon.userDisabled) {
this.resolve("<![CDATA[" +
gcli.lookupFormat("addonAlreadyEnabled", [name]) + "]]>");
} else {
addon.userDisabled = false;
// nl-nl: {$1} is ingeschakeld.
this.resolve("<![CDATA[" +
gcli.lookupFormat("addonEnabled", [name]) + "]]>");
}
}
let promise = context.createPromise();
// List the installed add-ons, enable one when done listing.
AddonManager.getAllAddons(enable.bind(promise, aArgs.name));
return promise;
}
});
/**
* 'addon disable' command.
*/
gcli.addCommand({
name: "addon disable",
description: gcli.lookup("addonDisableDesc"),
params: [nameParameter],
exec: function(aArgs, context) {
/**
* Like enable, but ... you know ... the exact opposite.
*/
function disable(aName, addons) {
// Find the add-on.
let addon = null;
addons.some(function(candidate) {
if (candidate.name == aName) {
addon = candidate;
return true;
} else {
return false;
}
});
let name = representAddon(addon);
if (addon.userDisabled) {
this.resolve("<![CDATA[" +
gcli.lookupFormat("addonAlreadyDisabled", [name]) + "]]>");
} else {
addon.userDisabled = true;
// nl-nl: {$1} is uitgeschakeld.
this.resolve("<![CDATA[" +
gcli.lookupFormat("addonDisabled", [name]) + "]]>");
}
}
let promise = context.createPromise();
// List the installed add-ons, disable one when done listing.
AddonManager.getAllAddons(disable.bind(promise, aArgs.name));
return promise;
}
});
Services.obs.notifyObservers(null, "gcli_addon_commands_ready", null);
});
/* Responsive Mode commands */
(function gcli_cmd_resize_container() {
function gcli_cmd_resize(args, context) {
let browserDoc = context.environment.chromeDocument;
let browserWindow = browserDoc.defaultView;
let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
mgr.handleGcliCommand(browserWindow,
browserWindow.gBrowser.selectedTab,
this.name,
args);
}
gcli.addCommand({
name: 'resize',
description: gcli.lookup('resizeModeDesc')
});
gcli.addCommand({
name: 'resize on',
description: gcli.lookup('resizeModeOnDesc'),
manual: gcli.lookup('resizeModeManual'),
exec: gcli_cmd_resize
});
gcli.addCommand({
name: 'resize off',
description: gcli.lookup('resizeModeOffDesc'),
manual: gcli.lookup('resizeModeManual'),
exec: gcli_cmd_resize
});
gcli.addCommand({
name: 'resize toggle',
description: gcli.lookup('resizeModeToggleDesc'),
manual: gcli.lookup('resizeModeManual'),
exec: gcli_cmd_resize
});
gcli.addCommand({
name: 'resize to',
description: gcli.lookup('resizeModeToDesc'),
params: [
{
name: 'width',
type: 'number',
description: gcli.lookup("resizePageArgWidthDesc"),
},
{
name: 'height',
type: 'number',
description: gcli.lookup("resizePageArgHeightDesc"),
},
],
exec: gcli_cmd_resize
});
})();

View File

@ -0,0 +1,204 @@
/* 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 EXPORTED_SYMBOLS = [ ];
Components.utils.import("resource:///modules/devtools/gcli.jsm");
// We should really be using nsICookieManager so we can read more than just the
// key/value of cookies. The difficulty is filtering the cookies that are
// relevant to the current page. See
// https://github.com/firebug/firebug/blob/master/extension/content/firebug/cookies/cookieObserver.js#L123
// For details on how this is done with Firebug
/**
* 'cookie' command
*/
gcli.addCommand({
name: "cookie",
description: gcli.lookup("cookieDesc"),
manual: gcli.lookup("cookieManual")
});
/**
* The template for the 'cookie list' command.
*/
var cookieListHtml = "" +
"<table>" +
" <tr>" +
" <th>" + gcli.lookup("cookieListOutKey") + "</th>" +
" <th>" + gcli.lookup("cookieListOutValue") + "</th>" +
" <th>" + gcli.lookup("cookieListOutActions") + "</th>" +
" </tr>" +
" <tr foreach='cookie in ${cookies}'>" +
" <td>${cookie.key}</td>" +
" <td>${cookie.value}</td>" +
" <td>" +
" <span class='gcli-out-shortcut'" +
" onclick='${onclick}' ondblclick='${ondblclick}'" +
" data-command='cookie set ${cookie.key}'" +
" >" + gcli.lookup("cookieListOutEdit") + "</span>" +
" <span class='gcli-out-shortcut'" +
" onclick='${onclick}' ondblclick='${ondblclick}'" +
" data-command='cookie remove ${cookie.key}'" +
" >" + gcli.lookup("cookieListOutRemove") + "</span>" +
" </td>" +
" </tr>" +
"</table>" +
"";
/**
* 'cookie list' command
*/
gcli.addCommand({
name: "cookie list",
description: gcli.lookup("cookieListDesc"),
manual: gcli.lookup("cookieListManual"),
returnType: "string",
exec: function Command_cookieList(args, context) {
// Parse out an array of { key:..., value:... } objects for each cookie
var doc = context.environment.contentDocument;
var cookies = doc.cookie.split("; ").map(function(cookieStr) {
var equalsPos = cookieStr.indexOf("=");
return {
key: cookieStr.substring(0, equalsPos),
value: cookieStr.substring(equalsPos + 1)
};
});
return context.createView({
html: cookieListHtml,
data: {
cookies: cookies,
onclick: createUpdateHandler(context),
ondblclick: createExecuteHandler(context),
}
});
}
});
/**
* 'cookie remove' command
*/
gcli.addCommand({
name: "cookie remove",
description: gcli.lookup("cookieRemoveDesc"),
manual: gcli.lookup("cookieRemoveManual"),
params: [
{
name: "key",
type: "string",
description: gcli.lookup("cookieRemoveKeyDesc"),
}
],
exec: function Command_cookieRemove(args, context) {
let document = context.environment.contentDocument;
let expDate = new Date();
expDate.setDate(expDate.getDate() - 1);
document.cookie = escape(args.key) + "=; expires=" + expDate.toGMTString();
}
});
/**
* 'cookie set' command
*/
gcli.addCommand({
name: "cookie set",
description: gcli.lookup("cookieSetDesc"),
manual: gcli.lookup("cookieSetManual"),
params: [
{
name: "key",
type: "string",
description: gcli.lookup("cookieSetKeyDesc")
},
{
name: "value",
type: "string",
description: gcli.lookup("cookieSetValueDesc")
},
{
group: gcli.lookup("cookieSetOptionsDesc"),
params: [
{
name: "path",
type: "string",
defaultValue: "/",
description: gcli.lookup("cookieSetPathDesc")
},
{
name: "domain",
type: "string",
defaultValue: null,
description: gcli.lookup("cookieSetDomainDesc")
},
{
name: "secure",
type: "boolean",
description: gcli.lookup("cookieSetSecureDesc")
}
]
}
],
exec: function Command_cookieSet(args, context) {
let document = context.environment.contentDocument;
document.cookie = escape(args.key) + "=" + escape(args.value) +
(args.domain ? "; domain=" + args.domain : "") +
(args.path ? "; path=" + args.path : "") +
(args.secure ? "; secure" : "");
}
});
/**
* Helper to find the 'data-command' attribute and call some action on it.
* @see |updateCommand()| and |executeCommand()|
*/
function withCommand(element, action) {
var command = element.getAttribute("data-command");
if (!command) {
command = element.querySelector("*[data-command]")
.getAttribute("data-command");
}
if (command) {
action(command);
}
else {
console.warn("Missing data-command for " + util.findCssSelector(element));
}
}
/**
* Create a handler to update the requisition to contain the text held in the
* first matching data-command attribute under the currentTarget of the event.
* @param context Either a Requisition or an ExecutionContext or another object
* that contains an |update()| function that follows a similar contract.
*/
function createUpdateHandler(context) {
return function(ev) {
withCommand(ev.currentTarget, function(command) {
context.update(command);
});
}
}
/**
* Create a handler to execute the text held in the data-command attribute
* under the currentTarget of the event.
* @param context Either a Requisition or an ExecutionContext or another object
* that contains an |update()| function that follows a similar contract.
*/
function createExecuteHandler(context) {
return function(ev) {
withCommand(ev.currentTarget, function(command) {
context.exec({
visible: true,
typed: command
});
});
}
}

View File

@ -12,12 +12,17 @@ relativesrcdir = browser/devtools/commandline/test
include $(DEPTH)/config/autoconf.mk
MOCHITEST_BROWSER_FILES = \
browser_gcli_addon.js \
browser_gcli_break.js \
browser_gcli_commands.js \
browser_gcli_cookie.js \
browser_gcli_edit.js \
browser_gcli_inspect.js \
browser_gcli_integrate.js \
browser_gcli_pagemod_export.js \
browser_gcli_pref.js \
browser_gcli_responsivemode.js \
browser_gcli_restart.js \
browser_gcli_settings.js \
browser_gcli_web.js \
head.js \
@ -33,3 +38,4 @@ MOCHITEST_BROWSER_FILES += \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,43 @@
function test() {
DeveloperToolbarTest.test("about:blank", function GAT_test() {
function GAT_ready() {
Services.obs.removeObserver(GAT_ready, "gcli_addon_commands_ready", false);
DeveloperToolbarTest.checkInputStatus({
typed: "addon list dictionary",
status: "VALID"
});
DeveloperToolbarTest.checkInputStatus({
typed: "addon list extension",
status: "VALID"
});
DeveloperToolbarTest.checkInputStatus({
typed: "addon list locale",
status: "VALID"
});
DeveloperToolbarTest.checkInputStatus({
typed: "addon list plugin",
status: "VALID"
});
DeveloperToolbarTest.checkInputStatus({
typed: "addon list theme",
status: "VALID"
});
DeveloperToolbarTest.checkInputStatus({
typed: "addon list all",
status: "VALID"
});
DeveloperToolbarTest.checkInputStatus({
typed: "addon disable Test_Plug-in_1.0.0.0",
status: "VALID"
});
DeveloperToolbarTest.checkInputStatus({
typed: "addon enable Test_Plug-in_1.0.0.0",
status: "VALID"
});
DeveloperToolbarTest.exec({ completed: false });
finish();
}
Services.obs.addObserver(GAT_ready, "gcli_addon_commands_ready", false);
});
}

View File

@ -0,0 +1,68 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that the cookie commands works as they should
const TEST_URI = "data:text/html;charset=utf-8,gcli-cookie";
function test() {
DeveloperToolbarTest.test(TEST_URI, function(browser, tab) {
testCookieCommands();
finish();
});
}
function testCookieCommands() {
DeveloperToolbarTest.checkInputStatus({
typed: "cook",
directTabText: "ie",
status: "ERROR"
});
DeveloperToolbarTest.checkInputStatus({
typed: "cookie l",
directTabText: "ist",
status: "ERROR"
});
DeveloperToolbarTest.checkInputStatus({
typed: "cookie list",
status: "VALID",
emptyParameters: [ ]
});
DeveloperToolbarTest.checkInputStatus({
typed: "cookie remove",
status: "ERROR",
emptyParameters: [ " <key>" ]
});
DeveloperToolbarTest.checkInputStatus({
typed: "cookie set",
status: "ERROR",
emptyParameters: [ " <key>", " <value>" ],
});
DeveloperToolbarTest.exec({
typed: "cookie set fruit banana",
args: {
key: "fruit",
value: "banana",
path: "/",
domain: null,
secure: false
},
blankOutput: true,
});
DeveloperToolbarTest.exec({
typed: "cookie list",
outputMatch: /Key/
});
DeveloperToolbarTest.exec({
typed: "cookie remove fruit",
args: { key: "fruit" },
blankOutput: true,
});
}

View File

@ -0,0 +1,272 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that the inspect command works as it should
const TEST_URI = "http://example.com/browser/browser/devtools/commandline/test/browser_gcli_inspect.html";
function test() {
let initialHtml = "";
DeveloperToolbarTest.test(TEST_URI, function(browser, tab) {
initialHtml = content.document.documentElement.innerHTML;
testExportHtml();
testPageModReplace();
testPageModRemoveElement();
testPageModRemoveAttribute();
finish();
});
function testExportHtml() {
DeveloperToolbarTest.checkInputStatus({
typed: "export html",
status: "VALID"
});
let oldOpen = content.open;
let openURL = "";
content.open = function(aUrl) {
openURL = aUrl;
};
DeveloperToolbarTest.exec({ blankOutput: true });
openURL = decodeURIComponent(openURL);
isnot(openURL.indexOf('<html lang="en">'), -1, "export html works: <html>");
isnot(openURL.indexOf("<title>GCLI"), -1, "export html works: <title>");
isnot(openURL.indexOf('<p id="someid">#'), -1, "export html works: <p>");
content.open = oldOpen;
}
function getContent() {
return content.document.documentElement.innerHTML;
}
function resetContent() {
content.document.documentElement.innerHTML = initialHtml;
}
function testPageModReplace() {
DeveloperToolbarTest.checkInputStatus({
typed: "pagemod replace",
emptyParameters: [" <search>", " <replace>", " [ignoreCase]",
" [selector]", " [root]", " [attrOnly]",
" [contentOnly]", " [attributes]"],
status: "ERROR"
});
DeveloperToolbarTest.checkInputStatus({
typed: "pagemod replace some foo",
emptyParameters: [" [ignoreCase]", " [selector]", " [root]",
" [attrOnly]", " [contentOnly]", " [attributes]"],
status: "VALID"
});
DeveloperToolbarTest.checkInputStatus({
typed: "pagemod replace some foo true",
emptyParameters: [" [selector]", " [root]", " [attrOnly]",
" [contentOnly]", " [attributes]"],
status: "VALID"
});
DeveloperToolbarTest.checkInputStatus({
typed: "pagemod replace some foo true --attrOnly",
emptyParameters: [" [selector]", " [root]", " [contentOnly]",
" [attributes]"],
status: "VALID"
});
DeveloperToolbarTest.exec({
typed: "pagemod replace sOme foOBar",
outputMatch: /^[^:]+: 13\. [^:]+: 0\. [^:]+: 0\.\s*$/
});
is(getContent(), initialHtml, "no change in the page");
DeveloperToolbarTest.exec({
typed: "pagemod replace sOme foOBar true",
outputMatch: /^[^:]+: 13\. [^:]+: 2\. [^:]+: 2\.\s*$/
});
isnot(getContent().indexOf('<p class="foOBarclass">.foOBarclass'), -1,
".someclass changed to .foOBarclass");
isnot(getContent().indexOf('<p id="foOBarid">#foOBarid'), -1,
"#someid changed to #foOBarid");
resetContent();
DeveloperToolbarTest.exec({
typed: "pagemod replace some foobar --contentOnly",
outputMatch: /^[^:]+: 13\. [^:]+: 2\. [^:]+: 0\.\s*$/
});
isnot(getContent().indexOf('<p class="someclass">.foobarclass'), -1,
".someclass changed to .foobarclass (content only)");
isnot(getContent().indexOf('<p id="someid">#foobarid'), -1,
"#someid changed to #foobarid (content only)");
resetContent();
DeveloperToolbarTest.exec({
typed: "pagemod replace some foobar --attrOnly",
outputMatch: /^[^:]+: 13\. [^:]+: 0\. [^:]+: 2\.\s*$/
});
isnot(getContent().indexOf('<p class="foobarclass">.someclass'), -1,
".someclass changed to .foobarclass (attr only)");
isnot(getContent().indexOf('<p id="foobarid">#someid'), -1,
"#someid changed to #foobarid (attr only)");
resetContent();
DeveloperToolbarTest.exec({
typed: "pagemod replace some foobar --root head",
outputMatch: /^[^:]+: 2\. [^:]+: 0\. [^:]+: 0\.\s*$/
});
is(getContent(), initialHtml, "nothing changed");
DeveloperToolbarTest.exec({
typed: "pagemod replace some foobar --selector .someclass,div,span",
outputMatch: /^[^:]+: 4\. [^:]+: 1\. [^:]+: 1\.\s*$/
});
isnot(getContent().indexOf('<p class="foobarclass">.foobarclass'), -1,
".someclass changed to .foobarclass");
isnot(getContent().indexOf('<p id="someid">#someid'), -1,
"#someid did not change");
resetContent();
}
function testPageModRemoveElement() {
DeveloperToolbarTest.checkInputStatus({
typed: "pagemod remove",
status: "ERROR"
});
DeveloperToolbarTest.checkInputStatus({
typed: "pagemod remove element",
emptyParameters: [" <search>", " [root]", " [stripOnly]", " [ifEmptyOnly]"],
status: "ERROR"
});
DeveloperToolbarTest.checkInputStatus({
typed: "pagemod remove element foo",
emptyParameters: [" [root]", " [stripOnly]", " [ifEmptyOnly]"],
status: "VALID"
});
DeveloperToolbarTest.exec({
typed: "pagemod remove element p",
outputMatch: /^[^:]+: 3\. [^:]+: 3\.\s*$/
});
is(getContent().indexOf('<p class="someclass">'), -1, "p.someclass removed");
is(getContent().indexOf('<p id="someid">'), -1, "p#someid removed");
is(getContent().indexOf("<p><strong>"), -1, "<p> wrapping <strong> removed");
isnot(getContent().indexOf("<span>"), -1, "<span> not removed");
resetContent();
DeveloperToolbarTest.exec({
typed: "pagemod remove element p head",
outputMatch: /^[^:]+: 0\. [^:]+: 0\.\s*$/
});
is(getContent(), initialHtml, "nothing changed in the page");
DeveloperToolbarTest.exec({
typed: "pagemod remove element p --ifEmptyOnly",
outputMatch: /^[^:]+: 3\. [^:]+: 0\.\s*$/
});
is(getContent(), initialHtml, "nothing changed in the page");
DeveloperToolbarTest.exec({
typed: "pagemod remove element meta,title --ifEmptyOnly",
outputMatch: /^[^:]+: 2\. [^:]+: 1\.\s*$/
});
is(getContent().indexOf("<meta charset="), -1, "<meta> removed");
isnot(getContent().indexOf("<title>"), -1, "<title> not removed");
resetContent();
DeveloperToolbarTest.exec({
typed: "pagemod remove element p --stripOnly",
outputMatch: /^[^:]+: 3\. [^:]+: 3\.\s*$/
});
is(getContent().indexOf('<p class="someclass">'), -1, "p.someclass removed");
is(getContent().indexOf('<p id="someid">'), -1, "p#someid removed");
is(getContent().indexOf("<p><strong>"), -1, "<p> wrapping <strong> removed");
isnot(getContent().indexOf(".someclass"), -1, ".someclass still exists");
isnot(getContent().indexOf("#someid"), -1, "#someid still exists");
isnot(getContent().indexOf("<strong>p"), -1, "<strong> still exists");
resetContent();
}
function testPageModRemoveAttribute() {
DeveloperToolbarTest.checkInputStatus({
typed: "pagemod remove attribute",
emptyParameters: [" <searchAttributes>", " <searchElements>", " [root]", " [ignoreCase]"],
status: "ERROR"
});
DeveloperToolbarTest.checkInputStatus({
typed: "pagemod remove attribute foo bar",
emptyParameters: [" [root]", " [ignoreCase]"],
status: "VALID"
});
DeveloperToolbarTest.exec({
typed: "pagemod remove attribute foo bar",
outputMatch: /^[^:]+: 0\. [^:]+: 0\.\s*$/
});
is(getContent(), initialHtml, "nothing changed in the page");
DeveloperToolbarTest.exec({
typed: "pagemod remove attribute foo p",
outputMatch: /^[^:]+: 3\. [^:]+: 0\.\s*$/
});
is(getContent(), initialHtml, "nothing changed in the page");
DeveloperToolbarTest.exec({
typed: "pagemod remove attribute id p,span",
outputMatch: /^[^:]+: 5\. [^:]+: 1\.\s*$/
});
is(getContent().indexOf('<p id="someid">#someid'), -1,
"p#someid attribute removed");
isnot(getContent().indexOf("<p>#someid"), -1,
"p with someid content still exists");
resetContent();
DeveloperToolbarTest.exec({
typed: "pagemod remove attribute Class p",
outputMatch: /^[^:]+: 3\. [^:]+: 0\.\s*$/
});
is(getContent(), initialHtml, "nothing changed in the page");
DeveloperToolbarTest.exec({
typed: "pagemod remove attribute Class p --ignoreCase",
outputMatch: /^[^:]+: 3\. [^:]+: 1\.\s*$/
});
is(getContent().indexOf('<p class="someclass">.someclass'), -1,
"p.someclass attribute removed");
isnot(getContent().indexOf("<p>.someclass"), -1,
"p with someclass content still exists");
resetContent();
}
}

View File

@ -0,0 +1,58 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
DeveloperToolbarTest.test("about:blank", function GAT_test() {
DeveloperToolbarTest.checkInputStatus({
typed: "resize toggle",
status: "VALID"
});
DeveloperToolbarTest.exec();
ok(isOpen(), "responsive mode is open");
DeveloperToolbarTest.checkInputStatus({
typed: "resize toggle",
status: "VALID"
});
DeveloperToolbarTest.exec();
ok(isClosed(), "responsive mode is closed");
DeveloperToolbarTest.checkInputStatus({
typed: "resize on",
status: "VALID"
});
DeveloperToolbarTest.exec();
ok(isOpen(), "responsive mode is open");
DeveloperToolbarTest.checkInputStatus({
typed: "resize off",
status: "VALID"
});
DeveloperToolbarTest.exec();
ok(isClosed(), "responsive mode is closed");
DeveloperToolbarTest.checkInputStatus({
typed: "resize to 400 400",
status: "VALID"
});
DeveloperToolbarTest.exec();
ok(isOpen(), "responsive mode is open");
DeveloperToolbarTest.checkInputStatus({
typed: "resize off",
status: "VALID"
});
DeveloperToolbarTest.exec();
ok(isClosed(), "responsive mode is closed");
executeSoon(finish);
});
function isOpen() {
return !!gBrowser.selectedTab.__responsiveUI;
}
function isClosed() {
return !isOpen();
}
}

View File

@ -0,0 +1,48 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that restart command works properly (input wise)
const TEST_URI = "data:text/html;charset=utf-8,gcli-command-restart";
function test() {
DeveloperToolbarTest.test(TEST_URI, function(browser, tab) {
testRestart();
finish();
});
}
function testRestart() {
DeveloperToolbarTest.checkInputStatus({
typed: "restart",
markup: "VVVVVVV",
status: "VALID",
emptyParameters: [ " [nocache]" ],
});
DeveloperToolbarTest.checkInputStatus({
typed: "restart ",
markup: "VVVVVVVV",
status: "VALID",
directTabText: "false"
});
DeveloperToolbarTest.checkInputStatus({
typed: "restart t",
markup: "VVVVVVVVI",
status: "ERROR",
directTabText: "rue"
});
DeveloperToolbarTest.checkInputStatus({
typed: "restart --nocache",
markup: "VVVVVVVVVVVVVVVVV",
status: "VALID"
});
DeveloperToolbarTest.checkInputStatus({
typed: "restart --noca",
markup: "VVVVVVVVEEEEEE",
status: "ERROR",
});
}

View File

@ -34,6 +34,38 @@ let ResponsiveUIManager = {
aTab.__responsiveUI = new ResponsiveUI(aWindow, aTab);
}
},
/**
* Handle gcli commands.
*
* @param aWindow the browser window.
* @param aTab the tab targeted.
* @param aCommand the command name.
* @param aArgs command arguments.
*/
handleGcliCommand: function(aWindow, aTab, aCommand, aArgs) {
switch (aCommand) {
case "resize to":
if (!aTab.__responsiveUI) {
aTab.__responsiveUI = new ResponsiveUI(aWindow, aTab);
}
aTab.__responsiveUI.setSize(aArgs.width, aArgs.height);
break;
case "resize on":
if (!aTab.__responsiveUI) {
aTab.__responsiveUI = new ResponsiveUI(aWindow, aTab);
}
break;
case "resize off":
if (aTab.__responsiveUI) {
aTab.__responsiveUI.close();
}
break;
case "resize toggle":
this.toggle(aWindow, aTab);
default:
}
},
}
let presets = [
@ -376,8 +408,8 @@ ResponsiveUI.prototype = {
* @param aHeight height of the browser.
*/
setSize: function RUI_setSize(aWidth, aHeight) {
this.currentWidth = aWidth;
this.currentHeight = aHeight;
this.currentWidth = Math.min(Math.max(aWidth, MIN_WIDTH), MAX_WIDTH);
this.currentHeight = Math.min(Math.max(aHeight, MIN_HEIGHT), MAX_WIDTH);
// We resize the containing stack.
let style = "max-width: %width;" +

View File

@ -110,6 +110,19 @@ DeveloperToolbar.prototype.toggle = function DT_toggle()
}
};
/**
* Called from browser.xul in response to menu-click or keyboard shortcut to
* toggle the toolbar
*/
DeveloperToolbar.prototype.focus = function DT_focus()
{
if (this.visible) {
this._input.focus();
} else {
this.show(true);
}
};
/**
* Even if the user has not clicked on 'Got it' in the intro, we only show it
* once per session.

View File

@ -289,7 +289,8 @@ let Manager = {
case "LocationChange":
ConsoleProgressListener.startMonitor(ConsoleProgressListener
.MONITOR_LOCATION_CHANGE);
ConsoleProgressListener.sendLocation();
ConsoleProgressListener.sendLocation(this.window.location.href,
this.window.document.title);
break;
default:
Cu.reportError("Web Console content: unknown feature " + aFeature);
@ -2225,7 +2226,7 @@ let NetworkMonitor = {
// DNS timing information is available only in when the DNS record is not
// cached.
harTimings.dns = timings.STATUS_RESOLVING ?
harTimings.dns = timings.STATUS_RESOLVING && timings.STATUS_RESOLVED ?
timings.STATUS_RESOLVED.last -
timings.STATUS_RESOLVING.first : -1;
@ -2471,17 +2472,24 @@ let ConsoleProgressListener = {
_checkLocationChange:
function CPL__checkLocationChange(aProgress, aRequest, aState, aStatus)
{
let isStart = aState & Ci.nsIWebProgressListener.STATE_START;
let isStop = aState & Ci.nsIWebProgressListener.STATE_STOP;
let isNetwork = aState & Ci.nsIWebProgressListener.STATE_IS_NETWORK;
let isWindow = aState & Ci.nsIWebProgressListener.STATE_IS_WINDOW;
// Skip non-interesting states.
if (!isStop || !isNetwork || !isWindow ||
if (!isNetwork || !isWindow ||
aProgress.DOMWindow != Manager.window) {
return;
}
this.sendLocation();
if (isStart && aRequest instanceof Ci.nsIChannel) {
this.sendLocation(aRequest.URI.spec, "");
}
else if (isStop) {
this.sendLocation(Manager.window.location.href,
Manager.window.document.title);
}
},
onLocationChange: function() {},
@ -2493,12 +2501,17 @@ let ConsoleProgressListener = {
* Send the location of the current top window to the remote Web Console.
* A "WebConsole:LocationChange" message is sent. The JSON object holds two
* properties: location and title.
*
* @param string aLocation
* Current page address.
* @param string aTitle
* Current page title.
*/
sendLocation: function CPL_sendLocation()
sendLocation: function CPL_sendLocation(aLocation, aTitle)
{
let message = {
"location": Manager.window.location.href,
"title": Manager.window.document.title,
"location": aLocation,
"title": aTitle,
};
Manager.sendMessage("WebConsole:LocationChange", message);
},

View File

@ -10,6 +10,8 @@ const Cu = Components.utils;
const CONSOLEAPI_CLASS_ID = "{b49c18f8-3379-4fc0-8c90-d7772c1a9ff3}";
const MIXED_CONTENT_LEARN_MORE = "https://developer.mozilla.org/en/Security/MixedContent";
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
@ -2150,6 +2152,14 @@ HeadsUpDisplay.prototype = {
urlNode.classList.add("webconsole-msg-url");
linkNode.appendChild(urlNode);
let severity = SEVERITY_LOG;
if(this.isMixedContentLoad(request.url, this.contentLocation)) {
urlNode.classList.add("webconsole-mixed-content");
this.makeMixedContentNode(linkNode);
//If we define a SEVERITY_SECURITY in the future, switch this to SEVERITY_SECURITY
severity = SEVERITY_WARNING;
}
let statusNode = this.chromeDocument.createElementNS(XUL_NS, "label");
statusNode.setAttribute("value", "");
statusNode.classList.add("hud-clickable");
@ -2161,7 +2171,7 @@ HeadsUpDisplay.prototype = {
let messageNode = ConsoleUtils.createMessageNode(this.chromeDocument,
CATEGORY_NETWORK,
SEVERITY_LOG,
severity,
msgNode,
this.hudId,
null,
@ -2951,6 +2961,53 @@ HeadsUpDisplay.prototype = {
this.closeButton.removeEventListener("command",
this.closeButtonOnCommand, false);
},
/**
* Determine whether the request should display a Mixed Content warning
*
* @param string request
* location of the requested content
* @param string contentLocation
* location of the current page
* @return bool
* True if the content is mixed, false if not
*/
isMixedContentLoad: function HUD_isMixedContentLoad(request, contentLocation) {
try {
let requestURIObject = Services.io.newURI(request, null, null);
let contentWindowURI = Services.io.newURI(contentLocation, null, null);
return (contentWindowURI.scheme == "https" && requestURIObject.scheme != "https");
} catch(e) {
return false;
}
},
/**
* Create a mixedContentWarningNode and add it the webconsole output.
*
* @param linkNode
* parent to the requested urlNode
*/
makeMixedContentNode: function HUD_makeMixedContentNode(linkNode) {
let mixedContentWarning = "[" + l10n.getStr("webConsoleMixedContentWarning") + "]";
//mixedContentWarning message links to a Learn More page
let mixedContentWarningNode = this.chromeDocument.createElement("label");
mixedContentWarningNode.setAttribute("value", mixedContentWarning);
mixedContentWarningNode.setAttribute("title", mixedContentWarning);
//UI for mixed content warning.
mixedContentWarningNode.classList.add("hud-clickable");
mixedContentWarningNode.classList.add("webconsole-mixed-content-link");
linkNode.appendChild(mixedContentWarningNode);
mixedContentWarningNode.addEventListener("click", function(aEvent) {
this.chromeWindow.openUILinkIn(MIXED_CONTENT_LEARN_MORE, "tab");
aEvent.preventDefault();
aEvent.stopPropagation();
}.bind(this));
},
};
/**

View File

@ -246,18 +246,21 @@ var WebConsoleUtils = {
output = type;
break;
default:
if (aResult.toSource) {
try {
try {
if (aResult.toSource) {
output = aResult.toSource();
} catch (ex) { }
}
if (!output || output == "({})") {
output = aResult + "";
}
}
if (!output || output == "({})") {
output = aResult.toString();
catch (ex) {
output = ex;
}
break;
}
return output;
return output + "";
},
/**

View File

@ -109,6 +109,8 @@ MOCHITEST_BROWSER_FILES = \
browser_cached_messages.js \
browser_bug664688_sandbox_update_after_navigation.js \
browser_webconsole_menustatus.js \
browser_result_format_as_string.js \
browser_webconsole_bug_737873_mixedcontent.js \
head.js \
$(NULL)
@ -181,6 +183,8 @@ MOCHITEST_BROWSER_FILES += \
test-bug-658368-time-methods.html \
test-webconsole-error-observer.html \
test-for-of.html \
test-result-format-as-string.html \
test-bug-737873-mixedcontent.html \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,49 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Make sure that JS eval result are properly formatted as strings.
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-result-format-as-string.html";
function test()
{
waitForExplicitFinish();
addTab(TEST_URI);
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openConsole(null, performTest);
}, true);
}
function performTest(hud)
{
hud.jsterm.clearOutput(true);
hud.jsterm.execute("document.querySelector('p')");
waitForSuccess({
name: "eval result shown",
validatorFn: function()
{
return hud.outputNode.querySelector(".webconsole-msg-output");
},
successFn: function()
{
is(hud.outputNode.textContent.indexOf("bug772506_content"), -1,
"no content element found");
ok(!hud.outputNode.querySelector("div"), "no div element found");
let msg = hud.outputNode.querySelector(".webconsole-msg-output");
ok(msg, "eval output node found");
isnot(msg.textContent.indexOf("HTMLDivElement"), -1,
"HTMLDivElement string found");
EventUtils.synthesizeMouseAtCenter(msg, {type: "mousemove"});
ok(!gBrowser._bug772506, "no content variable");
finishTest();
},
failureFn: finishTest,
});
}

View File

@ -0,0 +1,80 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* ***** BEGIN LICENSE BLOCK *****
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* Contributor(s):
* Tanvi Vyas <tanvi@mozilla.com>
*
* ***** END LICENSE BLOCK ***** */
// Tests that the Web Console Mixed Content messages are displayed
const TEST_HTTPS_URI = "https://example.com/browser/browser/devtools/webconsole/test/test-bug-737873-mixedcontent.html";
function test() {
addTab("data:text/html,Web Console basic network logging test");
browser.addEventListener("load", onLoad, true);
}
function onLoad(aEvent) {
browser.removeEventListener("load", onLoad, true);
openConsole(null, testMixedContent);
}
function testMixedContent(hud) {
content.location = TEST_HTTPS_URI;
var aOutputNode = hud.outputNode;
waitForSuccess(
{
name: "mixed content warning displayed successfully",
validatorFn: function() {
return ( aOutputNode.querySelector(".webconsole-mixed-content") );
},
successFn: function() {
//tests on the urlnode
let node = aOutputNode.querySelector(".webconsole-mixed-content");
ok(testSeverity(node), "Severity type is SEVERITY_WARNING.");
//tests on the warningNode
let warningNode = aOutputNode.querySelector(".webconsole-mixed-content-link");
is(warningNode.value, "[Mixed Content]", "Message text is accurate." );
testClickOpenNewTab(warningNode);
finishTest();
},
failureFn: finishTest,
}
);
}
function testSeverity(node) {
let linkNode = node.parentNode;
let msgNode = linkNode.parentNode;
let bodyNode = msgNode.parentNode;
let finalNode = bodyNode.parentNode;
return finalNode.classList.contains("webconsole-msg-warn");
}
function testClickOpenNewTab(warningNode) {
/* Invoke the click event and check if a new tab would open to the correct page */
let linkOpened = false;
let oldOpenUILinkIn = window.openUILinkIn;
window.openUILinkIn = function(aLink) {
if (aLink == "https://developer.mozilla.org/en/Security/MixedContent");
linkOpened = true;
}
EventUtils.synthesizeMouse(warningNode, 2, 2, {});
ok(linkOpened, "Clicking the Mixed Content Warning node opens the desired page");
window.openUILinkIn = oldOpenUILinkIn;
}

View File

@ -0,0 +1,14 @@
<!DOCTYPE HTML>
<html dir="ltr" xml:lang="en-US" lang="en-US"><head>
<title>Mixed Content test - http on https</title>
<script src="testscript.js"></script>
<!--
- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/
-->
</head>
<body>
<iframe src = "http://example.com"></iframe>
</body>
</html>

View File

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Web Console test: jsterm eval format as a string</title>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
</head>
<body>
<p>Make sure js eval results are formatted as strings.</p>
<script>
document.querySelector("p").toSource = function() {
var element = document.createElement("div");
element.textContent = "bug772506_content";
element.setAttribute("onmousemove",
"(function () {" +
" gBrowser._bug772506 = 'foobar';" +
"})();"
);
return element;
};
</script>
</body>
</html>

View File

@ -237,6 +237,9 @@ These should match what Safari and other Apple applications use on OS X Lion. --
<!ENTITY devToolbarCloseButton.tooltiptext "Close Developer Toolbar">
<!ENTITY devToolbarMenu.label "Developer Toolbar">
<!ENTITY devToolbarMenu.accesskey "v">
<!ENTITY devToolbar.keycode "VK_F2">
<!ENTITY devToolbar.keytext "F2">
<!ENTITY webConsoleButton.label "Web Console">
<!ENTITY inspectorButton.label "Inspector">

View File

@ -80,6 +80,24 @@ screenshotFullPageDesc=Entire webpage? (true/false)
# asks for help on what it does.
screenshotFullPageManual=True if the screenshot should also include parts of the webpage which are outside the current scrolled bounds.
# LOCALIZATION NOTE (restartFirefoxDesc) A very short description of the
# 'restart' command. This string is designed to be shown in a menu alongside the
# command name, which is why it should be as short as possible.
restartFirefoxDesc=Restart Firefox
# LOCALIZATION NOTE (restartFirefoxNocacheDesc) A very short string to
# describe the 'nocache' parameter to the 'restart' command, which is
# displayed in a dialog when the user is using this command.
restartFirefoxNocacheDesc=Disables loading content from cache upon restart
# LOCALIZATION NOTE (restartFirefoxRequestCancelled) A string dispalyed to the
# user when a scheduled restart has been aborted by the user.
restartFirefoxRequestCancelled=Restart request cancelled by user.
# LOCALIZATION NOTE (restartFirefoxRestarting) A string dispalyed to the
# user when a restart has been initiated without a delay.
restartFirefoxRestarting=Restarting Firefox...
# LOCALIZATION NOTE (inspectDesc) A very short description of the 'inspect'
# command. See inspectManual for a fuller description of what it does. This
# string is designed to be shown in a menu alongside the command name, which
@ -333,6 +351,50 @@ editResourceDesc=URL to edit
# when the user is using this command.
editLineToJumpToDesc=Line to jump to
# LOCALIZATION NOTE (resizePageDesc) A very short string to describe the
# 'resizepage' command. This string is designed to be shown in a menu
# alongside the command name, which is why it should be as short as possible.
resizePageDesc=Resize the page
# LOCALIZATION NOTE (resizePageArgWidthDesc) A very short string to describe the
# 'width' parameter to the 'resizepage' command, which is displayed in a dialog
# when the user is using this command.
resizePageArgWidthDesc=Width in pixels
# LOCALIZATION NOTE (resizePageArgWidthDesc) A very short string to describe the
# 'height' parameter to the 'resizepage' command, which is displayed in a dialog
# when the user is using this command.
resizePageArgHeightDesc=Height in pixels
# LOCALIZATION NOTE (resizeModeOnDesc) A very short string to describe the
# 'resizeon ' command. This string is designed to be shown in a menu
# alongside the command name, which is why it should be as short as possible.
resizeModeOnDesc=Enter Responsive Design Mode
# LOCALIZATION NOTE (resizeModeOffDesc) A very short string to describe the
# 'resize off' command. This string is designed to be shown in a menu
# alongside the command name, which is why it should be as short as possible.
resizeModeOffDesc=Exit Responsive Design Mode
# LOCALIZATION NOTE (resizeModeToggleDesc) A very short string to describe the
# 'resize toggle' command. This string is designed to be shown in a menu
# alongside the command name, which is why it should be as short as possible.
resizeModeToggleDesc=Toggle Responsive Design Mode
# LOCALIZATION NOTE (resizeModeToDesc) A very short string to describe the
# 'resize to' command. This string is designed to be shown in a menu
# alongside the command name, which is why it should be as short as possible.
resizeModeToDesc=Alter page size
# LOCALIZATION NOTE (resizeModeDesc) A very short string to describe the
# 'resize' command. This string is designed to be shown in a menu
# alongside the command name, which is why it should be as short as possible.
resizeModeDesc=Control Responsive Design Mode
# LOCALIZATION NOTE (resizeModeManual) A fuller description of the 'resize'
# command, displayed when the user asks for help on what it does.
resizeModeManual=Responsive websites respond to their environment, so they look good on a mobile display, a cinema display and everything in-between. Responsive Design Mode allows you to easily test a variety of page sizes in Firefox without needing to resize your whole browser.
# LOCALIZATION NOTE (cmdDesc) A very short description of the 'cmd'
# command. This string is designed to be shown in a menu alongside the command
# name, which is why it should be as short as possible.
@ -342,3 +404,290 @@ cmdDesc=Manipulate the commands
# command. This string is designed to be shown in a menu alongside the command
# name, which is why it should be as short as possible.
cmdRefreshDesc=Re-read mozcmd directory
# LOCALIZATION NOTE (addonDesc) A very short description of the 'addon'
# command. This string is designed to be shown in a menu alongside the command
# name, which is why it should be as short as possible.
addonDesc=Manipulate add-ons
# LOCALIZATION NOTE (addonListDesc) A very short description of the 'addon list'
# command. This string is designed to be shown in a menu alongside the command
# name, which is why it should be as short as possible.
addonListDesc=List installed add-ons
# LOCALIZATION NOTE (addonListTypeDesc) A very short description of the
# 'addon list <type>' command. This string is designed to be shown in a menu
# alongside the command name, which is why it should be as short as possible.
addonListTypeDesc=Select an addon type
# LOCALIZATION NOTE (addonListDictionaryHeading, addonListExtensionHeading,
# addonListLocaleHeading, addonListPluginHeading, addonListThemeHeading,
# addonListUnknownHeading) Used in the output of the 'addon list' command as the
# first line of output.
addonListDictionaryHeading=The following dictionaries are currently installed:
addonListExtensionHeading=The following extensions are currently installed:
addonListLocaleHeading=The following locales are currently installed:
addonListPluginHeading=The following plugins are currently installed:
addonListThemeHeading=The following themes are currently installed:
addonListAllHeading=The following addons are currently installed:
addonListUnknownHeading=The following addons of the selected type are currently installed:
# LOCALIZATION NOTE (addonNameDesc) A very short description of the
# name parameter of numerous addon commands. This string is designed to be shown
# in a menu alongside the command name, which is why it should be as short as
# possible.
addonNameDesc=The name of the add-on
# LOCALIZATION NOTE (addonNoneOfType) Used in the output of the 'addon list'
# command when a search for addons of a particular type were not found.
addonNoneOfType=There are no addons of that type installed.
# LOCALIZATION NOTE (addonEnableDesc) A very short description of the
# 'addon enable <type>' command. This string is designed to be shown in a menu
# alongside the command name, which is why it should be as short as possible.
addonEnableDesc=Enable the specified add-on
# LOCALIZATION NOTE (addonAlreadyEnabled) Used in the output of the
# 'addon enable' command when an attempt is made to enable an addon is already
# enabled.
addonAlreadyEnabled=%S is already enabled.
# LOCALIZATION NOTE (addonEnabled) Used in the output of the 'addon enable'
# command when an addon is enabled.
addonEnabled=%S enabled.
# LOCALIZATION NOTE (addonDisableDesc) A very short description of the
# 'addon disable <type>' command. This string is designed to be shown in a menu
# alongside the command name, which is why it should be as short as possible.
addonDisableDesc=Disable the specified add-on
# LOCALIZATION NOTE (addonAlreadyDisabled) Used in the output of the
# 'addon disable' command when an attempt is made to disable an addon is already
# disabled.
addonAlreadyDisabled=%S is already disabled.
# LOCALIZATION NOTE (addonDisabled) Used in the output of the 'addon disable'
# command when an addon is disabled.
addonDisabled=%S disabled.
# LOCALIZATION NOTE (exportDesc) A very short description of the 'export'
# command. This string is designed to be shown in a menu alongside the command
# name, which is why it should be as short as possible.
exportDesc=Export resources
# LOCALIZATION NOTE (exportHtmlDesc) A very short description of the 'export
# html' command. This string is designed to be shown in a menu alongside the
# command name, which is why it should be as short as possible.
exportHtmlDesc=Export HTML from page
# LOCALIZATION NOTE (pagemodDesc) A very short description of the 'pagemod'
# command. This string is designed to be shown in a menu alongside the command
# name, which is why it should be as short as possible.
pagemodDesc=Make page changes
# LOCALIZATION NOTE (pagemodReplaceDesc) A very short description of the
# 'pagemod replace' command. This string is designed to be shown in a menu
# alongside the command name, which is why it should be as short as possible.
pagemodReplaceDesc=Search and replace in page elements
# LOCALIZATION NOTE (pagemodReplaceSearchDesc) A very short string to describe
# the 'search' parameter to the 'pagemod replace' command, which is displayed in
# a dialog when the user is using this command.
pagemodReplaceSearchDesc=What to search for
# LOCALIZATION NOTE (pagemodReplaceReplaceDesc) A very short string to describe
# the 'replace' parameter to the 'pagemod replace' command, which is displayed in
# a dialog when the user is using this command.
pagemodReplaceReplaceDesc=Replacement string
# LOCALIZATION NOTE (pagemodReplaceIgnoreCaseDesc) A very short string to
# describe the 'ignoreCase' parameter to the 'pagemod replace' command, which is
# displayed in a dialog when the user is using this command.
pagemodReplaceIgnoreCaseDesc=Perform case-insensitive search
# LOCALIZATION NOTE (pagemodReplaceRootDesc) A very short string to describe the
# 'root' parameter to the 'pagemod replace' command, which is displayed in
# a dialog when the user is using this command.
pagemodReplaceRootDesc=CSS selector to root of search
# LOCALIZATION NOTE (pagemodReplaceSelectorDesc) A very short string to describe
# the 'selector' parameter to the 'pagemod replace' command, which is displayed
# in a dialog when the user is using this command.
pagemodReplaceSelectorDesc=CSS selector to match in search
# LOCALIZATION NOTE (pagemodReplaceAttributesDesc) A very short string to
# describe the 'attributes' parameter to the 'pagemod replace' command, which is
# displayed in a dialog when the user is using this command.
pagemodReplaceAttributesDesc=Attribute match regexp
# LOCALIZATION NOTE (pagemodReplaceAttrOnlyDesc) A very short string to describe
# the 'attrOnly' parameter to the 'pagemod replace' command, which is displayed
# in a dialog when the user is using this command.
pagemodReplaceAttrOnlyDesc=Restrict search to attributes
# LOCALIZATION NOTE (pagemodReplaceContentOnlyDesc) A very short string to
# describe the 'contentOnly' parameter to the 'pagemod replace' command, which
# is displayed in a dialog when the user is using this command.
pagemodReplaceContentOnlyDesc=Restrict search to text nodes
# LOCALIZATION NOTE (pagemodReplaceResultMatchedElements) A string displayed as
# the result of the 'pagemod replace' command.
pagemodReplaceResult=Elements matched by selector: %1$S. Replaces in text nodes: %2$S. Replaces in attributes: %3$S.
# LOCALIZATION NOTE (pagemodRemoveDesc) A very short description of the
# 'pagemod remove' command. This string is designed to be shown in a menu
# alongside the command name, which is why it should be as short as possible.
pagemodRemoveDesc=Remove elements and attributes from page
# LOCALIZATION NOTE (pagemodRemoveElementDesc) A very short description of the
# 'pagemod remove element' command. This string is designed to be shown in
# a menu alongside the command name, which is why it should be as short as
# possible.
pagemodRemoveElementDesc=Remove elements from page
# LOCALIZATION NOTE (pagemodRemoveElementSearchDesc) A very short string to
# describe the 'search' parameter to the 'pagemod remove element' command, which
# is displayed in a dialog when the user is using this command.
pagemodRemoveElementSearchDesc=CSS selector specifying elements to remove
# LOCALIZATION NOTE (pagemodRemoveElementRootDesc) A very short string to
# describe the 'root' parameter to the 'pagemod remove element' command, which
# is displayed in a dialog when the user is using this command.
pagemodRemoveElementRootDesc=CSS selector specifying root of search
# LOCALIZATION NOTE (pagemodRemoveElementStripOnlyDesc) A very short string to
# describe the 'stripOnly' parameter to the 'pagemod remove element' command,
# which is displayed in a dialog when the user is using this command.
pagemodRemoveElementStripOnlyDesc=Remove element, but leave content
# LOCALIZATION NOTE (pagemodRemoveElementIfEmptyOnlyDesc) A very short string to
# describe the 'ifEmptyOnly' parameter to the 'pagemod remove element' command,
# which is displayed in a dialog when the user is using this command.
pagemodRemoveElementIfEmptyOnlyDesc=Remove only empty elements
# LOCALIZATION NOTE (pagemodRemoveElementResultMatchedAndRemovedElements)
# A string displayed as the result of the 'pagemod remove element' command.
pagemodRemoveElementResultMatchedAndRemovedElements=Elements matched by selector: %1$S. Elements removed: %2$S.
# LOCALIZATION NOTE (pagemodRemoveAttributeDesc) A very short description of the
# 'pagemod remove attribute' command. This string is designed to be shown in
# a menu alongside the command name, which is why it should be as short as
# possible.
pagemodRemoveAttributeDesc=Remove matching atributes
# LOCALIZATION NOTE (pagemodRemoveAttributeSearchAttributesDesc) A very short
# string to describe the 'searchAttributes' parameter to the 'pagemod remove
# attribute' command, which is displayed in a dialog when the user is using this
# command.
pagemodRemoveAttributeSearchAttributesDesc=Regexp specifying attributes to remove
# LOCALIZATION NOTE (pagemodRemoveAttributeSearchElementsDesc) A very short
# string to describe the 'searchElements' parameter to the 'pagemod remove
# attribute' command, which is displayed in a dialog when the user is using this
# command.
pagemodRemoveAttributeSearchElementsDesc=CSS selector of elements to include
# LOCALIZATION NOTE (pagemodRemoveAttributeRootDesc) A very short string to
# describe the 'root' parameter to the 'pagemod remove attribute' command, which
# is displayed in a dialog when the user is using this command.
pagemodRemoveAttributeRootDesc=CSS selector of root of search
# LOCALIZATION NOTE (pagemodRemoveAttributeIgnoreCaseDesc) A very short string
# to describe the 'ignoreCase' parameter to the 'pagemod remove attribute'
# command, which is displayed in a dialog when the user is using this command.
pagemodRemoveAttributeIgnoreCaseDesc=Perform case-insensitive search
# LOCALIZATION NOTE (pagemodRemoveAttributeResult) A string displayed as the
# result of the 'pagemod remove attribute' command.
pagemodRemoveAttributeResult=Elements matched by selector: %1$S. Attributes removed: %2$S.
# LOCALIZATION NOTE (cookieDesc) A very short description of the 'cookie'
# command. See cookieManual for a fuller description of what it does. This
# string is designed to be shown in a menu alongside the command name, which
# is why it should be as short as possible.
cookieDesc=Display and alter cookies
# LOCALIZATION NOTE (cookieManual) A fuller description of the 'cookie'
# command, displayed when the user asks for help on what it does.
cookieManual=Commands to list, create, delete and alter cookies for the current domain.
# LOCALIZATION NOTE (cookieListDesc) A very short description of the
# 'cookie list' command. This string is designed to be shown in a menu
# alongside the command name, which is why it should be as short as possible.
cookieListDesc=Display cookies
# LOCALIZATION NOTE (cookieListManual) A fuller description of the 'cookie list'
# command, displayed when the user asks for help on what it does.
cookieListManual=Display a list of the cookies relevant to the current page.
# LOCALIZATION NOTE (cookieListOutKey) A heading used in the output from the
# 'cookie list' command above a list of cookie keys
cookieListOutKey=Key
# LOCALIZATION NOTE (cookieListOutValue) A heading used in the output from the
# 'cookie list' command above a list of cookie values
cookieListOutValue=Value
# LOCALIZATION NOTE (cookieListOutActions) A heading used in the output from the
# 'cookie list' command above a list of actions to take on cookies
cookieListOutActions=Actions
# LOCALIZATION NOTE (cookieListOutEdit) A title used in the output from the
# 'cookie list' command on a button which can be used to edit cookie values
cookieListOutEdit=Edit
# LOCALIZATION NOTE (cookieListOutRemove) A title used in the output from the
# 'cookie list' command on a button which can be used to remove cookies
cookieListOutRemove=Remove
# LOCALIZATION NOTE (cookieRemoveDesc) A very short description of the
# 'cookie remove' command. This string is designed to be shown in a menu
# alongside the command name, which is why it should be as short as possible.
cookieRemoveDesc=Remove a cookie
# LOCALIZATION NOTE (cookieRemoveManual) A fuller description of the 'cookie remove'
# command, displayed when the user asks for help on what it does.
cookieRemoveManual=Remove a cookie, given its key
# LOCALIZATION NOTE (cookieRemoveKeyDesc) A very short string to describe the
# 'key' parameter to the 'cookie remove' command, which is displayed in a dialog
# when the user is using this command.
cookieRemoveKeyDesc=The key of the cookie to remove
# LOCALIZATION NOTE (cookieSetDesc) A very short description of the
# 'cookie set' command. This string is designed to be shown in a menu
# alongside the command name, which is why it should be as short as possible.
cookieSetDesc=Set a cookie
# LOCALIZATION NOTE (cookieSetManual) A fuller description of the 'cookie set'
# command, displayed when the user asks for help on what it does.
cookieSetManual=Set a cookie by specifying a key name, it's value and optionally one or more of the following attributes: expires (max-age in seconds or the expires date in GMTString format), path, domain, secure
# LOCALIZATION NOTE (cookieSetKeyDesc) A very short string to describe the
# 'key' parameter to the 'cookie set' command, which is displayed in a dialog
# when the user is using this command.
cookieSetKeyDesc=The key of the cookie to set
# LOCALIZATION NOTE (cookieSetValueDesc) A very short string to describe the
# 'value' parameter to the 'cookie set' command, which is displayed in a dialog
# when the user is using this command.
cookieSetValueDesc=The value of the cookie to set
# LOCALIZATION NOTE (cookieSetOptionsDesc) The title of a set of options to
# the 'cookie set' command, displayed as a heading to the list of option.
cookieSetOptionsDesc=Options
# LOCALIZATION NOTE (cookieSetPathDesc) A very short string to describe the
# 'path' parameter to the 'cookie set' command, which is displayed in a dialog
# when the user is using this command.
cookieSetPathDesc=The path of the cookie to set
# LOCALIZATION NOTE (cookieSetDomainDesc) A very short string to describe the
# 'domain' parameter to the 'cookie set' command, which is displayed in a dialog
# when the user is using this command.
cookieSetDomainDesc=The domain of the cookie to set
# LOCALIZATION NOTE (cookieSetSecureDesc) A very short string to describe the
# 'secure' parameter to the 'cookie set' command, which is displayed in a dialog
# when the user is using this command.
cookieSetSecureDesc=Only transmitted over https

View File

@ -150,6 +150,11 @@ webConsolePositionWindow=Window
# the correct direction.
webConsoleWindowTitleAndURL=Web Console - %S
# LOCALIZATION NOTE (webConsoleMixedContentWarning): Message displayed after a
# URL in the Web Console that has been flagged for Mixed Content (i.e. http
# content in an https page)
webConsoleMixedContentWarning=Mixed Content
# LOCALIZATION NOTE (scratchpad.linkText):
# The text used in the right hand side of the web console command line when
# Javascript is being entered, to indicate how to jump into scratchpad mode

View File

@ -129,3 +129,8 @@
text-align: right;
-moz-padding-end: 8px;
}
.gcli-addon-disabled {
opacity: 0.6;
text-decoration: line-through;
}

View File

@ -94,6 +94,15 @@
text-align: end;
}
.webconsole-mixed-content {
color: #FF0000;
}
.webconsole-mixed-content-link {
color: #0000EE;
margin: 0;
}
.hud-msg-node[selected="true"] > .webconsole-timestamp,
.hud-msg-node[selected="true"] > .webconsole-location {
color: inherit;

View File

@ -131,3 +131,8 @@
text-align: right;
-moz-padding-end: 8px;
}
.gcli-addon-disabled {
opacity: 0.6;
text-decoration: line-through;
}

View File

@ -254,6 +254,15 @@
-moz-image-region: rect(24px, 32px, 32px, 24px);
}
.webconsole-mixed-content {
color: #FF0000;
}
.webconsole-mixed-content-link {
color: #0000EE;
margin: 0;
}
/* Input and output styles */
.webconsole-msg-input > .webconsole-msg-icon-container,
.webconsole-msg-output > .webconsole-msg-icon-container {

View File

@ -129,3 +129,8 @@
text-align: right;
-moz-padding-end: 8px;
}
.gcli-addon-disabled {
opacity: 0.6;
text-decoration: line-through;
}

View File

@ -205,6 +205,15 @@
-moz-image-region: rect(24px, 32px, 32px, 24px);
}
.webconsole-mixed-content {
color: #FF0000;
}
.webconsole-mixed-content-link {
color: #0000EE;
margin: 0;
}
/* Input and output styles */
.webconsole-msg-input > .webconsole-msg-icon-container,
.webconsole-msg-output > .webconsole-msg-icon-container {

View File

@ -10018,7 +10018,7 @@ nsDocShell::ShouldAddToSessionHistory(nsIURI * aURI)
// should just do a spec compare, rather than two gets of the scheme and
// then the path. -Gagan
nsresult rv;
nsCAutoString buf;
nsCAutoString buf, pref;
rv = aURI->GetScheme(buf);
if (NS_FAILED(rv))
@ -10033,7 +10033,14 @@ nsDocShell::ShouldAddToSessionHistory(nsIURI * aURI)
return false;
}
}
return true;
rv = aURI->GetSpec(buf);
NS_ENSURE_SUCCESS(rv, true);
rv = Preferences::GetDefaultCString("browser.newtab.url", &pref);
NS_ENSURE_SUCCESS(rv, true);
return !buf.Equals(pref);
}
nsresult

View File

@ -69,8 +69,8 @@ using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::widget;
//#define DEBUG_FOCUS 1
//#define DEBUG_FOCUS_NAVIGATION 1
#define DEBUG_FOCUS 1
#define DEBUG_FOCUS_NAVIGATION 1
#define PRINTTAGF(format, content) \
{ \
nsAutoString tag(NS_LITERAL_STRING("(none)")); \