merge fx-team to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2014-11-27 17:01:23 +01:00
commit 79cdd7fb8f
65 changed files with 1694 additions and 49 deletions

View File

@ -422,6 +422,8 @@ pref("browser.search.update.interval", 21600);
// enable search suggestions by default
pref("browser.search.suggest.enabled", true);
pref("browser.search.showOneOffButtons", true);
#ifdef MOZ_OFFICIAL_BRANDING
// {moz:official} expands to "official"
pref("browser.search.official", true);

View File

@ -415,6 +415,15 @@ panel[noactions] > richlistbox > richlistitem[type~="action"] > .ac-url-box > .a
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#browser-autocomplete-result-popup");
}
#PopupSearchAutoComplete {
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#browser-search-autocomplete-result-popup");
margin-left: -23px;
}
searchbar[oneoffui] {
-moz-binding: url("chrome://browser/content/search/search.xml#searchbar-flare") !important;
}
#PopupAutoCompleteRichResult {
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#urlbar-rich-result-popup");
}

View File

@ -3304,13 +3304,6 @@ const BrowserSearch = {
return;
}
// Append the URI and an appropriate title to the browser data.
// Use documentURIObject in the check for shouldLoadFavIcon so that we
// do the right thing with about:-style error pages. Bug 453442
var iconURL = null;
if (gBrowser.shouldLoadFavIcon(uri))
iconURL = uri.prePath + "/favicon.ico";
var hidden = false;
// If this engine (identified by title) is already in the list, add it
// to the list of hidden engines rather than to the main list.
@ -3323,7 +3316,8 @@ const BrowserSearch = {
engines.push({ uri: engine.href,
title: engine.title,
icon: iconURL });
get icon() { return browser.mIconURL; }
});
if (hidden)
browser.hiddenEngines = engines;
@ -7821,4 +7815,3 @@ let PanicButtonNotifier = {
popup.hidePopup();
},
};

View File

@ -140,6 +140,9 @@
<!-- for search and content formfill/pw manager -->
<panel type="autocomplete" id="PopupAutoComplete" noautofocus="true" hidden="true"/>
<!-- for search with one-off buttons -->
<panel type="autocomplete" id="PopupSearchAutoComplete" noautofocus="true" hidden="true"/>
<!-- for url bar autocomplete -->
<panel type="autocomplete-richlistbox" id="PopupAutoCompleteRichResult" noautofocus="true" hidden="true"/>

View File

@ -4,6 +4,12 @@
let originalTab;
let newTab;
function isCurrent(tab, msg) {
const tolerance = 1;
const difference = Math.abs(Date.now() - tab.lastAccessed);
ok(difference <= tolerance, msg + " (difference: " + difference + ")");
}
function test() {
waitForExplicitFinish();
@ -12,7 +18,7 @@ function test() {
}
function step2() {
is(originalTab.lastAccessed, Date.now(), "selected tab has the current timestamp");
isCurrent(originalTab, "selected tab has the current timestamp");
newTab = gBrowser.addTab("about:blank", {skipAnimation: true});
setTimeout(step3, 100);
}
@ -20,15 +26,14 @@ function step2() {
function step3() {
ok(newTab.lastAccessed < Date.now(), "new tab hasn't been selected so far");
gBrowser.selectedTab = newTab;
is(newTab.lastAccessed, Date.now(), "new tab has the current timestamp after being selected");
isCurrent(newTab, "new tab has the current timestamp after being selected");
setTimeout(step4, 100);
}
function step4() {
ok(originalTab.lastAccessed < Date.now(),
"original tab has old timestamp after being deselected");
is(newTab.lastAccessed, Date.now(),
"new tab has the current timestamp since it's still selected");
isCurrent(newTab, "new tab has the current timestamp since it's still selected");
gBrowser.removeTab(newTab);
finish();

View File

@ -951,6 +951,269 @@
</implementation>
</binding>
<!-- Note: this binding is applied to the autocomplete popup used in the Search bar -->
<binding id="browser-search-autocomplete-result-popup" extends="chrome://browser/content/urlbarBindings.xml#browser-autocomplete-result-popup">
<resources>
<stylesheet src="chrome://browser/skin/searchbar.css"/>
</resources>
<content ignorekeys="true" level="top" consumeoutsideclicks="false">
<xul:hbox xbl:inherits="collapsed=showonlysettings"
class="search-panel-header search-panel-current-engine">
<xul:image class="searchbar-engine-image" xbl:inherits="src"/>
<xul:label anonid="searchbar-engine-name" flex="1" crop="end"/>
</xul:hbox>
<xul:tree anonid="tree" flex="1"
class="autocomplete-tree plain search-panel-tree"
hidecolumnpicker="true" seltype="single">
<xul:treecols anonid="treecols">
<xul:treecol id="treecolAutoCompleteValue" class="autocomplete-treecol" flex="1" overflow="true"/>
</xul:treecols>
<xul:treechildren class="autocomplete-treebody"/>
</xul:tree>
<xul:hbox anonid="search-panel-one-offs-header"
class="search-panel-header search-panel-current-input"
xbl:inherits="hidden=showonlysettings">
<xul:label anonid="searchbar-oneoffheader-before" value="&searchFor.label;"/>
<xul:label anonid="searchbar-oneoffheader-searchtext" flex="1" crop="end" class="search-panel-input-value"/>
<xul:label anonid="searchbar-oneoffheader-after" flex="10000" value="&searchWith.label;"/>
</xul:hbox>
<xul:description anonid="search-panel-one-offs"
class="search-panel-one-offs"
xbl:inherits="hidden=showonlysettings"/>
<xul:vbox anonid="add-engines"/>
<xul:button anonid="search-settings"
xbl:inherits="showonlysettings"
oncommand="openPreferences('paneSearch')"
class="search-setting-button search-panel-header"
label="&changeSearchSettings.button;"/>
</content>
<handlers>
<handler event="popupshowing"><![CDATA[
// First handle deciding if we are showing the reduced version of the
// popup containing only the preferences button. We do this if the
// glass icon has been clicked if the text field is empty.
let searchbar = document.getElementById("searchbar");
let tree = document.getAnonymousElementByAttribute(this, "anonid",
"tree")
if (searchbar.hasAttribute("showonlysettings")) {
searchbar.removeAttribute("showonlysettings");
this.setAttribute("showonlysettings", "true");
// Setting this with an xbl-inherited attribute gets overridden the
// second time the user clicks the glass icon for some reason...
tree.collapsed = true;
}
else {
this.removeAttribute("showonlysettings");
tree.collapsed = false;
}
// Show the current default engine in the top header of the panel.
let currentEngine = Services.search.currentEngine;
let uri = currentEngine.iconURI;
if (uri) {
uri = uri.spec;
this.setAttribute("src", PlacesUtils.getImageURLForResolution(window, uri));
}
else {
// If the default has just been changed to a provider without icon,
// avoid showing the icon of the previous default provider.
this.removeAttribute("src");
}
const kBundleURI = "chrome://browser/locale/search.properties";
let bundle = Services.strings.createBundle(kBundleURI);
let headerText = bundle.formatStringFromName("searchHeader",
[currentEngine.name], 1);
document.getAnonymousElementByAttribute(this, "anonid", "searchbar-engine-name")
.setAttribute("value", headerText);
// Update the 'Search for <keywords> with:" header.
let headerSearchText =
document.getAnonymousElementByAttribute(this, "anonid",
"searchbar-oneoffheader-searchtext");
let textbox = searchbar.textbox;
let self = this;
let keyPressHandler = function() {
headerSearchText.setAttribute("value", textbox.value);
if (textbox.value)
self.removeAttribute("showonlysettings");
};
textbox.addEventListener("keyup", keyPressHandler);
this.addEventListener("popuphiding", function hiding() {
textbox.removeEventListener("keyup", keyPressHandler);
this.removeEventListener("popuphiding", hiding);
});
keyPressHandler();
// Handle opensearch items. This needs to be done before building the
// list of one off providers, as that code will return early if all the
// alternative engines are hidden.
let addEngineList =
document.getAnonymousElementByAttribute(this, "anonid", "add-engines");
while (addEngineList.firstChild)
addEngineList.firstChild.remove();
const kXULNS =
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
let addEngines = getBrowser().mCurrentBrowser.engines;
if (addEngines && addEngines.length > 0) {
const kBundleURI = "chrome://browser/locale/search.properties";
let bundle = Services.strings.createBundle(kBundleURI);
for (let engine of addEngines) {
let button = document.createElementNS(kXULNS, "button");
let label = bundle.formatStringFromName("cmd_addFoundEngine",
[engine.title], 1);
button.setAttribute("class", "addengine-item");
button.setAttribute("label", label);
button.setAttribute("pack", "start");
button.setAttribute("crop", "end");
button.setAttribute("tooltiptext", engine.uri);
button.setAttribute("uri", engine.uri);
if (engine.icon) {
let uri = PlacesUtils.getImageURLForResolution(window, engine.icon);
button.setAttribute("image", uri);
}
button.setAttribute("title", engine.title);
addEngineList.appendChild(button);
}
}
// Finally, build the list of one-off buttons.
let list = document.getAnonymousElementByAttribute(this, "anonid",
"search-panel-one-offs")
while (list.firstChild)
list.firstChild.remove();
let hiddenList;
try {
let pref =
Services.prefs.getCharPref("browser.search.hiddenOneOffs");
hiddenList = pref ? pref.split(",") : [];
} catch(e) {
hiddenList = [];
}
let engines = Services.search.getVisibleEngines()
.filter(e => e.name != currentEngine.name &&
hiddenList.indexOf(e.name) == -1);
let header = document.getAnonymousElementByAttribute(this, "anonid",
"search-panel-one-offs-header")
header.collapsed = list.collapsed = !engines.length;
if (!engines.length)
return;
let panel = document.getElementById("PopupSearchAutoComplete");
let minWidth = parseInt(panel.width) + 23;
panel.setAttribute("style", "min-width: " + minWidth + "px");
// 49px is the min-width of each search engine button,
// adapt this const when changing the css.
// It's actually 48px + 1px of right border.
// The + 1 is because the last button doesn't have a right border.
let panelWidth = parseInt(panel.clientWidth);
let enginesPerRow = Math.floor((panelWidth + 1) / 49);
let buttonWidth = Math.floor(panelWidth / enginesPerRow);
// There will be an emtpy area of:
// panelWidth - enginesPerRow * buttonWidth px
// at the end of each row.
// If the <description> tag with the list of search engines doesn't have
// a fixed height, the panel will be sized incorrectly, causing the bottom
// of the suggestion <tree> to be hidden.
let rowCount = Math.ceil(engines.length / enginesPerRow);
let height = rowCount * 33; // 32px per row, 1px border.
list.setAttribute("height", height + "px");
let dummyItems = enginesPerRow - (engines.length % enginesPerRow || enginesPerRow);
for (let i = 0; i < engines.length; ++i) {
let engine = engines[i];
let button = document.createElementNS(kXULNS, "button");
button.setAttribute("label", engine.name);
let uri = "chrome://browser/skin/search-engine-placeholder.png";
if (engine.iconURI) {
uri = PlacesUtils.getImageURLForResolution(window, engine.iconURI.spec);
}
button.setAttribute("image", uri);
button.setAttribute("class", "searchbar-engine-one-off-item");
button.setAttribute("tooltiptext", engine.name);
button.setAttribute("width", buttonWidth);
button.engine = engine;
if ((i + 1) % enginesPerRow == 0)
button.classList.add("last-of-row");
if (i >= engines.length + dummyItems - enginesPerRow)
button.classList.add("last-row");
list.appendChild(button);
}
while (dummyItems) {
let button = document.createElementNS(kXULNS, "button");
button.setAttribute("class", "searchbar-engine-one-off-item dummy last-row");
button.setAttribute("width", buttonWidth);
if (!--dummyItems)
button.classList.add("last-of-row");
list.appendChild(button);
}
]]></handler>
<handler event="mousedown"><![CDATA[
// Required to receive click events from the buttons on Linux.
event.preventDefault();
]]></handler>
<handler event="mouseover"><![CDATA[
let target = event.originalTarget;
if (target.localName == "button" &&
target.classList.contains("searchbar-engine-one-off-item") &&
!target.classList.contains("dummy")) {
let list = document.getAnonymousElementByAttribute(this, "anonid",
"search-panel-one-offs")
for (let button = list.firstChild; button; button = button.nextSibling)
button.removeAttribute("selected");
}
]]></handler>
<handler event="click"><![CDATA[
if (event.button == 2)
return; // ignore right clicks.
let button = event.originalTarget;
if (button.localName != "button" || !button.engine)
return;
let searchbar = document.getElementById("searchbar");
searchbar.handleSearchCommand(event, button.engine);
]]></handler>
<handler event="command"><![CDATA[
let target = event.originalTarget;
if (target.classList.contains("addengine-item")) {
// On success, hide and reshow the panel to show the new engine.
let installCallback = {
onSuccess: function(engine) {
event.target.hidePopup();
BrowserSearch.searchBar.openSuggestionsPanel();
}
}
Services.search.addEngine(target.getAttribute("uri"),
Ci.nsISearchEngine.DATA_XML,
target.getAttribute("src"), false,
installCallback);
}
]]></handler>
</handlers>
</binding>
<binding id="urlbar-rich-result-popup" extends="chrome://global/content/bindings/autocomplete.xml#autocomplete-rich-result-popup">
<implementation>
<field name="_maxResults">0</field>

View File

@ -67,6 +67,13 @@ add_task(function*() {
yield PanelUI.show();
yield waitForCondition(() => "value" in searchbar && searchbar.value === "");
// Focusing a non-empty searchbox will cause us to open the
// autocomplete panel and search for suggestions, which would
// trigger network requests. Temporarily disable suggestions.
let suggestEnabled =
Services.prefs.getBoolPref("browser.search.suggest.enabled");
Services.prefs.setBoolPref("browser.search.suggest.enabled", false);
searchbar.value = "foo";
searchbar.focus();
// Reaching into this context menu is pretty evil, but hey... it's a test.
@ -83,12 +90,18 @@ add_task(function*() {
EventUtils.synthesizeMouseAtCenter(selectAll, {});
yield contextMenuHidden;
// Hide the suggestion panel.
searchbar.textbox.popup.hidePopup();
ok(isPanelUIOpen(), "Panel should still be open");
let hiddenPanelPromise = promisePanelHidden(window);
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield hiddenPanelPromise;
ok(!isPanelUIOpen(), "Panel should no longer be open");
Services.prefs.setBoolPref("browser.search.suggest.enabled", suggestEnabled);
CustomizableUI.reset();
});
add_task(function*() {
@ -121,4 +134,3 @@ registerCleanupFunction(function() {
PanelUI.hide();
}
});

View File

@ -587,8 +587,10 @@ loop.panel = (function(_, mozL10n) {
React.DOM.span({className: "room-notification"}),
room.roomName,
React.DOM.button({className: copyButtonClasses,
title: mozL10n.get("rooms_list_copy_url_tooltip"),
onClick: this.handleCopyButtonClick}),
React.DOM.button({className: "delete-link",
title: mozL10n.get("rooms_list_delete_tooltip"),
onClick: this.handleDeleteButtonClick})
),
React.DOM.p(null,

View File

@ -587,8 +587,10 @@ loop.panel = (function(_, mozL10n) {
<span className="room-notification" />
{room.roomName}
<button className={copyButtonClasses}
title={mozL10n.get("rooms_list_copy_url_tooltip")}
onClick={this.handleCopyButtonClick} />
<button className="delete-link"
title={mozL10n.get("rooms_list_delete_tooltip")}
onClick={this.handleDeleteButtonClick} />
</h2>
<p>

View File

@ -251,7 +251,7 @@ loop.roomViews = (function(mozL10n) {
var localStreamClasses = React.addons.classSet({
local: true,
"local-stream": true,
"local-stream-audio": !this.state.videoMuted,
"local-stream-audio": this.state.videoMuted,
"room-preview": this.state.roomState !== ROOM_STATES.HAS_PARTICIPANTS
});

View File

@ -251,7 +251,7 @@ loop.roomViews = (function(mozL10n) {
var localStreamClasses = React.addons.classSet({
local: true,
"local-stream": true,
"local-stream-audio": !this.state.videoMuted,
"local-stream-audio": this.state.videoMuted,
"room-preview": this.state.roomState !== ROOM_STATES.HAS_PARTICIPANTS
});

View File

@ -342,7 +342,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
hide: !this._roomIsActive(),
local: true,
"local-stream": true,
"local-stream-audio": false
"local-stream-audio": this.state.videoMuted
});
return (

View File

@ -342,7 +342,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
hide: !this._roomIsActive(),
local: true,
"local-stream": true,
"local-stream-audio": false
"local-stream-audio": this.state.videoMuted
});
return (

View File

@ -330,5 +330,20 @@ describe("loop.roomViews", function () {
loop.shared.views.FeedbackView);
});
});
describe("Mute", function() {
it("should render local media as audio-only if video is muted",
function() {
activeRoomStore.setStoreState({
roomState: ROOM_STATES.SESSION_CONNECTED,
videoMuted: true
});
view = mountTestComponent();
expect(view.getDOMNode().querySelector(".local-stream-audio"))
.not.eql(null);
});
});
});
});

View File

@ -311,6 +311,19 @@ describe("loop.standaloneRoomViews", function() {
sinon.assert.calledWithExactly(dispatch, new sharedActions.FeedbackComplete());
});
});
describe("Mute", function() {
it("should render local media as audio-only if video is muted",
function() {
activeRoomStore.setStoreState({
roomState: ROOM_STATES.SESSION_CONNECTED,
videoMuted: true
});
expect(view.getDOMNode().querySelector(".local-stream-audio"))
.not.eql(null);
});
});
});
});
});

View File

@ -14,3 +14,5 @@ browser.jar:
content/browser/preferences/in-content/content.js
content/browser/preferences/in-content/sync.js
content/browser/preferences/in-content/security.js
content/browser/preferences/in-content/search.css
content/browser/preferences/in-content/search.js

View File

@ -24,6 +24,7 @@ function init_all() {
gSubDialog.init();
gMainPane.init();
gSearchPane.init();
gPrivacyPane.init();
gAdvancedPane.init();
gApplicationsPane.init();

View File

@ -14,6 +14,7 @@
<?xml-stylesheet
href="chrome://browser/content/preferences/handlers.css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/applications.css"?>
<?xml-stylesheet href="chrome://browser/content/preferences/in-content/search.css"?>
<!DOCTYPE page [
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
@ -22,6 +23,7 @@
"chrome://browser/locale/preferences/preferences.dtd">
<!ENTITY % privacyDTD SYSTEM "chrome://browser/locale/preferences/privacy.dtd">
<!ENTITY % tabsDTD SYSTEM "chrome://browser/locale/preferences/tabs.dtd">
<!ENTITY % searchDTD SYSTEM "chrome://browser/locale/preferences/search.dtd">
<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
<!ENTITY % syncDTD SYSTEM "chrome://browser/locale/preferences/sync.dtd">
<!ENTITY % securityDTD SYSTEM
@ -39,6 +41,7 @@
%preferencesDTD;
%privacyDTD;
%tabsDTD;
%searchDTD;
%syncBrandDTD;
%syncDTD;
%securityDTD;
@ -96,6 +99,16 @@
<label class="category-name" flex="1">&paneGeneral.title;</label>
</richlistitem>
<richlistitem id="category-search"
class="category"
value="paneSearch"
helpTopic="prefs-main"
tooltiptext="&paneSearch.title;"
align="center">
<image class="category-icon"/>
<label class="category-name" flex="1">&paneSearch.title;</label>
</richlistitem>
<richlistitem id="category-content"
class="category"
value="paneContent"
@ -162,6 +175,7 @@
<vbox class="main-content" flex="1">
<prefpane id="mainPrefPane">
#include main.xul
#include search.xul
#include privacy.xul
#include advanced.xul
#include applications.xul

View File

@ -0,0 +1,20 @@
/* 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/. */
#oneClickProvidersList richlistitem {
-moz-binding: url("chrome://global/content/bindings/checkbox.xml#checkbox");
}
.searchengine-menuitem > .menu-iconic-left {
display: -moz-box
}
.checkbox-label-box {
-moz-box-align: center;
}
.checkbox-icon {
-moz-margin-end: 8px;
max-width: 16px;
}

View File

@ -0,0 +1,75 @@
/* 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/. */
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
var gSearchPane = {
init: function ()
{
if (!Services.prefs.getBoolPref("browser.search.showOneOffButtons")) {
document.getElementById("category-search").hidden = true;
if (document.location.hash == "#search")
document.location.hash = "";
return;
}
let list = document.getElementById("defaultEngine");
let currentEngine = Services.search.currentEngine.name;
Services.search.getVisibleEngines().forEach(e => {
let item = list.appendItem(e.name);
item.setAttribute("class", "menuitem-iconic searchengine-menuitem menuitem-with-favicon");
if (e.iconURI)
item.setAttribute("image", e.iconURI.spec);
item.engine = e;
if (e.name == currentEngine)
list.selectedItem = item;
});
this.displayOneClickEnginesList();
document.getElementById("oneClickProvidersList")
.addEventListener("CheckboxStateChange", gSearchPane.saveOneClickEnginesList);
},
displayOneClickEnginesList: function () {
let richlistbox = document.getElementById("oneClickProvidersList");
let pref = document.getElementById("browser.search.hiddenOneOffs").value;
let hiddenList = pref ? pref.split(",") : [];
while (richlistbox.firstChild)
richlistbox.firstChild.remove();
let currentEngine = Services.search.currentEngine.name;
Services.search.getVisibleEngines().forEach(e => {
if (e.name == currentEngine)
return;
let item = document.createElement("richlistitem");
item.setAttribute("label", e.name);
if (hiddenList.indexOf(e.name) == -1)
item.setAttribute("checked", "true");
if (e.iconURI)
item.setAttribute("src", e.iconURI.spec);
richlistbox.appendChild(item);
});
},
saveOneClickEnginesList: function () {
let richlistbox = document.getElementById("oneClickProvidersList");
let hiddenList = [];
for (let child of richlistbox.childNodes) {
if (!child.checked)
hiddenList.push(child.getAttribute("label"));
}
document.getElementById("browser.search.hiddenOneOffs").value =
hiddenList.join(",");
},
setDefaultEngine: function () {
Services.search.currentEngine =
document.getElementById("defaultEngine").selectedItem.engine;
this.displayOneClickEnginesList();
}
};

View File

@ -0,0 +1,47 @@
<preferences id="searchPreferences">
<!-- Suggest -->
<preference id="browser.search.suggest.enabled"
name="browser.search.suggest.enabled"
type="bool"/>
<!-- One off providers -->
<preference id="browser.search.hiddenOneOffs"
name="browser.search.hiddenOneOffs"
type="string"/>
</preferences>
<script type="application/javascript"
src="chrome://browser/content/preferences/in-content/search.js"/>
<hbox id="header-search"
class="header"
hidden="true"
data-category="paneSearch">
<label class="header-name">&paneSearch.title;</label>
</hbox>
<!-- Default Search Engine -->
<groupbox id="defaultEngineGroup" align="start" data-category="paneSearch">
<caption label="&defaultSearchEngine.label;"/>
<label>&chooseYourDefaultSearchEngine.label;</label>
<menulist id="defaultEngine" oncommand="gSearchPane.setDefaultEngine();">
<menupopup/>
</menulist>
<checkbox id="suggestionsInSearchFieldsCheckbox"
label="&provideSearchSuggestions.label;"
accesskey="&provideSearchSuggestions.accesskey;"
preference="browser.search.suggest.enabled"/>
</groupbox>
<groupbox id="oneClickSearchProvidersGroup" data-category="paneSearch">
<caption label="&oneClickSearchEngines.label;"/>
<label>&chooseWhichOneToDisplay.label;</label>
<richlistbox id="oneClickProvidersList"/>
<hbox pack="end">
<label id="addEngines" class="text-link" value="&addMoreSearchEngines.label;"
onclick="if (event.button == 0) { Services.wm.getMostRecentWindow('navigator:browser').BrowserSearch.loadAddEngines(); }"/>
</hbox>
</groupbox>

View File

@ -31,6 +31,7 @@ browser.jar:
* content/browser/preferences/permissions.xul
* content/browser/preferences/permissions.js
* content/browser/preferences/preferences.xul
content/browser/preferences/preferences.js
content/browser/preferences/privacy.xul
* content/browser/preferences/privacy.js
content/browser/preferences/sanitize.xul
@ -43,6 +44,9 @@ browser.jar:
content/browser/preferences/sync.xul
content/browser/preferences/sync.js
#endif
content/browser/preferences/search.xul
content/browser/preferences/search.css
content/browser/preferences/search.js
* content/browser/preferences/tabs.xul
* content/browser/preferences/tabs.js
* content/browser/preferences/translation.xul

View File

@ -0,0 +1,19 @@
/* - This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this file,
- You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
Components.utils.import("resource://gre/modules/Services.jsm");
if (!Services.prefs.getBoolPref("browser.search.showOneOffButtons")) {
addEventListener("load", function onLoad() {
removeEventListener("load", onLoad);
let pane =
document.getAnonymousElementByAttribute(document.documentElement,
"pane", "paneSearch");
pane.hidden = true;
if (pane.selected)
document.documentElement.showPane(document.getElementById("paneMain"));
});
}

View File

@ -16,6 +16,7 @@
-->
<?xml-stylesheet href="chrome://browser/content/preferences/handlers.css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/applications.css"?>
<?xml-stylesheet href="chrome://browser/content/preferences/search.css"?>
<!DOCTYPE prefwindow [
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
@ -66,6 +67,8 @@
src="chrome://browser/content/preferences/main.xul"/>
<prefpane id="paneTabs" label="&paneTabs.title;"
src="chrome://browser/content/preferences/tabs.xul"/>
<prefpane id="paneSearch" label="&paneSearch.title;"
src="chrome://browser/content/preferences/search.xul"/>
<prefpane id="paneContent" label="&paneContent.title;"
src="chrome://browser/content/preferences/content.xul"/>
<prefpane id="paneApplications" label="&paneApplications.title;"
@ -81,6 +84,8 @@
<prefpane id="paneAdvanced" label="&paneAdvanced.title;"
src="chrome://browser/content/preferences/advanced.xul"/>
<script type="application/javascript"
src="chrome://browser/content/preferences/preferences.js"/>
#ifdef XP_MACOSX
#include ../../base/content/browserMountPoints.inc
#endif

View File

@ -0,0 +1,29 @@
/* 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/. */
#oneClickProvidersList richlistitem {
-moz-binding: url("chrome://global/content/bindings/checkbox.xml#checkbox");
-moz-padding-start: 5px;
height: 22px; /* setting the height of checkboxes is required to let the
window auto-sizing code work. */
}
#oneClickProvidersList {
height: 178px;
}
.searchengine-menuitem > .menu-iconic-left {
display: -moz-box
}
.checkbox-label-box {
-moz-box-align: center;
-moz-appearance: none;
border: none;
}
.checkbox-icon {
margin: 3px 3px;
max-width: 16px;
}

View File

@ -0,0 +1,68 @@
/* 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/. */
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
var gSearchPane = {
init: function ()
{
let list = document.getElementById("defaultEngine");
let currentEngine = Services.search.currentEngine.name;
Services.search.getVisibleEngines().forEach(e => {
let item = list.appendItem(e.name);
item.setAttribute("class", "menuitem-iconic searchengine-menuitem menuitem-with-favicon");
if (e.iconURI)
item.setAttribute("image", e.iconURI.spec);
item.engine = e;
if (e.name == currentEngine)
list.selectedItem = item;
});
this.displayOneClickEnginesList();
document.getElementById("oneClickProvidersList")
.addEventListener("CheckboxStateChange", gSearchPane.saveOneClickEnginesList);
},
displayOneClickEnginesList: function () {
let richlistbox = document.getElementById("oneClickProvidersList");
let pref = document.getElementById("browser.search.hiddenOneOffs").value;
let hiddenList = pref ? pref.split(",") : [];
while (richlistbox.firstChild)
richlistbox.firstChild.remove();
let currentEngine = Services.search.currentEngine.name;
Services.search.getVisibleEngines().forEach(e => {
if (e.name == currentEngine)
return;
let item = document.createElement("richlistitem");
item.setAttribute("label", e.name);
if (hiddenList.indexOf(e.name) == -1)
item.setAttribute("checked", "true");
if (e.iconURI)
item.setAttribute("src", e.iconURI.spec);
richlistbox.appendChild(item);
});
},
saveOneClickEnginesList: function () {
let richlistbox = document.getElementById("oneClickProvidersList");
let hiddenList = [];
for (let child of richlistbox.childNodes) {
if (!child.checked)
hiddenList.push(child.getAttribute("label"));
}
document.getElementById("browser.search.hiddenOneOffs").value =
hiddenList.join(",");
},
setDefaultEngine: function () {
Services.search.currentEngine =
document.getElementById("defaultEngine").selectedItem.engine;
this.displayOneClickEnginesList();
}
};

View File

@ -0,0 +1,63 @@
<?xml version="1.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/. -->
<!DOCTYPE overlay [
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
<!ENTITY % searchDTD SYSTEM "chrome://browser/locale/preferences/search.dtd">
%brandDTD;
%searchDTD;
]>
<overlay id="SearchPaneOverlay"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml">
<prefpane id="paneSearch" helpTopic="prefs-search"
onpaneload="gSearchPane.init();">
<preferences id="searchPreferences">
<!-- Suggest -->
<preference id="browser.search.suggest.enabled"
name="browser.search.suggest.enabled"
type="bool"/>
<!-- One off providers -->
<preference id="browser.search.hiddenOneOffs"
name="browser.search.hiddenOneOffs"
type="string"/>
</preferences>
<script type="application/javascript" src="chrome://browser/content/preferences/search.js"/>
<!-- Default Search Engine -->
<groupbox id="defaultEngineGroup" align="start">
<caption label="&defaultSearchEngine.label;"/>
<label>&chooseYourDefaultSearchEngine.label;</label>
<menulist id="defaultEngine" oncommand="gSearchPane.setDefaultEngine();">
<menupopup/>
</menulist>
<checkbox id="suggestionsInSearchFieldsCheckbox"
label="&provideSearchSuggestions.label;"
accesskey="&provideSearchSuggestions.accesskey;"
preference="browser.search.suggest.enabled"/>
</groupbox>
<groupbox id="oneClickSearchProvidersGroup">
<caption label="&oneClickSearchEngines.label;"/>
<label>&chooseWhichOneToDisplay.label;</label>
<richlistbox id="oneClickProvidersList"/>
<hbox pack="end" style="margin-bottom: 1em">
<label id="addEngines" class="text-link" value="&addMoreSearchEngines.label;"
onclick="if (event.button == 0) { Services.wm.getMostRecentWindow('navigator:browser').BrowserSearch.loadAddEngines(); }"/>
</hbox>
</groupbox>
</prefpane>
</overlay>

View File

@ -73,6 +73,12 @@
<implementation implements="nsIObserver">
<constructor><![CDATA[
if (!this.hasAttribute("oneoffui") &&
Services.prefs.getBoolPref("browser.search.showOneOffButtons")) {
this.setAttribute("oneoffui", "true");
return;
}
if (this.parentNode.parentNode.localName == "toolbarpaletteitem")
return;
// Make sure we rebuild the popup in onpopupshowing
@ -100,6 +106,11 @@
]]></constructor>
<destructor><![CDATA[
this.destroy();
]]></destructor>
<method name="destroy">
<body><![CDATA[
if (this._initialized) {
this._initialized = false;
@ -112,7 +123,8 @@
// the world. But make sure it's actually pointing to us.
if (this._textbox.mController.input == this)
this._textbox.mController.input = null;
]]></destructor>
]]></body>
</method>
<field name="_stringBundle">document.getAnonymousElementByAttribute(this,
"anonid", "searchbar-stringbundle");</field>
@ -304,7 +316,12 @@
var name = this.currentEngine.name;
var text = this._stringBundle.getFormattedString("searchtip", [name]);
this._textbox.placeholder = name;
if (Services.prefs.getBoolPref("browser.search.showOneOffButtons"))
this._textbox.placeholder = this._stringBundle.getString("searchPlaceholder");
else
this._textbox.placeholder = name;
this._textbox.label = text;
this._textbox.tooltipText = text;
]]></body>
@ -449,6 +466,7 @@
<method name="handleSearchCommand">
<parameter name="aEvent"/>
<parameter name="aEngine"/>
<body><![CDATA[
var textBox = this._textbox;
var textValue = textBox.value;
@ -465,13 +483,14 @@
where = "tab";
}
this.doSearch(textValue, where);
this.doSearch(textValue, where, aEngine);
]]></body>
</method>
<method name="doSearch">
<parameter name="aData"/>
<parameter name="aWhere"/>
<parameter name="aEngine"/>
<body><![CDATA[
var textBox = this._textbox;
@ -485,10 +504,11 @@
Components.utils.reportError("Saving search to form history failed: " + aError.message);
}});
}
let engine = aEngine || this.currentEngine;
var submission = engine.getSubmission(aData, null, "searchbar");
BrowserSearch.recordSearchInHealthReport(engine, "searchbar");
// null parameter below specifies HTML response for search
var submission = this.currentEngine.getSubmission(aData, null, "searchbar");
BrowserSearch.recordSearchInHealthReport(this.currentEngine, "searchbar");
openUILinkIn(submission.uri.spec, aWhere, null, submission.postData);
]]></body>
</method>
@ -536,6 +556,124 @@
</handlers>
</binding>
<binding id="searchbar-flare" extends="chrome://browser/content/search/search.xml#searchbar">
<resources>
<stylesheet src="chrome://browser/content/search/searchbarBindings.css"/>
<stylesheet src="chrome://browser/skin/searchbar.css"/>
</resources>
<content>
<xul:stringbundle src="chrome://browser/locale/search.properties"
anonid="searchbar-stringbundle"/>
<!--
There is a dependency between "maxrows" attribute and
"SuggestAutoComplete._historyLimit" (nsSearchSuggestions.js). Changing
one of them requires changing the other one.
-->
<xul:textbox class="searchbar-textbox"
anonid="searchbar-textbox"
type="autocomplete"
flex="1"
autocompletepopup="PopupSearchAutoComplete"
autocompletesearch="search-autocomplete"
autocompletesearchparam="searchbar-history"
maxrows="10"
completeselectedindex="true"
tabscrolling="true"
xbl:inherits="disabled,disableautocomplete,searchengine,src,newlines">
<!--
Empty <box> to properly position the icon within the autocomplete
binding's anonymous children (the autocomplete binding positions <box>
children differently)
-->
<xul:box>
<xul:hbox class="searchbar-search-button-container">
<xul:image class="searchbar-search-button"
anonid="searchbar-search-button"
tooltiptext="&searchEndCap.label;"/>
</xul:hbox>
<xul:button class="searchbar-engine-button"
type="menu"
anonid="searchbar-engine-button">
<xul:image class="searchbar-engine-image" xbl:inherits="src"/>
<xul:image class="searchbar-dropmarker-image"/>
<xul:menupopup class="searchbar-popup"
anonid="searchbar-popup">
<xul:menuseparator/>
<xul:menuitem class="open-engine-manager"
anonid="open-engine-manager"
label="&cmd_engineManager.label;"
oncommand="openManager(event);"/>
</xul:menupopup>
</xul:button>
</xul:box>
<xul:hbox class="search-go-container">
<xul:image class="search-go-button" hidden="true"
anonid="search-go-button"
onclick="handleSearchCommand(event);"
tooltiptext="&searchEndCap.label;"/>
</xul:hbox>
</xul:textbox>
</content>
<implementation>
<destructor><![CDATA[
// For some reason the destructor of the base binding is called
// automatically when the window is closed, but now when the node
// is removed from the DOM.
this.destroy();
]]></destructor>
<method name="selectEngine">
<body><![CDATA[
// Override this method to avoid accidentally changing the default
// engine using the keyboard shortcuts of the old UI.
]]></body>
</method>
<method name="updateGoButtonVisibility">
<body><![CDATA[
document.getAnonymousElementByAttribute(this, "anonid",
"search-go-button")
.hidden = !this._textbox.value;
]]></body>
</method>
<method name="openSuggestionsPanel">
<parameter name="aShowOnlySettingsIfEmpty"/>
<body><![CDATA[
if (this._textbox.open)
return;
this._textbox.showHistoryPopup();
if (this._textbox.value) {
// showHistoryPopup does a startSearch("") call, ensure the
// controller handles the text from the input box instead:
this._textbox.mController.handleText();
}
else if (aShowOnlySettingsIfEmpty) {
this.setAttribute("showonlysettings", "true");
}
]]></body>
</method>
</implementation>
<handlers>
<handler event="input" action="this.updateGoButtonVisibility();"/>
<handler event="drop" action="this.updateGoButtonVisibility();"/>
<handler event="focus">
<![CDATA[
if (this._textbox.value)
this.openSuggestionsPanel();
]]></handler>
<handler event="click">
<![CDATA[
if (event.originalTarget.getAttribute("anonid") == "searchbar-search-button")
this.openSuggestionsPanel(true);
]]></handler>
</handlers>
</binding>
<binding id="searchbar-textbox"
extends="chrome://global/content/bindings/autocomplete.xml#autocomplete">
<implementation implements="nsIObserver">
@ -731,11 +869,154 @@
<parameter name="aEvent"/>
<body><![CDATA[
var evt = aEvent || this.mEnterEvent;
document.getBindingParent(this).handleSearchCommand(evt);
let engine;
let oneOff = this.getSelectedOneOff();
if (oneOff)
engine = oneOff.engine;
document.getBindingParent(this).handleSearchCommand(evt, engine);
this.mEnterEvent = null;
]]></body>
</method>
<method name="getSelectedOneOff">
<body><![CDATA[
let list = document.getAnonymousElementByAttribute(this.popup, "anonid",
"search-panel-one-offs");
if (!list)
return null;
for (let button = list.firstChild; button; button = button.nextSibling) {
if (button.hasAttribute("selected"))
return button;
}
return null;
]]></body>
</method>
<method name="handleKeyboardNavigation">
<parameter name="aEvent"/>
<body><![CDATA[
// XXXFlorian This method could likely be shortened with a helper
// handling moving the selection within the one-off list and
// returning a boolean indicating if the event should be stopped.
let popup = this.popup;
if (!popup.popupOpen)
return;
if (aEvent.keyCode == KeyEvent.DOM_VK_DOWN &&
popup.hasAttribute("showonlysettings")) {
// If the suggestion tree is collapsed, don't let the down arrow
// key event reach the tree.
aEvent.preventDefault();
aEvent.stopPropagation();
return;
}
let list = document.getAnonymousElementByAttribute(popup, "anonid",
"search-panel-one-offs");
if (!list)
return;
let selectedButton = this.getSelectedOneOff();
// If the last suggestion is selected, DOWN selects the first one-off.
if (aEvent.keyCode == KeyEvent.DOM_VK_DOWN &&
popup.selectedIndex + 1 == popup.view.rowCount) {
if (selectedButton)
selectedButton.removeAttribute("selected");
selectedButton = list.firstChild;
if (selectedButton)
selectedButton.setAttribute("selected", "true");
}
// If no suggestion is selected and a one-off is selected,
// UP and DOWN cycle through one-off buttons.
if (popup.selectedIndex == -1 && selectedButton &&
(aEvent.keyCode == KeyEvent.DOM_VK_DOWN ||
aEvent.keyCode == KeyEvent.DOM_VK_UP)) {
selectedButton.removeAttribute("selected");
if (aEvent.keyCode == KeyEvent.DOM_VK_DOWN)
selectedButton = selectedButton.nextSibling;
else
selectedButton = selectedButton.previousSibling;
if (selectedButton && selectedButton.classList.contains("dummy"))
selectedButton = null;
if (selectedButton) {
selectedButton.setAttribute("selected", "true");
aEvent.preventDefault();
aEvent.stopPropagation();
}
else {
// Set the selectedIndex to something that will make
// handleKeyNavigation (called by autocomplete.xml's onKeyPress
// method) reset the text field value to what the user typed.
if (aEvent.keyCode == KeyEvent.DOM_VK_UP)
popup.selectedIndex = popup.view.rowCount;
else
popup.selectedIndex = popup.view.rowCount - 1;
}
}
// If nothing is selected, UP selects the last one-off button.
if (aEvent.keyCode == KeyEvent.DOM_VK_UP &&
popup.selectedIndex == -1 && !selectedButton) {
selectedButton = list.lastChild;
while (selectedButton.classList.contains("dummy"))
selectedButton = selectedButton.previousSibling;
selectedButton.setAttribute("selected", "true");
aEvent.preventDefault();
aEvent.stopPropagation();
}
if (aEvent.keyCode == KeyEvent.DOM_VK_TAB) {
if (selectedButton) {
// TAB cycles though the list of one-off buttons.
selectedButton.removeAttribute("selected");
if (aEvent.shiftKey)
selectedButton = selectedButton.previousSibling;
else
selectedButton = selectedButton.nextSibling;
// Avoid selecting dummy buttons.
if (selectedButton && selectedButton.classList.contains("dummy"))
selectedButton = null;
// If we are out of the list, revert the text field to what the user typed.
if (!selectedButton) {
// Set the selectedIndex to something that will make
// handleKeyNavigation (called by autocomplete.xml's onKeyPress
// method) reset the text field value to what the user typed.
popup.selectedIndex = aEvent.shiftKey ? 0 : popup.view.rowCount - 1;
return;
}
}
else {
// If no selection, select the first or last one-off button.
if (aEvent.shiftKey) {
selectedButton = list.lastChild;
while (selectedButton.classList.contains("dummy"))
selectedButton = selectedButton.previousSibling;
}
else {
selectedButton = list.firstChild;
}
}
selectedButton.setAttribute("selected", "true");
aEvent.preventDefault();
aEvent.stopPropagation();
}
]]></body>
</method>
<!-- nsIController -->
<field name="searchbarController" readonly="true"><![CDATA[({
_self: this,
@ -772,6 +1053,9 @@
</implementation>
<handlers>
<handler event="keypress" phase="capturing"
action="return this.handleKeyboardNavigation(event);"/>
<handler event="keypress" keycode="VK_UP" modifiers="accel"
phase="capturing"
action="document.getBindingParent(this).selectEngine(event, false);"/>

View File

@ -1,7 +1,10 @@
function test() {
var searchBar = BrowserSearch.searchBar;
ok(searchBar, "got search bar");
if (searchBar.getAttribute("oneoffui"))
return; // The oneoffui removes the menu that's being tested here.
searchBar.focus();
var pbo = searchBar._popup.popupBoxObject;

View File

@ -141,6 +141,7 @@ function* prepareTest() {
searchBar.removeEventListener("focus", onFocus);
deferred.resolve();
});
gURLBar.focus();
searchBar.focus();
} else {
deferred.resolve();
@ -228,11 +229,10 @@ add_task(function testShiftMiddleClick() {
add_task(function testDropText() {
yield prepareTest();
let promisePreventPopup = promiseEvent(searchBar, "popupshowing", true);
// drop on the search button so that we don't need to worry about the
// default handlers for textboxes.
ChromeUtils.synthesizeDrop(searchBar.searchButton, searchBar.searchButton, [[ {type: "text/plain", data: "Some Text" } ]], "copy", window);
yield promisePreventPopup;
let searchButton = document.getAnonymousElementByAttribute(searchBar, "anonid", "searchbar-search-button");
ChromeUtils.synthesizeDrop(searchButton, searchButton, [[ {type: "text/plain", data: "Some Text" } ]], "copy", window);
let event = yield promiseOnLoad();
is(event.originalTarget.URL, expectedURL(searchBar.value), "testDropText opened correct search page");
is(searchBar.value, "Some Text", "drop text/plain on searchbar");
@ -240,9 +240,8 @@ add_task(function testDropText() {
add_task(function testDropInternalText() {
yield prepareTest();
let promisePreventPopup = promiseEvent(searchBar, "popupshowing", true);
ChromeUtils.synthesizeDrop(searchBar.searchButton, searchBar.searchButton, [[ {type: "text/x-moz-text-internal", data: "More Text" } ]], "copy", window);
yield promisePreventPopup;
let searchButton = document.getAnonymousElementByAttribute(searchBar, "anonid", "searchbar-search-button");
ChromeUtils.synthesizeDrop(searchButton, searchButton, [[ {type: "text/x-moz-text-internal", data: "More Text" } ]], "copy", window);
let event = yield promiseOnLoad();
is(event.originalTarget.URL, expectedURL(searchBar.value), "testDropInternalText opened correct search page");
is(searchBar.value, "More Text", "drop text/x-moz-text-internal on searchbar");
@ -251,9 +250,7 @@ add_task(function testDropInternalText() {
// were merged so that if testDropInternalText failed it wouldn't cause testDropLink
// to fail unexplainably.
yield prepareTest();
promisePreventPopup = promiseEvent(searchBar, "popupshowing", true);
ChromeUtils.synthesizeDrop(searchBar.searchButton, searchBar.searchButton, [[ {type: "text/uri-list", data: "http://www.mozilla.org" } ]], "copy", window);
yield promisePreventPopup;
is(searchBar.value, "More Text", "drop text/uri-list on searchbar shouldn't change anything");
});
@ -268,6 +265,9 @@ add_task(function testRightClick() {
deferred.resolve();
}, 5000);
yield deferred.promise;
// The click in the searchbox focuses it, which opens the suggestion
// panel. Clean up after ourselves.
searchBar.textbox.popup.hidePopup();
});
add_task(function testSearchHistory() {
@ -302,4 +302,3 @@ add_task(function asyncCleanup() {
content.location.href = "about:blank";
yield promiseRemoveEngine();
});

View File

@ -415,6 +415,13 @@ These should match what Safari and other Apple applications use on OS X Lion. --
<!ENTITY searchFocus.commandkey2 "e">
<!ENTITY searchFocusUnix.commandkey "j">
<!-- LOCALIZATION NOTE (searchFor.label, searchWith.label):
These two strings are used to build the header above the list of one-click
search providers: "Search for <used typed keywords> with:" -->
<!ENTITY searchFor.label "Search for ">
<!ENTITY searchWith.label " with:">
<!ENTITY changeSearchSettings.button "Change Search Settings">
<!ENTITY tabView.commandkey "e">
<!ENTITY openLinkCmdInTab.label "Open Link in New Tab">

View File

@ -306,7 +306,7 @@ rooms_list_delete_tooltip=Delete conversation
rooms_list_deleteConfirmation_label=Are you sure?
rooms_list_no_current_conversations=No current conversations
rooms_name_this_room_label=Name this conversation
rooms_name_this_room_tooltip=Click to edit the room name
rooms_name_this_room_tooltip2=Click to edit the conversation name
rooms_name_change_failed_label=Conversation cannot be renamed
rooms_new_room_button_label=Start a conversation
rooms_only_occupant_label=You're the first one here.

View File

@ -15,6 +15,7 @@
<!ENTITY paneGeneral.title "General">
<!ENTITY paneTabs.title "Tabs">
<!ENTITY paneSearch.title "Search">
<!ENTITY paneContent.title "Content">
<!ENTITY paneApplications.title "Applications">
<!ENTITY panePrivacy.title "Privacy">

View File

@ -0,0 +1,17 @@
<!-- 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/. -->
<!ENTITY defaultSearchEngine.label "Default Search Engine">
<!ENTITY chooseYourDefaultSearchEngine.label "Choose your default search engine. &brandShortName; uses it in the location bar, search bar, and start page.">
<!ENTITY provideSearchSuggestions.label "Provide search suggestions">
<!ENTITY provideSearchSuggestions.accesskey "s">
<!ENTITY oneClickSearchEngines.label "One-click search engines">
<!ENTITY chooseWhichOneToDisplay.label "The search bar lets you search alternate engines directly. Choose which ones to display.">
<!ENTITY addMoreSearchEngines.label "Add more search engines…">

View File

@ -4,6 +4,15 @@
searchtip=Search using %S
# LOCALIZATION NOTE (searchPlaceholder): this is shown in the searchbox when
# the user hasn't typed anything yet.
searchPlaceholder=Search
# LOCALIZATION NOTE (searchHeader): this is displayed at the top of the panel
# showing search suggestions.
# %S is replaced with the name of the current default search engine.
searchHeader=%S Search
# LOCALIZATION NOTE (cmd_pasteAndSearch): "Search" is a verb, this is the
# search bar equivalent to the url bar's "Paste & Go"
cmd_pasteAndSearch=Paste & Search

View File

@ -131,6 +131,7 @@
locale/browser/preferences/sync.dtd (%chrome/browser/preferences/sync.dtd)
#endif
locale/browser/preferences/tabs.dtd (%chrome/browser/preferences/tabs.dtd)
locale/browser/preferences/search.dtd (%chrome/browser/preferences/search.dtd)
locale/browser/preferences/translation.dtd (%chrome/browser/preferences/translation.dtd)
#ifdef MOZ_SERVICES_SYNC
locale/browser/syncBrand.dtd (%chrome/browser/syncBrand.dtd)

View File

@ -128,12 +128,49 @@ this.UITour = {
["searchProvider", {
query: (aDocument) => {
let searchbar = aDocument.getElementById("searchbar");
if (searchbar.hasAttribute("oneoffui")) {
return null;
}
return aDocument.getAnonymousElementByAttribute(searchbar,
"anonid",
"searchbar-engine-button");
},
widgetName: "search-container",
}],
["searchIcon", {
query: (aDocument) => {
let searchbar = aDocument.getElementById("searchbar");
if (!searchbar.hasAttribute("oneoffui")) {
return null;
}
return aDocument.getAnonymousElementByAttribute(searchbar,
"anonid",
"searchbar-search-button");
},
widgetName: "search-container",
}],
["searchPrefsLink", {
query: (aDocument) => {
let element = null;
let searchbar = aDocument.getElementById("searchbar");
if (searchbar.hasAttribute("oneoffui")) {
let popup = aDocument.getElementById("PopupSearchAutoComplete");
if (popup.state != "open")
return null;
element = aDocument.getAnonymousElementByAttribute(popup,
"anonid",
"search-settings");
} else {
element = aDocument.getAnonymousElementByAttribute(searchbar,
"anonid",
"open-engine-manager");
}
if (!element || !UITour.isElementVisible(element)) {
return null;
}
return element;
},
}],
["selectedTabIcon", {
query: (aDocument) => {
let selectedtab = aDocument.defaultView.gBrowser.selectedTab;

View File

@ -221,8 +221,13 @@ let tests = [
gContentAPI.showHighlight("urlbar");
waitForElementToBeVisible(highlight, () => {
let searchbar = document.getElementById("searchbar");
if (searchbar.getAttribute("oneoffui")) {
done();
return; // The oneoffui removes the menu that's being tested here.
}
gContentAPI.showMenu("searchEngines", function() {
let searchbar = document.getElementById("searchbar");
isnot(searchbar, null, "Should have found searchbar");
let searchPopup = document.getAnonymousElementByAttribute(searchbar,
"anonid",

View File

@ -41,7 +41,7 @@ let tests = [
"privateWindow",
"quit",
"search",
"searchProvider",
"searchIcon",
"urlbar",
...searchEngineTargets(),
...(hasWebIDE ? ["webide"] : [])
@ -72,7 +72,7 @@ let tests = [
"privateWindow",
"quit",
"search",
"searchProvider",
"searchIcon",
"urlbar",
...searchEngineTargets(),
...(hasWebIDE ? ["webide"] : [])
@ -92,7 +92,7 @@ let tests = [
// Make sure the callback still fires with the other available targets.
CustomizableUI.removeWidgetFromArea("search-container");
gContentAPI.getConfiguration("availableTargets", (data) => {
// Default minus "search" and "searchProvider"
// Default minus "search" and "searchProvider" and "searchIcon"
ok_targets(data, [
"accountStatus",
"addons",

View File

@ -60,7 +60,7 @@ let tests = [
function test_highlight_panel_click_find(done) {
gContentAPI.showHighlight("help");
gContentAPI.showInfo("searchProvider", "test title", "test text");
gContentAPI.showInfo("searchIcon", "test title", "test text");
waitForElementToBeVisible(highlight, function checkPanelIsOpen() {
isnot(PanelUI.panel.state, "closed", "Panel should have opened");

View File

@ -62,6 +62,11 @@ browser.jar:
skin/classic/browser/privatebrowsing-mask.png
skin/classic/browser/reload-stop-go.png
skin/classic/browser/searchbar.css
skin/classic/browser/search-pref.png (../shared/search/search-pref.png)
skin/classic/browser/search-indicator.png (../shared/search/search-indicator.png)
skin/classic/browser/search-indicator-add-engine.png (../shared/search/search-indicator-add-engine.png)
skin/classic/browser/search-engine-placeholder.png (../shared/search/search-engine-placeholder.png)
skin/classic/browser/badge-add-engine.png (../shared/search/badge-add-engine.png)
skin/classic/browser/Secure.png
skin/classic/browser/Security-broken.png
skin/classic/browser/setDesktopBackground.css

View File

@ -20,6 +20,14 @@ radio[pane=paneTabs] {
-moz-image-region: rect(0px, 64px, 32px, 32px)
}
#BrowserPreferences radio[pane=paneSearch] {
list-style-image: url("chrome://browser/skin/search-pref.png");
}
.checkbox-check {
-moz-appearance: checkbox;
}
radio[pane=paneContent] {
-moz-image-region: rect(0px, 96px, 32px, 64px)
}

View File

@ -67,3 +67,178 @@ menuitem[cmd="cmd_clearhistory"][disabled] {
list-style-image: url("moz-icon://stock/gtk-clear?size=menu&state=disabled");
}
.searchbar-search-button-container {
-moz-box-align: center;
padding: 2px 3px;
-moz-padding-end: 2px;
}
.searchbar-search-button {
list-style-image: url("chrome://browser/skin/search-indicator.png");
-moz-image-region: rect(0, 20px, 20px, 0);
margin: -2px -2px;
}
.searchbar-search-button:hover {
-moz-image-region: rect(0, 40px, 20px, 20px);
}
.searchbar-search-button:hover:active {
-moz-image-region: rect(0, 60px, 20px, 40px);
}
searchbar[oneoffui] .search-go-button {
list-style-image: url("chrome://browser/skin/reload-stop-go.png");
-moz-image-region: rect(0, 42px, 14px, 28px);
}
searchbar[oneoffui] .search-go-button:hover {
-moz-image-region: rect(14px, 42px, 28px, 28px);
}
searchbar[oneoffui] .search-go-button:hover:active {
-moz-image-region: rect(28px, 42px, 42px, 28px);
}
searchbar[oneoffui] .search-go-button:-moz-locale-dir(rtl) > .toolbarbutton-icon {
transform: scaleX(-1);
}
.search-panel-current-engine {
border-top: none !important;
border-bottom: 1px solid #ccc;
-moz-box-align: center;
}
.search-panel-header {
font-weight: normal;
background-color: rgb(245, 245, 245);
border-top: 1px solid #ccc;
margin: 0 1px;
padding: 3px 5px;
color: #666;
}
.search-panel-current-input > label {
margin: 0 0 !important;
}
.search-panel-input-value {
color: black;
}
.search-panel-one-offs {
margin: 0 0 !important;
border-top: 1px solid #ccc;
}
.searchbar-engine-one-off-item {
-moz-appearance: none;
display: inline-block;
border: none;
min-width: 48px;
height: 32px;
margin: 0 0;
padding: 0 0;
background: none;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAWCAYAAAABxvaqAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gofECQNNVW2/AAAABBJREFUGFdjOHPmzH8GehEA/KpKg9YTf4AAAAAASUVORK5CYII=');
background-repeat: no-repeat;
background-position: right center;
}
.searchbar-engine-one-off-item:not(.last-row) {
box-sizing: padding-box;
border-bottom: 1px solid #ccc;
}
.searchbar-engine-one-off-item.last-of-row {
background-image: none;
}
.searchbar-engine-one-off-item:hover:not(.dummy),
.searchbar-engine-one-off-item[selected] {
background-color: Highlight;
background-image: none;
}
.searchbar-engine-one-off-item > .button-box {
border: none;
padding: 0 0;
}
.searchbar-engine-one-off-item > .button-box > .button-text {
display: none;
}
.searchbar-engine-one-off-item > .button-box > .button-icon {
display: -moz-box;
-moz-margin-end: 0;
width: 16px;
height: 16px;
}
.addengine-item {
-moz-appearance: none;
border: none;
height: 32px;
margin: 0 0;
padding: 0 10px;
}
.addengine-item > .button-box {
-moz-box-pack: start;
}
.addengine-item:first-of-type {
border-top: 1px solid #ccc;
}
.addengine-item:hover {
background-color: Highlight;
color: HighlightText;
}
.addengine-item > .button-box > .button-icon {
width: 16px;
}
.addengine-item > .button-box > .button-text {
-moz-box-flex: 1;
text-align: start;
-moz-padding-start: 10px;
}
.addengine-item:not([image]) {
list-style-image: url("chrome://browser/skin/search-engine-placeholder.png");
}
searchbar[oneoffui] .searchbar-engine-button {
display: none;
}
.search-panel-tree > .autocomplete-treebody::-moz-tree-cell {
-moz-padding-start: 16px;
border-top: none !important;
}
searchbar[oneoffui] .searchbar-engine-image {
-moz-margin-start: -1px;
}
.search-setting-button {
-moz-appearance: none;
border-bottom: none;
border-left: none;
border-right: none;
-moz-border-top-colors: none;
min-height: 32px;
}
.search-setting-button:hover {
background-color: #d3d3d3;
border-top-color: #bdbebe;
}

View File

@ -100,6 +100,15 @@ browser.jar:
skin/classic/browser/searchbar.css
skin/classic/browser/Search.png
skin/classic/browser/Search@2x.png
skin/classic/browser/search-pref.png (../shared/search/search-pref.png)
skin/classic/browser/search-indicator.png (../shared/search/search-indicator.png)
skin/classic/browser/search-indicator@2x.png (../shared/search/search-indicator@2x.png)
skin/classic/browser/search-indicator-add-engine.png (../shared/search/search-indicator-add-engine.png)
skin/classic/browser/search-indicator-add-engine@2x.png (../shared/search/search-indicator-add-engine@2x.png)
skin/classic/browser/search-engine-placeholder.png (../shared/search/search-engine-placeholder.png)
skin/classic/browser/search-engine-placeholder@2x.png (../shared/search/search-engine-placeholder@2x.png)
skin/classic/browser/badge-add-engine.png (../shared/search/badge-add-engine.png)
skin/classic/browser/badge-add-engine@2x.png (../shared/search/badge-add-engine@2x.png)
skin/classic/browser/Secure-Glyph.png
skin/classic/browser/Secure-Glyph@2x.png
skin/classic/browser/slowStartup-16.png

View File

@ -32,6 +32,12 @@ radio[pane=paneTabs] {
-moz-image-region: rect(0px, 64px, 32px, 32px);
}
/* ----- SEARCH BUTTON ----- */
radio[pane=paneSearch] {
list-style-image: url("chrome://browser/skin/search-pref.png");
}
/* ----- CONTENT BUTTON ----- */
radio[pane=paneContent] {

View File

@ -47,10 +47,43 @@
-moz-padding-end: 6px;
}
.searchbar-search-button-container {
-moz-box-align: center;
-moz-padding-start: 6px;
-moz-padding-end: 4px;
}
.search-go-button {
list-style-image: url("chrome://browser/skin/Search.png");
}
.searchbar-search-button {
list-style-image: url("chrome://browser/skin/search-indicator.png");
-moz-image-region: rect(0, 20px, 20px, 0);
margin: 0 -3px;
}
.searchbar-search-button:hover {
-moz-image-region: rect(0, 40px, 20px, 20px);
}
.searchbar-search-button:hover:active {
-moz-image-region: rect(0, 60px, 20px, 40px);
}
searchbar[oneoffui] .search-go-button {
list-style-image: url("chrome://browser/skin/reload-stop-go.png");
-moz-image-region: rect(0, 42px, 14px, 28px);
}
searchbar[oneoffui] .search-go-button:hover:active {
-moz-image-region: rect(14px, 42px, 28px, 28px);
}
searchbar[oneoffui] .search-go-button:-moz-locale-dir(rtl) > .toolbarbutton-icon {
transform: scaleX(-1);
}
@media (min-resolution: 2dppx) {
.searchbar-engine-image {
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon@2x.png");
@ -65,4 +98,165 @@
list-style-image: url("chrome://browser/skin/Search@2x.png");
width: 14px;
}
.searchbar-search-button {
list-style-image: url("chrome://browser/skin/search-indicator@2x.png");
width: 20px;
-moz-image-region: rect(0, 40px, 40px, 0);
}
.searchbar-search-button:hover {
-moz-image-region: rect(0, 80px, 40px, 40px);
}
.searchbar-search-button:hover:active {
-moz-image-region: rect(0, 120px, 40px, 80px);
}
searchbar[oneoffui] .search-go-button {
list-style-image: url("chrome://browser/skin/reload-stop-go@2x.png");
-moz-image-region: rect(0, 84px, 28px, 56px);
width: 14px;
}
searchbar[oneoffui] .search-go-button:hover:active {
list-style-image: url("chrome://browser/skin/reload-stop-go@2x.png");
-moz-image-region: rect(28px, 84px, 56px, 56px);
width: 14px;
}
}
.search-panel-current-engine {
border-top: none !important;
border-bottom: 1px solid #ccc;
border-radius: 4px 4px 0 0;
}
.search-panel-header {
font-size: 10px;
font-weight: normal;
background-color: rgb(245, 245, 245);
border-top: 1px solid #ccc;
margin: 0;
padding: 3px 6px;
color: #666;
}
.search-panel-current-input > label {
margin: 0 0 !important;
}
.search-panel-input-value {
color: black;
}
.search-panel-one-offs {
border-top: 1px solid #ccc;
margin-bottom: 0 !important;
}
.searchbar-engine-one-off-item {
-moz-appearance: none;
display: inline-block;
min-width: 48px;
height: 32px;
margin: 0 0;
padding: 0 0;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAWCAYAAAABxvaqAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gofECQNNVW2/AAAABBJREFUGFdjOHPmzH8GehEA/KpKg9YTf4AAAAAASUVORK5CYII=');
background-repeat: no-repeat;
background-position: right center;
}
.searchbar-engine-one-off-item:not(.last-row) {
box-sizing: padding-box;
border-bottom: 1px solid #ccc;
}
.searchbar-engine-one-off-item.last-of-row {
background-image: none;
}
.searchbar-engine-one-off-item:hover:not(.dummy),
.searchbar-engine-one-off-item[selected] {
background-color: Highlight;
background-image: none;
}
.searchbar-engine-one-off-item > .button-box > .button-text {
display: none;
}
.searchbar-engine-one-off-item > .button-box > .button-icon {
-moz-margin-start: 0;
width: 16px;
height: 16px;
}
.addengine-item {
-moz-appearance: none;
font-size: 10px;
height: 32px;
margin: 0 0;
padding: 0 10px;
}
.addengine-item > .button-box {
-moz-box-pack: start;
}
.addengine-item:first-of-type {
border-top: 1px solid #ccc;
}
.addengine-item:hover {
background-color: Highlight;
color: HighlightText;
}
.addengine-item > .button-box > .button-icon {
width: 16px;
}
.addengine-item > .button-box > .button-text {
-moz-box-flex: 1;
text-align: start;
-moz-padding-start: 10px;
}
.addengine-item:not([image]) {
list-style-image: url("chrome://browser/skin/search-engine-placeholder.png");
}
@media (min-resolution: 2dppx) {
.addengine-item:not([image]) {
list-style-image: url("chrome://browser/skin/search-engine-placeholder@2x.png");
}
}
searchbar[oneoffui] .searchbar-engine-button {
display: none;
}
.search-panel-tree > .autocomplete-treebody::-moz-tree-cell {
-moz-padding-start: 22px;
border-top: none !important;
}
#PopupSearchAutoComplete {
border-radius: 4px;
}
.search-setting-button {
-moz-appearance: none;
border-radius: 0 0 4px 4px;
min-height: 32px;
}
.search-setting-button[showonlysettings] {
border-radius: 4px;
}
.search-setting-button:hover {
background-color: #d3d3d3;
border-top-color: #bdbebe;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -33,6 +33,10 @@ treecol {
-moz-image-region: rect(0, 24px, 24px, 0);
}
#category-search > .category-icon {
-moz-image-region: rect(0, 194px, 24px, 168px);
}
#category-content > .category-icon {
-moz-image-region: rect(0, 48px, 24px, 24px);
}
@ -66,6 +70,10 @@ treecol {
-moz-image-region: rect(0, 48px, 48px, 0);
}
#category-search > .category-icon {
-moz-image-region: rect(0, 384px, 48px, 336px);
}
#category-content > .category-icon {
-moz-image-region: rect(0, 96px, 48px, 48px);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 888 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 461 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 461 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -77,6 +77,11 @@ browser.jar:
skin/classic/browser/reload-stop-go.png
skin/classic/browser/searchbar.css
skin/classic/browser/searchbar-dropdown-arrow.png
skin/classic/browser/search-pref.png (../shared/search/search-pref.png)
skin/classic/browser/search-indicator.png (../shared/search/search-indicator.png)
skin/classic/browser/search-indicator-add-engine.png (../shared/search/search-indicator-add-engine.png)
skin/classic/browser/search-engine-placeholder.png (../shared/search/search-engine-placeholder.png)
skin/classic/browser/badge-add-engine.png (../shared/search/badge-add-engine.png)
skin/classic/browser/Secure24.png
skin/classic/browser/setDesktopBackground.css
skin/classic/browser/slowStartup-16.png
@ -511,6 +516,11 @@ browser.jar:
skin/classic/aero/browser/reload-stop-go.png
skin/classic/aero/browser/searchbar.css
skin/classic/aero/browser/searchbar-dropdown-arrow.png (searchbar-dropdown-arrow-aero.png)
skin/classic/aero/browser/search-pref.png (../shared/search/search-pref.png)
skin/classic/aero/browser/search-indicator.png (../shared/search/search-indicator.png)
skin/classic/aero/browser/search-indicator-add-engine.png (../shared/search/search-indicator-add-engine.png)
skin/classic/aero/browser/search-engine-placeholder.png (../shared/search/search-engine-placeholder.png)
skin/classic/aero/browser/badge-add-engine.png (../shared/search/badge-add-engine.png)
skin/classic/aero/browser/Secure24.png (Secure24-aero.png)
skin/classic/aero/browser/setDesktopBackground.css
skin/classic/aero/browser/slowStartup-16.png

View File

@ -19,6 +19,10 @@ radio[pane=paneTabs] {
-moz-image-region: rect(0, 64px, 32px, 32px);
}
#BrowserPreferences radio[pane=paneSearch] {
list-style-image: url("chrome://browser/skin/search-pref.png");
}
radio[pane=paneContent] {
-moz-image-region: rect(0, 96px, 32px, 64px);
}

View File

@ -78,3 +78,176 @@
.searchbar-engine-menuitem[selected="true"] > .menu-iconic-text {
font-weight: bold;
}
.searchbar-search-button-container {
-moz-box-align: center;
padding: 3px 4px;
-moz-padding-end: 2px;
}
.searchbar-search-button {
list-style-image: url("chrome://browser/skin/search-indicator.png");
-moz-image-region: rect(0, 20px, 20px, 0);
margin: -2px -2px;
}
.searchbar-search-button:hover {
-moz-image-region: rect(0, 40px, 20px, 20px);
}
.searchbar-search-button:hover:active {
-moz-image-region: rect(0, 60px, 20px, 40px);
}
searchbar[oneoffui] .search-go-button {
list-style-image: url("chrome://browser/skin/reload-stop-go.png");
-moz-image-region: rect(0, 42px, 14px, 28px);
}
searchbar[oneoffui] .search-go-button:hover {
-moz-image-region: rect(14px, 42px, 28px, 28px);
}
searchbar[oneoffui] .search-go-button:hover:active {
-moz-image-region: rect(28px, 42px, 42px, 28px);
}
searchbar[oneoffui] .search-go-button:-moz-locale-dir(rtl) > .toolbarbutton-icon {
transform: scaleX(-1);
}
.search-panel-current-engine {
border-top: none !important;
border-bottom: 1px solid #ccc;
-moz-box-align: center;
}
.search-panel-header {
font-weight: normal;
background-color: rgb(245, 245, 245);
border-top: 1px solid #ccc;
margin: 0;
padding: 3px 6px;
color: #666;
}
.search-panel-current-input > label {
margin: 0 0 !important;
}
.search-panel-input-value {
color: black;
}
.search-panel-one-offs {
margin: 0 0 !important;
border-top: 1px solid #ccc;
}
.searchbar-engine-one-off-item {
-moz-appearance: none;
display: inline-block;
border: none;
min-width: 48px;
height: 32px;
margin: 0 0;
padding: 0 0;
background: none;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAWCAYAAAABxvaqAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gofECQNNVW2/AAAABBJREFUGFdjOHPmzH8GehEA/KpKg9YTf4AAAAAASUVORK5CYII=');
background-repeat: no-repeat;
background-position: right center;
}
.searchbar-engine-one-off-item:not(.last-row) {
box-sizing: padding-box;
border-bottom: 1px solid #ccc;
}
.searchbar-engine-one-off-item.last-of-row {
background-image: none;
}
.searchbar-engine-one-off-item:hover:not(.dummy),
.searchbar-engine-one-off-item[selected] {
background-color: Highlight;
background-image: none;
}
.searchbar-engine-one-off-item > .button-box {
border: none;
padding: 0 0;
}
.searchbar-engine-one-off-item > .button-box > .button-text {
display: none;
}
.searchbar-engine-one-off-item > .button-box > .button-icon {
width: 16px;
height: 16px;
}
.addengine-item {
-moz-appearance: none;
border: none;
height: 32px;
margin: 0 0;
padding: 0 10px;
}
.addengine-item > .button-box {
-moz-box-pack: start;
}
.addengine-item:first-of-type {
border-top: 1px solid #ccc;
}
.addengine-item:hover {
background-color: Highlight;
color: HighlightText;
}
.addengine-item > .button-box > .button-icon {
width: 16px;
}
.addengine-item > .button-box > .button-text {
-moz-box-flex: 1;
text-align: start;
-moz-padding-start: 10px;
}
.addengine-item:not([image]) {
list-style-image: url("chrome://browser/skin/search-engine-placeholder.png");
}
searchbar[oneoffui] .searchbar-engine-button {
display: none;
}
.search-panel-tree > .autocomplete-treebody::-moz-tree-cell {
-moz-padding-start: 15px;
border-top: none !important;
}
searchbar[oneoffui] .searchbar-engine-image {
-moz-margin-start: -1px;
}
.search-setting-button {
-moz-appearance: none;
border-bottom: none;
border-left: none;
border-right: none;
-moz-border-top-colors: none;
min-height: 32px;
}
.search-setting-button:hover {
background-color: #d3d3d3;
border-top-color: #bdbebe;
}

View File

@ -50,10 +50,12 @@ this.SearchSuggestionController.prototype = {
* The maximum number of local form history results to return. This limit is
* only enforced if remote results are also returned.
*/
maxLocalResults: 7,
maxLocalResults: 5,
/**
* The maximum number of remote search engine results to return.
* We'll actually only display at most
* maxRemoteResults - <displayed local results count> remote results.
*/
maxRemoteResults: 10,
@ -316,7 +318,13 @@ this.SearchSuggestionController.prototype = {
* @return {Object}
*/
_dedupeAndReturnResults: function(suggestResults) {
NS_ASSERT(this._searchString !== null, "this._searchString shouldn't be null when returning results");
if (this._searchString === null) {
// _searchString can be null if stop() was called and remote suggestions
// were disabled (stopping if we are fetching remote suggestions will
// cause a promise rejection before we reach _dedupeAndReturnResults).
return null;
}
let results = {
term: this._searchString,
remote: [],
@ -353,7 +361,8 @@ this.SearchSuggestionController.prototype = {
}
// Trim the number of results to the maximum requested (now that we've pruned dupes).
results.remote = results.remote.slice(0, this.maxRemoteResults);
results.remote =
results.remote.slice(0, this.maxRemoteResults - results.local.length);
if (this._callback) {
this._callback(results);

View File

@ -73,6 +73,13 @@ SuggestAutoComplete.prototype = {
finalComments = finalComments.concat(comments);
}
// If no result, add the search term so that the panel of the new UI is shown anyway.
if (!finalResults.length &&
Services.prefs.getBoolPref("browser.search.showOneOffButtons")) {
finalResults.push(results.term);
finalComments.push("");
}
// Notify the FE of our new results
this.onResultsReady(results.term, finalResults, finalComments, results.formHistoryResult);
},

View File

@ -261,8 +261,8 @@ add_task(function* both_identical_with_more_than_max_results() {
for (let i = 0; i < controller.maxLocalResults; i++) {
do_check_eq(result.local[i], "letter " + String.fromCharCode("A".charCodeAt() + i));
}
do_check_eq(result.remote.length, 10);
for (let i = 0; i < controller.maxRemoteResults; i++) {
do_check_eq(result.local.length + result.remote.length, 10);
for (let i = 0; i < result.remote.length; i++) {
do_check_eq(result.remote[i],
"letter " + String.fromCharCode("A".charCodeAt() + controller.maxLocalResults + i));
}
@ -284,7 +284,7 @@ add_task(function* noremote_maxLocal() {
add_task(function* someremote_maxLocal() {
let controller = new SearchSuggestionController();
controller.maxLocalResults = 2;
controller.maxRemoteResults = 2;
controller.maxRemoteResults = 4;
let result = yield controller.fetch("letter ", false, getEngine);
do_check_eq(result.term, "letter ");
do_check_eq(result.local.length, 2);
@ -301,7 +301,7 @@ add_task(function* someremote_maxLocal() {
add_task(function* one_of_each() {
let controller = new SearchSuggestionController();
controller.maxLocalResults = 1;
controller.maxRemoteResults = 1;
controller.maxRemoteResults = 2;
let result = yield controller.fetch("letter ", false, getEngine);
do_check_eq(result.term, "letter ");
do_check_eq(result.local.length, 1);
@ -344,7 +344,7 @@ add_task(function* one_of_each_disabled_before_creation_enabled_after_creation_o
Services.prefs.setBoolPref("browser.search.suggest.enabled", false);
let controller = new SearchSuggestionController();
controller.maxLocalResults = 1;
controller.maxRemoteResults = 1;
controller.maxRemoteResults = 2;
Services.prefs.setBoolPref("browser.search.suggest.enabled", true);
let result = yield controller.fetch("letter ", false, getEngine);
do_check_eq(result.term, "letter ");

View File

@ -177,6 +177,10 @@ xul|menulist > xul|*.menulist-label-box {
padding-left: 10px !important;
}
xul|menulist > xul|*.menulist-label-box > xul|*.menulist-icon {
-moz-margin-end: 5px;
}
xul|button[type="menu"] > xul|*.button-box > xul|*.button-menu-dropmarker {
-moz-appearance: none;
margin: 1px 0;
@ -427,6 +431,10 @@ xul|*.checkbox-label-box {
}
}
xul|richlistitem > xul|*.checkbox-check {
margin: 3px 6px;
}
xul|*.radio-check {
-moz-appearance: none;
width: 23px;