Merge m-i and f-t to m-c, a=merge

This commit is contained in:
Phil Ringnalda 2014-11-27 22:30:17 -08:00
commit b93ac838f3
15 changed files with 506 additions and 1 deletions

View File

@ -429,6 +429,9 @@ pref("browser.search.showOneOffButtons", true);
pref("browser.search.official", true);
#endif
// How many times to show the new search highlight
pref("browser.search.highlightCount", 5);
pref("browser.sessionhistory.max_entries", 50);
// handle links targeting new windows

View File

@ -19,5 +19,7 @@
#endif
<!ENTITY % aboutHomeDTD SYSTEM "chrome://browser/locale/aboutHome.dtd">
%aboutHomeDTD;
<!ENTITY % searchBarDTD SYSTEM "chrome://browser/locale/searchbar.dtd">
%searchBarDTD;
]>

View File

@ -1397,6 +1397,7 @@ var gBrowserInit = {
SocialUI.init();
TabView.init();
SearchHighlight.init();
// Telemetry for master-password - we do this after 5 seconds as it
// can cause IO if NSS/PSM has not already initialized.
@ -3558,6 +3559,138 @@ const BrowserSearch = {
},
};
const SearchHighlight = {
eventsReady: false,
// The pref that controls how many times to show the highlight.
countPref: "browser.search.highlightCount",
// The current highlight to show.
currentPos: 0,
// Tracks if the popup closed very recently.
hideTimer: null,
// The list of highlights and the items in the panel to anchor them to.
highlights: [{
id: "SearchHighlight1",
anchor: "search-panel-one-offs"
}, {
id: "SearchHighlight2",
anchor: "searchbar-engine",
}],
init: function() {
this.panel = document.getElementById("PopupSearchAutoComplete");
this.panel.addEventListener("popupshowing", this.searchPanelShown.bind(this), false);
},
initEvents: function() {
if (this.eventsReady) {
return;
}
this.panel.addEventListener("popuphidden", this.searchPanelHidden.bind(this), false);
for (let highlight of this.highlights) {
highlight.panel = document.getElementById(highlight.id);
highlight.panel.addEventListener("popupshowing", this.disablePanelHiding.bind(this), false);
highlight.panel.addEventListener("popuphiding", this.enablePanelHiding.bind(this), false);
highlight.panel.querySelector("button").addEventListener("command", this.highlightButtonClicked.bind(this), false);
}
this.eventsReady = true;
},
get highlightPanel() {
return this.highlights[this.currentPos].panel;
},
showHighlight: function() {
// Check that all the events are setup.
this.initEvents();
// If a highlight is already showing then do nothing.
if (this.highlightPanel.state != "closed") {
return;
}
// Show the first highlight.
this.currentPos = 0;
this.showCurrentHighlight();
},
showCurrentHighlight: function() {
let highlight = this.highlights[this.currentPos];
let anchor = document.getAnonymousElementByAttribute(this.panel, "anonid", highlight.anchor);
highlight.panel.hidden = false;
highlight.panel.openPopup(anchor, "leftcenter topright");
},
searchPanelShown: function() {
let placement = CustomizableUI.getPlacementOfWidget("search-container");
if (placement.area == CustomizableUI.AREA_PANEL) {
// Opening a panel anchored to a panel anchored to a panel anchored to the
// window doesn't work very well
return;
}
if (!BrowserSearch.searchBar.value) {
// Don't show the panels when there is no text in the search box
return;
}
// If the panel was only very recently closed re-show the last highlight.
if (this.hideTimer) {
clearTimeout(this.hideTimer);
this.hideTimer = null;
this.showCurrentHighlight();
return;
}
// If the highlight has already been show the appropriate number of times
// do nothing.
let count = Services.prefs.getIntPref(this.countPref);
if (count <= 0)
return;
this.showHighlight();
Services.prefs.setIntPref(this.countPref, count - 1);
},
searchPanelHidden: function() {
if (this.highlightPanel.state == "closed") {
return;
}
this.highlightPanel.hidePopup();
// Set a flag when the panel was closed in the last short time.
this.hideTimer = setTimeout(() => {
this.hideTimer = null;
}, 500);
},
highlightButtonClicked: function() {
// When the button is clicked close the current highlight and open the next
// one.
this.highlightPanel.hidePopup();
this.currentPos++;
if (this.currentPos < this.highlights.length) {
this.showCurrentHighlight();
} else {
Services.prefs.setIntPref(this.countPref, 0);
this.currentPos = 0;
}
},
disablePanelHiding: function() {
this.panel.setAttribute("noautohide", "true");
},
enablePanelHiding: function() {
this.panel.setAttribute("noautohide", "false");
},
};
function FillHistoryMenu(aParent) {
// Lazily add the hover listeners on first showing and never remove them
if (!aParent.hasStatusListener) {

View File

@ -240,6 +240,41 @@
mousethrough="always">
<box id="UITourHighlight"></box>
</panel>
<!-- Used to highlight the new search experience -->
<panel id="SearchHighlight1"
class="SearchHighlight"
type="arrow"
hidden="true"
noautofocus="true"
noautohide="true"
orient="vertical"
align="stretch">
<label class="SearchHighlightTitle">&SearchHighlight1.title;</label>
<description class="SearchHighlightText" flex="1">&SearchHighlight1.text;</description>
<hbox class="SearchHighlightFooter" align="center">
<spacer class="dot filled"/>
<spacer class="dot"/>
<spacer flex="1"/>
<button label="&SearchHighlightNext;"/>
</hbox>
</panel>
<panel id="SearchHighlight2"
class="SearchHighlight"
type="arrow"
hidden="true"
noautofocus="true"
noautohide="true"
orient="vertical"
align="stretch">
<label class="SearchHighlightTitle">&SearchHighlight2.title;</label>
<description class="SearchHighlightText" flex="1">&SearchHighlight2.text;</description>
<hbox class="SearchHighlightFooter" align="center">
<spacer class="dot"/>
<spacer class="dot filled"/>
<spacer flex="1"/>
<button label="&SearchHighlightClose;"/>
</hbox>
</panel>
<panel id="social-share-panel"
class="social-panel"

View File

@ -400,6 +400,8 @@ skip-if = buildapp == 'mulet' || e10s # e10s: Bug 933103 - mochitest's EventUtil
skip-if = buildapp == 'mulet' || e10s # Bug 1100698 - test uses synthesizeMouse and then does a load of other stuff that breaks in e10s
[browser_save_video_frame.js]
[browser_scope.js]
[browser_searchHighlight.js]
skip-if = true
[browser_searchSuggestionUI.js]
skip-if = e10s
support-files =

View File

@ -0,0 +1,260 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
const TEST_ENGINE_BASENAME = "searchSuggestionEngine.xml";
const PREF = "browser.search.highlightCount";
const searchBar = BrowserSearch.searchBar;
const popup = document.getElementById("PopupSearchAutoComplete");
const panel1 = document.getElementById("SearchHighlight1");
const panel2 = document.getElementById("SearchHighlight2");
let current = Services.prefs.getIntPref(PREF);
registerCleanupFunction(() => {
Services.prefs.setIntPref(PREF, current);
});
// The highlight panel should be displayed a set number of times
add_task(function* firstrun() {
yield promiseNewEngine(TEST_ENGINE_BASENAME);
ok(searchBar, "got search bar");
if (!searchBar.getAttribute("oneoffui"))
return; // This tests the one-off UI
searchBar.value = "foo";
searchBar.focus();
Services.prefs.setIntPref(PREF, 2);
let promise = promiseWaitForEvent(panel1, "popupshown");
EventUtils.synthesizeKey("VK_DOWN", {});
yield promise
ok(true, "Saw panel 1 show");
is(Services.prefs.getIntPref(PREF), 1, "Should have counted this show");
promise = promiseWaitForEvent(panel1, "popuphidden");
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield promise;
ok(true, "Saw panel 1 hide");
clearTimer();
promise = promiseWaitForEvent(panel1, "popupshown");
EventUtils.synthesizeKey("VK_DOWN", {});
yield promise
ok(true, "Saw panel 1 show");
is(Services.prefs.getIntPref(PREF), 0, "Should have counted this show");
promise = promiseWaitForEvent(panel1, "popuphidden");
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield promise;
ok(true, "Saw panel 1 hide");
clearTimer();
function listener() {
ok(false, "Should not have seen the pane show");
}
panel1.addEventListener("popupshowing", listener, false);
promise = promiseWaitForEvent(popup, "popupshown");
EventUtils.synthesizeKey("VK_DOWN", {});
yield promise;
ok(true, "Saw popup show");
promise = promiseWaitForEvent(popup, "popuphidden");
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield promise;
ok(true, "Saw popup hide");
panel1.removeEventListener("popupshowing", listener, false);
clearTimer();
});
// Completing the tour should stop the popup from showing again
add_task(function* dismiss() {
ok(searchBar, "got search bar");
if (!searchBar.getAttribute("oneoffui"))
return; // This tests the one-off UI
searchBar.value = "foo";
searchBar.focus();
Services.prefs.setIntPref(PREF, 200);
let promise = promiseWaitForEvent(panel1, "popupshown");
EventUtils.synthesizeKey("VK_DOWN", {});
yield promise
ok(true, "Saw panel 1 show");
promise = promiseWaitForEvent(panel2, "popupshown");
EventUtils.synthesizeMouseAtCenter(panel1.querySelector("button"), {});
yield promise;
ok(true, "Saw panel 2 show");
promise = promiseWaitForEvent(panel2, "popuphidden");
EventUtils.synthesizeMouseAtCenter(panel2.querySelector("button"), {});
yield promise;
ok(true, "Saw panel 2 hide");
is(Services.prefs.getIntPref(PREF), 0, "Should have cleared the counter");
promise = promiseWaitForEvent(popup, "popuphidden");
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield promise;
ok(true, "Saw popup hide");
clearTimer();
function listener() {
ok(false, "Should not have seen the pane show");
}
panel1.addEventListener("popupshowing", listener, false);
promise = promiseWaitForEvent(popup, "popupshown");
EventUtils.synthesizeKey("VK_DOWN", {});
yield promise;
ok(true, "Saw popup show");
promise = promiseWaitForEvent(popup, "popuphidden");
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield promise;
ok(true, "Saw popup hide");
panel1.removeEventListener("popupshowing", listener, false);
clearTimer();
});
// The highlight panel should be re-displayed if the search popup closes and
// opens quickly
add_task(function* testRedisplay() {
ok(searchBar, "got search bar");
if (!searchBar.getAttribute("oneoffui"))
return; // This tests the one-off UI
searchBar.value = "foo";
searchBar.focus();
Services.prefs.setIntPref(PREF, 2);
let promise = promiseWaitForEvent(panel1, "popupshown");
EventUtils.synthesizeKey("VK_DOWN", {});
yield promise
ok(true, "Saw panel 1 show");
is(Services.prefs.getIntPref(PREF), 1, "Should have counted this show");
promise = promiseWaitForEvent(panel2, "popupshown");
EventUtils.synthesizeMouseAtCenter(panel1.querySelector("button"), {});
yield promise;
ok(true, "Saw panel 2 show");
promise = promiseWaitForEvent(panel2, "popuphidden");
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield promise;
ok(true, "Saw panel 2 hide");
promise = promiseWaitForEvent(panel2, "popupshown");
EventUtils.synthesizeKey("VK_DOWN", {});
yield promise;
ok(true, "Saw panel 2 show");
is(Services.prefs.getIntPref(PREF), 1, "Should not have counted this show");
promise = promiseWaitForEvent(panel2, "popuphidden");
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield promise;
ok(true, "Saw panel 2 hide");
clearTimer();
});
// The highlight panel shouldn't be displayed if there is no text in the search
// box
add_task(function* testNoText() {
ok(searchBar, "got search bar");
if (!searchBar.getAttribute("oneoffui"))
return; // This tests the one-off UI
searchBar.value = "";
searchBar.focus();
Services.prefs.setIntPref(PREF, 2);
function listener() {
ok(false, "Should not have seen the pane show");
}
panel1.addEventListener("popupshowing", listener, false);
let button = document.getAnonymousElementByAttribute(searchBar,
"anonid",
"searchbar-search-button");
let promise = promiseWaitForEvent(popup, "popupshown");
EventUtils.synthesizeMouseAtCenter(button, {});
yield promise;
ok(true, "Saw popup show");
promise = promiseWaitForEvent(popup, "popuphidden");
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield promise;
ok(true, "Saw popup hide");
clearTimer();
promise = promiseWaitForEvent(popup, "popupshown");
EventUtils.synthesizeKey("VK_DOWN", {});
yield promise;
ok(true, "Saw popup show");
promise = promiseWaitForEvent(popup, "popuphidden");
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield promise;
ok(true, "Saw popup hide");
panel1.removeEventListener("popupshowing", listener, false);
clearTimer();
});
function clearTimer() {
// Clear the timeout
clearTimeout(SearchHighlight.hideTimer);
SearchHighlight.hideTimer = null;
}
function promiseWaitForEvent(node, type, capturing) {
return new Promise((resolve) => {
node.addEventListener(type, function listener(event) {
node.removeEventListener(type, listener, capturing);
resolve(event);
}, capturing);
});
}
function promiseNewEngine(basename) {
return new Promise((resolve, reject) => {
info("Waiting for engine to be added: " + basename);
Services.search.init({
onInitComplete: function() {
let url = getRootDirectory(gTestPath) + basename;
let current = Services.search.currentEngine;
Services.search.addEngine(url, Ci.nsISearchEngine.TYPE_MOZSEARCH, "", false, {
onSuccess: function (engine) {
info("Search engine added: " + basename);
Services.search.currentEngine = engine;
registerCleanupFunction(() => {
Services.search.currentEngine = current;
Services.search.removeEngine(engine);
});
resolve(engine);
},
onError: function (errCode) {
ok(false, "addEngine failed with error code " + errCode);
reject();
},
});
}
});
});
}

View File

@ -957,7 +957,7 @@
<stylesheet src="chrome://browser/skin/searchbar.css"/>
</resources>
<content ignorekeys="true" level="top" consumeoutsideclicks="false">
<xul:hbox xbl:inherits="collapsed=showonlysettings"
<xul:hbox xbl:inherits="collapsed=showonlysettings" anonid="searchbar-engine"
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"/>

View File

@ -4,3 +4,14 @@
<!ENTITY cmd_engineManager.label "Manage Search Engines…">
<!ENTITY searchEndCap.label "Search">
<!-- LOCALIZATION NOTE: The SearchHighlight strings are used in the
- UITour popups that shows on first use of the new search panel. -->
<!ENTITY SearchHighlight1.title "One-Click Searches">
<!ENTITY SearchHighlight1.text "Search any of these sites instantly, without changing your default.">
<!ENTITY SearchHighlight2.title "Smart Suggestions">
<!ENTITY SearchHighlight2.text "Suggestions from your default search engine appear as you type.">
<!ENTITY SearchHighlightNext "Next">
<!ENTITY SearchHighlightClose "Thanks!">

View File

@ -27,6 +27,8 @@ browser.jar:
* skin/classic/browser/browser-lightweightTheme.css
skin/classic/browser/click-to-play-warning-stripes.png
* skin/classic/browser/content-contextmenu.svg
skin/classic/browser/dots.png (../shared/dots.png)
skin/classic/browser/dots@2x.png (../shared/dots@2x.png)
* skin/classic/browser/engineManager.css
skin/classic/browser/fullscreen-darknoise.png
skin/classic/browser/Geolocation-16.png

View File

@ -27,6 +27,8 @@ browser.jar:
* skin/classic/browser/browser-lightweightTheme.css
skin/classic/browser/click-to-play-warning-stripes.png
* skin/classic/browser/content-contextmenu.svg
skin/classic/browser/dots.png (../shared/dots.png)
skin/classic/browser/dots@2x.png (../shared/dots@2x.png)
* skin/classic/browser/engineManager.css (engineManager.css)
skin/classic/browser/fullscreen-darknoise.png
skin/classic/browser/Geolocation-16.png

View File

@ -147,3 +147,51 @@
#UITourTooltipButtons > button.button-primary:not(:active):hover {
background-color: rgb(105,173,61);
}
.SearchHighlight {
-moz-margin-end: 6px;
font-size: 110%;
width: 225px;
}
.SearchHighlight label,
.SearchHighlight description {
color: #535353;
margin: 0 0 8px 0;
padding: 0;
}
.SearchHighlightTitle {
font-weight: bold;
}
.SearchHighlight .dot {
width: 7px;
height: 7px;
background-image: -moz-image-rect(url("chrome://browser/skin/dots.png"), 0, 100%, 100%, 9);
background-size: 7px;
background-position: center center;
background-repeat: no-repeat;
-moz-margin-end: 2px;
}
.SearchHighlight .dot.filled {
background-image: -moz-image-rect(url("chrome://browser/skin/dots.png"), 0, 7, 100%, 0);
}
.SearchHighlight button {
margin: 0;
/* On some platforms clicking the button will steal focus from the search box
causing the popup to close. */
-moz-user-focus: ignore;
}
@media not all and (max-resolution: 1dppx) {
.SearchHighlight .dot {
background-image: -moz-image-rect(url("chrome://browser/skin/dots@2x.png"), 0, 100%, 100%, 18);
}
.SearchHighlight .dot.filled {
background-image: -moz-image-rect(url("chrome://browser/skin/dots@2x.png"), 0, 14, 100%, 0);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 496 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 519 B

View File

@ -29,6 +29,8 @@ browser.jar:
* skin/classic/browser/browser-lightweightTheme.css
skin/classic/browser/click-to-play-warning-stripes.png
* skin/classic/browser/content-contextmenu.svg
skin/classic/browser/dots.png (../shared/dots.png)
skin/classic/browser/dots@2x.png (../shared/dots@2x.png)
* skin/classic/browser/engineManager.css
skin/classic/browser/fullscreen-darknoise.png
skin/classic/browser/Geolocation-16.png
@ -465,6 +467,8 @@ browser.jar:
* skin/classic/aero/browser/browser-lightweightTheme.css
skin/classic/aero/browser/click-to-play-warning-stripes.png
* skin/classic/aero/browser/content-contextmenu.svg
skin/classic/aero/browser/dots.png (../shared/dots.png)
skin/classic/aero/browser/dots@2x.png (../shared/dots@2x.png)
* skin/classic/aero/browser/engineManager.css
skin/classic/aero/browser/fullscreen-darknoise.png
skin/classic/aero/browser/Geolocation-16.png

View File

@ -267,6 +267,9 @@ user_pref("loop.CSP","default-src 'self' about: file: chrome: data: wss://* http
user_pref("browser.uitour.pinnedTabUrl", "http://%(server)s/uitour-dummy/pinnedTab");
user_pref("browser.uitour.url", "http://%(server)s/uitour-dummy/tour");
// Don't show the search first run UI by default
user_pref("browser.search.highlightCount", 0);
user_pref("media.eme.enabled", true);
// Don't prompt about e10s