зеркало из https://github.com/mozilla/gecko-dev.git
merge fx-team to mozilla-central a=merge
This commit is contained in:
Коммит
9a10019bbf
|
@ -144,7 +144,7 @@ skip-if = true
|
|||
[test-timer.js]
|
||||
[test-traceback.js]
|
||||
[test-ui-action-button.js]
|
||||
skip-if = (os == "linux" || os == "win") && debug
|
||||
skip-if = debug || asan # Bug 1208727
|
||||
[test-ui-frame.js]
|
||||
[test-ui-id.js]
|
||||
[test-ui-sidebar-private-browsing.js]
|
||||
|
|
|
@ -21,7 +21,7 @@ const DATABASE_NAME = "abouthome";
|
|||
const DATABASE_VERSION = 1;
|
||||
const DATABASE_STORAGE = "persistent";
|
||||
const SNIPPETS_OBJECTSTORE_NAME = "snippets";
|
||||
var searchText, findKey;
|
||||
var searchText;
|
||||
|
||||
// This global tracks if the page has been set up before, to prevent double inits
|
||||
var gInitialized = false;
|
||||
|
@ -55,14 +55,20 @@ window.addEventListener("pagehide", function() {
|
|||
window.removeEventListener("resize", fitToWidth);
|
||||
});
|
||||
|
||||
// make Accel+f focus the search box
|
||||
window.addEventListener("keypress", ev => {
|
||||
// Make Ctrl/Cmd+f focus the search box.
|
||||
let modifiers = ev.ctrlKey + ev.altKey + ev.shiftKey + ev.metaKey;
|
||||
if (ev.getModifierState("Accel") && modifiers == 1 && ev.key == findKey) {
|
||||
// focus the search-box on keypress
|
||||
if (document.activeElement.id == "searchText") // unless already focussed
|
||||
return;
|
||||
|
||||
let modifiers = ev.ctrlKey + ev.altKey + ev.metaKey;
|
||||
// ignore Ctrl/Cmd/Alt, but not Shift
|
||||
// also ignore Tab, Insert, PageUp, etc., and Space
|
||||
if (modifiers != 0 || ev.charCode == 0 || ev.charCode == 32)
|
||||
return;
|
||||
|
||||
searchText.focus();
|
||||
ev.preventDefault();
|
||||
}
|
||||
// need to send the first keypress outside the search-box manually to it
|
||||
searchText.value += ev.key;
|
||||
});
|
||||
|
||||
// This object has the same interface as Map and is used to store and retrieve
|
||||
|
@ -195,7 +201,6 @@ function setupSearch()
|
|||
searchText.removeEventListener("blur", searchText_onBlur);
|
||||
searchText.removeAttribute("autofocus");
|
||||
});
|
||||
findKey = searchText.dataset.findkey;
|
||||
|
||||
if (!gContentSearchController) {
|
||||
gContentSearchController =
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
<div id="searchIcon"/>
|
||||
<input type="text" name="q" value="" id="searchText" maxlength="256"
|
||||
aria-label="&contentSearchInput.label;" autofocus="autofocus"
|
||||
dir="auto" data-findkey="&find.commandkey;"/>
|
||||
dir="auto"/>
|
||||
<input id="searchSubmit" type="button" value="" onclick="onSearchSubmit(event)"
|
||||
aria-label="&contentSearchSubmit.label;"/>
|
||||
</div>
|
||||
|
|
|
@ -420,7 +420,7 @@ var gTests = [
|
|||
}
|
||||
},
|
||||
{
|
||||
desc: "Cmd+f should focus the search box in the page",
|
||||
desc: "Pressing any key should focus the search box in the page, and send the key to it",
|
||||
setup: function () {},
|
||||
run: Task.async(function* () {
|
||||
let doc = gBrowser.selectedBrowser.contentDocument;
|
||||
|
@ -430,9 +430,10 @@ var gTests = [
|
|||
EventUtils.synthesizeMouseAtCenter(logo, {});
|
||||
isnot(searchInput, doc.activeElement, "Search input should not be the active element.");
|
||||
|
||||
EventUtils.synthesizeKey("f", { accelKey: true });
|
||||
EventUtils.synthesizeKey("a", {});
|
||||
yield promiseWaitForCondition(() => doc.activeElement === searchInput);
|
||||
is(searchInput, doc.activeElement, "Search input should be the active element.");
|
||||
is(searchInput.value, "a", "Search input should be 'a'.");
|
||||
})
|
||||
},
|
||||
{
|
||||
|
@ -491,6 +492,25 @@ var gTests = [
|
|||
is(result.pane, "paneSync", "openPreferences should be called with paneSync");
|
||||
is(result.params.urlParams.entrypoint, "abouthome", "openPreferences should be called with abouthome entrypoint");
|
||||
})
|
||||
},
|
||||
{
|
||||
desc: "Pressing Space while the Addons button is focussed should activate it",
|
||||
setup: function () {},
|
||||
run: Task.async(function* () {
|
||||
// Skip this test on Mac, because Space doesn't activate the button there.
|
||||
if (navigator.platform.indexOf("Mac") == 0) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
info("Waiting for about:addons tab to open...");
|
||||
let promiseTabOpened = BrowserTestUtils.waitForNewTab(gBrowser, "about:addons");
|
||||
let addOnsButton = gBrowser.selectedBrowser.contentDocument.getElementById("addons");
|
||||
addOnsButton.focus();
|
||||
EventUtils.synthesizeKey(" ", {});
|
||||
let tab = yield promiseTabOpened;
|
||||
is(tab.linkedBrowser.currentURI.spec, "about:addons", "Should have seen the about:addons tab");
|
||||
yield BrowserTestUtils.removeTab(tab);
|
||||
})
|
||||
}
|
||||
|
||||
];
|
||||
|
|
|
@ -757,9 +757,7 @@ body[platform="win"] .share-service-dropdown.overflow > .dropdown-menu-item {
|
|||
}
|
||||
|
||||
.context-url-view-wrapper {
|
||||
/* 18px for indent of .text-chat-arrow, 1px for border of .text-chat-entry > p,
|
||||
0.5rem for padding of .text-chat-entry > p */
|
||||
padding: calc(18px - 1px - 0.5rem);
|
||||
padding: 12px;
|
||||
margin-bottom: 0.5em;
|
||||
background-color: #dbf7ff;
|
||||
}
|
||||
|
@ -1182,32 +1180,44 @@ body[platform="win"] .share-service-dropdown.overflow > .dropdown-menu-item {
|
|||
background: white;
|
||||
}
|
||||
|
||||
.text-chat-box {
|
||||
flex: 0 0 auto;
|
||||
max-height: 40px;
|
||||
min-height: 40px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.text-chat-entries {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.text-chat-entry {
|
||||
.text-chat-entry,
|
||||
.text-chat-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-right: .2em;
|
||||
margin-bottom: .5em;
|
||||
text-align: start;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: flex-start;
|
||||
align-content: stretch;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .text-chat-entry {
|
||||
margin-right: auto;
|
||||
margin-left: .2em;
|
||||
.text-chat-entry {
|
||||
/* aligns paragraph to side where reading starts from */
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
/* Sent text chat entries should be on the right */
|
||||
.text-chat-entry.sent {
|
||||
/* aligns paragraph to right side */
|
||||
justify-content: flex-end;
|
||||
margin-left: 0;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.text-chat-entry.received {
|
||||
margin-left: 4px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .text-chat-entry.sent {
|
||||
margin-left: 5px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
|
||||
html[dir="rtl"] .text-chat-entry.received {
|
||||
margin-left: 0;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
/* If you change this entry, check it doesn't affect the "special" text
|
||||
|
@ -1217,57 +1227,34 @@ html[dir="rtl"] .text-chat-entry {
|
|||
z-index: 10;
|
||||
/* Drop the default margins from the 'p' element. */
|
||||
margin: 0;
|
||||
padding: .5rem;
|
||||
padding: .8rem;
|
||||
/* leave some room for the chat bubble arrow */
|
||||
max-width: 80%;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #5cccee;
|
||||
max-width: 70%;
|
||||
border-radius: 15px;
|
||||
border: 1px solid #5cccee;
|
||||
background: #fff;
|
||||
word-wrap: break-word;
|
||||
flex: 0 1 auto;
|
||||
align-self: auto;
|
||||
}
|
||||
|
||||
.text-chat-entry.sent > p,
|
||||
.text-chat-entry.received > p {
|
||||
background: #fff;
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.text-chat-entry.sent > p {
|
||||
border-radius: 15px;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.text-chat-entry.received > p {
|
||||
border-radius: 15px;
|
||||
border-top-left-radius: 0;
|
||||
border-color: #d8d8d8;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .text-chat-entry.sent > p {
|
||||
border-radius: 15px;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 15px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .text-chat-entry.received > p {
|
||||
border-radius: 15px;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
||||
.text-chat-entry.received > p {
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.text-chat-entry.sent > p {
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.text-chat-entry.received {
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.text-chat-entry.received > p {
|
||||
border-color: #d8d8d8;
|
||||
border-top-left-radius: 15px;
|
||||
}
|
||||
|
||||
/* Text chat entry timestamp */
|
||||
|
@ -1280,38 +1267,34 @@ html[dir="rtl"] .text-chat-entry.received > p {
|
|||
align-self: center;
|
||||
}
|
||||
|
||||
/* Sent text chat entries should be on the right */
|
||||
.text-chat-entry.sent {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.received > .text-chat-entry-timestamp {
|
||||
order: 2;
|
||||
}
|
||||
|
||||
/* Pseudo element used to cover part between chat bubble and chat arrow. */
|
||||
/* Pseudo element used to cover part between chat bubble and chat arrow.
|
||||
dimensions may change for each position */
|
||||
.text-chat-entry > p:after {
|
||||
position: absolute;
|
||||
background: #fff;
|
||||
content: "";
|
||||
/* default dimensions */
|
||||
width: 6px;
|
||||
height: 7px;
|
||||
}
|
||||
|
||||
.text-chat-entry.sent > p:after {
|
||||
right: -2px;
|
||||
right: -1px;
|
||||
bottom: 0;
|
||||
width: 15px;
|
||||
height: 9px;
|
||||
border-top-left-radius: 15px;
|
||||
border-top-right-radius: 22px;
|
||||
width: 7px;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
|
||||
.text-chat-entry.received > p:after {
|
||||
top: 0;
|
||||
left: -2px;
|
||||
width: 15px;
|
||||
height: 9px;
|
||||
border-bottom-left-radius: 22px;
|
||||
border-bottom-right-radius: 15px;
|
||||
left: -1px;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .text-chat-entry.sent > p:after {
|
||||
|
@ -1319,16 +1302,13 @@ html[dir="rtl"] .text-chat-entry.sent > p:after {
|
|||
right: auto;
|
||||
left: -1px;
|
||||
bottom: 0;
|
||||
width: 15px;
|
||||
height: 9px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .text-chat-entry.received > p:after {
|
||||
/* Reset */
|
||||
left: auto;
|
||||
top: 0;
|
||||
right: -1px;
|
||||
width: 15px;
|
||||
width: 9px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
|
@ -1374,7 +1354,7 @@ html[dir="rtl"] .text-chat-entry.received .text-chat-arrow {
|
|||
margin-left: -10px;
|
||||
}
|
||||
|
||||
.text-chat-entry.special.room-name {
|
||||
.text-chat-header.special.room-name {
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
text-align: start;
|
||||
|
@ -1383,7 +1363,7 @@ html[dir="rtl"] .text-chat-entry.received .text-chat-arrow {
|
|||
margin-right: 0;
|
||||
}
|
||||
|
||||
.text-chat-entry.special.room-name p {
|
||||
.text-chat-header.special.room-name p {
|
||||
background: #dbf7ff;
|
||||
max-width: 100%;
|
||||
/* 18px for indent of .text-chat-arrow, 1px for border of .text-chat-entry > p,
|
||||
|
@ -1391,12 +1371,16 @@ html[dir="rtl"] .text-chat-entry.received .text-chat-arrow {
|
|||
padding: calc(18px - 1px - 0.5rem);
|
||||
}
|
||||
|
||||
.text-chat-entry.special > p {
|
||||
.text-chat-header.special > p {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.text-chat-box {
|
||||
margin: auto;
|
||||
flex: 0 0 auto;
|
||||
max-height: 40px;
|
||||
min-height: 40px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.text-chat-box > form > input {
|
||||
|
|
|
@ -81,7 +81,7 @@ loop.shared.views.chat = (function(mozL10n) {
|
|||
|
||||
render: function() {
|
||||
return (
|
||||
React.createElement("div", {className: "text-chat-entry special room-name"},
|
||||
React.createElement("div", {className: "text-chat-header special room-name"},
|
||||
React.createElement("p", null, mozL10n.get("rooms_welcome_title", {conversationName: this.props.message}))
|
||||
)
|
||||
);
|
||||
|
|
|
@ -81,7 +81,7 @@ loop.shared.views.chat = (function(mozL10n) {
|
|||
|
||||
render: function() {
|
||||
return (
|
||||
<div className="text-chat-entry special room-name">
|
||||
<div className="text-chat-header special room-name">
|
||||
<p>{mozL10n.get("rooms_welcome_title", {conversationName: this.props.message})}</p>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -580,7 +580,7 @@ describe("loop.shared.views.TextChatView", function () {
|
|||
var node = view.getDOMNode();
|
||||
expect(node.querySelector(".text-chat-entries")).to.not.eql(null);
|
||||
|
||||
var entries = node.querySelectorAll(".text-chat-entry");
|
||||
var entries = node.querySelectorAll(".text-chat-header");
|
||||
expect(entries.length).eql(1);
|
||||
expect(entries[0].classList.contains("special")).eql(true);
|
||||
expect(entries[0].classList.contains("room-name")).eql(true);
|
||||
|
|
|
@ -37,7 +37,3 @@
|
|||
<!ENTITY abouthome.appsButton2.label "Apps">
|
||||
<!ENTITY abouthome.downloadsButton.label "Downloads">
|
||||
<!ENTITY abouthome.syncButton.label "&syncBrand.shortName.label;">
|
||||
|
||||
<!-- LOCALIZATION NOTE (find.commandkey): This is the key to use in
|
||||
conjunction with accel (Command on Mac or Ctrl on other platforms) to find -->
|
||||
<!ENTITY find.commandkey "f">
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
|
||||
var Ci = Components.interfaces, Cc = Components.classes, Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://services-common/utils.js"); /*global: CommonUtils */
|
||||
Cu.import("resource://gre/modules/Messaging.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm")
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/TelemetryStopwatch.jsm");
|
||||
|
||||
|
@ -49,39 +50,97 @@ var Logins = {
|
|||
_filterTimer: null,
|
||||
_selectedLogin: null,
|
||||
|
||||
_getLogins: function() {
|
||||
let logins;
|
||||
// Load the logins list, displaying interstitial UI (see
|
||||
// #logins-list-loading-body) while loading. There are careful
|
||||
// jank-avoiding measures taken in this function; be careful when
|
||||
// modifying it!
|
||||
//
|
||||
// Returns a Promise that resolves to the list of logins, ordered by
|
||||
// hostname.
|
||||
_promiseLogins: function() {
|
||||
let contentBody = document.getElementById("content-body");
|
||||
let emptyBody = document.getElementById("empty-body");
|
||||
let filterIcon = document.getElementById("filter-button");
|
||||
|
||||
let showSpinner = () => {
|
||||
this._toggleListBody(true);
|
||||
emptyBody.classList.add("hidden");
|
||||
};
|
||||
|
||||
let getAllLogins = () => {
|
||||
let logins = [];
|
||||
try {
|
||||
TelemetryStopwatch.start("PWMGR_ABOUT_LOGINS_GET_ALL_LOGINS_MS");
|
||||
logins = Services.logins.getAllLogins();
|
||||
TelemetryStopwatch.finish("PWMGR_ABOUT_LOGINS_GET_ALL_LOGINS_MS");
|
||||
} catch(e) {
|
||||
// Master password was not entered
|
||||
debug("Master password permissions error: " + e);
|
||||
logins = [];
|
||||
}
|
||||
this._toggleListBody(false);
|
||||
|
||||
if (!logins.length) {
|
||||
emptyBody.classList.remove("hidden");
|
||||
|
||||
filterIcon.classList.add("hidden");
|
||||
contentBody.classList.add("hidden");
|
||||
} else {
|
||||
emptyBody.classList.add("hidden");
|
||||
|
||||
filterIcon.classList.remove("hidden");
|
||||
// It's likely that the Master Password was not entered; give
|
||||
// a hint to the next person.
|
||||
throw new Error("Possible Master Password permissions error: " + e.toString());
|
||||
}
|
||||
|
||||
logins.sort((a, b) => a.hostname.localeCompare(b.hostname));
|
||||
return this._logins = logins;
|
||||
|
||||
return logins;
|
||||
};
|
||||
|
||||
let hideSpinner = (logins) => {
|
||||
this._toggleListBody(false);
|
||||
|
||||
if (!logins.length) {
|
||||
contentBody.classList.add("hidden");
|
||||
filterIcon.classList.add("hidden");
|
||||
emptyBody.classList.remove("hidden");
|
||||
} else {
|
||||
contentBody.classList.remove("hidden");
|
||||
emptyBody.classList.add("hidden");
|
||||
}
|
||||
|
||||
return logins;
|
||||
};
|
||||
|
||||
// Return a promise that is resolved after a paint.
|
||||
let waitForPaint = () => {
|
||||
// We're changing 'display'. We need to wait for the new value to take
|
||||
// effect; otherwise, we'll block and never paint a change. Since
|
||||
// requestAnimationFrame callback is generally triggered *before* any
|
||||
// style flush and layout, we wait for two animation frames. This
|
||||
// approach was cribbed from
|
||||
// https://dxr.mozilla.org/mozilla-central/rev/5abe3c4deab94270440422c850bbeaf512b1f38d/browser/base/content/browser-fullScreen.js?offset=0#469.
|
||||
return new Promise(function(resolve, reject) {
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(() => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// getAllLogins janks the main-thread. We need to paint before that jank;
|
||||
// by throwing the janky load onto the next tick, we paint the spinner; the
|
||||
// spinner is CSS animated off-main-thread.
|
||||
return Promise.resolve()
|
||||
.then(showSpinner)
|
||||
.then(waitForPaint)
|
||||
.then(getAllLogins)
|
||||
.then(hideSpinner);
|
||||
},
|
||||
|
||||
// Reload the logins list, displaying interstitial UI while loading.
|
||||
// Update the stored and displayed list upon completion.
|
||||
_reloadList: function() {
|
||||
this._promiseLogins()
|
||||
.then((logins) => {
|
||||
this._logins = logins;
|
||||
this._loadList(logins);
|
||||
})
|
||||
.catch((e) => {
|
||||
// There's no way to recover from errors, sadly. Log and make
|
||||
// it obvious that something is up.
|
||||
this._logins = [];
|
||||
debug("Failed to _reloadList!");
|
||||
Cu.reportError(e);
|
||||
});
|
||||
},
|
||||
|
||||
_toggleListBody: function(isLoading) {
|
||||
|
@ -95,7 +154,6 @@ var Logins = {
|
|||
loadingBody.classList.add("hidden");
|
||||
contentBody.classList.remove("hidden");
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
init: function () {
|
||||
|
@ -105,8 +163,6 @@ var Logins = {
|
|||
document.getElementById("update-btn").addEventListener("click", this._onSaveEditLogin.bind(this), false);
|
||||
document.getElementById("password-btn").addEventListener("click", this._onPasswordBtn.bind(this), false);
|
||||
|
||||
this._loadList(this._getLogins());
|
||||
|
||||
let filterInput = document.getElementById("filter-input");
|
||||
let filterContainer = document.getElementById("filter-input-container");
|
||||
|
||||
|
@ -147,6 +203,8 @@ var Logins = {
|
|||
this._showList();
|
||||
|
||||
this._updatePasswordBtn(true);
|
||||
|
||||
this._reloadList();
|
||||
},
|
||||
|
||||
uninit: function () {
|
||||
|
@ -439,8 +497,7 @@ var Logins = {
|
|||
observe: function (subject, topic, data) {
|
||||
switch(topic) {
|
||||
case "passwordmgr-storage-changed": {
|
||||
// Reload logins content.
|
||||
this._loadList(this._getLogins());
|
||||
this._reloadList();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ support-files =
|
|||
basic_article.html
|
||||
desktopmode_user_agent.sjs
|
||||
devicesearch.xml
|
||||
head.js
|
||||
session_formdata_sample.html
|
||||
simpleservice.xml
|
||||
video_controls.html
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function promiseBrowserEvent(browser, eventType) {
|
||||
return new Promise((resolve) => {
|
||||
function handle(event) {
|
||||
// Since we'll be redirecting, don't make assumptions about the given URL and the loaded URL
|
||||
if (event.target != browser.contentDocument || event.target.location.href == "about:blank") {
|
||||
info("Skipping spurious '" + eventType + "' event" + " for " + event.target.location.href);
|
||||
return;
|
||||
}
|
||||
info("Received event " + eventType + " from browser");
|
||||
browser.removeEventListener(eventType, handle, true);
|
||||
resolve(event);
|
||||
}
|
||||
|
||||
browser.addEventListener(eventType, handle, true);
|
||||
info("Now waiting for " + eventType + " event from browser");
|
||||
});
|
||||
}
|
||||
|
||||
function promiseNotification(topic) {
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
function observe(subject, topic, data) {
|
||||
info("Received " + topic + " notification from Gecko");
|
||||
Services.obs.removeObserver(observe, topic);
|
||||
resolve();
|
||||
}
|
||||
Services.obs.addObserver(observe, topic, false);
|
||||
info("Now waiting for " + topic + " notification from Gecko");
|
||||
});
|
||||
}
|
|
@ -8,11 +8,13 @@ Migrated from Robocop: https://bugzilla.mozilla.org/show_bug.cgi?id=1184186
|
|||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1136477</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://global/skin"/>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript;version=1.7">
|
||||
<script type="application/javascript;version=1.8" src="head.js"></script>
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
"use strict"
|
||||
"use strict";
|
||||
|
||||
const { interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
|
@ -31,11 +33,6 @@ Migrated from Robocop: https://bugzilla.mozilla.org/show_bug.cgi?id=1184186
|
|||
|
||||
const LoginInfo = Components.Constructor("@mozilla.org/login-manager/loginInfo;1", "nsILoginInfo", "init");
|
||||
|
||||
let BrowserApp;
|
||||
let browser;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function add_login(login) {
|
||||
let newLogin = new LoginInfo(login.hostname,
|
||||
login.formSubmitUrl,
|
||||
|
@ -48,23 +45,41 @@ Migrated from Robocop: https://bugzilla.mozilla.org/show_bug.cgi?id=1184186
|
|||
Services.logins.addLogin(newLogin);
|
||||
}
|
||||
|
||||
function password_setup() {
|
||||
add_task(function* test_passwords_list() {
|
||||
add_login(LOGIN_FIELDS);
|
||||
|
||||
// Load about:logins.
|
||||
BrowserApp = Services.wm.getMostRecentWindow("navigator:browser").BrowserApp;
|
||||
browser = BrowserApp.addTab("about:logins", { selected: true, parentId: BrowserApp.selectedTab.id }).browser;
|
||||
let BrowserApp = Services.wm.getMostRecentWindow("navigator:browser").BrowserApp;
|
||||
let browser = BrowserApp.addTab("about:logins", { selected: true, parentId: BrowserApp.selectedTab.id }).browser;
|
||||
|
||||
browser.addEventListener("load", function handle(event) {
|
||||
browser.removeEventListener("load", handle, true);
|
||||
Services.tm.mainThread.dispatch(test_passwords_list, Ci.nsIThread.DISPATCH_NORMAL);
|
||||
}, true);
|
||||
yield promiseBrowserEvent(browser, "load");
|
||||
|
||||
let logins_list_parent = browser.contentDocument.getElementById("logins-list").parentNode;
|
||||
|
||||
let waitForLoginToBeAdded = new Promise((resolve) => {
|
||||
let observer = new MutationObserver((mutations) => {
|
||||
for (let mutation of mutations) {
|
||||
for (let node of mutation.addedNodes) {
|
||||
if (node.id == 'logins-list') {
|
||||
info("Received mutation replacing 'logins-list'");
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
info("Skipping spurious mutation not replacing 'logins-list'");
|
||||
});
|
||||
observer.observe(logins_list_parent, {
|
||||
childList: true,
|
||||
});
|
||||
info("Now waiting for mutation to replace 'logins-list'");
|
||||
});
|
||||
|
||||
yield waitForLoginToBeAdded;
|
||||
|
||||
function test_passwords_list() {
|
||||
// Test that the (single) entry added in setup is correct.
|
||||
let logins_list = browser.contentDocument.getElementById("logins-list");
|
||||
|
||||
// Test that the (single) entry added in setup is correct.
|
||||
let hostname = logins_list.querySelector(".hostname");
|
||||
is(hostname.textContent, LOGIN_FIELDS.hostname, "hostname is correct");
|
||||
|
||||
|
@ -73,11 +88,7 @@ Migrated from Robocop: https://bugzilla.mozilla.org/show_bug.cgi?id=1184186
|
|||
|
||||
// Cleanup: close about:logins, opened in password_setup()
|
||||
BrowserApp.closeTab(BrowserApp.selectedTab);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
password_setup();
|
||||
});
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -11,6 +11,7 @@ Migrated from Robocop: https://bugzilla.mozilla.org/show_bug.cgi?id=1184186
|
|||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://global/skin"/>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript" src="head.js"></script>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
"use strict";
|
||||
|
@ -19,24 +20,6 @@ Migrated from Robocop: https://bugzilla.mozilla.org/show_bug.cgi?id=1184186
|
|||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function promiseBrowserEvent(browser, eventType) {
|
||||
return new Promise((resolve) => {
|
||||
function handle(event) {
|
||||
// Since we'll be redirecting, don't make assumptions about the given URL and the loaded URL
|
||||
if (event.target != browser.contentDocument || event.target.location.href == "about:blank") {
|
||||
info("Skipping spurious '" + eventType + "' event" + " for " + event.target.location.href);
|
||||
return;
|
||||
}
|
||||
info("Received event " + eventType + " from browser");
|
||||
browser.removeEventListener(eventType, handle, true);
|
||||
resolve(event);
|
||||
}
|
||||
|
||||
browser.addEventListener(eventType, handle, true);
|
||||
info("Now waiting for " + eventType + " event from browser");
|
||||
});
|
||||
}
|
||||
|
||||
// Load a custom sjs script that echos our "User-Agent" header back at us
|
||||
const TestURI = Services.io.newURI("http://mochi.test:8888/chrome/mobile/android/tests/browser/chrome/desktopmode_user_agent.sjs", null, null);
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ Migrated from Robocop: https://bugzilla.mozilla.org/show_bug.cgi?id=1184186
|
|||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://global/skin"/>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript" src="head.js"></script>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
"use strict";
|
||||
|
@ -21,24 +22,6 @@ Migrated from Robocop: https://bugzilla.mozilla.org/show_bug.cgi?id=1184186
|
|||
Cu.import("resource://gre/modules/Messaging.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
function promiseBrowserEvent(browser, eventType) {
|
||||
return new Promise((resolve) => {
|
||||
function handle(event) {
|
||||
// Since we'll be redirecting, don't make assumptions about the given URL and the loaded URL
|
||||
if (event.target != browser.contentDocument || event.target.location.href == "about:blank") {
|
||||
info("Skipping spurious '" + eventType + "' event" + " for " + event.target.location.href);
|
||||
return;
|
||||
}
|
||||
info("Received event " + eventType + " from browser");
|
||||
browser.removeEventListener(eventType, handle, true);
|
||||
resolve(event);
|
||||
}
|
||||
|
||||
browser.addEventListener(eventType, handle, true);
|
||||
info("Now waiting for " + eventType + " event from browser");
|
||||
});
|
||||
}
|
||||
|
||||
// Provide a helper to yield until we are sure the offline state has changed
|
||||
function promiseOffline(isOffline) {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
|
|
@ -11,40 +11,13 @@ Migrated from Robocop: https://bugzilla.mozilla.org/show_bug.cgi?id=1184186
|
|||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://global/skin"/>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript" src="head.js"></script>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function promiseBrowserEvent(browser, eventType) {
|
||||
return new Promise((resolve) => {
|
||||
function handle(event) {
|
||||
// Since we'll be redirecting, don't make assumptions about the given URL and the loaded URL
|
||||
if (event.target != browser.contentDocument || event.target.location.href == "about:blank") {
|
||||
info("Skipping spurious '" + eventType + "' event" + " for " + event.target.location.href);
|
||||
return;
|
||||
}
|
||||
info("Received event " + eventType + " from browser");
|
||||
browser.removeEventListener(eventType, handle, true);
|
||||
resolve(event);
|
||||
}
|
||||
|
||||
browser.addEventListener(eventType, handle, true);
|
||||
info("Now waiting for " + eventType + " event from browser");
|
||||
});
|
||||
}
|
||||
|
||||
function promiseNotification(topic) {
|
||||
return new Promise((resolve, reject) => {
|
||||
function observe(subject, topic, data) {
|
||||
Services.obs.removeObserver(observe, topic);
|
||||
resolve();
|
||||
}
|
||||
Services.obs.addObserver(observe, topic, false);
|
||||
});
|
||||
}
|
||||
|
||||
add_task(function* test_reader_view_visibility() {
|
||||
let gWin = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let BrowserApp = gWin.BrowserApp;
|
||||
|
|
|
@ -11,6 +11,7 @@ Migrated from Robocop: https://bugzilla.mozilla.org/show_bug.cgi?id=1184186
|
|||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://global/skin"/>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript" src="head.js"></script>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
"use strict";
|
||||
|
@ -38,25 +39,6 @@ function sleep(wait) {
|
|||
});
|
||||
}
|
||||
|
||||
function promiseBrowserLoaded(browser, eventType="load") {
|
||||
return new Promise((resolve, reject) => {
|
||||
dump("Wait browser event: " + eventType);
|
||||
|
||||
function handle(event) {
|
||||
if (event.target != browser.contentDocument) {
|
||||
dump("Skipping spurious '" + eventType + "' event" + " for " + event.target.location.href);
|
||||
return;
|
||||
}
|
||||
|
||||
browser.removeEventListener(eventType, handle, true);
|
||||
dump("Browser event received: " + eventType);
|
||||
resolve(event);
|
||||
}
|
||||
|
||||
browser.addEventListener(eventType, handle, true);
|
||||
});
|
||||
}
|
||||
|
||||
function queryElement(contentWindow, data) {
|
||||
let frame = contentWindow;
|
||||
if (data.hasOwnProperty("frame")) {
|
||||
|
@ -129,7 +111,7 @@ add_task(function* test_formdata() {
|
|||
// Create a new tab.
|
||||
let tab = gBrowserApp.addTab(URL);
|
||||
let browser = tab.browser;
|
||||
yield promiseBrowserLoaded(browser);
|
||||
yield promiseBrowserEvent(browser, "load");
|
||||
|
||||
// Modify form data.
|
||||
setInputValue(browser, {id: "txt", value: OUTER_VALUE});
|
||||
|
@ -184,7 +166,7 @@ add_task(function* test_formdata2() {
|
|||
// Create a new tab.
|
||||
let tab = gBrowserApp.addTab(URL);
|
||||
let browser = tab.browser;
|
||||
yield promiseBrowserLoaded(browser);
|
||||
yield promiseBrowserEvent(browser, "load");
|
||||
|
||||
// Modify form data.
|
||||
setInputValue(browser, {id: "txt", value: OUTER_VALUE});
|
||||
|
@ -205,7 +187,7 @@ add_task(function* test_formdata2() {
|
|||
// Restore the closed tab.
|
||||
let closedTabData = ss.getClosedTabs(gChromeWin)[0];
|
||||
let browser = ss.undoCloseTab(gChromeWin, closedTabData);
|
||||
yield promiseBrowserLoaded(browser);
|
||||
yield promiseBrowserEvent(browser, "load");
|
||||
|
||||
// Check the form data.
|
||||
is(getInputValue(browser, {id: "txt"}), OUTER_VALUE, "outer value restored correctly");
|
||||
|
|
Загрузка…
Ссылка в новой задаче