зеркало из https://github.com/mozilla/gecko-dev.git
merge fx-team to mozilla-central a=merge
This commit is contained in:
Коммит
a6d609feb2
|
@ -34,20 +34,22 @@ function close() {
|
|||
return p.kill();
|
||||
}
|
||||
|
||||
let appinfo = {};
|
||||
let name;
|
||||
|
||||
AddonManager.getAddonByID(require("addon").id, function (addon) {
|
||||
appinfo.label = addon.name.replace(" Simulator", "");
|
||||
name = addon.name.replace(" Simulator", "");
|
||||
|
||||
Simulator.register(appinfo.label, {
|
||||
appinfo: appinfo,
|
||||
Simulator.register(name, {
|
||||
// We keep the deprecated `appinfo` object so that recent simulator addons
|
||||
// remain forward-compatible with older Firefox.
|
||||
appinfo: { label: name },
|
||||
launch: launch,
|
||||
close: close
|
||||
});
|
||||
});
|
||||
|
||||
exports.shutdown = function () {
|
||||
Simulator.unregister(appinfo.label);
|
||||
Simulator.unregister(name);
|
||||
close();
|
||||
}
|
||||
|
||||
|
|
|
@ -76,6 +76,36 @@ a {
|
|||
min-width: 70px;
|
||||
}
|
||||
|
||||
#searchIcon {
|
||||
border: 1px solid transparent;
|
||||
-moz-margin-end: 5px;
|
||||
height: 38px;
|
||||
width: 38px;
|
||||
background-image: url("chrome://browser/skin/magnifier.png");
|
||||
background-size: 26px;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
#searchIcon[active],
|
||||
#searchIcon:hover {
|
||||
background-color: #e9e9e9;
|
||||
border: 1px solid rgb(226, 227, 229);
|
||||
border-radius: 2.5px;
|
||||
}
|
||||
|
||||
html[searchUIConfiguration="oldsearchui"] #searchIcon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
html:not([searchUIConfiguration="oldsearchui"]) #searchText::-moz-placeholder {
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
html:not([searchUIConfiguration="oldsearchui"]) #searchLogoContainer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#searchText {
|
||||
-moz-box-flex: 1;
|
||||
padding: 6px 8px;
|
||||
|
@ -368,6 +398,10 @@ body[narrow] #restorePreviousSession::before {
|
|||
background-image: url("chrome://branding/content/about-logo@2x.png");
|
||||
}
|
||||
|
||||
#searchIcon {
|
||||
background-image: url("chrome://browser/skin/magnifier@2x.png");
|
||||
}
|
||||
|
||||
#defaultSnippet1,
|
||||
#defaultSnippet2,
|
||||
#rightsSnippet {
|
||||
|
|
|
@ -41,7 +41,8 @@
|
|||
|
||||
<div id="searchContainer">
|
||||
<form name="searchForm" id="searchForm" onsubmit="onSearchSubmit(event)">
|
||||
<div id="searchLogoContainer"><img id="searchEngineLogo"/></div>
|
||||
<div id="searchLogoContainer" hidden="true"><img id="searchEngineLogo"/></div>
|
||||
<button id="searchIcon" type="button" />
|
||||
<input type="text" name="q" value="" id="searchText" maxlength="256"
|
||||
autofocus="autofocus" dir="auto"/>
|
||||
<input id="searchSubmit" type="submit" value="&abouthome.searchEngineButton.label;"/>
|
||||
|
|
|
@ -1221,6 +1221,29 @@ toolbarpaletteitem[place="palette"][hidden] {
|
|||
animation-duration: 2s;
|
||||
}
|
||||
|
||||
#abouthome-search-panel .panel-arrowcontent {
|
||||
-moz-padding-start: 0;
|
||||
-moz-padding-end: 0;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
background: rgb(248, 250, 251);
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
.abouthome-search-panel-item {
|
||||
-moz-box-align: center;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
-moz-padding-start: 24px;
|
||||
-moz-padding-end: 24px;
|
||||
}
|
||||
|
||||
.abouthome-search-panel-item > label {
|
||||
-moz-padding-start: 0;
|
||||
-moz-margin-start: 0;
|
||||
color: rgb(130, 132, 133);
|
||||
}
|
||||
|
||||
/* Combined context-menu items */
|
||||
#context-navigation > .menuitem-iconic > .menu-iconic-text,
|
||||
#context-navigation > .menuitem-iconic > .menu-accel-container {
|
||||
|
|
|
@ -276,6 +276,14 @@
|
|||
</hbox>
|
||||
</panel>
|
||||
|
||||
<panel id="abouthome-search-panel" orient="vertical" type="arrow" hidden="true"
|
||||
onclick="this.hidePopup()">
|
||||
<hbox id="abouthome-search-panel-manage" class="abouthome-search-panel-item"
|
||||
onclick="openPreferences('paneSearch')">
|
||||
<label>&changeSearchSettings.button;</label>
|
||||
</hbox>
|
||||
</panel>
|
||||
|
||||
<panel id="social-share-panel"
|
||||
class="social-panel"
|
||||
type="arrow"
|
||||
|
|
|
@ -269,6 +269,9 @@ let AboutHomeListener = {
|
|||
case "AboutHomeSearchEvent":
|
||||
this.onSearch(aEvent);
|
||||
break;
|
||||
case "AboutHomeSearchPanel":
|
||||
this.onOpenSearchPanel(aEvent);
|
||||
break;
|
||||
case "click":
|
||||
this.onClick(aEvent);
|
||||
break;
|
||||
|
@ -320,6 +323,10 @@ let AboutHomeListener = {
|
|||
addEventListener("click", this, true);
|
||||
addEventListener("pagehide", this, true);
|
||||
|
||||
if (!Services.prefs.getBoolPref("browser.search.showOneOffButtons")) {
|
||||
doc.documentElement.setAttribute("searchUIConfiguration", "oldsearchui");
|
||||
}
|
||||
|
||||
// XXX bug 738646 - when Marketplace is launched, remove this statement and
|
||||
// the hidden attribute set on the apps button in aboutHome.xhtml
|
||||
if (Services.prefs.getPrefType("browser.aboutHome.apps") == Services.prefs.PREF_BOOL &&
|
||||
|
@ -328,6 +335,7 @@ let AboutHomeListener = {
|
|||
|
||||
sendAsyncMessage("AboutHome:RequestUpdate");
|
||||
doc.addEventListener("AboutHomeSearchEvent", this, true, true);
|
||||
doc.addEventListener("AboutHomeSearchPanel", this, true, true);
|
||||
},
|
||||
|
||||
onClick: function(aEvent) {
|
||||
|
@ -378,6 +386,10 @@ let AboutHomeListener = {
|
|||
case "settings":
|
||||
sendAsyncMessage("AboutHome:Settings");
|
||||
break;
|
||||
|
||||
case "searchIcon":
|
||||
sendAsyncMessage("AboutHome:OpenSearchPanel", null, { anchor: originalTarget });
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -397,6 +409,10 @@ let AboutHomeListener = {
|
|||
sendAsyncMessage("AboutHome:Search", { searchData: aEvent.detail });
|
||||
},
|
||||
|
||||
onOpenSearchPanel: function(aEvent) {
|
||||
sendAsyncMessage("AboutHome:OpenSearchPanel");
|
||||
},
|
||||
|
||||
onFocusInput: function () {
|
||||
let searchInput = content.document.getElementById("searchText");
|
||||
if (searchInput) {
|
||||
|
|
|
@ -345,6 +345,19 @@ input[type=button] {
|
|||
background-size: 26px 26px;
|
||||
}
|
||||
|
||||
#newtab-search-logo.magnifier {
|
||||
width: 38px; /* 26 image width + 6 left "padding" + 6 right "padding" */
|
||||
-moz-margin-end: 5px;
|
||||
background-size: 26px;
|
||||
background-image: url("chrome://browser/skin/magnifier.png");
|
||||
}
|
||||
|
||||
@media not all and (max-resolution: 1dppx) {
|
||||
#newtab-search-icon.magnifier {
|
||||
background-image: url("chrome://browser/skin/magnifier@2x.png");
|
||||
}
|
||||
}
|
||||
|
||||
#newtab-search-logo[type="logo"] {
|
||||
background-size: 65px 26px;
|
||||
width: 77px; /* 65 image width + 6 left "padding" + 6 right "padding" */
|
||||
|
@ -366,7 +379,7 @@ input[type=button] {
|
|||
}
|
||||
|
||||
#newtab-search-text {
|
||||
height: 38px;
|
||||
height: 38px; /* same height as #newtab-search-logo */
|
||||
-moz-box-flex: 1;
|
||||
|
||||
padding: 0 8px;
|
||||
|
@ -390,7 +403,7 @@ input[type=button] {
|
|||
}
|
||||
|
||||
#newtab-search-submit {
|
||||
height: 38px;
|
||||
height: 38px; /* same height as #newtab-search-logo */
|
||||
font-size: 13px !important;
|
||||
|
||||
-moz-margin-start: -1px;
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
%newTabDTD;
|
||||
<!ENTITY % searchBarDTD SYSTEM "chrome://browser/locale/searchbar.dtd">
|
||||
%searchBarDTD;
|
||||
<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
|
||||
%browserDTD;
|
||||
]>
|
||||
|
||||
<xul:window id="newtab-window" xmlns="http://www.w3.org/1999/xhtml"
|
||||
|
@ -28,7 +30,7 @@
|
|||
<xul:panel id="newtab-search-panel" orient="vertical" type="arrow"
|
||||
noautohide="true" hidden="true">
|
||||
<xul:hbox id="newtab-search-manage" class="newtab-search-panel-engine">
|
||||
<xul:label>&cmd_engineManager.label;</xul:label>
|
||||
<xul:label>&changeSearchSettings.button;</xul:label>
|
||||
</xul:hbox>
|
||||
</xul:panel>
|
||||
|
||||
|
|
|
@ -8,12 +8,23 @@ let gSearch = {
|
|||
|
||||
currentEngineName: null,
|
||||
|
||||
get useNewUI() {
|
||||
let newUI = Services.prefs.getBoolPref("browser.search.showOneOffButtons");
|
||||
delete this.useNewUI;
|
||||
this.useNewUI = newUI;
|
||||
return newUI;
|
||||
},
|
||||
|
||||
init: function () {
|
||||
for (let idSuffix of this._nodeIDSuffixes) {
|
||||
this._nodes[idSuffix] =
|
||||
document.getElementById("newtab-search-" + idSuffix);
|
||||
}
|
||||
|
||||
if (this.useNewUI) {
|
||||
this._nodes.logo.classList.add("magnifier");
|
||||
}
|
||||
|
||||
window.addEventListener("ContentSearchService", this);
|
||||
this._send("GetState");
|
||||
},
|
||||
|
@ -122,6 +133,11 @@ let gSearch = {
|
|||
},
|
||||
|
||||
_setUpPanel: function () {
|
||||
// The new search UI only contains the "manage" engine entry in the panel
|
||||
if (this.useNewUI) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Build the panel if necessary.
|
||||
if (this._newEngines) {
|
||||
this._buildPanel(this._newEngines);
|
||||
|
@ -198,28 +214,30 @@ let gSearch = {
|
|||
_setCurrentEngine: function (engine) {
|
||||
this.currentEngineName = engine.name;
|
||||
|
||||
let type = "";
|
||||
let uri;
|
||||
let logoBuf = window.devicePixelRatio >= 2 ?
|
||||
engine.logo2xBuffer || engine.logoBuffer :
|
||||
engine.logoBuffer || engine.logo2xBuffer;
|
||||
if (logoBuf) {
|
||||
uri = URL.createObjectURL(new Blob([logoBuf]));
|
||||
type = "logo";
|
||||
}
|
||||
else if (engine.iconBuffer) {
|
||||
uri = this._getFaviconURIFromBuffer(engine.iconBuffer);
|
||||
type = "favicon";
|
||||
}
|
||||
this._nodes.logo.setAttribute("type", type);
|
||||
if (!this.useNewUI) {
|
||||
let type = "";
|
||||
let uri;
|
||||
let logoBuf = window.devicePixelRatio >= 2 ?
|
||||
engine.logo2xBuffer || engine.logoBuffer :
|
||||
engine.logoBuffer || engine.logo2xBuffer;
|
||||
if (logoBuf) {
|
||||
uri = URL.createObjectURL(new Blob([logoBuf]));
|
||||
type = "logo";
|
||||
}
|
||||
else if (engine.iconBuffer) {
|
||||
uri = this._getFaviconURIFromBuffer(engine.iconBuffer);
|
||||
type = "favicon";
|
||||
}
|
||||
this._nodes.logo.setAttribute("type", type);
|
||||
|
||||
if (uri) {
|
||||
this._nodes.logo.style.backgroundImage = "url(" + uri + ")";
|
||||
if (uri) {
|
||||
this._nodes.logo.style.backgroundImage = "url(" + uri + ")";
|
||||
}
|
||||
else {
|
||||
this._nodes.logo.style.backgroundImage = "";
|
||||
}
|
||||
this._nodes.text.placeholder = engine.placeholder;
|
||||
}
|
||||
else {
|
||||
this._nodes.logo.style.backgroundImage = "";
|
||||
}
|
||||
this._nodes.text.placeholder = engine.placeholder;
|
||||
|
||||
// Set up the suggestion controller.
|
||||
if (!this._suggestionController) {
|
||||
|
|
|
@ -78,25 +78,6 @@ let gTests = [
|
|||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Check that search engine logo has alt text",
|
||||
setup: function () { },
|
||||
run: function ()
|
||||
{
|
||||
let doc = gBrowser.selectedTab.linkedBrowser.contentDocument;
|
||||
|
||||
let searchEngineLogoElt = doc.getElementById("searchEngineLogo");
|
||||
ok(searchEngineLogoElt, "Found search engine logo");
|
||||
|
||||
let altText = searchEngineLogoElt.alt;
|
||||
ok(typeof altText == "string" && altText.length > 0,
|
||||
"Search engine logo's alt text is a nonempty string");
|
||||
|
||||
isnot(altText, "undefined",
|
||||
"Search engine logo's alt text shouldn't be the string 'undefined'");
|
||||
}
|
||||
},
|
||||
|
||||
// Disabled on Linux for intermittent issues with FHR, see Bug 945667.
|
||||
{
|
||||
desc: "Check that performing a search fires a search event and records to " +
|
||||
|
@ -252,52 +233,6 @@ let gTests = [
|
|||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Check that the search UI/ action is updated when the search engine is changed",
|
||||
setup: function() {},
|
||||
run: function()
|
||||
{
|
||||
let currEngine = Services.search.currentEngine;
|
||||
let unusedEngines = [].concat(Services.search.getVisibleEngines()).filter(x => x != currEngine);
|
||||
let searchbar = document.getElementById("searchbar");
|
||||
|
||||
function checkSearchUI(engine) {
|
||||
let doc = gBrowser.selectedTab.linkedBrowser.contentDocument;
|
||||
let searchText = doc.getElementById("searchText");
|
||||
let logoElt = doc.getElementById("searchEngineLogo");
|
||||
let engineName = doc.documentElement.getAttribute("searchEngineName");
|
||||
|
||||
is(engineName, engine.name, "Engine name should've been updated");
|
||||
|
||||
if (!logoElt.parentNode.hidden) {
|
||||
is(logoElt.alt, engineName, "Alt text of logo image should match search engine name")
|
||||
} else {
|
||||
is(searchText.placeholder, engineName, "Placeholder text should match search engine name");
|
||||
}
|
||||
}
|
||||
// Do a sanity check that all attributes are correctly set to begin with
|
||||
checkSearchUI(currEngine);
|
||||
|
||||
let deferred = Promise.defer();
|
||||
promiseBrowserAttributes(gBrowser.selectedTab).then(function() {
|
||||
// Test if the update propagated
|
||||
checkSearchUI(unusedEngines[0]);
|
||||
searchbar.currentEngine = currEngine;
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
// The following cleanup function will set currentEngine back to the previous
|
||||
// engine if we fail to do so above.
|
||||
registerCleanupFunction(function() {
|
||||
searchbar.currentEngine = currEngine;
|
||||
});
|
||||
// Set the current search engine to an unused one
|
||||
searchbar.currentEngine = unusedEngines[0];
|
||||
searchbar.select();
|
||||
return deferred.promise;
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Check POST search engine support",
|
||||
setup: function() {},
|
||||
|
@ -492,6 +427,26 @@ let gTests = [
|
|||
is(gBrowser.currentURI.spec, "about:accounts?entrypoint=abouthome",
|
||||
"Entry point should be `abouthome`.");
|
||||
})
|
||||
},
|
||||
{
|
||||
desc: "Clicking the icon should open the popup",
|
||||
setup: function () {},
|
||||
run: Task.async(function* () {
|
||||
let doc = gBrowser.selectedBrowser.contentDocument;
|
||||
let searchIcon = doc.getElementById("searchIcon");
|
||||
let panel = window.document.getElementById("abouthome-search-panel");
|
||||
|
||||
info("Waiting for popup to open");
|
||||
EventUtils.synthesizeMouseAtCenter(searchIcon, {}, gBrowser.selectedBrowser.contentWindow);
|
||||
yield promiseWaitForEvent(panel, "popupshown");
|
||||
ok("Saw popup open");
|
||||
|
||||
let promise = promisePrefsOpen();
|
||||
let item = window.document.getElementById("abouthome-search-panel-manage");
|
||||
EventUtils.synthesizeMouseAtCenter(item, {});
|
||||
|
||||
yield promise;
|
||||
})
|
||||
}
|
||||
|
||||
];
|
||||
|
@ -667,6 +622,24 @@ function waitForLoad(cb) {
|
|||
}, true);
|
||||
}
|
||||
|
||||
function promiseWaitForEvent(node, type, capturing) {
|
||||
return new Promise((resolve) => {
|
||||
node.addEventListener(type, function listener(event) {
|
||||
node.removeEventListener(type, listener, capturing);
|
||||
resolve(event);
|
||||
}, capturing);
|
||||
});
|
||||
}
|
||||
|
||||
let promisePrefsOpen = Task.async(function*() {
|
||||
info("Waiting for the preferences tab to open...");
|
||||
let event = yield promiseWaitForEvent(gBrowser.tabContainer, "TabOpen", true);
|
||||
let tab = event.target;
|
||||
yield promiseTabLoadEvent(tab);
|
||||
is(tab.linkedBrowser.currentURI.spec, "about:preferences#search", "Should have seen the prefs tab");
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
|
||||
function promiseNewEngine(basename) {
|
||||
info("Waiting for engine to be added: " + basename);
|
||||
let addDeferred = Promise.defer();
|
||||
|
|
|
@ -119,41 +119,12 @@ let runTaskifiedTests = Task.async(function* () {
|
|||
promiseClick(logoImg()),
|
||||
]);
|
||||
|
||||
// In the search panel, click the no-logo engine. It should become the
|
||||
// current engine.
|
||||
let noLogoBox = null;
|
||||
for (let box of panel.childNodes) {
|
||||
if (box.getAttribute("engine") == noLogoEngine.name) {
|
||||
noLogoBox = box;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ok(noLogoBox, "Search panel should contain the no-logo engine");
|
||||
yield Promise.all([
|
||||
promiseSearchEvents(["CurrentEngine"]),
|
||||
promiseClick(noLogoBox),
|
||||
]);
|
||||
|
||||
yield checkCurrentEngine(ENGINE_NO_LOGO);
|
||||
|
||||
// Switch back to the 1x-and-2x logo engine.
|
||||
Services.search.currentEngine = logo1x2xEngine;
|
||||
yield promiseSearchEvents(["CurrentEngine"]);
|
||||
yield checkCurrentEngine(ENGINE_1X_2X_LOGO);
|
||||
|
||||
// Open the panel again.
|
||||
yield Promise.all([
|
||||
promisePanelShown(panel),
|
||||
promiseClick(logoImg()),
|
||||
]);
|
||||
|
||||
// In the search panel, click the Manage Engines box.
|
||||
let manageBox = $("manage");
|
||||
ok(!!manageBox, "The Manage Engines box should be present in the document");
|
||||
yield Promise.all([
|
||||
promiseManagerOpen(),
|
||||
promiseClick(manageBox),
|
||||
]);
|
||||
is(panel.childNodes.length, 1, "Search panel should only contain the Manage Engines entry");
|
||||
is(panel.childNodes[0], manageBox, "Search panel should contain the Manage Engines entry");
|
||||
|
||||
panel.hidePopup();
|
||||
|
||||
// Add the engine that provides search suggestions and switch to it.
|
||||
let suggestionEngine = yield promiseNewSearchEngine(ENGINE_SUGGESTIONS);
|
||||
|
@ -340,42 +311,6 @@ let checkCurrentEngine = Task.async(function* ({name: basename, logoPrefix1x, lo
|
|||
// gSearch.currentEngineName
|
||||
is(gSearch().currentEngineName, engine.name,
|
||||
"currentEngineName: " + engine.name);
|
||||
|
||||
let expectedLogoPrefix = window.devicePixelRatio >= 2 ? logoPrefix2x : logoPrefix1x;
|
||||
|
||||
// Check that the right logo is set.
|
||||
let logo = logoImg();
|
||||
if (expectedLogoPrefix) {
|
||||
let objectURL = logo.style.backgroundImage.match(/^url\("([^"]*)"\)$/)[1];
|
||||
ok(objectURL, "ObjectURL should be there.");
|
||||
|
||||
let blob = yield objectURLToBlob(objectURL);
|
||||
let base64 = yield blobToBase64(blob);
|
||||
|
||||
ok(base64.startsWith(expectedLogoPrefix), "Checking image prefix.");
|
||||
|
||||
logo.click();
|
||||
let panel = searchPanel();
|
||||
yield promisePanelShown(panel);
|
||||
|
||||
panel.hidePopup();
|
||||
for (let engineBox of panel.childNodes) {
|
||||
let engineName = engineBox.getAttribute("engine");
|
||||
if (engineName == engine.name) {
|
||||
is(engineBox.getAttribute("selected"), "true",
|
||||
"Engine box's selected attribute should be true for " +
|
||||
"selected engine: " + engineName);
|
||||
}
|
||||
else {
|
||||
ok(!engineBox.hasAttribute("selected"),
|
||||
"Engine box's selected attribute should be absent for " +
|
||||
"non-selected engine: " + engineName);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
is(logo.style.backgroundImage, "", "backgroundImage should be empty");
|
||||
}
|
||||
});
|
||||
|
||||
function promisePanelShown(panel) {
|
||||
|
@ -399,31 +334,6 @@ function promiseClick(node) {
|
|||
return deferred.promise;
|
||||
}
|
||||
|
||||
function promiseManagerOpen() {
|
||||
info("Waiting for the search manager window to open...");
|
||||
let deferred = Promise.defer();
|
||||
let winWatcher = Cc["@mozilla.org/embedcomp/window-watcher;1"].
|
||||
getService(Ci.nsIWindowWatcher);
|
||||
winWatcher.registerNotification(function onWin(subj, topic, data) {
|
||||
if (topic == "domwindowopened" && subj instanceof Ci.nsIDOMWindow) {
|
||||
subj.addEventListener("load", function onLoad() {
|
||||
subj.removeEventListener("load", onLoad);
|
||||
if (subj.document.documentURI ==
|
||||
"chrome://browser/content/search/engineManager.xul") {
|
||||
winWatcher.unregisterNotification(onWin);
|
||||
ok(true, "Observed search manager window opened");
|
||||
is(subj.opener, gWindow,
|
||||
"Search engine manager opener should be the chrome browser " +
|
||||
"window containing the newtab page");
|
||||
subj.close();
|
||||
deferred.resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function searchPanel() {
|
||||
return $("panel");
|
||||
}
|
||||
|
|
|
@ -629,6 +629,12 @@
|
|||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="inputChanged">
|
||||
<body><![CDATA[
|
||||
this.updateGoButtonVisibility();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="updateGoButtonVisibility">
|
||||
<body><![CDATA[
|
||||
document.getAnonymousElementByAttribute(this, "anonid",
|
||||
|
@ -657,8 +663,8 @@
|
|||
</method>
|
||||
</implementation>
|
||||
<handlers>
|
||||
<handler event="input" action="this.updateGoButtonVisibility();"/>
|
||||
<handler event="drop" action="this.updateGoButtonVisibility();"/>
|
||||
<handler event="input" action="this.inputChanged();"/>
|
||||
<handler event="drop" action="this.inputChanged();"/>
|
||||
<handler event="focus">
|
||||
<![CDATA[
|
||||
if (this._textbox.value)
|
||||
|
|
|
@ -137,7 +137,7 @@ let UI = {
|
|||
startSimulator: function(version) {
|
||||
this._portBeforeSimulatorStarted = this.connection.port;
|
||||
let port = ConnectionManager.getFreeTCPPort();
|
||||
let simulator = Simulator.getByVersion(version);
|
||||
let simulator = Simulator.getByName(version);
|
||||
if (!simulator) {
|
||||
this.connection.log("Error: can't find simulator: " + version);
|
||||
return;
|
||||
|
|
|
@ -9,11 +9,11 @@ const {Simulator} = Cu.import("resource://gre/modules/devtools/Simulator.jsm");
|
|||
let store = new ObservableObject({versions:[]});
|
||||
|
||||
function feedStore() {
|
||||
store.object.versions = Simulator.availableVersions().map(v => {
|
||||
let simulator = Simulator.getByVersion(v);
|
||||
store.object.versions = Simulator.availableNames().map(name => {
|
||||
let simulator = Simulator.getByName(name);
|
||||
return {
|
||||
version: v,
|
||||
label: simulator.appinfo.label
|
||||
version: name,
|
||||
label: simulator ? name : "Unknown"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -159,11 +159,14 @@ BrowserToolboxProcess.prototype = {
|
|||
try {
|
||||
debuggingProfileDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
|
||||
} catch (ex) {
|
||||
if (ex.result !== Cr.NS_ERROR_FILE_ALREADY_EXISTS) {
|
||||
// Don't re-copy over the prefs again if this profile already exists
|
||||
if (ex.result === Cr.NS_ERROR_FILE_ALREADY_EXISTS) {
|
||||
this._dbgProfilePath = debuggingProfileDir.path;
|
||||
} else {
|
||||
dumpn("Error trying to create a profile directory, failing.");
|
||||
dumpn("Error: " + (ex.message || ex));
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this._dbgProfilePath = debuggingProfileDir.path;
|
||||
|
|
|
@ -71,9 +71,21 @@ function openToolbox(form) {
|
|||
};
|
||||
devtools.TargetFactory.forRemoteTab(options).then(target => {
|
||||
let frame = document.getElementById("toolbox-iframe");
|
||||
let selectedTool = "jsdebugger";
|
||||
|
||||
try {
|
||||
// Remember the last panel that was used inside of this profile.
|
||||
selectedTool = Services.prefs.getCharPref("devtools.toolbox.selectedTool");
|
||||
} catch(e) {}
|
||||
|
||||
try {
|
||||
// But if we are testing, then it should always open the debugger panel.
|
||||
selectedTool = Services.prefs.getCharPref("devtools.browsertoolbox.panel");
|
||||
} catch(e) {}
|
||||
|
||||
let options = { customIframe: frame };
|
||||
gDevTools.showToolbox(target,
|
||||
"jsdebugger",
|
||||
selectedTool,
|
||||
devtools.Toolbox.HostType.CUSTOM,
|
||||
options)
|
||||
.then(onNewToolbox);
|
||||
|
|
|
@ -204,7 +204,7 @@ var TextEditor = Class({
|
|||
*/
|
||||
load: function(resource) {
|
||||
// Wait for the editor.appendTo and resource.load before proceeding.
|
||||
// They can run in parallel.
|
||||
// They can run in parallel.
|
||||
return promise.all([
|
||||
resource.load(),
|
||||
this.appended
|
||||
|
@ -245,7 +245,9 @@ var TextEditor = Class({
|
|||
*/
|
||||
focus: function() {
|
||||
return this.appended.then(() => {
|
||||
this.editor.focus();
|
||||
if (this.editor) {
|
||||
this.editor.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -6,8 +6,6 @@ const {Cu} = require("chrome");
|
|||
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm");
|
||||
const {AddonManager} = Cu.import("resource://gre/modules/AddonManager.jsm");
|
||||
const {EventEmitter} = Cu.import("resource://gre/modules/devtools/event-emitter.js");
|
||||
const {Simulator} = Cu.import("resource://gre/modules/devtools/Simulator.jsm");
|
||||
const {Devices} = Cu.import("resource://gre/modules/devtools/Devices.jsm");
|
||||
const {Services} = Cu.import("resource://gre/modules/Services.jsm");
|
||||
const {GetAddonsJSON} = require("devtools/webide/remote-resources");
|
||||
|
||||
|
|
|
@ -205,8 +205,8 @@ let SimulatorScanner = {
|
|||
|
||||
_updateRuntimes() {
|
||||
this._runtimes = [];
|
||||
for (let version of Simulator.availableVersions()) {
|
||||
this._runtimes.push(new SimulatorRuntime(version));
|
||||
for (let name of Simulator.availableNames()) {
|
||||
this._runtimes.push(new SimulatorRuntime(name));
|
||||
}
|
||||
this._emitUpdated();
|
||||
},
|
||||
|
@ -463,15 +463,15 @@ WiFiRuntime.prototype = {
|
|||
// For testing use only
|
||||
exports._WiFiRuntime = WiFiRuntime;
|
||||
|
||||
function SimulatorRuntime(version) {
|
||||
this.version = version;
|
||||
function SimulatorRuntime(name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
SimulatorRuntime.prototype = {
|
||||
type: RuntimeTypes.SIMULATOR,
|
||||
connect: function(connection) {
|
||||
let port = ConnectionManager.getFreeTCPPort();
|
||||
let simulator = Simulator.getByVersion(this.version);
|
||||
let simulator = Simulator.getByName(this.name);
|
||||
if (!simulator || !simulator.launch) {
|
||||
return promise.reject("Can't find simulator: " + this.name);
|
||||
}
|
||||
|
@ -484,14 +484,7 @@ SimulatorRuntime.prototype = {
|
|||
});
|
||||
},
|
||||
get id() {
|
||||
return this.version;
|
||||
},
|
||||
get name() {
|
||||
let simulator = Simulator.getByVersion(this.version);
|
||||
if (!simulator) {
|
||||
return "Unknown";
|
||||
}
|
||||
return Simulator.getByVersion(this.version).appinfo.label;
|
||||
return this.name;
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -28,10 +28,14 @@
|
|||
adbAddonsInstalled.resolve();
|
||||
});
|
||||
|
||||
function onSimulatorInstalled(version) {
|
||||
function getVersion(name) {
|
||||
return name.match(/(\d+\.\d+)/)[0];
|
||||
}
|
||||
|
||||
function onSimulatorInstalled(name) {
|
||||
let deferred = promise.defer();
|
||||
Simulator.on("register", function onUpdate() {
|
||||
if (Simulator.getByVersion(version)) {
|
||||
if (Simulator.getByName(name)) {
|
||||
Simulator.off("register", onUpdate);
|
||||
nextTick().then(deferred.resolve);
|
||||
}
|
||||
|
@ -39,17 +43,17 @@
|
|||
return deferred.promise;
|
||||
}
|
||||
|
||||
function installSimulatorFromUI(doc, version) {
|
||||
let li = doc.querySelector('[addon="simulator-' + version + '"]');
|
||||
function installSimulatorFromUI(doc, name) {
|
||||
let li = doc.querySelector('[addon="simulator-' + getVersion(name) + '"]');
|
||||
li.querySelector(".install-button").click();
|
||||
return onSimulatorInstalled(version);
|
||||
return onSimulatorInstalled(name);
|
||||
}
|
||||
|
||||
function uninstallSimulatorFromUI(doc, version) {
|
||||
function uninstallSimulatorFromUI(doc, name) {
|
||||
let deferred = promise.defer();
|
||||
Simulator.on("unregister", function onUpdate() {
|
||||
nextTick().then(() => {
|
||||
let li = doc.querySelector('[status="uninstalled"][addon="simulator-' + version + '"]');
|
||||
let li = doc.querySelector('[status="uninstalled"][addon="simulator-' + getVersion(name) + '"]');
|
||||
if (li) {
|
||||
Simulator.off("unregister", onUpdate);
|
||||
deferred.resolve();
|
||||
|
@ -58,7 +62,7 @@
|
|||
}
|
||||
})
|
||||
});
|
||||
let li = doc.querySelector('[status="installed"][addon="simulator-' + version + '"]');
|
||||
let li = doc.querySelector('[status="installed"][addon="simulator-' + getVersion(name) + '"]');
|
||||
li.querySelector(".uninstall-button").click();
|
||||
return deferred.promise;
|
||||
}
|
||||
|
@ -100,7 +104,7 @@
|
|||
let sim10 = addons.simulators.filter(a => a.version == "1.0")[0];
|
||||
sim10.install();
|
||||
|
||||
yield onSimulatorInstalled("1.0");
|
||||
yield onSimulatorInstalled("Firefox OS 1.0");
|
||||
|
||||
win.Cmds.showAddons();
|
||||
|
||||
|
@ -119,11 +123,11 @@
|
|||
|
||||
info("Uninstalling Simulator 2.0");
|
||||
|
||||
yield installSimulatorFromUI(addonDoc, "2.0");
|
||||
yield installSimulatorFromUI(addonDoc, "Firefox OS 2.0");
|
||||
|
||||
info("Uninstalling Simulator 3.0");
|
||||
|
||||
yield installSimulatorFromUI(addonDoc, "3.0");
|
||||
yield installSimulatorFromUI(addonDoc, "Firefox OS 3.0");
|
||||
|
||||
yield nextTick();
|
||||
|
||||
|
@ -136,9 +140,9 @@
|
|||
items = panelNode.querySelectorAll(".runtime-panel-item-simulator");
|
||||
is(items.length, 3, "Found 3 simulators button");
|
||||
|
||||
yield uninstallSimulatorFromUI(addonDoc, "1.0");
|
||||
yield uninstallSimulatorFromUI(addonDoc, "2.0");
|
||||
yield uninstallSimulatorFromUI(addonDoc, "3.0");
|
||||
yield uninstallSimulatorFromUI(addonDoc, "Firefox OS 1.0");
|
||||
yield uninstallSimulatorFromUI(addonDoc, "Firefox OS 2.0");
|
||||
yield uninstallSimulatorFromUI(addonDoc, "Firefox OS 3.0");
|
||||
|
||||
items = panelNode.querySelectorAll(".runtime-panel-item-simulator");
|
||||
is(items.length, 0, "No simulator listed");
|
||||
|
|
|
@ -170,6 +170,7 @@
|
|||
@RESPATH@/components/browser-element.xpt
|
||||
@RESPATH@/browser/components/browsercompsbase.xpt
|
||||
@RESPATH@/browser/components/browser-feeds.xpt
|
||||
@RESPATH@/browser/components/browsermodules.manifest
|
||||
@RESPATH@/components/caps.xpt
|
||||
@RESPATH@/components/chrome.xpt
|
||||
@RESPATH@/components/commandhandler.xpt
|
||||
|
|
|
@ -97,6 +97,7 @@ let AboutHome = {
|
|||
"AboutHome:Settings",
|
||||
"AboutHome:RequestUpdate",
|
||||
"AboutHome:Search",
|
||||
"AboutHome:OpenSearchPanel",
|
||||
],
|
||||
|
||||
init: function() {
|
||||
|
@ -203,6 +204,18 @@ let AboutHome = {
|
|||
});
|
||||
|
||||
break;
|
||||
|
||||
case "AboutHome:OpenSearchPanel":
|
||||
let panel = window.document.getElementById("abouthome-search-panel");
|
||||
let anchor = aMessage.objects.anchor;
|
||||
panel.hidden = false;
|
||||
panel.openPopup(anchor);
|
||||
anchor.setAttribute("active", "true");
|
||||
panel.addEventListener("popuphidden", function onHidden() {
|
||||
panel.removeEventListener("popuphidden", onHidden);
|
||||
anchor.removeAttribute("active");
|
||||
});
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -220,6 +220,12 @@ this.ContentSearch = {
|
|||
|
||||
_onMessageManageEngines: function (msg, data) {
|
||||
let browserWin = msg.target.ownerDocument.defaultView;
|
||||
|
||||
if (Services.prefs.getBoolPref("browser.search.showOneOffButtons")) {
|
||||
browserWin.openPreferences("paneSearch");
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
let wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
|
||||
getService(Components.interfaces.nsIWindowMediator);
|
||||
let window = wm.getMostRecentWindow("Browser:SearchManager");
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["UITour"];
|
||||
this.EXPORTED_SYMBOLS = ["UITour", "UITourMetricsProvider"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
|
@ -23,7 +23,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "UITelemetry",
|
|||
"resource://gre/modules/UITelemetry.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry",
|
||||
"resource:///modules/BrowserUITelemetry.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Metrics",
|
||||
"resource://gre/modules/Metrics.jsm");
|
||||
|
||||
// See LOG_LEVELS in Console.jsm. Common examples: "All", "Info", "Warn", & "Error".
|
||||
const PREF_LOG_LEVEL = "browser.uitour.loglevel";
|
||||
|
@ -521,6 +522,64 @@ this.UITour = {
|
|||
}).catch(log.error);
|
||||
break;
|
||||
}
|
||||
|
||||
case "setDefaultSearchEngine": {
|
||||
let enginePromise = this.selectSearchEngine(data.identifier);
|
||||
enginePromise.catch(Cu.reportError);
|
||||
break;
|
||||
}
|
||||
|
||||
case "setTreatmentTag": {
|
||||
let name = data.name;
|
||||
let value = data.value;
|
||||
let string = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
|
||||
string.data = value;
|
||||
Services.prefs.setComplexValue("browser.uitour.treatment." + name,
|
||||
Ci.nsISupportsString, string);
|
||||
UITourHealthReport.recordTreatmentTag(name, value);
|
||||
break;
|
||||
}
|
||||
|
||||
case "getTreatmentTag": {
|
||||
let name = data.name;
|
||||
let value;
|
||||
try {
|
||||
value = Services.prefs.getComplexValue("browser.uitour.treatment." + name,
|
||||
Ci.nsISupportsString).data;
|
||||
} catch (ex) {}
|
||||
this.sendPageCallback(messageManager, data.callbackID, { value: value });
|
||||
break;
|
||||
}
|
||||
|
||||
case "setSearchTerm": {
|
||||
let targetPromise = this.getTarget(window, "search");
|
||||
targetPromise.then(target => {
|
||||
let searchbar = target.node;
|
||||
searchbar.value = data.term;
|
||||
searchbar.inputChanged();
|
||||
}).then(null, Cu.reportError);
|
||||
break;
|
||||
}
|
||||
|
||||
case "openSearchPanel": {
|
||||
let targetPromise = this.getTarget(window, "search");
|
||||
targetPromise.then(target => {
|
||||
let searchbar = target.node;
|
||||
|
||||
if (searchbar.textbox.open) {
|
||||
this.sendPageCallback(messageManager, data.callbackID);
|
||||
} else {
|
||||
let onPopupShown = () => {
|
||||
searchbar.textbox.popup.removeEventListener("popupshown", onPopupShown);
|
||||
this.sendPageCallback(messageManager, data.callbackID);
|
||||
};
|
||||
|
||||
searchbar.textbox.popup.addEventListener("popupshown", onPopupShown);
|
||||
searchbar.openSuggestionsPanel();
|
||||
}
|
||||
}).then(null, Cu.reportError);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!window.gMultiProcessBrowser) { // Non-e10s. See bug 1089000.
|
||||
|
@ -1105,9 +1164,14 @@ this.UITour = {
|
|||
|
||||
tooltip.setAttribute("targetName", aAnchor.targetName);
|
||||
tooltip.hidden = false;
|
||||
let xOffset = 0, yOffset = 0;
|
||||
let alignment = "bottomcenter topright";
|
||||
if (aAnchor.targetName == "search") {
|
||||
alignment = "after_start";
|
||||
xOffset = 18;
|
||||
}
|
||||
this._addAnnotationPanelMutationObserver(tooltip);
|
||||
tooltip.openPopup(aAnchorEl, alignment);
|
||||
tooltip.openPopup(aAnchorEl, alignment, xOffset, yOffset);
|
||||
if (tooltip.state == "closed") {
|
||||
document.defaultView.addEventListener("endmodalstate", function endModalStateHandler() {
|
||||
document.defaultView.removeEventListener("endmodalstate", endModalStateHandler);
|
||||
|
@ -1290,6 +1354,19 @@ this.UITour = {
|
|||
props.forEach(property => appinfo[property] = Services.appinfo[property]);
|
||||
this.sendPageCallback(aMessageManager, aCallbackID, appinfo);
|
||||
break;
|
||||
case "selectedSearchEngine":
|
||||
Services.search.init(rv => {
|
||||
let engine;
|
||||
if (Components.isSuccessCode(rv)) {
|
||||
engine = Services.search.defaultEngine;
|
||||
} else {
|
||||
engine = { identifier: "" };
|
||||
}
|
||||
this.sendPageCallback(aMessageManager, aCallbackID, {
|
||||
searchEngineIdentifier: engine.identifier
|
||||
});
|
||||
});
|
||||
break;
|
||||
default:
|
||||
log.error("getConfiguration: Unknown configuration requested: " + aConfiguration);
|
||||
break;
|
||||
|
@ -1397,6 +1474,26 @@ this.UITour = {
|
|||
}
|
||||
},
|
||||
|
||||
selectSearchEngine(aID) {
|
||||
return new Promise((resolve, reject) => {
|
||||
Services.search.init((rv) => {
|
||||
if (!Components.isSuccessCode(rv)) {
|
||||
reject("selectSearchEngine: search service init failed: " + rv);
|
||||
return;
|
||||
}
|
||||
|
||||
let engines = Services.search.getVisibleEngines();
|
||||
for (let engine of engines) {
|
||||
if (engine.identifier == aID) {
|
||||
Services.search.defaultEngine = engine;
|
||||
return resolve();
|
||||
}
|
||||
}
|
||||
reject("selectSearchEngine could not find engine with given ID");
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
getAvailableSearchEngineTargets(aWindow) {
|
||||
return new Promise(resolve => {
|
||||
this.getTarget(aWindow, "search").then(searchTarget => {
|
||||
|
@ -1448,3 +1545,105 @@ this.UITour = {
|
|||
};
|
||||
|
||||
this.UITour.init();
|
||||
|
||||
/**
|
||||
* UITour Health Report
|
||||
*/
|
||||
const DAILY_DISCRETE_TEXT_FIELD = Metrics.Storage.FIELD_DAILY_DISCRETE_TEXT;
|
||||
|
||||
/**
|
||||
* Public API to be called by the UITour code
|
||||
*/
|
||||
const UITourHealthReport = {
|
||||
recordTreatmentTag: function(tag, value) {
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
Task.spawn(function*() {
|
||||
let reporter = Cc["@mozilla.org/datareporting/service;1"]
|
||||
.getService()
|
||||
.wrappedJSObject
|
||||
.healthReporter;
|
||||
|
||||
// This can happen if the FHR component of the data reporting service is
|
||||
// disabled. This is controlled by a pref that most will never use.
|
||||
if (!reporter) {
|
||||
return;
|
||||
}
|
||||
|
||||
yield reporter.onInit();
|
||||
|
||||
// Get the UITourMetricsProvider instance from the Health Reporter
|
||||
reporter.getProvider("org.mozilla.uitour").recordTreatmentTag(tag, value);
|
||||
});
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
this.UITourMetricsProvider = function() {
|
||||
Metrics.Provider.call(this);
|
||||
}
|
||||
|
||||
UITourMetricsProvider.prototype = Object.freeze({
|
||||
__proto__: Metrics.Provider.prototype,
|
||||
|
||||
name: "org.mozilla.uitour",
|
||||
|
||||
measurementTypes: [
|
||||
UITourTreatmentMeasurement1,
|
||||
],
|
||||
|
||||
recordTreatmentTag: function(tag, value) {
|
||||
let m = this.getMeasurement(UITourTreatmentMeasurement1.prototype.name,
|
||||
UITourTreatmentMeasurement1.prototype.version);
|
||||
let field = tag;
|
||||
|
||||
if (this.storage.hasFieldFromMeasurement(m.id, field,
|
||||
DAILY_DISCRETE_TEXT_FIELD)) {
|
||||
let fieldID = this.storage.fieldIDFromMeasurement(m.id, field);
|
||||
return this.enqueueStorageOperation(function recordKnownField() {
|
||||
return this.storage.addDailyDiscreteTextFromFieldID(fieldID, value);
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
// Otherwise, we first need to create the field.
|
||||
return this.enqueueStorageOperation(function recordField() {
|
||||
// This function has to return a promise.
|
||||
return Task.spawn(function () {
|
||||
let fieldID = yield this.storage.registerField(m.id, field,
|
||||
DAILY_DISCRETE_TEXT_FIELD);
|
||||
yield this.storage.addDailyDiscreteTextFromFieldID(fieldID, value);
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
},
|
||||
});
|
||||
|
||||
function UITourTreatmentMeasurement1() {
|
||||
Metrics.Measurement.call(this);
|
||||
|
||||
this._serializers = {};
|
||||
this._serializers[this.SERIALIZE_JSON] = {
|
||||
//singular: We don't need a singular serializer because we have none of this data
|
||||
daily: this._serializeJSONDaily.bind(this)
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
UITourTreatmentMeasurement1.prototype = Object.freeze({
|
||||
__proto__: Metrics.Measurement.prototype,
|
||||
|
||||
name: "treatment",
|
||||
version: 1,
|
||||
|
||||
// our fields are dynamic
|
||||
fields: { },
|
||||
|
||||
// We need a custom serializer because the default one doesn't accept unknown fields
|
||||
_serializeJSONDaily: function(data) {
|
||||
let result = {_v: this.version };
|
||||
|
||||
for (let [field, data] of data) {
|
||||
result[field] = data;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
category healthreport-js-provider-default UITourMetricsProvider resource:///modules/UITour.jsm
|
||||
#endif
|
|
@ -55,5 +55,9 @@ EXTRA_PP_JS_MODULES += [
|
|||
'webrtcUI.jsm',
|
||||
]
|
||||
|
||||
EXTRA_PP_COMPONENTS += [
|
||||
'browsermodules.manifest',
|
||||
]
|
||||
|
||||
if CONFIG['MOZILLA_OFFICIAL']:
|
||||
DEFINES['MOZILLA_OFFICIAL'] = 1
|
||||
|
|
|
@ -70,34 +70,6 @@ add_task(function* SetCurrentEngine() {
|
|||
});
|
||||
});
|
||||
|
||||
add_task(function* ManageEngines() {
|
||||
yield addTab();
|
||||
gMsgMan.sendAsyncMessage(TEST_MSG, {
|
||||
type: "ManageEngines",
|
||||
});
|
||||
let deferred = Promise.defer();
|
||||
let winWatcher = Cc["@mozilla.org/embedcomp/window-watcher;1"].
|
||||
getService(Ci.nsIWindowWatcher);
|
||||
winWatcher.registerNotification(function onOpen(subj, topic, data) {
|
||||
if (topic == "domwindowopened" && subj instanceof Ci.nsIDOMWindow) {
|
||||
subj.addEventListener("load", function onLoad() {
|
||||
subj.removeEventListener("load", onLoad);
|
||||
if (subj.document.documentURI ==
|
||||
"chrome://browser/content/search/engineManager.xul") {
|
||||
winWatcher.unregisterNotification(onOpen);
|
||||
ok(true, "Observed search manager window open");
|
||||
is(subj.opener, window,
|
||||
"Search engine manager opener should be this chrome window");
|
||||
subj.close();
|
||||
deferred.resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
info("Waiting for search engine manager window to open...");
|
||||
yield deferred.promise;
|
||||
});
|
||||
|
||||
add_task(function* modifyEngine() {
|
||||
yield addTab();
|
||||
let engine = Services.search.currentEngine;
|
||||
|
|
|
@ -369,6 +369,44 @@ let tests = [
|
|||
});
|
||||
});
|
||||
},
|
||||
function test_select_search_engine(done) {
|
||||
Services.search.init(rv => {
|
||||
if (!Components.isSuccessCode(rv)) {
|
||||
ok(false, "search service init failed: " + rv);
|
||||
done();
|
||||
return;
|
||||
}
|
||||
let defaultEngine = Services.search.defaultEngine;
|
||||
gContentAPI.getConfiguration("availableTargets", data => {
|
||||
let searchEngines = data.targets.filter(t => t.startsWith("searchEngine-"));
|
||||
let someOtherEngineID = searchEngines.filter(t => t != "searchEngine-" + defaultEngine.identifier)[0];
|
||||
someOtherEngineID = someOtherEngineID.replace(/^searchEngine-/, "");
|
||||
|
||||
let observe = function (subject, topic, verb) {
|
||||
info("browser-search-engine-modified: " + verb);
|
||||
if (verb == "engine-current") {
|
||||
is(Services.search.defaultEngine.identifier, someOtherEngineID, "correct engine was switched to");
|
||||
done();
|
||||
}
|
||||
};
|
||||
Services.obs.addObserver(observe, "browser-search-engine-modified", false);
|
||||
registerCleanupFunction(() => {
|
||||
// Clean up
|
||||
Services.obs.removeObserver(observe, "browser-search-engine-modified");
|
||||
Services.search.defaultEngine = defaultEngine;
|
||||
});
|
||||
|
||||
gContentAPI.setDefaultSearchEngine(someOtherEngineID);
|
||||
});
|
||||
});
|
||||
},
|
||||
function test_treatment_tag(done) {
|
||||
gContentAPI.setTreatmentTag("foobar", "baz");
|
||||
gContentAPI.getTreatmentTag("foobar", (data) => {
|
||||
is(data.value, "baz", "set and retrieved treatmentTag");
|
||||
done();
|
||||
});
|
||||
},
|
||||
|
||||
// Make sure this test is last in the file so the appMenu gets left open and done will confirm it got tore down.
|
||||
taskify(function* cleanupMenus() {
|
||||
|
|
|
@ -8,6 +8,7 @@ let gContentAPI;
|
|||
let gContentWindow;
|
||||
|
||||
Components.utils.import("resource:///modules/UITour.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
requestLongerTimeout(2);
|
||||
|
||||
|
@ -145,4 +146,54 @@ let tests = [
|
|||
|
||||
popup.removeAttribute("animate");
|
||||
}),
|
||||
|
||||
function test_getConfiguration_selectedSearchEngine(done) {
|
||||
Services.search.init(rv => {
|
||||
ok(Components.isSuccessCode(rv), "Search service initialized");
|
||||
let engine = Services.search.defaultEngine;
|
||||
gContentAPI.getConfiguration("selectedSearchEngine", (data) => {
|
||||
is(data.searchEngineIdentifier, engine.identifier, "Correct engine identifier");
|
||||
done();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
function test_setSearchTerm(done) {
|
||||
const TERM = "UITour Search Term";
|
||||
gContentAPI.setSearchTerm(TERM);
|
||||
|
||||
let searchbar = document.getElementById("searchbar");
|
||||
// The UITour gets to the searchbar element through a promise, so the value setting
|
||||
// only happens after a tick.
|
||||
waitForCondition(() => searchbar.value == TERM, done, "Correct term set");
|
||||
},
|
||||
|
||||
function test_clearSearchTerm(done) {
|
||||
gContentAPI.setSearchTerm("");
|
||||
|
||||
let searchbar = document.getElementById("searchbar");
|
||||
// The UITour gets to the searchbar element through a promise, so the value setting
|
||||
// only happens after a tick.
|
||||
waitForCondition(() => searchbar.value == "", done, "Search term cleared");
|
||||
},
|
||||
|
||||
function test_openSearchPanel(done) {
|
||||
let searchbar = document.getElementById("searchbar");
|
||||
|
||||
// If suggestions are enabled, the panel will attempt to use the network to connect
|
||||
// to the suggestions provider, causing the test suite to fail.
|
||||
Services.prefs.setBoolPref("browser.search.suggest.enabled", false);
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref("browser.search.suggest.enabled");
|
||||
});
|
||||
|
||||
ok(!searchbar.textbox.open, "Popup starts as closed");
|
||||
gContentAPI.openSearchPanel(() => {
|
||||
ok(searchbar.textbox.open, "Popup was opened");
|
||||
searchbar.textbox.closePopup();
|
||||
ok(!searchbar.textbox.open, "Popup was closed");
|
||||
done();
|
||||
});
|
||||
},
|
||||
|
||||
];
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
Cu.import("resource:///modules/UITour.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "UITour",
|
||||
"resource:///modules/UITour.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
const SINGLE_TRY_TIMEOUT = 100;
|
||||
|
@ -219,6 +220,7 @@ function UITourTest() {
|
|||
|
||||
registerCleanupFunction(function() {
|
||||
delete window.UITour;
|
||||
delete window.UITourMetricsProvider;
|
||||
delete window.gContentWindow;
|
||||
delete window.gContentAPI;
|
||||
if (gTestTab)
|
||||
|
|
|
@ -207,4 +207,36 @@ if (typeof Mozilla == 'undefined') {
|
|||
});
|
||||
};
|
||||
|
||||
Mozilla.UITour.setDefaultSearchEngine = function(identifier) {
|
||||
_sendEvent('setDefaultSearchEngine', {
|
||||
identifier: identifier,
|
||||
});
|
||||
};
|
||||
|
||||
Mozilla.UITour.setTreatmentTag = function(name, value) {
|
||||
_sendEvent('setTreatmentTag', {
|
||||
name: name,
|
||||
value: value
|
||||
});
|
||||
};
|
||||
|
||||
Mozilla.UITour.getTreatmentTag = function(name, callback) {
|
||||
_sendEvent('getTreatmentTag', {
|
||||
name: name,
|
||||
callbackID: _waitForCallback(callback)
|
||||
});
|
||||
};
|
||||
|
||||
Mozilla.UITour.setSearchTerm = function(term) {
|
||||
_sendEvent('setSearchTerm', {
|
||||
term: term
|
||||
});
|
||||
};
|
||||
|
||||
Mozilla.UITour.openSearchPanel = function(callback) {
|
||||
_sendEvent('openSearchPanel', {
|
||||
callbackID: _waitForCallback(callback)
|
||||
});
|
||||
};
|
||||
|
||||
})();
|
||||
|
|
|
@ -40,6 +40,8 @@ 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/magnifier.png (../shared/magnifier.png)
|
||||
skin/classic/browser/magnifier@2x.png (../shared/magnifier@2x.png)
|
||||
skin/classic/browser/mask.png (../shared/mask.png)
|
||||
skin/classic/browser/mask@2x.png (../shared/mask@2x.png)
|
||||
skin/classic/browser/menuPanel.png
|
||||
|
|
|
@ -58,6 +58,8 @@ browser.jar:
|
|||
skin/classic/browser/notification-16@2x.png
|
||||
skin/classic/browser/notification-64.png
|
||||
skin/classic/browser/notification-64@2x.png
|
||||
skin/classic/browser/magnifier.png (../shared/magnifier.png)
|
||||
skin/classic/browser/magnifier@2x.png (../shared/magnifier@2x.png)
|
||||
skin/classic/browser/mask.png (../shared/mask.png)
|
||||
skin/classic/browser/mask@2x.png (../shared/mask@2x.png)
|
||||
skin/classic/browser/menuPanel.png
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 371 B |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 689 B |
|
@ -45,6 +45,8 @@ browser.jar:
|
|||
skin/classic/browser/keyhole-forward-mask.svg
|
||||
skin/classic/browser/KUI-background.png
|
||||
skin/classic/browser/livemark-folder.png
|
||||
skin/classic/browser/magnifier.png (../shared/magnifier.png)
|
||||
skin/classic/browser/magnifier@2x.png (../shared/magnifier@2x.png)
|
||||
skin/classic/browser/mask.png (../shared/mask.png)
|
||||
skin/classic/browser/mask@2x.png (../shared/mask@2x.png)
|
||||
skin/classic/browser/menu-back.png
|
||||
|
@ -483,6 +485,8 @@ browser.jar:
|
|||
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)
|
||||
skin/classic/aero/browser/magnifier.png (../shared/magnifier.png)
|
||||
skin/classic/aero/browser/magnifier@2x.png (../shared/magnifier@2x.png)
|
||||
skin/classic/aero/browser/mask.png (../shared/mask.png)
|
||||
skin/classic/aero/browser/mask@2x.png (../shared/mask@2x.png)
|
||||
skin/classic/aero/browser/menu-back.png (menu-back-aero.png)
|
||||
|
|
|
@ -1831,3 +1831,32 @@ Example
|
|||
"lastActiveBranch": "control"
|
||||
}
|
||||
|
||||
org.mozilla.uitour.treatment
|
||||
----------------------------
|
||||
|
||||
Daily measurement reporting information about treatment tagging done
|
||||
by the UITour module.
|
||||
|
||||
Version 1
|
||||
^^^^^^^^^
|
||||
|
||||
Daily text values in the following properties:
|
||||
|
||||
<tag>:
|
||||
Array of discrete strings corresponding to calls for setTreatmentTag(tag, value).
|
||||
|
||||
Example
|
||||
^^^^^^^
|
||||
|
||||
::
|
||||
|
||||
"org.mozilla.uitour.treatment": {
|
||||
"_v": 1,
|
||||
"treatment": [
|
||||
"optin",
|
||||
"optin-DNT"
|
||||
],
|
||||
"another-tag": [
|
||||
"foobar-value"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ user_pref("shell.checkDefaultClient", false);
|
|||
user_pref("browser.warnOnQuit", false);
|
||||
user_pref("accessibility.typeaheadfind.autostart", false);
|
||||
user_pref("javascript.options.showInConsole", true);
|
||||
user_pref("devtools.browsertoolbox.panel", "jsdebugger");
|
||||
user_pref("devtools.errorconsole.enabled", true);
|
||||
user_pref("devtools.debugger.remote-port", 6023);
|
||||
user_pref("layout.debug.enable_data_xbl", true);
|
||||
|
|
|
@ -3905,16 +3905,7 @@ nsNavHistory::RowToResult(mozIStorageValueArray* aRow,
|
|||
|
||||
if (IsQueryURI(url)) {
|
||||
// Special case "place:" URIs: turn them into containers.
|
||||
nsRefPtr<nsNavHistoryResultNode> resultNode;
|
||||
rv = QueryRowToResult(itemId, url, title, accessCount, time, favicon,
|
||||
getter_AddRefs(resultNode));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
if (itemId != -1) {
|
||||
rv = aRow->GetUTF8String(nsNavBookmarks::kGetChildrenIndex_Guid,
|
||||
resultNode->mBookmarkGuid);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We should never expose the history title for query nodes if the
|
||||
// bookmark-item's title is set to null (the history title may be the
|
||||
// query string without the place: prefix). Thus we call getItemTitle
|
||||
|
@ -3923,7 +3914,18 @@ nsNavHistory::RowToResult(mozIStorageValueArray* aRow,
|
|||
nsNavBookmarks *bookmarks = nsNavBookmarks::GetBookmarksService();
|
||||
NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
rv = bookmarks->GetItemTitle(itemId, resultNode->mTitle);
|
||||
rv = bookmarks->GetItemTitle(itemId, title);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsRefPtr<nsNavHistoryResultNode> resultNode;
|
||||
rv = QueryRowToResult(itemId, url, title, accessCount, time, favicon,
|
||||
getter_AddRefs(resultNode));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
if (itemId != -1) {
|
||||
rv = aRow->GetUTF8String(nsNavBookmarks::kGetChildrenIndex_Guid,
|
||||
resultNode->mBookmarkGuid);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
// Test that result node for folder shortcuts get the target folder title if
|
||||
// the shortcut itself has no title set.
|
||||
add_task(function* () {
|
||||
let shortcutInfo = yield PlacesUtils.bookmarks.insert({
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "place:folder=TOOLBAR"
|
||||
});
|
||||
|
||||
let unfiledRoot =
|
||||
PlacesUtils.getFolderContents(PlacesUtils.unfiledBookmarksFolderId).root;
|
||||
let shortcutNode = unfiledRoot.getChild(unfiledRoot.childCount - 1);
|
||||
Assert.equal(shortcutNode.bookmarkGuid, shortcutInfo.guid);
|
||||
|
||||
let toolbarInfo =
|
||||
yield PlacesUtils.bookmarks.fetch(PlacesUtils.bookmarks.toolbarGuid);
|
||||
Assert.equal(shortcutNode.title, toolbarInfo.title);
|
||||
|
||||
unfiledRoot.containerOpen = false;
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
|
@ -56,6 +56,7 @@ skip-if = os == "android"
|
|||
[test_486978_sort_by_date_queries.js]
|
||||
[test_536081.js]
|
||||
[test_1085291.js]
|
||||
[test_1105208.js]
|
||||
[test_adaptive.js]
|
||||
# Bug 676989: test hangs consistently on Android
|
||||
skip-if = os == "android"
|
||||
|
|
|
@ -8,33 +8,27 @@ Components.utils.import("resource://gre/modules/devtools/event-emitter.js");
|
|||
|
||||
const EXPORTED_SYMBOLS = ["Simulator"];
|
||||
|
||||
function getVersionNumber(fullVersion) {
|
||||
return fullVersion.match(/(\d+\.\d+)/)[0];
|
||||
}
|
||||
|
||||
const Simulator = {
|
||||
_simulators: {},
|
||||
|
||||
register: function (label, simulator) {
|
||||
register: function (name, simulator) {
|
||||
// simulators register themselves as "Firefox OS X.Y"
|
||||
let versionNumber = getVersionNumber(label);
|
||||
this._simulators[versionNumber] = simulator;
|
||||
this.emit("register", versionNumber);
|
||||
this._simulators[name] = simulator;
|
||||
this.emit("register", name);
|
||||
},
|
||||
|
||||
unregister: function (label) {
|
||||
let versionNumber = getVersionNumber(label);
|
||||
delete this._simulators[versionNumber];
|
||||
this.emit("unregister", versionNumber);
|
||||
unregister: function (name) {
|
||||
delete this._simulators[name];
|
||||
this.emit("unregister", name);
|
||||
},
|
||||
|
||||
availableVersions: function () {
|
||||
availableNames: function () {
|
||||
return Object.keys(this._simulators).sort();
|
||||
},
|
||||
|
||||
getByVersion: function (version) {
|
||||
return this._simulators[version];
|
||||
}
|
||||
getByName: function (name) {
|
||||
return this._simulators[name];
|
||||
},
|
||||
};
|
||||
|
||||
EventEmitter.decorate(Simulator);
|
||||
|
|
Загрузка…
Ссылка в новой задаче