Merge mozilla-central and fx-team

This commit is contained in:
Ed Morley 2014-08-15 17:37:16 +01:00
commit ce398ca5f7
80 changed files with 734 additions and 381 deletions

View File

@ -1280,8 +1280,8 @@ pref("devtools.appmanager.enabled", true);
pref("devtools.appmanager.lastTab", "help");
pref("devtools.appmanager.manifestEditor.enabled", true);
// Disable devtools webide until bug 1007059
pref("devtools.webide.enabled", false);
// Enable DevTools WebIDE by default
pref("devtools.webide.enabled", true);
// Toolbox preferences
pref("devtools.toolbox.footer.height", 250);

View File

@ -2,7 +2,7 @@
* 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/. */
@import url("chrome://browser/skin/in-content/common.css");
@import url("chrome://global/skin/in-content/common.css");
body {
display: flex;

View File

@ -23,6 +23,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "ShortcutUtils",
"resource://gre/modules/ShortcutUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "GMPInstallManager",
"resource://gre/modules/GMPInstallManager.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ContentSearch",
"resource:///modules/ContentSearch.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AboutHome",
"resource:///modules/AboutHome.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "gDNSService",
"@mozilla.org/network/dns-service;1",
"nsIDNSService");
@ -3095,8 +3099,17 @@ const BrowserSearch = {
}
#endif
let openSearchPageIfFieldIsNotActive = function(aSearchBar) {
if (!aSearchBar || document.activeElement != aSearchBar.textbox.inputField)
let doc = gBrowser.selectedBrowser.contentDocument;
let url = doc.documentURI.toLowerCase();
let mm = gBrowser.selectedBrowser.messageManager;
if (url === "about:home") {
AboutHome.focusInput(mm);
} else if (url === "about:newtab") {
ContentSearch.focusInput(mm);
} else if (!aSearchBar || document.activeElement != aSearchBar.textbox.inputField) {
openUILinkIn("about:home", "current");
}
};
let searchBar = this.searchBar;

View File

@ -106,6 +106,9 @@ let AboutHomeListener = {
case "AboutHome:Update":
this.onUpdate(aMessage.data);
break;
case "AboutHome:FocusInput":
this.onFocusInput();
break;
}
},
@ -138,6 +141,7 @@ let AboutHomeListener = {
doc.documentElement.setAttribute("hasBrowserHandlers", "true");
let self = this;
addMessageListener("AboutHome:Update", self);
addMessageListener("AboutHome:FocusInput", self);
addEventListener("click", this.onClick, true);
addEventListener("pagehide", function onPageHide(event) {
if (event.target.defaultView.frameElement)
@ -212,6 +216,10 @@ let AboutHomeListener = {
break;
}
},
onFocusInput: function () {
content.document.getElementById("searchText").focus();
},
};
AboutHomeListener.init(this);

View File

@ -76,6 +76,10 @@ let gSearch = {
}
},
onFocusInput: function () {
this._nodes.text.focus();
},
_nodeIDSuffixes: [
"form",
"logo",

View File

@ -419,6 +419,22 @@ let gTests = [
});
}
},
{
desc: "Cmd+k should focus the search bar element",
setup: function () {},
run: Task.async(function* () {
let doc = gBrowser.selectedTab.linkedBrowser.contentDocument;
let logo = doc.getElementById("brandLogo");
let searchInput = doc.getElementById("searchText");
EventUtils.synthesizeMouseAtCenter(logo, {});
isnot(searchInput, doc.activeElement, "Search input should not be the active element.");
EventUtils.synthesizeKey("k", { accelKey: true });
yield promiseWaitForCondition(() => doc.activeElement === searchInput);
is(searchInput, doc.activeElement, "Search input should be the active element.");
})
},
];

View File

@ -82,6 +82,12 @@ function waitForCondition(condition, nextTest, errorMsg) {
var moveOn = function() { clearInterval(interval); nextTest(); };
}
function promiseWaitForCondition(aConditionFn) {
let deferred = Promise.defer();
waitForCondition(aConditionFn, deferred.resolve, "Condition didn't pass.");
return deferred.promise;
}
function getTestPlugin(aName) {
var pluginName = aName || "Test Plug-in";
var ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);

View File

@ -186,6 +186,16 @@ function runTests() {
EventUtils.synthesizeKey("VK_DELETE", {});
ok(table.hidden, "Search suggestion table hidden");
// Focus a different element than the search input.
let btn = getContentDocument().getElementById("newtab-customize-button");
yield promiseClick(btn).then(TestRunner.next);
isnot(input, getContentDocument().activeElement, "Search input should not be focused");
// Test that Ctrl/Cmd + K will focus the input field.
EventUtils.synthesizeKey("k", { accelKey: true });
yield promiseSearchEvents(["FocusInput"]).then(TestRunner.next);
is(input, getContentDocument().activeElement, "Search input should be focused");
// Done. Revert the current engine and remove the new engines.
Services.search.currentEngine = oldCurrentEngine;
yield promiseSearchEvents(["CurrentEngine"]).then(TestRunner.next);

View File

@ -309,6 +309,8 @@ function openLinkIn(url, where, params) {
// result in a new frontmost window (e.g. "javascript:window.open('');").
w.focus();
let newTab;
switch (where) {
case "current":
let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
@ -332,22 +334,29 @@ function openLinkIn(url, where, params) {
// fall through
case "tab":
let browser = w.gBrowser;
browser.loadOneTab(url, {
referrerURI: aReferrerURI,
charset: aCharset,
postData: aPostData,
inBackground: loadInBackground,
allowThirdPartyFixup: aAllowThirdPartyFixup,
relatedToCurrent: aRelatedToCurrent,
skipAnimation: aSkipTabAnimation,
allowMixedContent: aAllowMixedContent });
newTab = browser.loadOneTab(url, {
referrerURI: aReferrerURI,
charset: aCharset,
postData: aPostData,
inBackground: loadInBackground,
allowThirdPartyFixup: aAllowThirdPartyFixup,
relatedToCurrent: aRelatedToCurrent,
skipAnimation: aSkipTabAnimation,
allowMixedContent: aAllowMixedContent });
break;
}
w.gBrowser.selectedBrowser.focus();
if (!loadInBackground && w.isBlankPageURL(url))
if (!loadInBackground && w.isBlankPageURL(url)) {
if (newTab) {
// Remote tab content does not focus synchronously, so we set the flag
// on this tab to skip focusing the content if we want to focus the URL
// bar instead.
newTab._urlbarFocused = true;
}
w.focusAndSelectUrlBar();
}
}
// Used as an onclick handler for UI elements with link-like behavior.

View File

@ -160,6 +160,27 @@ function injectLoopAPI(targetWindow) {
}
},
/**
* Return any preference under "loop." that's coercible to a boolean
* preference.
*
* @param {String} prefName The name of the pref without the preceding
* "loop."
*
* Any errors thrown by the Mozilla pref API are logged to the console
* and cause null to be returned. This includes the case of the preference
* not being found.
*
* @return {String} on success, null on error
*/
getLoopBoolPref: {
enumerable: true,
writable: true,
value: function(prefName) {
return MozLoopService.getLoopBoolPref(prefName);
}
},
/**
* Starts alerting the user about an incoming call
*/

View File

@ -613,6 +613,29 @@ this.MozLoopService = {
}
},
/**
* Return any preference under "loop." that's coercible to a character
* preference.
*
* @param {String} prefName The name of the pref without the preceding
* "loop."
*
* Any errors thrown by the Mozilla pref API are logged to the console
* and cause null to be returned. This includes the case of the preference
* not being found.
*
* @return {String} on success, null on error
*/
getLoopBoolPref: function(prefName) {
try {
return Services.prefs.getBoolPref("loop." + prefName);
} catch (ex) {
console.log("getLoopBoolPref had trouble getting " + prefName +
"; exception: " + ex);
return null;
}
},
/**
* Performs a hawk based request to the loop server.
*

View File

@ -3,6 +3,6 @@ support-files =
head.js
[browser_mozLoop_appVersionInfo.js]
[browser_mozLoop_charPref.js]
[browser_mozLoop_prefs.js]
[browser_mozLoop_doNotDisturb.js]
skip-if = buildapp == 'mulet'

View File

@ -24,3 +24,17 @@ add_task(function* test_mozLoop_charPref() {
Assert.equal(gMozLoopAPI.getLoopCharPref("test"), "foo",
"should get loop pref value correctly");
});
add_task(function* test_mozLoop_boolPref() {
registerCleanupFunction(function () {
Services.prefs.clearUserPref("loop.testBool");
});
Assert.ok(gMozLoopAPI, "mozLoop should exist");
Services.prefs.setBoolPref("loop.testBool", true);
// Test getLoopCharPref
Assert.equal(gMozLoopAPI.getLoopBoolPref("testBool"), true,
"should get loop pref value correctly");
});

View File

@ -1,47 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/*global XPCOMUtils, Services, Assert */
var fakePrefName = "color";
var fakePrefValue = "green";
function test_getLoopCharPref()
{
Services.prefs.setCharPref("loop." + fakePrefName, fakePrefValue);
var returnedPref = MozLoopService.getLoopCharPref(fakePrefName);
Assert.equal(returnedPref, fakePrefValue,
"Should return a char pref under the loop. branch");
Services.prefs.clearUserPref("loop." + fakePrefName);
}
function test_getLoopCharPref_not_found()
{
var returnedPref = MozLoopService.getLoopCharPref(fakePrefName);
Assert.equal(returnedPref, null,
"Should return null if a preference is not found");
}
function test_getLoopCharPref_non_coercible_type()
{
Services.prefs.setBoolPref("loop." + fakePrefName, false );
var returnedPref = MozLoopService.getLoopCharPref(fakePrefName);
Assert.equal(returnedPref, null,
"Should return null if the preference exists & is of a non-coercible type");
}
function run_test()
{
test_getLoopCharPref();
test_getLoopCharPref_not_found();
test_getLoopCharPref_non_coercible_type();
do_register_cleanup(function() {
Services.prefs.clearUserPref("loop." + fakePrefName);
});
}

View File

@ -0,0 +1,106 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/*global XPCOMUtils, Services, Assert */
var fakeCharPrefName = "color";
var fakeBoolPrefName = "boolean";
var fakePrefValue = "green";
function test_getLoopCharPref()
{
Services.prefs.setCharPref("loop." + fakeCharPrefName, fakePrefValue);
var returnedPref = MozLoopService.getLoopCharPref(fakeCharPrefName);
Assert.equal(returnedPref, fakePrefValue,
"Should return a char pref under the loop. branch");
Services.prefs.clearUserPref("loop." + fakeCharPrefName);
}
function test_getLoopCharPref_not_found()
{
var returnedPref = MozLoopService.getLoopCharPref(fakeCharPrefName);
Assert.equal(returnedPref, null,
"Should return null if a preference is not found");
}
function test_getLoopCharPref_non_coercible_type()
{
Services.prefs.setBoolPref("loop." + fakeCharPrefName, false);
var returnedPref = MozLoopService.getLoopCharPref(fakeCharPrefName);
Assert.equal(returnedPref, null,
"Should return null if the preference exists & is of a non-coercible type");
}
function test_setLoopCharPref()
{
Services.prefs.setCharPref("loop." + fakeCharPrefName, "red");
MozLoopService.setLoopCharPref(fakeCharPrefName, fakePrefValue);
var returnedPref = Services.prefs.getCharPref("loop." + fakeCharPrefName);
Assert.equal(returnedPref, fakePrefValue,
"Should set a char pref under the loop. branch");
Services.prefs.clearUserPref("loop." + fakeCharPrefName);
}
function test_setLoopCharPref_new()
{
Services.prefs.clearUserPref("loop." + fakeCharPrefName);
MozLoopService.setLoopCharPref(fakeCharPrefName, fakePrefValue);
var returnedPref = Services.prefs.getCharPref("loop." + fakeCharPrefName);
Assert.equal(returnedPref, fakePrefValue,
"Should set a new char pref under the loop. branch");
Services.prefs.clearUserPref("loop." + fakeCharPrefName);
}
function test_setLoopCharPref_non_coercible_type()
{
MozLoopService.setLoopCharPref(fakeCharPrefName, true);
ok(true, "Setting non-coercible type should not fail");
}
function test_getLoopBoolPref()
{
Services.prefs.setBoolPref("loop." + fakeBoolPrefName, true);
var returnedPref = MozLoopService.getLoopBoolPref(fakeBoolPrefName);
Assert.equal(returnedPref, true,
"Should return a bool pref under the loop. branch");
Services.prefs.clearUserPref("loop." + fakeBoolPrefName);
}
function test_getLoopBoolPref_not_found()
{
var returnedPref = MozLoopService.getLoopBoolPref(fakeBoolPrefName);
Assert.equal(returnedPref, null,
"Should return null if a preference is not found");
}
function run_test()
{
test_getLoopCharPref();
test_getLoopCharPref_not_found();
test_getLoopCharPref_non_coercible_type();
test_setLoopCharPref();
test_setLoopCharPref_new();
test_setLoopCharPref_non_coercible_type();
test_getLoopBoolPref();
test_getLoopBoolPref_not_found();
do_register_cleanup(function() {
Services.prefs.clearUserPref("loop." + fakeCharPrefName);
Services.prefs.clearUserPref("loop." + fakeBoolPrefName);
});
}

View File

@ -1,49 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/*global XPCOMUtils, Services, Assert */
var fakePrefName = "color";
var fakePrefValue = "green";
function test_setLoopCharPref()
{
Services.prefs.setCharPref("loop." + fakePrefName, "red");
MozLoopService.setLoopCharPref(fakePrefName, fakePrefValue);
var returnedPref = Services.prefs.getCharPref("loop." + fakePrefName);
Assert.equal(returnedPref, fakePrefValue,
"Should set a char pref under the loop. branch");
Services.prefs.clearUserPref("loop." + fakePrefName);
}
function test_setLoopCharPref_new()
{
Services.prefs.clearUserPref("loop." + fakePrefName);
MozLoopService.setLoopCharPref(fakePrefName, fakePrefValue);
var returnedPref = Services.prefs.getCharPref("loop." + fakePrefName);
Assert.equal(returnedPref, fakePrefValue,
"Should set a new char pref under the loop. branch");
Services.prefs.clearUserPref("loop." + fakePrefName);
}
function test_setLoopCharPref_non_coercible_type()
{
MozLoopService.setLoopCharPref(fakePrefName, true);
ok(true, "Setting non-coercible type should not fail");
}
function run_test()
{
test_setLoopCharPref();
test_setLoopCharPref_new();
test_setLoopCharPref_non_coercible_type();
do_register_cleanup(function() {
Services.prefs.clearUserPref("loop." + fakePrefName);
});
}

View File

@ -6,8 +6,7 @@ firefox-appdir = browser
[test_looppush_initialize.js]
[test_loopservice_dnd.js]
[test_loopservice_expiry.js]
[test_loopservice_get_loop_char_pref.js]
[test_loopservice_set_loop_char_pref.js]
[test_loopservice_loop_prefs.js]
[test_loopservice_initialize.js]
[test_loopservice_locales.js]
[test_loopservice_registration.js]

View File

@ -8,7 +8,7 @@
<?xml-stylesheet href="chrome://mozapps/content/preferences/preferences.css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css"?>
<?xml-stylesheet href="chrome://browser/skin/in-content/common.css"?>
<?xml-stylesheet href="chrome://global/skin/in-content/common.css"?>
<?xml-stylesheet
href="chrome://browser/skin/preferences/in-content/preferences.css"?>
<?xml-stylesheet

View File

@ -11,7 +11,7 @@ let gSubDialog = {
_box: null,
_injectedStyleSheets: ["chrome://mozapps/content/preferences/preferences.css",
"chrome://browser/skin/preferences/preferences.css",
"chrome://browser/skin/in-content/common.css",
"chrome://global/skin/in-content/common.css",
"chrome://browser/skin/preferences/in-content/preferences.css"],
init: function() {

View File

@ -5,7 +5,6 @@
let gItemsToTest = {
"menu_devToolbar": "devtools.toolbar.enabled",
"menu_devAppMgr": "devtools.appmanager.enabled",
"menu_browserToolbox": ["devtools.chrome.enabled", "devtools.debugger.remote-enabled", "devtools.debugger.chrome-enabled"],
"javascriptConsole": "devtools.errorconsole.enabled",
"menu_devtools_connect": "devtools.debugger.remote-enabled",

View File

@ -76,6 +76,7 @@ function Toolbox(target, selectedTool, hostType, hostOptions) {
this._highlighterHidden = this._highlighterHidden.bind(this);
this._prefChanged = this._prefChanged.bind(this);
this._saveSplitConsoleHeight = this._saveSplitConsoleHeight.bind(this);
this._onFocus = this._onFocus.bind(this);
this._target.on("close", this.destroy);
@ -253,7 +254,7 @@ Toolbox.prototype = {
this._applyCacheSettings();
this._addKeysToWindow();
this._addReloadKeys();
this._addToolSwitchingKeys();
this._addHostListeners();
this._addZoomKeys();
this._loadInitialZoom();
@ -263,16 +264,19 @@ Toolbox.prototype = {
this.webconsolePanel.addEventListener("resize",
this._saveSplitConsoleHeight);
let splitConsolePromise = promise.resolve();
if (Services.prefs.getBoolPref(SPLITCONSOLE_ENABLED_PREF)) {
splitConsolePromise = this.openSplitConsole();
}
let buttonsPromise = this._buildButtons();
this._telemetry.toolOpened("toolbox");
this.selectTool(this._defaultToolId).then(panel => {
// Wait until the original tool is selected so that the split
// console input will receive focus.
let splitConsolePromise = promise.resolve();
if (Services.prefs.getBoolPref(SPLITCONSOLE_ENABLED_PREF)) {
splitConsolePromise = this.openSplitConsole();
}
promise.all([
splitConsolePromise,
buttonsPromise
@ -345,7 +349,7 @@ Toolbox.prototype = {
});
},
_addToolSwitchingKeys: function() {
_addHostListeners: function() {
let nextKey = this.doc.getElementById("toolbox-next-tool-key");
nextKey.addEventListener("command", this.selectNextTool.bind(this), true);
let prevKey = this.doc.getElementById("toolbox-previous-tool-key");
@ -354,6 +358,8 @@ Toolbox.prototype = {
// Split console uses keypress instead of command so the event can be
// cancelled with stopPropagation on the keypress, and not preventDefault.
this.doc.addEventListener("keypress", this._splitConsoleOnKeypress, false);
this.doc.addEventListener("focus", this._onFocus, true);
},
_saveSplitConsoleHeight: function() {
@ -976,12 +982,29 @@ Toolbox.prototype = {
* Focus split console's input line
*/
focusConsoleInput: function() {
let hud = this.getPanel("webconsole").hud;
if (hud && hud.jsterm) {
hud.jsterm.inputNode.focus();
let consolePanel = this.getPanel("webconsole");
if (consolePanel) {
consolePanel.focusInput();
}
},
/**
* If the console is split and we are focusing an element outside
* of the console, then store the newly focused element, so that
* it can be restored once the split console closes.
*/
_onFocus: function({originalTarget}) {
// Ignore any non element nodes, or any elements contained
// within the webconsole frame.
let webconsoleURL = gDevTools.getToolDefinition("webconsole").url;
if (originalTarget.nodeType !== 1 ||
originalTarget.baseURI === webconsoleURL) {
return;
}
this._lastFocusedElement = originalTarget;
},
/**
* Opens the split console.
*
@ -993,6 +1016,7 @@ Toolbox.prototype = {
Services.prefs.setBoolPref(SPLITCONSOLE_ENABLED_PREF, true);
this._refreshConsoleDisplay();
this.emit("split-console");
return this.loadTool("webconsole").then(() => {
this.focusConsoleInput();
});
@ -1009,6 +1033,10 @@ Toolbox.prototype = {
Services.prefs.setBoolPref(SPLITCONSOLE_ENABLED_PREF, false);
this._refreshConsoleDisplay();
this.emit("split-console");
if (this._lastFocusedElement) {
this._lastFocusedElement.focus();
}
return promise.resolve();
},
@ -1312,6 +1340,7 @@ Toolbox.prototype = {
destroyHost: function() {
this.doc.removeEventListener("keypress",
this._splitConsoleOnKeypress, false);
this.doc.removeEventListener("focus", this._onFocus, true);
return this._host.destroy();
},
@ -1334,6 +1363,7 @@ Toolbox.prototype = {
gDevTools.off("pref-changed", this._prefChanged);
this._lastFocusedElement = null;
this._saveSplitConsoleHeight();
this.webconsolePanel.removeEventListener("resize",
this._saveSplitConsoleHeight);

View File

@ -1614,8 +1614,11 @@ var Scratchpad = {
var lines = initialText.split("\n");
this.editor.on("change", this._onChanged);
let okstring = this.strings.GetStringFromName("selfxss.okstring");
let msg = this.strings.formatStringFromName("selfxss.msg", [okstring], 1);
this._onPaste = WebConsoleUtils.pasteHandlerGen(this.editor.container.contentDocument.body,
document.querySelector('#scratchpad-notificationbox'));
document.querySelector('#scratchpad-notificationbox'),
msg, okstring);
editorElement.addEventListener("paste", this._onPaste);
editorElement.addEventListener("drop", this._onPaste);
this.editor.on("save", () => this.saveFile());

View File

@ -58,7 +58,7 @@ function spawnTest() {
"Empty message hides even when loading node while open.");
ok(isVisible($("#web-audio-editor-tabs")),
"Switches to tab view when loading node while open.");
is($("#web-audio-inspector-title").value, "OscillatorNode (" + nodeIds[1] + ")",
is($("#web-audio-inspector-title").value, "Oscillator",
"Inspector title updates when loading node while open.");
yield teardown(panel);

View File

@ -43,7 +43,7 @@ function spawnTest() {
ok(isVisible($("#web-audio-editor-tabs")),
"InspectorView tabs view visible when node selected.");
is($("#web-audio-inspector-title").value, "OscillatorNode (" + nodeIds[1] + ")",
is($("#web-audio-inspector-title").value, "Oscillator",
"Inspector should have the node title when a node is selected.");
is($("#web-audio-editor-tabs").selectedIndex, 0,
@ -52,7 +52,7 @@ function spawnTest() {
click(panelWin, findGraphNode(panelWin, nodeIds[2]));
yield once(panelWin, EVENTS.UI_INSPECTOR_NODE_SET);
is($("#web-audio-inspector-title").value, "GainNode (" + nodeIds[2] + ")",
is($("#web-audio-inspector-title").value, "Gain",
"Inspector title updates when a new node is selected.");
yield teardown(panel);

View File

@ -156,7 +156,11 @@ let WebAudioGraphView = {
AudioNodes.forEach(node => {
// Add node to graph
graph.addNode(node.id, { label: node.type, id: node.id });
graph.addNode(node.id, {
type: node.type, // Just for storing type data
label: node.type.replace(/Node$/, ""), // Displayed in SVG node
id: node.id // Identification
});
// Add all of the connections from this node to the edge array to be added
// after all the nodes are added, otherwise edges will attempted to be created
@ -177,7 +181,7 @@ let WebAudioGraphView = {
let svgNodes = oldDrawNodes(graph, root);
svgNodes.attr("class", (n) => {
let node = graph.node(n);
return "audionode type-" + node.label;
return "audionode type-" + node.type;
});
svgNodes.attr("data-id", (n) => {
let node = graph.node(n);
@ -452,7 +456,7 @@ let WebAudioInspectorView = {
*/
_setTitle: function () {
let node = this._currentNode;
let title = node.type + " (" + node.id + ")";
let title = node.type.replace(/Node$/, "");
$("#web-audio-inspector-title").setAttribute("value", title);
},

View File

@ -281,6 +281,7 @@ skip-if = buildapp == 'mulet'
[browser_webconsole_scratchpad_panel_link.js]
[browser_webconsole_split.js]
[browser_webconsole_split_escape_key.js]
[browser_webconsole_split_focus.js]
[browser_webconsole_split_persist.js]
[browser_webconsole_view_source.js]
[browser_webconsole_reflow.js]

View File

@ -0,0 +1,74 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
function test() {
info("Test that the split console state is persisted");
let toolbox;
let TEST_URI = "data:text/html;charset=utf-8,<p>Web Console test for splitting</p>";
Task.spawn(runner).then(finish);
function* runner() {
info("Opening a tab while there is no user setting on split console pref");
let {tab} = yield loadTab(TEST_URI);
let target = TargetFactory.forTab(tab);
toolbox = yield gDevTools.showToolbox(target, "inspector");
ok(!toolbox.splitConsole, "Split console is hidden by default");
info ("Focusing the search box before opening the split console");
let inspector = toolbox.getPanel("inspector");
inspector.searchBox.focus();
// Use the binding element since inspector.searchBox is a XUL element.
let activeElement = getActiveElement(inspector.panelDoc);
activeElement = activeElement.ownerDocument.getBindingParent(activeElement);
is (activeElement, inspector.searchBox, "Search box is focused");
yield toolbox.openSplitConsole();
ok(toolbox.splitConsole, "Split console is now visible");
// Use the binding element since jsterm.inputNode is a XUL textarea element.
let activeElement = getActiveElement(toolbox.doc);
activeElement = activeElement.ownerDocument.getBindingParent(activeElement);
let inputNode = toolbox.getPanel("webconsole").hud.jsterm.inputNode;
is(activeElement, inputNode, "Split console input is focused by default");
yield toolbox.closeSplitConsole();
info ("Making sure that the search box is refocused after closing the split console");
// Use the binding element since inspector.searchBox is a XUL element.
let activeElement = getActiveElement(inspector.panelDoc);
activeElement = activeElement.ownerDocument.getBindingParent(activeElement);
is (activeElement, inspector.searchBox, "Search box is focused");
yield toolbox.destroy();
}
function getActiveElement(doc) {
let activeElement = doc.activeElement;
while (activeElement && activeElement.contentDocument) {
activeElement = activeElement.contentDocument.activeElement;
}
return activeElement;
}
function toggleSplitConsoleWithEscape() {
let onceSplitConsole = toolbox.once("split-console");
let contentWindow = toolbox.frame.contentWindow;
contentWindow.focus();
EventUtils.sendKey("ESCAPE", contentWindow);
return onceSplitConsole;
}
function finish() {
toolbox = TEST_URI = null;
Services.prefs.clearUserPref("devtools.toolbox.splitconsoleEnabled");
Services.prefs.clearUserPref("devtools.toolbox.splitconsoleHeight");
finishTest();
}
}

View File

@ -35,6 +35,12 @@ function test() {
ok(toolbox.splitConsole, "Split console is visible by default.");
is(getHeightPrefValue(), 200, "Height is set based on panel height after closing");
// Use the binding element since jsterm.inputNode is a XUL textarea element.
let activeElement = getActiveElement(toolbox.doc);
activeElement = activeElement.ownerDocument.getBindingParent(activeElement);
let inputNode = toolbox.getPanel("webconsole").hud.jsterm.inputNode;
is(activeElement, inputNode, "Split console input is focused by default");
toolbox.webconsolePanel.height = 1;
ok (toolbox.webconsolePanel.clientHeight > 1,
"The actual height of the console is bound with a min height");
@ -63,6 +69,14 @@ function test() {
yield toolbox.destroy();
}
function getActiveElement(doc) {
let activeElement = doc.activeElement;
while (activeElement && activeElement.contentDocument) {
activeElement = activeElement.contentDocument.activeElement;
}
return activeElement;
}
function getVisiblePrefValue() {
return Services.prefs.getBoolPref("devtools.toolbox.splitconsoleEnabled");
}

View File

@ -3137,7 +3137,11 @@ JSTerm.prototype = {
inputContainer.style.display = "none";
}
else {
this._onPaste = WebConsoleUtils.pasteHandlerGen(this.inputNode, doc.getElementById("webconsole-notificationbox"));
let okstring = l10n.getStr("selfxss.okstring");
let msg = l10n.getFormatStr("selfxss.msg", [okstring]);
this._onPaste = WebConsoleUtils.pasteHandlerGen(this.inputNode,
doc.getElementById("webconsole-notificationbox"),
msg, okstring);
this.inputNode.addEventListener("keypress", this._keyPress, false);
this.inputNode.addEventListener("paste", this._onPaste);
this.inputNode.addEventListener("drop", this._onPaste);

View File

@ -103,3 +103,13 @@ scratchpad.panelLabel=Scratchpad Panel
# tooltip of the tab when the Scratchpad is displayed inside the developer tools
# window.
scratchpad.tooltip=Scratchpad
# LOCALIZATION NOTE (selfxss.msg): the text that is displayed when
# a new user of the developer tools pastes code into the console
# %1 is the text of selfxss.okstring
selfxss.msg=Scam Warning: Take care when pasting things you don't understand. This could allow attackers to steal your identity or take control of your computer. Please type '%S' in the scratchpad below to allow pasting.
# LOCALIZATION NOTE (selfxss.msg): the string to be typed
# in by a new user of the developer tools when they receive the sefxss.msg prompt.
# Please avoid using non-keyboard characters here
selfxss.okstring=allow pasting

View File

@ -251,4 +251,13 @@ let AboutHome = {
Cu.reportError("Error in AboutHome.sendAboutHomeData: " + x);
});
},
/**
* Focuses the search input in the page with the given message manager.
* @param messageManager
* The MessageManager object of the selected browser.
*/
focusInput: function (messageManager) {
messageManager.sendAsyncMessage("AboutHome:FocusInput");
}
};

View File

@ -94,6 +94,17 @@ this.ContentSearch = {
Services.obs.addObserver(this, "browser-search-engine-modified", false);
},
/**
* Focuses the search input in the page with the given message manager.
* @param messageManager
* The MessageManager object of the selected browser.
*/
focusInput: function (messageManager) {
messageManager.sendAsyncMessage(OUTBOUND_MESSAGE, {
type: "FocusInput"
});
},
receiveMessage: function (msg) {
// Add a temporary event handler that exists only while the message is in
// the event queue. If the message's source docshell changes browsers in

View File

@ -881,7 +881,6 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
}
.urlbar-icon {
cursor: pointer;
padding: 0 3px;
}
@ -1524,7 +1523,6 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
#urlbar > toolbarbutton {
-moz-appearance: none;
padding: 0 2px;
cursor: pointer;
list-style-image: url("chrome://browser/skin/reload-stop-go.png");
}

View File

@ -35,17 +35,6 @@ browser.jar:
skin/classic/browser/identity-icons-https-mixed-active.png
skin/classic/browser/identity-icons-https-mixed-display.png
skin/classic/browser/Info.png
* skin/classic/browser/in-content/common.css (in-content/common.css)
skin/classic/browser/in-content/check.png (../shared/in-content/check.png)
skin/classic/browser/in-content/check@2x.png (../shared/in-content/check@2x.png)
skin/classic/browser/in-content/dropdown.png (../shared/in-content/dropdown.png)
skin/classic/browser/in-content/dropdown@2x.png (../shared/in-content/dropdown@2x.png)
skin/classic/browser/in-content/dropdown-disabled.png (../shared/in-content/dropdown-disabled.png)
skin/classic/browser/in-content/dropdown-disabled@2x.png (../shared/in-content/dropdown-disabled@2x.png)
skin/classic/browser/in-content/help-glyph.png (../shared/in-content/help-glyph.png)
skin/classic/browser/in-content/help-glyph@2x.png (../shared/in-content/help-glyph@2x.png)
skin/classic/browser/in-content/sorter.png (../shared/in-content/sorter.png)
skin/classic/browser/in-content/sorter@2x.png (../shared/in-content/sorter@2x.png)
skin/classic/browser/menuPanel.png
skin/classic/browser/menuPanel-customize.png
skin/classic/browser/menuPanel-exit.png

View File

@ -57,7 +57,6 @@
.search-go-button {
padding: 1px;
list-style-image: url(moz-icon://stock/gtk-find?size=menu);
cursor: pointer;
}
menuitem[cmd="cmd_clearhistory"] {

View File

@ -43,17 +43,6 @@ browser.jar:
skin/classic/browser/identity-icons-https-mixed-display.png
skin/classic/browser/identity-icons-https-mixed-display@2x.png
skin/classic/browser/Info.png
* skin/classic/browser/in-content/common.css (in-content/common.css)
skin/classic/browser/in-content/check.png (../shared/in-content/check.png)
skin/classic/browser/in-content/check@2x.png (../shared/in-content/check@2x.png)
skin/classic/browser/in-content/dropdown.png (../shared/in-content/dropdown.png)
skin/classic/browser/in-content/dropdown@2x.png (../shared/in-content/dropdown@2x.png)
skin/classic/browser/in-content/dropdown-disabled.png (../shared/in-content/dropdown-disabled.png)
skin/classic/browser/in-content/dropdown-disabled@2x.png (../shared/in-content/dropdown-disabled@2x.png)
skin/classic/browser/in-content/help-glyph.png (../shared/in-content/help-glyph.png)
skin/classic/browser/in-content/help-glyph@2x.png (../shared/in-content/help-glyph@2x.png)
skin/classic/browser/in-content/sorter.png (../shared/in-content/sorter.png)
skin/classic/browser/in-content/sorter@2x.png (../shared/in-content/sorter@2x.png)
skin/classic/browser/keyhole-circle.png
skin/classic/browser/keyhole-circle@2x.png
skin/classic/browser/KUI-background.png

View File

@ -897,14 +897,14 @@ toolbarbutton[panel-multiview-anchor="true"] > .toolbarbutton-menubutton-button
toolbarbutton[panel-multiview-anchor="true"] {
background-image: url(chrome://browser/skin/customizableui/subView-arrow-back-inverted.png),
linear-gradient(rgba(255,255,255,0.3), rgba(255,255,255,0));
background-position: right 5px center;
background-position: right calc(@menuPanelButtonWidth@ / 2 - @exitSubviewGutterWidth@ + 2px) center;
background-repeat: no-repeat, repeat;
}
toolbarbutton[panel-multiview-anchor="true"]:-moz-locale-dir(rtl) {
background-image: url(chrome://browser/skin/customizableui/subView-arrow-back-inverted-rtl.png),
linear-gradient(rgba(255,255,255,0.3), rgba(255,255,255,0));
background-position: left 5px center;
background-position: left calc(@menuPanelButtonWidth@ / 2 - @exitSubviewGutterWidth@ + 2px) center;
}
toolbarpaletteitem[place="palette"] > .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker,

View File

@ -99,6 +99,10 @@ text {
* Inspector Styles
*/
#web-audio-inspector-title {
margin: 6px;
}
.web-audio-inspector .error {
background-image: url(alerticon-warning.png);
background-size: 13px 12px;

View File

@ -167,7 +167,7 @@ prefpane {
#typeColumn > .treecol-sortdirection[sortDirection=descending],
#actionColumn > .treecol-sortdirection[sortDirection=descending] {
-moz-appearance: none;
list-style-image: url("chrome://browser/skin/in-content/sorter.png");
list-style-image: url("chrome://global/skin/in-content/sorter.png");
}
#typeColumn > .treecol-sortdirection[sortDirection=descending],
@ -182,7 +182,7 @@ prefpane {
#actionColumn > .treecol-sortdirection[sortDirection=descending] {
width: 12px;
height: 8px;
list-style-image: url("chrome://browser/skin/in-content/sorter@2x.png");
list-style-image: url("chrome://global/skin/in-content/sorter@2x.png");
}
}

View File

@ -37,17 +37,6 @@ browser.jar:
skin/classic/browser/identity-icons-https-ev.png
skin/classic/browser/identity-icons-https-mixed-active.png
skin/classic/browser/identity-icons-https-mixed-display.png
* skin/classic/browser/in-content/common.css (in-content/common.css)
skin/classic/browser/in-content/check.png (../shared/in-content/check.png)
skin/classic/browser/in-content/check@2x.png (../shared/in-content/check@2x.png)
skin/classic/browser/in-content/dropdown.png (../shared/in-content/dropdown.png)
skin/classic/browser/in-content/dropdown@2x.png (../shared/in-content/dropdown@2x.png)
skin/classic/browser/in-content/dropdown-disabled.png (../shared/in-content/dropdown-disabled.png)
skin/classic/browser/in-content/dropdown-disabled@2x.png (../shared/in-content/dropdown-disabled@2x.png)
skin/classic/browser/in-content/help-glyph.png (../shared/in-content/help-glyph.png)
skin/classic/browser/in-content/help-glyph@2x.png (../shared/in-content/help-glyph@2x.png)
skin/classic/browser/in-content/sorter.png (../shared/in-content/sorter.png)
skin/classic/browser/in-content/sorter@2x.png (../shared/in-content/sorter@2x.png)
skin/classic/browser/keyhole-forward-mask.svg
skin/classic/browser/KUI-background.png
skin/classic/browser/livemark-folder.png
@ -457,17 +446,6 @@ browser.jar:
skin/classic/aero/browser/identity-icons-https-ev.png
skin/classic/aero/browser/identity-icons-https-mixed-active.png
skin/classic/aero/browser/identity-icons-https-mixed-display.png
* skin/classic/aero/browser/in-content/common.css (in-content/common.css)
skin/classic/aero/browser/in-content/check.png (../shared/in-content/check.png)
skin/classic/aero/browser/in-content/check@2x.png (../shared/in-content/check@2x.png)
skin/classic/aero/browser/in-content/dropdown.png (../shared/in-content/dropdown.png)
skin/classic/aero/browser/in-content/dropdown@2x.png (../shared/in-content/dropdown@2x.png)
skin/classic/aero/browser/in-content/dropdown-disabled.png (../shared/in-content/dropdown-disabled.png)
skin/classic/aero/browser/in-content/dropdown-disabled@2x.png (../shared/in-content/dropdown-disabled@2x.png)
skin/classic/aero/browser/in-content/help-glyph.png (../shared/in-content/help-glyph.png)
skin/classic/aero/browser/in-content/help-glyph@2x.png (../shared/in-content/help-glyph@2x.png)
skin/classic/aero/browser/in-content/sorter.png (../shared/in-content/sorter.png)
skin/classic/aero/browser/in-content/sorter@2x.png (../shared/in-content/sorter@2x.png)
skin/classic/aero/browser/keyhole-forward-mask.svg
skin/classic/aero/browser/KUI-background.png
skin/classic/aero/browser/livemark-folder.png (livemark-folder-aero.png)

View File

@ -5,7 +5,7 @@
#include "nsISupports.idl"
[scriptable, uuid(0e56f04d-cda4-4a55-ab83-e5e29ddd370e)]
[scriptable, uuid(231df043-3a32-43c4-aaac-7ad2da81e84f)]
interface nsIPluginTag : nsISupports
{
// enabledState is stored as one of the following as an integer in prefs,
@ -25,6 +25,11 @@ interface nsIPluginTag : nsISupports
*/
readonly attribute boolean blocklisted;
/**
* true if the state is non-default and locked, false otherwise.
*/
readonly attribute boolean isEnabledStateLocked;
readonly attribute boolean disabled;
readonly attribute boolean clicktoplay;
attribute unsigned long enabledState;

View File

@ -16,6 +16,7 @@
#include "nsPluginLogging.h"
#include "nsNPAPIPlugin.h"
#include "mozilla/Preferences.h"
#include "mozilla/unused.h"
#include <cctype>
#include "mozilla/dom/EncodingUtils.h"
@ -340,6 +341,22 @@ nsPluginTag::GetBlocklisted(bool* aBlocklisted)
return NS_OK;
}
NS_IMETHODIMP
nsPluginTag::GetIsEnabledStateLocked(bool* aIsEnabledStateLocked)
{
*aIsEnabledStateLocked = false;
nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
if (NS_WARN_IF(!prefs)) {
return NS_ERROR_FAILURE;
}
unused << prefs->PrefIsLocked(GetStatePrefNameForPlugin(this).get(),
aIsEnabledStateLocked);
return NS_OK;
}
bool
nsPluginTag::IsClicktoplay()
{

View File

@ -2,10 +2,12 @@
* 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/. */
package org.mozilla.gecko.home;
package org.mozilla.gecko;
import org.mozilla.gecko.AppConstants;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.mozglue.RobocopTarget;
import org.mozilla.gecko.util.HardwareUtils;
import org.json.JSONArray;
@ -28,7 +30,11 @@ import java.util.ArrayList;
*/
public class SuggestClient {
private static final String LOGTAG = "GeckoSuggestClient";
private static final String USER_AGENT = GeckoAppShell.getGeckoInterface().getDefaultUAString();
// This should go through GeckoInterface to get the UA, but the search activity
// doesn't use a GeckoView yet. Until it does, get the UA directly.
private static final String USER_AGENT = HardwareUtils.isTablet() ?
AppConstants.USER_AGENT_FENNEC_TABLET : AppConstants.USER_AGENT_FENNEC_MOBILE;
private final Context mContext;
private final int mTimeout;
@ -112,7 +118,7 @@ public class SuggestClient {
*/
JSONArray results = new JSONArray(json);
JSONArray jsonSuggestions = results.getJSONArray(1);
int added = 0;
for (int i = 0; (i < jsonSuggestions.length()) && (added < mMaxResults); i++) {
String suggestion = jsonSuggestions.getString(i);

View File

@ -19,6 +19,7 @@ import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.GeckoEvent;
import org.mozilla.gecko.PrefsHelper;
import org.mozilla.gecko.R;
import org.mozilla.gecko.SuggestClient;
import org.mozilla.gecko.Tab;
import org.mozilla.gecko.Tabs;
import org.mozilla.gecko.Telemetry;

View File

@ -302,7 +302,6 @@ gbjar.sources += [
'home/SearchEngineRow.java',
'home/SearchLoader.java',
'home/SimpleCursorLoader.java',
'home/SuggestClient.java',
'home/TabMenuStrip.java',
'home/TabMenuStripLayout.java',
'home/TopSitesGridItemView.java',
@ -379,6 +378,7 @@ gbjar.sources += [
'sqlite/MatrixBlobCursor.java',
'sqlite/SQLiteBridge.java',
'sqlite/SQLiteBridgeException.java',
'SuggestClient.java',
'SurfaceBits.java',
'Tab.java',
'Tabs.java',

View File

@ -46,11 +46,10 @@
android:layout_height="match_parent"
android:visibility="gone"/>
<org.mozilla.gecko.tabs.RemoteTabsPanel
android:id="@+id/remote_tabs"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:visibility="gone"/>
<ViewStub android:id="@+id/remote_tabs_panel_stub"
android:layout="@layout/remote_tabs_panel_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</view>

View File

@ -0,0 +1,9 @@
<?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/. -->
<org.mozilla.gecko.tabs.RemoteTabsPanel xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/remote_tabs_panel"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

View File

@ -45,11 +45,10 @@
android:layout_height="match_parent"
android:visibility="gone"/>
<org.mozilla.gecko.tabs.RemoteTabsPanel
android:id="@+id/remote_tabs"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:visibility="gone"/>
<ViewStub android:id="@+id/remote_tabs_panel_stub"
android:layout="@layout/remote_tabs_panel_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</view>

View File

@ -32,6 +32,7 @@ import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewStub;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageButton;
@ -113,7 +114,7 @@ public class TabsPanel extends LinearLayout
public void onResume() {
if (mPanel == mPanelRemote) {
// Refresh the remote panel.
mPanelRemote.show();
getRemotePanelView().show();
}
}
@ -127,7 +128,23 @@ public class TabsPanel extends LinearLayout
};
}
/**
* Initializes views in tabs_panel layout
*
* @throws IllegalStateException
* mCurrentPanel must have a non-null value
*/
private void initialize() {
if (mCurrentPanel == null) {
throw new IllegalStateException(
"mCurrentPanel cannot be null in order for RemotePanelView to be initialized");
}
if (mCurrentPanel == Panel.REMOTE_TABS) {
// Initializes mPanelRemote
getRemotePanelView();
}
mHeader = (RelativeLayout) findViewById(R.id.tabs_panel_header);
mTabsContainer = (TabsListContainer) findViewById(R.id.tabs_container);
@ -137,9 +154,6 @@ public class TabsPanel extends LinearLayout
mPanelPrivate = (PanelView) findViewById(R.id.private_tabs_panel);
mPanelPrivate.setTabsPanel(this);
mPanelRemote = (PanelView) findViewById(R.id.remote_tabs);
mPanelRemote.setTabsPanel(this);
mFooter = (RelativeLayout) findViewById(R.id.tabs_panel_footer);
mAddTab = (ImageButton) findViewById(R.id.add_tab);
@ -416,7 +430,7 @@ public class TabsPanel extends LinearLayout
mPanel = mPanelPrivate;
break;
case REMOTE_TABS:
mPanel = mPanelRemote;
mPanel = getRemotePanelView();
break;
default:
@ -472,6 +486,9 @@ public class TabsPanel extends LinearLayout
public void refresh() {
removeAllViews();
// The View that mPanelRemote points to is invalidated because the layout is invalidated.
// mPanelRemote must be null in order to properly initialize RemotePanelView.
mPanelRemote = null;
LayoutInflater.from(mContext).inflate(R.layout.tabs_panel, this);
initialize();
@ -570,4 +587,18 @@ public class TabsPanel extends LinearLayout
public void setIconDrawable(Panel panel, int resource) {
mTabWidget.setIconDrawable(panel.ordinal(), resource);
}
/**
* Initializes mPanelRemote if necessary and provides getter because you
* should probably not access mPanelRemote directly
*
* @return PanelView
*/
private PanelView getRemotePanelView() {
if (mPanelRemote == null) {
mPanelRemote = (PanelView) ((ViewStub) findViewById(R.id.remote_tabs_panel_stub)).inflate();
mPanelRemote.setTabsPanel(TabsPanel.this);
}
return mPanelRemote;
}
}

View File

@ -5,8 +5,8 @@ import java.util.HashMap;
import org.mozilla.gecko.Actions;
import org.mozilla.gecko.R;
import org.mozilla.gecko.SuggestClient;
import org.mozilla.gecko.home.BrowserSearch;
import org.mozilla.gecko.home.SuggestClient;
import android.app.Activity;
import android.support.v4.app.Fragment;

View File

@ -1,145 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.search.autocomplete;
import org.json.JSONArray;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.text.TextUtils;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
/**
* Use network-based search suggestions.
*/
public class SuggestClient {
private static final String LOGTAG = "GeckoSuggestClient";
private static final String USER_AGENT = "";
private final Context mContext;
private final int mTimeout;
// should contain the string "__searchTerms__", which is replaced with the query
private final String mSuggestTemplate;
// the maximum number of suggestions to return
private final int mMaxResults;
// used by robocop for testing
private boolean mCheckNetwork;
// used to make suggestions appear instantly after opt-in
private String mPrevQuery;
private ArrayList<String> mPrevResults;
public SuggestClient(Context context, String suggestTemplate, int timeout, int maxResults) {
mContext = context;
mMaxResults = maxResults;
mSuggestTemplate = suggestTemplate;
mTimeout = timeout;
mCheckNetwork = true;
}
/**
* Queries for a given search term and returns an ArrayList of suggestions.
*/
public ArrayList<String> query(String query) {
if (query.equals(mPrevQuery))
return mPrevResults;
ArrayList<String> suggestions = new ArrayList<String>();
if (TextUtils.isEmpty(mSuggestTemplate) || TextUtils.isEmpty(query)) {
return suggestions;
}
if (!isNetworkConnected() && mCheckNetwork) {
Log.i(LOGTAG, "Not connected to network");
return suggestions;
}
try {
String encoded = URLEncoder.encode(query, "UTF-8");
String suggestUri = mSuggestTemplate.replace("__searchTerms__", encoded);
URL url = new URL(suggestUri);
String json = null;
HttpURLConnection urlConnection = null;
InputStream in = null;
try {
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setConnectTimeout(mTimeout);
urlConnection.setRequestProperty("User-Agent", USER_AGENT);
in = new BufferedInputStream(urlConnection.getInputStream());
json = convertStreamToString(in);
} finally {
if (urlConnection != null)
urlConnection.disconnect();
if (in != null) {
try {
in.close();
} catch (IOException e) {
Log.e(LOGTAG, "error", e);
}
}
}
if (json != null) {
/*
* Sample result:
* ["foo",["food network","foothill college","foot locker",...]]
*/
JSONArray results = new JSONArray(json);
JSONArray jsonSuggestions = results.getJSONArray(1);
int added = 0;
for (int i = 0; (i < jsonSuggestions.length()) && (added < mMaxResults); i++) {
String suggestion = jsonSuggestions.getString(i);
if (!suggestion.equalsIgnoreCase(query)) {
suggestions.add(suggestion);
added++;
}
}
} else {
Log.e(LOGTAG, "Suggestion query failed");
}
} catch (Exception e) {
Log.e(LOGTAG, "Error", e);
}
mPrevQuery = query;
mPrevResults = suggestions;
return suggestions;
}
private boolean isNetworkConnected() {
NetworkInfo networkInfo = getActiveNetworkInfo();
return networkInfo != null && networkInfo.isConnected();
}
private NetworkInfo getActiveNetworkInfo() {
ConnectivityManager connectivity = (ConnectivityManager) mContext
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity == null)
return null;
return connectivity.getActiveNetworkInfo();
}
private String convertStreamToString(java.io.InputStream is) {
try {
return new java.util.Scanner(is).useDelimiter("\\A").next();
} catch (java.util.NoSuchElementException e) {
return "";
}
}
}

View File

@ -21,6 +21,7 @@ import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import org.mozilla.gecko.SuggestClient;
import org.mozilla.gecko.Telemetry;
import org.mozilla.gecko.TelemetryContract;
import org.mozilla.search.AcceptsSearchQuery;

View File

@ -8,7 +8,6 @@ search_activity_sources = [
'java/org/mozilla/search/AcceptsSearchQuery.java',
'java/org/mozilla/search/autocomplete/AutoCompleteAdapter.java',
'java/org/mozilla/search/autocomplete/ClearableEditText.java',
'java/org/mozilla/search/autocomplete/SuggestClient.java',
'java/org/mozilla/search/autocomplete/SuggestionsFragment.java',
'java/org/mozilla/search/Constants.java',
'java/org/mozilla/search/MainActivity.java',

View File

@ -570,7 +570,7 @@ let WebConsoleUtils = {
* @param nsIDOMElement notificationBox
* @returns A function to be added as a handler to 'paste' and 'drop' events on the input field
*/
pasteHandlerGen: function WCU_pasteHandlerGen(inputField, notificationBox){
pasteHandlerGen: function WCU_pasteHandlerGen(inputField, notificationBox, msg, okstring) {
let handler = function WCU_pasteHandler(aEvent) {
if (WebConsoleUtils.usageCount >= CONSOLE_ENTRY_THRESHOLD) {
inputField.removeEventListener("paste", handler);
@ -582,9 +582,7 @@ let WebConsoleUtils = {
aEvent.stopPropagation();
return false;
}
let l10n = new WebConsoleUtils.l10n("chrome://browser/locale/devtools/webconsole.properties");
let okstring = l10n.getStr("selfxss.okstring");
let msg = l10n.getFormatStr("selfxss.msg", [okstring]);
let notification = notificationBox.appendNotification(msg,
"selfxss-notification", null, notificationBox.PRIORITY_WARNING_HIGH, null,

View File

@ -3106,13 +3106,13 @@ var gDetailView = {
let menulist = document.getElementById("detail-state-menulist");
let addonType = AddonManager.addonTypes[this._addon.type];
if (addonType.flags & AddonManager.TYPE_SUPPORTS_ASK_TO_ACTIVATE &&
(hasPermission(this._addon, "ask_to_activate") ||
hasPermission(this._addon, "enable") ||
hasPermission(this._addon, "disable"))) {
if (addonType.flags & AddonManager.TYPE_SUPPORTS_ASK_TO_ACTIVATE) {
let askItem = document.getElementById("detail-ask-to-activate-menuitem");
let alwaysItem = document.getElementById("detail-always-activate-menuitem");
let neverItem = document.getElementById("detail-never-activate-menuitem");
let hasActivatePermission =
["ask_to_activate", "enable", "disable"].some(perm => hasPermission(this._addon, perm));
if (this._addon.userDisabled === true) {
menulist.selectedItem = neverItem;
} else if (this._addon.userDisabled == AddonManager.STATE_ASK_TO_ACTIVATE) {
@ -3120,7 +3120,10 @@ var gDetailView = {
} else {
menulist.selectedItem = alwaysItem;
}
menulist.disabled = !hasActivatePermission;
menulist.hidden = false;
menulist.classList.add('no-auto-hide');
} else {
menulist.hidden = true;
}

View File

@ -1306,10 +1306,7 @@
this.mAddon.optionsType == AddonManager.OPTIONS_TYPE_INLINE_INFO;
let addonType = AddonManager.addonTypes[this.mAddon.type];
if (addonType.flags & AddonManager.TYPE_SUPPORTS_ASK_TO_ACTIVATE &&
(this.hasPermission("ask_to_activate") ||
this.hasPermission("enable") ||
this.hasPermission("disable"))) {
if (addonType.flags & AddonManager.TYPE_SUPPORTS_ASK_TO_ACTIVATE) {
this._enableBtn.disabled = true;
this._disableBtn.disabled = true;
this._askToActivateMenuitem.disabled = !this.hasPermission("ask_to_activate");
@ -1322,10 +1319,13 @@
} else {
this._stateMenulist.selectedItem = this._alwaysActivateMenuitem;
}
this._stateMenulist.selectedItem.disabled = false;
this._stateMenulist.disabled = false;
let hasActivatePermission =
["ask_to_activate", "enable", "disable"].some(perm => this.hasPermission(perm));
this._stateMenulist.disabled = !hasActivatePermission;
this._stateMenulist.hidden = false;
this._stateMenulist.classList.add('no-auto-hide');
} else {
this._stateMenulist.disabled = true;
this._stateMenulist.hidden = true;
if (this.hasPermission("enable")) {
this._enableBtn.hidden = false;
let tooltip = gViewController.commands["cmd_enableItem"]

View File

@ -461,6 +461,9 @@ function PluginWrapper(aId, aName, aDescription, aTags) {
this.__defineGetter__("permissions", function() {
let permissions = 0;
if (aTags[0].isEnabledStateLocked) {
return permissions;
}
if (!this.appDisabled) {
if (this.userDisabled !== true)

View File

@ -44,6 +44,7 @@ skip-if = buildapp == 'mulet'
[browser_searching.js]
[browser_sorting.js]
[browser_sorting_plugins.js]
[browser_plugin_enabled_state_locked.js]
skip-if = e10s # Bug ?????? - leaked until shutdown [nsGlobalWindow #1760 about:blank]
[browser_uninstalling.js]
skip-if = e10s # Bug ?????? - leaked until shutdown [nsGlobalWindow #1760 about:blank]

View File

@ -200,7 +200,7 @@ function part12(aWindow) {
let pluginEl = get_addon_element(gManagerWindow, gTestPluginId);
pluginEl.parentNode.ensureElementIsVisible(pluginEl);
let menu = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "state-menulist");
is_element_hidden(menu, "part12: state menu should be hidden");
is(menu.disabled, true, "part12: state menu should be disabled");
let details = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "details-btn");
EventUtils.synthesizeMouseAtCenter(details, {}, gManagerWindow);
@ -209,7 +209,7 @@ function part12(aWindow) {
function part13() {
let menu = gManagerWindow.document.getElementById("detail-state-menulist");
is_element_hidden(menu, "part13: detail state menu should be hidden");
is(menu.disabled, true, "part13: detail state menu should be disabled");
setAndUpdateBlocklist(gHttpTestRoot + "blockNoPlugins.xml", function() {
run_next_test();

View File

@ -0,0 +1,121 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Tests that state menu is displayed correctly (enabled or disabled) in the add-on manager
// when the preference is unlocked / locked
const {classes: Cc, interfaces: Ci} = Components;
const gIsWindows = ("@mozilla.org/windows-registry-key;1" in Cc);
const gIsOSX = ("nsILocalFileMac" in Ci);
const gIsLinux = ("@mozilla.org/gnome-gconf-service;1" in Cc) ||
("@mozilla.org/gio-service;1" in Cc);
let gManagerWindow;
let gCategoryUtilities;
let gPluginElement;
function getTestPluginPref() {
let prefix = "plugin.state.";
if (gIsWindows)
return prefix + "nptest";
else if (gIsLinux)
return prefix + "libnptest";
else
return prefix + "test";
}
registerCleanupFunction(() => {
Services.prefs.unlockPref(getTestPluginPref());
Services.prefs.clearUserPref(getTestPluginPref());
});
function getPlugins() {
let deferred = Promise.defer();
AddonManager.getAddonsByTypes(["plugin"], plugins => deferred.resolve(plugins));
return deferred.promise;
}
function getTestPlugin(aPlugins) {
let testPluginId;
for (let plugin of aPlugins) {
if (plugin.name == "Test Plug-in") {
testPluginId = plugin.id;
break;
}
}
Assert.ok(testPluginId, "Test Plug-in should exist");
let pluginElement = get_addon_element(gManagerWindow, testPluginId);
pluginElement.parentNode.ensureElementIsVisible(pluginElement);
return pluginElement;
}
function checkStateMenu(locked) {
Assert.equal(Services.prefs.prefIsLocked(getTestPluginPref()), locked,
"Preference lock state should be correct.");
let menuList = gManagerWindow.document.getAnonymousElementByAttribute(gPluginElement, "anonid", "state-menulist");
is_element_visible(menuList, "State menu should be visible.");
Assert.equal(menuList.disabled, locked,
"State menu should" + (locked === true ? "" : " not") + " be disabled.");
}
function checkStateMenuDetail(locked) {
Assert.equal(Services.prefs.prefIsLocked(getTestPluginPref()), locked,
"Preference should be " + (locked === true ? "" : "un") + "locked.");
// open details menu
let details = gManagerWindow.document.getAnonymousElementByAttribute(gPluginElement, "anonid", "details-btn");
is_element_visible(details, "Details link should be visible.");
EventUtils.synthesizeMouseAtCenter(details, {}, gManagerWindow);
let deferred = Promise.defer();
wait_for_view_load(gManagerWindow, function() {
let menuList = gManagerWindow.document.getElementById("detail-state-menulist");
is_element_visible(menuList, "Details state menu should be visible.");
Assert.equal(menuList.disabled, locked,
"Details state menu enabled state should be correct.");
deferred.resolve();
});
return deferred.promise;
}
add_task(function* initializeState() {
Services.prefs.setIntPref(getTestPluginPref(), Ci.nsIPluginTag.STATE_ENABLED);
Services.prefs.unlockPref(getTestPluginPref());
gManagerWindow = yield open_manager();
gCategoryUtilities = new CategoryUtilities(gManagerWindow);
yield gCategoryUtilities.openType("plugin");
let plugins = yield getPlugins();
gPluginElement = getTestPlugin(plugins);
});
// Tests that plugin state menu is enabled if the preference is unlocked
add_task(function* taskCheckStateMenuIsEnabled() {
checkStateMenu(false);
yield checkStateMenuDetail(false);
});
// Lock the preference and then reload the plugin category
add_task(function* reinitializeState() {
// lock the preference
Services.prefs.lockPref(getTestPluginPref());
yield gCategoryUtilities.openType("plugin");
// Retrieve the test plugin element
let plugins = yield getPlugins();
gPluginElement = getTestPlugin(plugins);
});
// Tests that plugin state menu is disabled if the preference is locked
add_task(function* taskCheckStateMenuIsDisabled() {
checkStateMenu(true);
yield checkStateMenuDetail(true);
});
add_task(function* testCleanup() {
yield close_manager(gManagerWindow);
});

View File

@ -2,7 +2,7 @@
- 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 ../../shared/in-content/common.inc.css
%include ../../../shared/in-content/common.inc.css
xul|tab[selected] {
/* Override styles for tab[selected] from

View File

@ -54,4 +54,15 @@ toolkit.jar:
+ skin/classic/global/icons/webapps-16.png (icons/webapps-16.png)
+ skin/classic/global/icons/webapps-64.png (icons/webapps-64.png)
skin/classic/global/menu/shared-menu-check.png (../../shared/menu-check.png)
* skin/classic/global/in-content/common.css (in-content/common.css)
skin/classic/global/in-content/check.png (../../shared/in-content/check.png)
skin/classic/global/in-content/check@2x.png (../../shared/in-content/check@2x.png)
skin/classic/global/in-content/dropdown.png (../../shared/in-content/dropdown.png)
skin/classic/global/in-content/dropdown@2x.png (../../shared/in-content/dropdown@2x.png)
skin/classic/global/in-content/dropdown-disabled.png (../../shared/in-content/dropdown-disabled.png)
skin/classic/global/in-content/dropdown-disabled@2x.png (../../shared/in-content/dropdown-disabled@2x.png)
skin/classic/global/in-content/help-glyph.png (../../shared/in-content/help-glyph.png)
skin/classic/global/in-content/help-glyph@2x.png (../../shared/in-content/help-glyph@2x.png)
skin/classic/global/in-content/sorter.png (../../shared/in-content/sorter.png)
skin/classic/global/in-content/sorter@2x.png (../../shared/in-content/sorter@2x.png)
+ skin/classic/global/toolbar/spring.png (toolbar/spring.png)

View File

@ -884,6 +884,10 @@ setting[type="radio"] > radiogroup {
display: none;
}
.addon-control.no-auto-hide {
display: block;
}
.addon-control.enable {
list-style-image: url("moz-icon://stock/gtk-yes?size=button");
}

View File

@ -2,7 +2,7 @@
- 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 ../../shared/in-content/common.inc.css
%include ../../../shared/in-content/common.inc.css
xul|tabs {
padding-right: 0;

View File

@ -184,6 +184,17 @@ toolkit.jar:
skin/classic/global/menu/menu-arrow@2x.png (menu/menu-arrow@2x.png)
skin/classic/global/menu/shared-menu-check.png (../../shared/menu-check.png)
skin/classic/global/menu/shared-menu-check@2x.png (../../shared/menu-check@2x.png)
* skin/classic/global/in-content/common.css (in-content/common.css)
skin/classic/global/in-content/check.png (../../shared/in-content/check.png)
skin/classic/global/in-content/check@2x.png (../../shared/in-content/check@2x.png)
skin/classic/global/in-content/dropdown.png (../../shared/in-content/dropdown.png)
skin/classic/global/in-content/dropdown@2x.png (../../shared/in-content/dropdown@2x.png)
skin/classic/global/in-content/dropdown-disabled.png (../../shared/in-content/dropdown-disabled.png)
skin/classic/global/in-content/dropdown-disabled@2x.png (../../shared/in-content/dropdown-disabled@2x.png)
skin/classic/global/in-content/help-glyph.png (../../shared/in-content/help-glyph.png)
skin/classic/global/in-content/help-glyph@2x.png (../../shared/in-content/help-glyph@2x.png)
skin/classic/global/in-content/sorter.png (../../shared/in-content/sorter.png)
skin/classic/global/in-content/sorter@2x.png (../../shared/in-content/sorter@2x.png)
skin/classic/global/scale/scale-tray-horiz.gif (scale/scale-tray-horiz.gif)
skin/classic/global/scale/scale-tray-vert.gif (scale/scale-tray-vert.gif)
skin/classic/global/splitter/dimple.png (splitter/dimple.png)

View File

@ -1108,6 +1108,10 @@ setting[type="radio"] > radiogroup {
display: none;
}
.addon-control.no-auto-hide {
display: block;
}
button.button-link {
-moz-appearance: none;
background: transparent;

View File

Before

Width:  |  Height:  |  Size: 288 B

After

Width:  |  Height:  |  Size: 288 B

View File

Before

Width:  |  Height:  |  Size: 471 B

After

Width:  |  Height:  |  Size: 471 B

View File

@ -194,7 +194,7 @@ xul|button[type="menu"] > xul|*.button-box > xul|*.button-menu-dropmarker {
height: 16px;
border: none;
background-color: transparent;
list-style-image: url("chrome://browser/skin/in-content/dropdown.png");
list-style-image: url("chrome://global/skin/in-content/dropdown.png");
}
xul|*.help-button {
@ -227,14 +227,14 @@ xul|*.help-button > xul|*.button-box {
xul|*.help-button > xul|*.button-box > xul|*.button-icon {
width: 26px;
height: 26px;
background-image: url("chrome://browser/skin/in-content/help-glyph.png");
background-image: url("chrome://global/skin/in-content/help-glyph.png");
background-position: center;
}
@media (min-resolution: 2dppx) {
xul|*.help-button > xul|*.button-box > xul|*.button-icon {
background-size: 26px 26px;
background-image: url("chrome://browser/skin/in-content/help-glyph@2x.png");
background-image: url("chrome://global/skin/in-content/help-glyph@2x.png");
}
}
@ -283,21 +283,21 @@ xul|menulist:not([editable="true"]) > xul|*.menulist-dropmarker {
padding: 0;
border: none;
background-color: transparent;
list-style-image: url("chrome://browser/skin/in-content/dropdown.png");
list-style-image: url("chrome://global/skin/in-content/dropdown.png");
}
xul|menulist[disabled="true"]:not([editable="true"]) > xul|*.menulist-dropmarker {
list-style-image: url("chrome://browser/skin/in-content/dropdown-disabled.png")
list-style-image: url("chrome://global/skin/in-content/dropdown-disabled.png")
}
@media (min-resolution: 2dppx) {
xul|menulist:not([editable="true"]) > xul|*.menulist-dropmarker,
xul|button[type="menu"] > xul|*.button-box > xul|*.button-menu-dropmarker {
list-style-image: url("chrome://browser/skin/in-content/dropdown@2x.png");
list-style-image: url("chrome://global/skin/in-content/dropdown@2x.png");
}
xul|menulist[disabled="true"]:not([editable="true"]) > xul|*.menulist-dropmarker {
list-style-image: url("chrome://browser/skin/in-content/dropdown-disabled@2x.png")
list-style-image: url("chrome://global/skin/in-content/dropdown-disabled@2x.png")
}
xul|menulist:not([editable="true"]) > xul|*.menulist-dropmarker > xul|*.dropmarker-icon,
@ -431,7 +431,7 @@ xul|checkbox:not([disabled="true"]):hover > xul|*.checkbox-check {
}
xul|*.checkbox-check[checked] {
background-image: url("chrome://browser/skin/in-content/check.png"),
background-image: url("chrome://global/skin/in-content/check.png"),
/* !important needed to override toolkit !important rule */
linear-gradient(#fff, rgba(255,255,255,0.8)) !important;
}
@ -448,7 +448,7 @@ xul|*.checkbox-label-box {
@media (min-resolution: 2dppx) {
xul|*.checkbox-check[checked] {
background-size: 12px 12px, auto;
background-image: url("chrome://browser/skin/in-content/check@2x.png"),
background-image: url("chrome://global/skin/in-content/check@2x.png"),
linear-gradient(#fff, rgba(255,255,255,0.8)) !important;
}
}

View File

Before

Width:  |  Height:  |  Size: 412 B

After

Width:  |  Height:  |  Size: 412 B

View File

Before

Width:  |  Height:  |  Size: 865 B

After

Width:  |  Height:  |  Size: 865 B

View File

Before

Width:  |  Height:  |  Size: 421 B

After

Width:  |  Height:  |  Size: 421 B

View File

Before

Width:  |  Height:  |  Size: 885 B

After

Width:  |  Height:  |  Size: 885 B

View File

Before

Width:  |  Height:  |  Size: 280 B

After

Width:  |  Height:  |  Size: 280 B

View File

Before

Width:  |  Height:  |  Size: 500 B

After

Width:  |  Height:  |  Size: 500 B

View File

Before

Width:  |  Height:  |  Size: 264 B

After

Width:  |  Height:  |  Size: 264 B

View File

Before

Width:  |  Height:  |  Size: 523 B

After

Width:  |  Height:  |  Size: 523 B

View File

@ -2,7 +2,7 @@
- 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 ../../shared/in-content/common.inc.css
%include ../../../shared/in-content/common.inc.css
xul|caption {
background-color: transparent;

View File

@ -169,6 +169,17 @@ toolkit.jar:
skin/classic/global/media/clicktoplay-bgtexture.png (media/clicktoplay-bgtexture.png)
skin/classic/global/media/videoClickToPlayButton.svg (media/videoClickToPlayButton.svg)
skin/classic/global/menu/shared-menu-check.png (../../shared/menu-check.png)
* skin/classic/global/in-content/common.css (in-content/common.css)
skin/classic/global/in-content/check.png (../../shared/in-content/check.png)
skin/classic/global/in-content/check@2x.png (../../shared/in-content/check@2x.png)
skin/classic/global/in-content/dropdown.png (../../shared/in-content/dropdown.png)
skin/classic/global/in-content/dropdown@2x.png (../../shared/in-content/dropdown@2x.png)
skin/classic/global/in-content/dropdown-disabled.png (../../shared/in-content/dropdown-disabled.png)
skin/classic/global/in-content/dropdown-disabled@2x.png (../../shared/in-content/dropdown-disabled@2x.png)
skin/classic/global/in-content/help-glyph.png (../../shared/in-content/help-glyph.png)
skin/classic/global/in-content/help-glyph@2x.png (../../shared/in-content/help-glyph@2x.png)
skin/classic/global/in-content/sorter.png (../../shared/in-content/sorter.png)
skin/classic/global/in-content/sorter@2x.png (../../shared/in-content/sorter@2x.png)
skin/classic/global/printpreview/arrow-left.png (printpreview/arrow-left.png)
skin/classic/global/printpreview/arrow-left-end.png (printpreview/arrow-left-end.png)
skin/classic/global/printpreview/arrow-right.png (printpreview/arrow-right.png)
@ -352,6 +363,17 @@ toolkit.jar:
skin/classic/aero/global/media/clicktoplay-bgtexture.png (media/clicktoplay-bgtexture.png)
skin/classic/aero/global/media/videoClickToPlayButton.svg (media/videoClickToPlayButton.svg)
skin/classic/aero/global/menu/shared-menu-check.png (../../shared/menu-check.png)
* skin/classic/aero/global/in-content/common.css (in-content/common.css)
skin/classic/aero/global/in-content/check.png (../../shared/in-content/check.png)
skin/classic/aero/global/in-content/check@2x.png (../../shared/in-content/check@2x.png)
skin/classic/aero/global/in-content/dropdown.png (../../shared/in-content/dropdown.png)
skin/classic/aero/global/in-content/dropdown@2x.png (../../shared/in-content/dropdown@2x.png)
skin/classic/aero/global/in-content/dropdown-disabled.png (../../shared/in-content/dropdown-disabled.png)
skin/classic/aero/global/in-content/dropdown-disabled@2x.png (../../shared/in-content/dropdown-disabled@2x.png)
skin/classic/aero/global/in-content/help-glyph.png (../../shared/in-content/help-glyph.png)
skin/classic/aero/global/in-content/help-glyph@2x.png (../../shared/in-content/help-glyph@2x.png)
skin/classic/aero/global/in-content/sorter.png (../../shared/in-content/sorter.png)
skin/classic/aero/global/in-content/sorter@2x.png (../../shared/in-content/sorter@2x.png)
skin/classic/aero/global/printpreview/arrow-left.png (printpreview/arrow-left-aero.png)
skin/classic/aero/global/printpreview/arrow-left-end.png (printpreview/arrow-left-end-aero.png)
skin/classic/aero/global/printpreview/arrow-right.png (printpreview/arrow-right-aero.png)

View File

@ -1124,6 +1124,10 @@ menulist { /* Fixes some styling inconsistencies */
display: none;
}
.addon-control.no-auto-hide {
display: block;
}
button.button-link {
-moz-appearance: none;
background: transparent;