Merge mozilla-central and fx-team
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -76,6 +76,10 @@ let gSearch = {
|
||||
}
|
||||
},
|
||||
|
||||
onFocusInput: function () {
|
||||
this._nodes.text.focus();
|
||||
},
|
||||
|
||||
_nodeIDSuffixes: [
|
||||
"form",
|
||||
"logo",
|
||||
|
@ -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.");
|
||||
})
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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'
|
||||
|
@ -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");
|
||||
});
|
@ -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);
|
||||
});
|
||||
}
|
@ -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);
|
||||
});
|
||||
}
|
@ -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);
|
||||
});
|
||||
}
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -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",
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
},
|
||||
|
||||
|
@ -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]
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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");
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
}
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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"] {
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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);
|
@ -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;
|
||||
|
@ -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',
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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"/>
|
@ -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>
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 "";
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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',
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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"]
|
||||
|
@ -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)
|
||||
|
@ -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]
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
});
|
@ -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
|
@ -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)
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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;
|
@ -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)
|
||||
|
@ -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;
|
||||
|
Before Width: | Height: | Size: 288 B After Width: | Height: | Size: 288 B |
Before Width: | Height: | Size: 471 B After Width: | Height: | Size: 471 B |
@ -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;
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 412 B After Width: | Height: | Size: 412 B |
Before Width: | Height: | Size: 865 B After Width: | Height: | Size: 865 B |
Before Width: | Height: | Size: 421 B After Width: | Height: | Size: 421 B |
Before Width: | Height: | Size: 885 B After Width: | Height: | Size: 885 B |
Before Width: | Height: | Size: 280 B After Width: | Height: | Size: 280 B |
Before Width: | Height: | Size: 500 B After Width: | Height: | Size: 500 B |
Before Width: | Height: | Size: 264 B After Width: | Height: | Size: 264 B |
Before Width: | Height: | Size: 523 B After Width: | Height: | Size: 523 B |
@ -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;
|
@ -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)
|
||||
|
@ -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;
|
||||
|