This commit is contained in:
Ryan VanderMeulen 2014-12-22 17:35:26 -05:00
Родитель 880c471b34 d55f7227af
Коммит f9e95a3452
139 изменённых файлов: 1573 добавлений и 1047 удалений

Просмотреть файл

@ -1662,7 +1662,7 @@ pref("loop.enabled", true);
pref("loop.server", "https://loop.services.mozilla.com/v0");
pref("loop.seenToS", "unseen");
pref("loop.gettingStarted.seen", false);
pref("loop.gettingStarted.url", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/hello/start");
pref("loop.gettingStarted.url", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/hello/start/");
pref("loop.gettingStarted.resumeOnFirstJoin", false);
pref("loop.learnMoreUrl", "https://www.firefox.com/hello/");
pref("loop.legal.ToS_url", "https://www.mozilla.org/about/legal/terms/firefox-hello/");

Просмотреть файл

@ -2,19 +2,12 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
XPCOMUtils.defineLazyGetter(this, "FxAccountsCommon", function () {
return Cu.import("resource://gre/modules/FxAccountsCommon.js", {});
});
XPCOMUtils.defineLazyModuleGetter(this, "fxaMigrator",
"resource://services-sync/FxaMigrator.jsm");
const PREF_SYNC_START_DOORHANGER = "services.sync.ui.showSyncStartDoorhanger";
const DOORHANGER_ACTIVATE_DELAY_MS = 5000;
const SYNC_MIGRATION_NOTIFICATION_TITLE = "fxa-migration";
let gFxAccounts = {
PREF_SYNC_START_DOORHANGER: "services.sync.ui.showSyncStartDoorhanger",
DOORHANGER_ACTIVATE_DELAY_MS: 5000,
SYNC_MIGRATION_NOTIFICATION_TITLE: "fxa-migration",
_initialized: false,
_inCustomizationMode: false,
@ -34,8 +27,8 @@ let gFxAccounts = {
"weave:service:login:error",
"weave:service:setup-complete",
"fxa-migration:state-changed",
FxAccountsCommon.ONVERIFIED_NOTIFICATION,
FxAccountsCommon.ONLOGOUT_NOTIFICATION
this.FxAccountsCommon.ONVERIFIED_NOTIFICATION,
this.FxAccountsCommon.ONLOGOUT_NOTIFICATION
];
},
@ -108,8 +101,8 @@ let gFxAccounts = {
observe: function (subject, topic, data) {
switch (topic) {
case FxAccountsCommon.ONVERIFIED_NOTIFICATION:
Services.prefs.setBoolPref(PREF_SYNC_START_DOORHANGER, true);
case this.FxAccountsCommon.ONVERIFIED_NOTIFICATION:
Services.prefs.setBoolPref(this.PREF_SYNC_START_DOORHANGER, true);
break;
case "weave:service:sync:start":
this.onSyncStart();
@ -131,11 +124,11 @@ let gFxAccounts = {
let showDoorhanger = false;
try {
showDoorhanger = Services.prefs.getBoolPref(PREF_SYNC_START_DOORHANGER);
showDoorhanger = Services.prefs.getBoolPref(this.PREF_SYNC_START_DOORHANGER);
} catch (e) { /* The pref might not exist. */ }
if (showDoorhanger) {
Services.prefs.clearUserPref(PREF_SYNC_START_DOORHANGER);
Services.prefs.clearUserPref(this.PREF_SYNC_START_DOORHANGER);
this.showSyncStartedDoorhanger();
}
},
@ -155,7 +148,7 @@ let gFxAccounts = {
// a short delay. Without this delay the doorhanger would not show up
// or with a too small delay show up while we're still animating the
// window.
setTimeout(() => this.onSyncStart(), DOORHANGER_ACTIVATE_DELAY_MS);
setTimeout(() => this.onSyncStart(), this.DOORHANGER_ACTIVATE_DELAY_MS);
} else {
this._inCustomizationMode = event.type == "customizationstarting";
this.updateAppMenuItem();
@ -251,12 +244,12 @@ let gFxAccounts = {
let status = null;
let label = null;
switch (this._migrationInfo.state) {
case fxaMigrator.STATE_USER_FXA:
case this.fxaMigrator.STATE_USER_FXA:
status = "migrate-signup";
label = this.strings.formatStringFromName("needUserShort",
[this.button.getAttribute("fxabrandname")], 1);
break;
case fxaMigrator.STATE_USER_FXA_VERIFIED:
case this.fxaMigrator.STATE_USER_FXA_VERIFIED:
status = "migrate-verify";
label = this.strings.formatStringFromName("needVerifiedUserShort",
[this._migrationInfo.email],
@ -270,7 +263,7 @@ let gFxAccounts = {
updateMigrationNotification: Task.async(function* () {
if (!this._migrationInfo) {
Weave.Notifications.removeAll(SYNC_MIGRATION_NOTIFICATION_TITLE);
Weave.Notifications.removeAll(this.SYNC_MIGRATION_NOTIFICATION_TITLE);
return;
}
if (gBrowser.currentURI.spec.split("?")[0] == "about:accounts") {
@ -280,7 +273,7 @@ let gFxAccounts = {
}
let note = null;
switch (this._migrationInfo.state) {
case fxaMigrator.STATE_USER_FXA: {
case this.fxaMigrator.STATE_USER_FXA: {
let msg = this.strings.GetStringFromName("needUserLong");
let upgradeLabel =
this.strings.GetStringFromName("upgradeToFxA.label");
@ -289,13 +282,13 @@ let gFxAccounts = {
note = new Weave.Notification(
undefined, msg, undefined, Weave.Notifications.PRIORITY_WARNING, [
new Weave.NotificationButton(upgradeLabel, upgradeAccessKey, () => {
fxaMigrator.createFxAccount(window);
this.fxaMigrator.createFxAccount(window);
}),
]
);
break;
}
case fxaMigrator.STATE_USER_FXA_VERIFIED: {
case this.fxaMigrator.STATE_USER_FXA_VERIFIED: {
let msg =
this.strings.formatStringFromName("needVerifiedUserLong",
[this._migrationInfo.email], 1);
@ -306,14 +299,14 @@ let gFxAccounts = {
note = new Weave.Notification(
undefined, msg, undefined, Weave.Notifications.PRIORITY_INFO, [
new Weave.NotificationButton(resendLabel, resendAccessKey, () => {
fxaMigrator.resendVerificationMail();
this.fxaMigrator.resendVerificationMail();
}),
]
);
break;
}
}
note.title = SYNC_MIGRATION_NOTIFICATION_TITLE;
note.title = this.SYNC_MIGRATION_NOTIFICATION_TITLE;
Weave.Notifications.replaceTitle(note);
}),
@ -328,7 +321,7 @@ let gFxAccounts = {
this.openSignInAgainPage("menupanel");
break;
case "migrate-signup":
fxaMigrator.createFxAccount(window);
this.fxaMigrator.createFxAccount(window);
break;
case "migrate-verify":
// Instead of using the migrator module directly here the UX calls for
@ -374,3 +367,10 @@ let gFxAccounts = {
this.openAccountsPage("reauth", { entryPoint: entryPoint });
},
};
XPCOMUtils.defineLazyGetter(gFxAccounts, "FxAccountsCommon", function () {
return Cu.import("resource://gre/modules/FxAccountsCommon.js", {});
});
XPCOMUtils.defineLazyModuleGetter(gFxAccounts, "fxaMigrator",
"resource://services-sync/FxaMigrator.jsm");

Просмотреть файл

@ -11,7 +11,7 @@ add_task(function* test() {
// Fake the state where we need an FxA user.
let buttonPromise = promiseButtonMutation();
Services.obs.notifyObservers(null, STATE_CHANGED_TOPIC,
fxaMigrator.STATE_USER_FXA);
imports.fxaMigrator.STATE_USER_FXA);
let buttonState = yield buttonPromise;
assertButtonState(buttonState, "migrate-signup", true);
Assert.ok(Weave.Notifications.notifications.some(n => {
@ -24,7 +24,7 @@ add_task(function* test() {
createInstance(Ci.nsISupportsString);
email.data = "foo@example.com";
Services.obs.notifyObservers(email, STATE_CHANGED_TOPIC,
fxaMigrator.STATE_USER_FXA_VERIFIED);
imports.fxaMigrator.STATE_USER_FXA_VERIFIED);
buttonState = yield buttonPromise;
assertButtonState(buttonState, "migrate-verify", true,
"foo@example.com not verified");

Просмотреть файл

@ -300,10 +300,16 @@ loop.roomViews = (function(mozL10n) {
);
}
case ROOM_STATES.ENDED: {
return sharedViews.FeedbackView({
feedbackStore: this.props.feedbackStore,
onAfterFeedbackReceived: this.closeWindow}
);
if (this.state.used)
return sharedViews.FeedbackView({
feedbackStore: this.props.feedbackStore,
onAfterFeedbackReceived: this.closeWindow}
);
// In case the room was not used (no one was here), we
// bypass the feedback form.
this.closeWindow();
return null;
}
default: {
return (

Просмотреть файл

@ -300,10 +300,16 @@ loop.roomViews = (function(mozL10n) {
/>;
}
case ROOM_STATES.ENDED: {
return <sharedViews.FeedbackView
feedbackStore={this.props.feedbackStore}
onAfterFeedbackReceived={this.closeWindow}
/>;
if (this.state.used)
return <sharedViews.FeedbackView
feedbackStore={this.props.feedbackStore}
onAfterFeedbackReceived={this.closeWindow}
/>;
// In case the room was not used (no one was here), we
// bypass the feedback form.
this.closeWindow();
return null;
}
default: {
return (

Просмотреть файл

@ -67,7 +67,12 @@ loop.store.ActiveRoomStore = (function() {
roomState: ROOM_STATES.INIT,
audioMuted: false,
videoMuted: false,
failureReason: undefined
failureReason: undefined,
// Tracks if the room has been used during this
// session. 'Used' means at least one call has been placed
// with it. Entering and leaving the room without seeing
// anyone is not considered as 'used'
used: false
};
},
@ -361,7 +366,10 @@ loop.store.ActiveRoomStore = (function() {
* Handles recording when a remote peer has connected to the servers.
*/
remotePeerConnected: function() {
this.setStoreState({roomState: ROOM_STATES.HAS_PARTICIPANTS});
this.setStoreState({
roomState: ROOM_STATES.HAS_PARTICIPANTS,
used: true
});
// We've connected with a third-party, therefore stop displaying the ToS etc.
this._mozLoop.setLoopPref("seenToS", "seen");

Просмотреть файл

@ -115,14 +115,20 @@ loop.standaloneRoomViews = (function(mozL10n) {
);
}
case ROOM_STATES.ENDED: {
return (
React.DOM.div({className: "ended-conversation"},
sharedViews.FeedbackView({
feedbackStore: this.props.feedbackStore,
onAfterFeedbackReceived: this.onFeedbackSent}
if (this.props.roomUsed)
return (
React.DOM.div({className: "ended-conversation"},
sharedViews.FeedbackView({
feedbackStore: this.props.feedbackStore,
onAfterFeedbackReceived: this.onFeedbackSent}
)
)
)
);
);
// In case the room was not used (no one was here), we
// bypass the feedback form.
this.onFeedbackSent();
return null;
}
case ROOM_STATES.FAILED: {
return (
@ -362,7 +368,8 @@ loop.standaloneRoomViews = (function(mozL10n) {
joinRoom: this.joinRoom,
helper: this.props.helper,
activeRoomStore: this.props.activeRoomStore,
feedbackStore: this.props.feedbackStore}),
feedbackStore: this.props.feedbackStore,
roomUsed: this.state.used}),
React.DOM.div({className: "video-layout-wrapper"},
React.DOM.div({className: "conversation room-conversation"},
React.DOM.h2({className: "room-name"}, this.state.roomName),

Просмотреть файл

@ -115,14 +115,20 @@ loop.standaloneRoomViews = (function(mozL10n) {
);
}
case ROOM_STATES.ENDED: {
return (
<div className="ended-conversation">
<sharedViews.FeedbackView
feedbackStore={this.props.feedbackStore}
onAfterFeedbackReceived={this.onFeedbackSent}
/>
</div>
);
if (this.props.roomUsed)
return (
<div className="ended-conversation">
<sharedViews.FeedbackView
feedbackStore={this.props.feedbackStore}
onAfterFeedbackReceived={this.onFeedbackSent}
/>
</div>
);
// In case the room was not used (no one was here), we
// bypass the feedback form.
this.onFeedbackSent();
return null;
}
case ROOM_STATES.FAILED: {
return (
@ -362,7 +368,8 @@ loop.standaloneRoomViews = (function(mozL10n) {
joinRoom={this.joinRoom}
helper={this.props.helper}
activeRoomStore={this.props.activeRoomStore}
feedbackStore={this.props.feedbackStore} />
feedbackStore={this.props.feedbackStore}
roomUsed={this.state.used} />
<div className="video-layout-wrapper">
<div className="conversation room-conversation">
<h2 className="room-name">{this.state.roomName}</h2>

Просмотреть файл

@ -64,6 +64,7 @@ describe("loop.roomViews", function () {
audioMuted: false,
videoMuted: false,
failureReason: undefined,
used: false,
foo: "bar"
});
});
@ -355,13 +356,28 @@ describe("loop.roomViews", function () {
it("should render the FeedbackView if roomState is `ENDED`",
function() {
activeRoomStore.setStoreState({roomState: ROOM_STATES.ENDED});
activeRoomStore.setStoreState({
roomState: ROOM_STATES.ENDED,
used: true
});
view = mountTestComponent();
TestUtils.findRenderedComponentWithType(view,
loop.shared.views.FeedbackView);
});
it("should NOT render the FeedbackView if the room has not been used",
function() {
activeRoomStore.setStoreState({
roomState: ROOM_STATES.ENDED,
used: false
});
view = mountTestComponent();
expect(view.getDOMNode()).eql(null);
});
});
describe("Mute", function() {

Просмотреть файл

@ -300,7 +300,10 @@ describe("loop.standaloneRoomViews", function() {
describe("Feedback", function() {
beforeEach(function() {
activeRoomStore.setStoreState({roomState: ROOM_STATES.ENDED});
activeRoomStore.setStoreState({
roomState: ROOM_STATES.ENDED,
used: true
});
});
it("should display a feedback form when the user leaves the room",
@ -318,6 +321,13 @@ describe("loop.standaloneRoomViews", function() {
sinon.assert.calledOnce(dispatch);
sinon.assert.calledWithExactly(dispatch, new sharedActions.FeedbackComplete());
});
it("should NOT display a feedback form if the room has not been used",
function() {
activeRoomStore.setStoreState({used: false});
expect(view.getDOMNode().querySelector(".faces")).eql(null);
});
});
describe("Mute", function() {

Просмотреть файл

@ -15,6 +15,8 @@
<script type="application/javascript"
src="chrome://browser/content/preferences/in-content/search.js"/>
<stringbundle id="engineManagerBundle" src="chrome://browser/locale/engineManager.properties"/>
<hbox id="header-search"
class="header"
hidden="true"

Просмотреть файл

@ -80,7 +80,7 @@
<separator class="thin"/>
<hbox pack="start" style="margin-bottom: 1em">
<hbox pack="start">
<label id="addEngines" class="text-link" value="&addMoreSearchEngines.label;"
onclick="if (event.button == 0) { Services.wm.getMostRecentWindow('navigator:browser').BrowserSearch.loadAddEngines(); }"/>
</hbox>

Просмотреть файл

@ -645,6 +645,8 @@
this.destroy();
]]></destructor>
<field name="_ignoreFocus">false</field>
<method name="selectEngine">
<body><![CDATA[
// Override this method to avoid accidentally changing the default
@ -688,16 +690,42 @@
<handlers>
<handler event="input" action="this.inputChanged();"/>
<handler event="drop" action="this.inputChanged();"/>
<handler event="focus">
<handler event="blur">
<![CDATA[
if (this._textbox.value)
this.openSuggestionsPanel();
// If the input field is still focused then a different window has
// received focus, ignore the next focus event.
this._ignoreFocus = (document.activeElement == this._textbox.inputField);
]]></handler>
<handler event="click">
<handler event="focus">
<![CDATA[
if (event.originalTarget.getAttribute("anonid") == "searchbar-search-button")
if (this._ignoreFocus) {
// This window has been re-focused, don't show the suggestions
this._ignoreFocus = false;
return;
}
// Don't open the suggestions if there is no text in the textbox.
if (!this._textbox.value)
return;
// Don't open the suggestions if the mouse was used to focus the
// textbox, that will be taken care of in the click handler.
if (Services.focus.getLastFocusMethod(window) == Services.focus.FLAG_BYMOUSE)
return;
this.openSuggestionsPanel();
]]></handler>
<handler event="click" button="0">
<![CDATA[
// Open the suggestions whenever clicking on the search icon or if there
// is text in the textbox.
if (event.originalTarget.getAttribute("anonid") == "searchbar-search-button" ||
this._textbox.value) {
this.openSuggestionsPanel(true);
}
]]></handler>
</handlers>

Просмотреть файл

@ -37,3 +37,5 @@ skip-if = e10s # Bug ?????? - Test uses load event and checks event.target.
skip-if = e10s # Bug ?????? - some issue with progress listeners [JavaScript Error: "req.originalURI is null" {file: "chrome://mochitests/content/browser/browser/components/search/test/browser_bing_behavior.js" line: 127}]
[browser_abouthome_behavior.js]
skip-if = e10s || true # Bug ??????, Bug 1100301 - leaks windows until shutdown when --run-by-dir
[browser_searchbar_openpopup.js]
skip-if = os == "linux" || e10s # Linux has different focus behaviours and e10s seems to have timing issues.

Просмотреть файл

@ -0,0 +1,297 @@
// Tests that the suggestion popup appears at the right times in response to
// focus and clicks.
const searchbar = document.getElementById("searchbar");
const searchIcon = document.getAnonymousElementByAttribute(searchbar, "anonid", "searchbar-search-button");
const textbox = searchbar._textbox;
const searchPopup = document.getElementById("PopupSearchAutoComplete");
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);
info("Search engine removed: " + basename);
});
resolve(engine);
},
onError: function (errCode) {
ok(false, "addEngine failed with error code " + errCode);
reject();
}
});
}
});
});
}
add_task(function* init() {
yield promiseNewEngine("testEngine.xml");
});
// Adds a task that shouldn't show the search suggestions popup.
function add_no_popup_task(task) {
add_task(function*() {
let sawPopup = false;
function listener() {
sawPopup = true;
}
info("Entering test " + task.name);
searchPopup.addEventListener("popupshowing", listener, false);
yield Task.spawn(task);
searchPopup.removeEventListener("popupshowing", listener, false);
ok(!sawPopup, "Shouldn't have seen the suggestions popup");
info("Leaving test " + task.name);
});
}
// Simulates the full set of events for a context click
function context_click(target) {
for (let event of ["mousedown", "contextmenu", "mouseup"])
EventUtils.synthesizeMouseAtCenter(target, { type: event, button: 2 });
}
// Right clicking the icon should not open the popup.
add_no_popup_task(function* open_icon_context() {
gURLBar.focus();
let toolbarPopup = document.getElementById("toolbar-context-menu");
let promise = promiseEvent(toolbarPopup, "popupshown");
context_click(searchIcon);
yield promise;
promise = promiseEvent(toolbarPopup, "popuphidden");
toolbarPopup.hidePopup();
yield promise;
});
// With no text in the search box left clicking the icon should open the popup.
add_task(function* open_empty() {
gURLBar.focus();
let promise = promiseEvent(searchPopup, "popupshown");
info("Clicking icon");
EventUtils.synthesizeMouseAtCenter(searchIcon, {});
yield promise;
is(searchPopup.getAttribute("showonlysettings"), "true", "Should only show the settings");
promise = promiseEvent(searchPopup, "popuphidden");
info("Hiding popup");
searchPopup.hidePopup();
yield promise;
});
// With no text in the search box left clicking it should not open the popup.
add_no_popup_task(function* click_doesnt_open_popup() {
gURLBar.focus();
EventUtils.synthesizeMouseAtCenter(textbox, {});
is(Services.focus.focusedElement, textbox.inputField, "Should have focused the search bar");
is(textbox.selectionStart, 0, "Should have selected all of the text");
is(textbox.selectionEnd, 0, "Should have selected all of the text");
});
// Left clicking in a non-empty search box when unfocused should focus it and open the popup.
add_task(function* click_opens_popup() {
gURLBar.focus();
textbox.value = "foo";
let promise = promiseEvent(searchPopup, "popupshown");
EventUtils.synthesizeMouseAtCenter(textbox, {});
yield promise;
isnot(searchPopup.getAttribute("showonlysettings"), "true", "Should show the full popup");
is(Services.focus.focusedElement, textbox.inputField, "Should have focused the search bar");
is(textbox.selectionStart, 0, "Should have selected all of the text");
is(textbox.selectionEnd, 3, "Should have selected all of the text");
promise = promiseEvent(searchPopup, "popuphidden");
searchPopup.hidePopup();
yield promise;
textbox.value = "";
});
// Right clicking in a non-empty search box when unfocused should open the edit context menu.
add_no_popup_task(function* right_click_doesnt_open_popup() {
gURLBar.focus();
textbox.value = "foo";
let contextPopup = document.getAnonymousElementByAttribute(textbox.inputField.parentNode, "anonid", "input-box-contextmenu");
let promise = promiseEvent(contextPopup, "popupshown");
context_click(textbox);
yield promise;
is(Services.focus.focusedElement, textbox.inputField, "Should have focused the search bar");
is(textbox.selectionStart, 0, "Should have selected all of the text");
is(textbox.selectionEnd, 3, "Should have selected all of the text");
promise = promiseEvent(contextPopup, "popuphidden");
contextPopup.hidePopup();
yield promise;
textbox.value = "";
});
// Moving focus away from the search box should close the popup
add_task(function* focus_change_closes_popup() {
gURLBar.focus();
textbox.value = "foo";
let promise = promiseEvent(searchPopup, "popupshown");
EventUtils.synthesizeMouseAtCenter(textbox, {});
yield promise;
isnot(searchPopup.getAttribute("showonlysettings"), "true", "Should show the full popup");
is(Services.focus.focusedElement, textbox.inputField, "Should have focused the search bar");
is(textbox.selectionStart, 0, "Should have selected all of the text");
is(textbox.selectionEnd, 3, "Should have selected all of the text");
promise = promiseEvent(searchPopup, "popuphidden");
let promise2 = promiseEvent(searchbar, "blur");
EventUtils.synthesizeKey("VK_TAB", { shiftKey: true });
yield promise;
yield promise2;
textbox.value = "";
});
// Pressing escape should close the popup.
add_task(function* escape_closes_popup() {
gURLBar.focus();
textbox.value = "foo";
let promise = promiseEvent(searchPopup, "popupshown");
EventUtils.synthesizeMouseAtCenter(textbox, {});
yield promise;
isnot(searchPopup.getAttribute("showonlysettings"), "true", "Should show the full popup");
is(Services.focus.focusedElement, textbox.inputField, "Should have focused the search bar");
is(textbox.selectionStart, 0, "Should have selected all of the text");
is(textbox.selectionEnd, 3, "Should have selected all of the text");
promise = promiseEvent(searchPopup, "popuphidden");
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield promise;
textbox.value = "";
});
// Tabbing to the search box should open the popup if it contains text.
add_task(function* tab_opens_popup() {
gURLBar.focus();
textbox.value = "foo";
let promise = promiseEvent(searchPopup, "popupshown");
EventUtils.synthesizeKey("VK_TAB", {});
yield promise;
isnot(searchPopup.getAttribute("showonlysettings"), "true", "Should show the full popup");
is(Services.focus.focusedElement, textbox.inputField, "Should have focused the search bar");
is(textbox.selectionStart, 0, "Should have selected all of the text");
is(textbox.selectionEnd, 3, "Should have selected all of the text");
promise = promiseEvent(searchPopup, "popuphidden");
searchPopup.hidePopup();
yield promise;
textbox.value = "";
});
// Tabbing to the search box should not open the popup if it doesn't contain text.
add_no_popup_task(function* tab_doesnt_open_popup() {
gURLBar.focus();
textbox.value = "foo";
EventUtils.synthesizeKey("VK_TAB", {});
is(Services.focus.focusedElement, textbox.inputField, "Should have focused the search bar");
is(textbox.selectionStart, 0, "Should have selected all of the text");
is(textbox.selectionEnd, 3, "Should have selected all of the text");
textbox.value = "";
});
// Switching back to the window when the search box has focus from mouse should not open the popup.
add_task(function* refocus_window_doesnt_open_popup_mouse() {
gURLBar.focus();
textbox.value = "foo";
let promise = promiseEvent(searchPopup, "popupshown");
EventUtils.synthesizeMouseAtCenter(searchbar, {});
yield promise;
isnot(searchPopup.getAttribute("showonlysettings"), "true", "Should show the full popup");
is(Services.focus.focusedElement, textbox.inputField, "Should have focused the search bar");
is(textbox.selectionStart, 0, "Should have selected all of the text");
is(textbox.selectionEnd, 3, "Should have selected all of the text");
promise = promiseEvent(searchPopup, "popuphidden");
let newWin = OpenBrowserWindow();
yield new Promise(resolve => waitForFocus(resolve, newWin));
yield promise;
function listener() {
ok(false, "Should not have shown the popup.");
}
searchPopup.addEventListener("popupshowing", listener, false);
promise = promiseEvent(searchbar, "focus");
newWin.close();
yield promise;
// Wait a few ticks to allow any focus handlers to show the popup if they are going to.
yield new Promise(resolve => executeSoon(resolve));
yield new Promise(resolve => executeSoon(resolve));
yield new Promise(resolve => executeSoon(resolve));
searchPopup.removeEventListener("popupshowing", listener, false);
textbox.value = "";
});
// Switching back to the window when the search box has focus from keyboard should not open the popup.
add_task(function* refocus_window_doesnt_open_popup_keyboard() {
gURLBar.focus();
textbox.value = "foo";
let promise = promiseEvent(searchPopup, "popupshown");
EventUtils.synthesizeKey("VK_TAB", {});
yield promise;
isnot(searchPopup.getAttribute("showonlysettings"), "true", "Should show the full popup");
is(Services.focus.focusedElement, textbox.inputField, "Should have focused the search bar");
is(textbox.selectionStart, 0, "Should have selected all of the text");
is(textbox.selectionEnd, 3, "Should have selected all of the text");
promise = promiseEvent(searchPopup, "popuphidden");
let newWin = OpenBrowserWindow();
yield new Promise(resolve => waitForFocus(resolve, newWin));
yield promise;
function listener() {
ok(false, "Should not have shown the popup.");
}
searchPopup.addEventListener("popupshowing", listener, false);
promise = promiseEvent(searchbar, "focus");
newWin.close();
yield promise;
// Wait a few ticks to allow any focus handlers to show the popup if they are going to.
yield new Promise(resolve => executeSoon(resolve));
yield new Promise(resolve => executeSoon(resolve));
yield new Promise(resolve => executeSoon(resolve));
searchPopup.removeEventListener("popupshowing", listener, false);
textbox.value = "";
});

Просмотреть файл

@ -91,7 +91,7 @@ function waitForPopupShown(aPopupId, aCallback) {
registerCleanupFunction(removePopupShownListener);
}
function* promiseEvent(aTarget, aEventName, aPreventDefault) {
function promiseEvent(aTarget, aEventName, aPreventDefault) {
let deferred = Promise.defer();
aTarget.addEventListener(aEventName, function onEvent(aEvent) {
aTarget.removeEventListener(aEventName, onEvent, true);

Просмотреть файл

@ -7,6 +7,7 @@
const {Cu} = require("chrome");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Task.jsm");
var {Promise: promise} = require("resource://gre/modules/Promise.jsm");
var EventEmitter = require("devtools/toolkit/event-emitter");
@ -118,12 +119,17 @@ ToolSidebar.prototype = {
/**
* Remove an existing tab.
*/
removeTab: function(id) {
removeTab: Task.async(function*(id) {
let tab = this._tabbox.tabs.querySelector("tab#sidebar-tab-" + id);
if (!tab) {
return;
}
let win = this.getWindowForTab(id);
if ("destroy" in win) {
yield win.destroy();
}
tab.remove();
let panel = this.getTab(id);
@ -134,7 +140,7 @@ ToolSidebar.prototype = {
this._tabs.delete(id);
this.emit("tab-unregistered", id);
},
}),
/**
* Select a specific tab.
@ -241,7 +247,7 @@ ToolSidebar.prototype = {
/**
* Clean-up.
*/
destroy: function ToolSidebar_destroy() {
destroy: Task.async(function*() {
if (this._destroyed) {
return promise.resolve(null);
}
@ -252,7 +258,12 @@ ToolSidebar.prototype = {
this._tabbox.tabpanels.removeEventListener("select", this, true);
while (this._tabbox.tabpanels.hasChildNodes()) {
this._tabbox.tabpanels.removeChild(this._tabbox.tabpanels.firstChild);
let panel = this._tabbox.tabpanels.firstChild;
let win = panel.firstChild.contentWindow;
if ("destroy" in win) {
yield win.destroy();
}
panel.remove();
}
while (this._tabbox.tabs.hasChildNodes()) {
@ -271,5 +282,5 @@ ToolSidebar.prototype = {
this._toolPanel = null;
return promise.resolve(null);
},
}),
}

Просмотреть файл

@ -1578,9 +1578,12 @@ Toolbox.prototype = {
* @return {promise} to be resolved when the host is destroyed.
*/
destroyHost: function() {
this.doc.removeEventListener("keypress",
this._splitConsoleOnKeypress, false);
this.doc.removeEventListener("focus", this._onFocus, true);
// The host iframe's contentDocument may already be gone.
if (this.doc) {
this.doc.removeEventListener("keypress",
this._splitConsoleOnKeypress, false);
this.doc.removeEventListener("focus", this._onFocus, true);
}
return this._host.destroy();
},
@ -1645,18 +1648,17 @@ Toolbox.prototype = {
// We need to grab a reference to win before this._host is destroyed.
let win = this.frame.ownerGlobal;
// Remove the host UI
outstanding.push(this.destroyHost());
if (this._requisition) {
this._requisition.destroy();
}
this._telemetry.toolClosed("toolbox");
this._telemetry.destroy();
// Finish all outstanding tasks (successfully or not) before destroying the
// Finish all outstanding tasks (which means finish destroying panels and
// then destroying the host, successfully or not) before destroying the
// target.
this._destroyer = promise.all(outstanding).then(null, console.error).then(() => {
this._destroyer = promise.all(outstanding)
.then(() => this.destroyHost()).then(null, console.error).then(() => {
// Targets need to be notified that the toolbox is being torn down.
// This is done after other destruction tasks since it may tear down
// fronts and the debugger transport which earlier destroy methods may

Просмотреть файл

@ -549,7 +549,7 @@ InspectorPanel.prototype = {
this._toolbox.off("select", this.updateDebuggerPausedWarning);
this.sidebar.off("select", this._setDefaultSidebar);
this.sidebar.destroy();
let sidebarDestroyer = this.sidebar.destroy();
this.sidebar = null;
this.nodemenu.removeEventListener("popupshowing", this._setupNodeMenu, true);
@ -561,7 +561,7 @@ InspectorPanel.prototype = {
this.selection.off("before-new-node", this.onBeforeNewSelection);
this.selection.off("before-new-node-front", this.onBeforeNewSelection);
this.selection.off("detached-front", this.onDetached);
this._panelDestroyer = this._destroyMarkup();
let markupDestroyer = this._destroyMarkup();
this.panelWin.inspector = null;
this.target = null;
this.panelDoc = null;
@ -572,6 +572,11 @@ InspectorPanel.prototype = {
this.nodemenu = null;
this._toolbox = null;
this._panelDestroyer = promise.all([
sidebarDestroyer,
markupDestroyer
]);
return this._panelDestroyer;
},

Просмотреть файл

@ -35,6 +35,4 @@ add_task(function*() {
highlightedNode = yield getHighlitNode(toolbox);
is(highlightedNode, getNode("span"), "The highlighter highlights the right node");
gBrowser.removeCurrentTab();
});

Просмотреть файл

@ -17,8 +17,6 @@ add_task(function*() {
let {inspector} = yield openInspector();
yield checkDivHeight(inspector);
gBrowser.removeCurrentTab();
});
function* checkDivHeight(inspector) {

Просмотреть файл

@ -28,6 +28,4 @@ add_task(function*() {
let node = yield getHighlitNode(toolbox);
is(node, getNode("h1"), "The highlighter highlights the right node");
gBrowser.removeCurrentTab();
});

Просмотреть файл

@ -44,6 +44,4 @@ add_task(function*() {
info("Hide the box-model highlighter");
yield toolbox.highlighter.hideBoxModel();
gBrowser.removeCurrentTab();
});

Просмотреть файл

@ -16,8 +16,6 @@ add_task(function*() {
yield manyInstancesOfCustomHighlighters(inspector);
yield showHideMethodsAreAvailable(inspector);
yield unknownHighlighterTypeShouldntBeAccepted(inspector);
gBrowser.removeCurrentTab();
});
function* onlyOneInstanceOfMainHighlighter({inspector}) {

Просмотреть файл

@ -26,8 +26,6 @@ add_task(function*() {
yield linesLinkThePolygons(highlighter, inspector);
yield highlighter.finalize();
gBrowser.removeCurrentTab();
});
function* isHiddenByDefault(highlighterFront, inspector) {

Просмотреть файл

@ -53,8 +53,6 @@ add_task(function*() {
info("Hiding the transform highlighter");
yield highlighter.hide();
yield highlighter.finalize();
gBrowser.removeCurrentTab();
});
function* getAttribute(nodeID, name, {actorID}) {

Просмотреть файл

@ -149,8 +149,6 @@ add_task(function*() {
info("Hide the box-model highlighter");
yield toolbox.highlighter.hideBoxModel();
}
gBrowser.removeCurrentTab();
});
function* getAttribute(nodeID, name, toolbox) {

Просмотреть файл

@ -105,7 +105,6 @@ add_task(function*() {
yield highlighter.hide();
yield highlighter.finalize();
gBrowser.removeCurrentTab();
});
function* getAttribute(highlighter, name) {

Просмотреть файл

@ -33,7 +33,6 @@ add_task(function*() {
yield highlighter.hide();
yield highlighter.finalize();
gBrowser.removeCurrentTab();
});
function* getAttribute(highlighter, name) {

Просмотреть файл

@ -60,5 +60,4 @@ add_task(function*() {
}
yield highlighter.finalize();
gBrowser.removeCurrentTab();
});

Просмотреть файл

@ -58,5 +58,4 @@ add_task(function*() {
}
yield highlighter.finalize();
gBrowser.removeCurrentTab();
});

Просмотреть файл

@ -47,8 +47,6 @@ add_task(function*() {
let style = yield getRootNodeStyle(toolbox);
is(style, expected, "The style attribute of the root element is correct");
}
gBrowser.removeCurrentTab();
});
function* hoverElement(selector, inspector) {

Просмотреть файл

@ -50,8 +50,6 @@ add_task(function*() {
for (let currTest of testData) {
yield testPosition(currTest, inspector);
}
gBrowser.removeCurrentTab();
});
function* testPosition(test, inspector) {

Просмотреть файл

@ -64,7 +64,6 @@ add_task(function*() {
yield newRoot;
Services.prefs.clearUserPref("devtools.command-button-frames.enabled");
gBrowser.removeCurrentTab();
});
function assertMarkupViewIsLoaded(inspector) {

Просмотреть файл

@ -32,15 +32,11 @@ let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
Services.scriptloader.loadSubScript(testDir + "../../../commandline/test/helpers.js", this);
gDevTools.testing = true;
SimpleTest.registerCleanupFunction(() => {
registerCleanupFunction(() => {
gDevTools.testing = false;
});
SimpleTest.registerCleanupFunction(() => {
console.error("Here we are\n");
let {DebuggerServer} = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
console.error("DebuggerServer open connections: " + Object.getOwnPropertyNames(DebuggerServer._connections).length);
registerCleanupFunction(() => {
Services.prefs.clearUserPref("devtools.dump.emit");
Services.prefs.clearUserPref("devtools.inspector.activeSidebar");
});
@ -58,7 +54,6 @@ registerCleanupFunction(function*() {
while (gBrowser.tabs.length > 1) {
gBrowser.removeCurrentTab();
}
});
/**

Просмотреть файл

@ -391,6 +391,16 @@ let NetMonitorController = {
!this._target.isApp);
},
/**
* Getter that tells if the server includes the transferred (compressed /
* encoded) response size.
* @type boolean
*/
get supportsTransferredResponseSize() {
return this.webConsoleClient &&
this.webConsoleClient.traits.transferredResponseSize;
},
/**
* Getter that tells if the server can do network performance statistics.
* @type boolean
@ -590,6 +600,7 @@ NetworkEventsHandler.prototype = {
case "responseContent":
NetMonitorView.RequestsMenu.updateRequest(aPacket.from, {
contentSize: aPacket.contentSize,
transferredSize: aPacket.transferredSize,
mimeType: aPacket.mimeType
});
this.webConsoleClient.getResponseContent(actor, this._onResponseContent);

Просмотреть файл

@ -416,6 +416,11 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
$("#requests-menu-network-summary-button").hidden = true;
$("#requests-menu-network-summary-label").hidden = true;
}
if (!NetMonitorController.supportsTransferredResponseSize) {
$("#requests-menu-transferred-header-box").hidden = true;
$("#requests-menu-item-template .requests-menu-transferred").hidden = true;
}
},
/**
@ -799,8 +804,8 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
* Sorts all network requests in this container by a specified detail.
*
* @param string aType
* Either "status", "method", "file", "domain", "type", "size" or
* "waterfall".
* Either "status", "method", "file", "domain", "type", "transferred",
* "size" or "waterfall".
*/
sortBy: function(aType = "waterfall") {
let target = $("#requests-menu-" + aType + "-button");
@ -861,6 +866,13 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
this.sortContents((a, b) => !this._byType(a, b));
}
break;
case "transferred":
if (direction == "ascending") {
this.sortContents(this._byTransferred);
} else {
this.sortContents((a, b) => !this._byTransferred(a, b));
}
break;
case "size":
if (direction == "ascending") {
this.sortContents(this._bySize);
@ -993,8 +1005,13 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
: firstType > secondType;
},
_bySize: function({ attachment: first }, { attachment: second })
first.contentSize > second.contentSize,
_byTransferred: function({ attachment: first }, { attachment: second }) {
return first.transferredSize > second.transferredSize;
},
_bySize: function({ attachment: first }, { attachment: second }) {
return first.contentSize > second.contentSize;
},
/**
* Refreshes the status displayed in this container's footer, providing
@ -1159,6 +1176,10 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
requestItem.attachment.contentSize = value;
this.updateMenuView(requestItem, key, value);
break;
case "transferredSize":
requestItem.attachment.transferredSize = value;
this.updateMenuView(requestItem, key, value);
break;
case "mimeType":
requestItem.attachment.mimeType = value;
this.updateMenuView(requestItem, key, value);
@ -1307,6 +1328,20 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
node.setAttribute("tooltiptext", text);
break;
}
case "transferredSize": {
let text;
if (aValue === null) {
text = L10N.getStr("networkMenu.sizeUnavailable");
} else {
let kb = aValue / 1024;
let size = L10N.numberWithDecimals(kb, CONTENT_SIZE_DECIMALS);
text = L10N.getFormatStr("networkMenu.sizeKB", size);
}
let node = $(".requests-menu-transferred", target);
node.setAttribute("value", text);
node.setAttribute("tooltiptext", text);
break;
}
case "mimeType": {
let type = this._getAbbreviatedMimeType(aValue);
let node = $(".requests-menu-type", target);

Просмотреть файл

@ -101,6 +101,16 @@
flex="1">
</button>
</hbox>
<hbox id="requests-menu-transferred-header-box"
class="requests-menu-header requests-menu-transferred"
align="center">
<button id="requests-menu-transferred-button"
class="requests-menu-header-button requests-menu-transferred"
data-key="transferred"
label="&netmonitorUI.toolbar.transferred;"
flex="1">
</button>
</hbox>
<hbox id="requests-menu-size-header-box"
class="requests-menu-header requests-menu-size"
align="center">
@ -174,6 +184,8 @@
crop="end"/>
<label class="plain requests-menu-subitem requests-menu-type"
crop="end"/>
<label class="plain requests-menu-subitem requests-menu-transferred"
crop="end"/>
<label class="plain requests-menu-subitem requests-menu-size"
crop="end"/>
<hbox class="requests-menu-subitem requests-menu-waterfall"

Просмотреть файл

@ -65,6 +65,8 @@ function test() {
is(requestItem.attachment.headersSize, undefined,
"The headersSize should not yet be set.");
is(requestItem.attachment.transferredSize, undefined,
"The transferredSize should not yet be set.");
is(requestItem.attachment.contentSize, undefined,
"The contentSize should not yet be set.");
@ -156,6 +158,8 @@ function test() {
aMonitor.panelWin.once(aMonitor.panelWin.EVENTS.UPDATING_RESPONSE_CONTENT, () => {
let requestItem = RequestsMenu.getItemAtIndex(0);
is(requestItem.attachment.transferredSize, "12",
"The transferredSize attachment has an incorrect value.");
is(requestItem.attachment.contentSize, "12",
"The contentSize attachment has an incorrect value.");
is(requestItem.attachment.mimeType, "text/plain; charset=utf-8",
@ -164,6 +168,7 @@ function test() {
verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS, {
type: "plain",
fullMimeType: "text/plain; charset=utf-8",
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01),
});
});
@ -183,6 +188,7 @@ function test() {
verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS, {
type: "plain",
fullMimeType: "text/plain; charset=utf-8",
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01),
});
});

Просмотреть файл

@ -202,6 +202,7 @@ function test() {
statusText: "Switching Protocols",
type: "plain",
fullMimeType: "text/plain; charset=utf-8",
transferred: L10N.getStr("networkMenu.sizeUnavailable"),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0),
time: true
});
@ -211,6 +212,7 @@ function test() {
statusText: "Created",
type: "plain",
fullMimeType: "text/plain; charset=utf-8",
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
time: true
});
@ -220,6 +222,7 @@ function test() {
statusText: "See Other",
type: "plain",
fullMimeType: "text/plain; charset=utf-8",
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0),
time: true
});
@ -229,6 +232,7 @@ function test() {
statusText: "Not Found",
type: "plain",
fullMimeType: "text/plain; charset=utf-8",
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
time: true
});
@ -238,6 +242,7 @@ function test() {
statusText: "Not Implemented",
type: "plain",
fullMimeType: "text/plain; charset=utf-8",
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
time: true
});

Просмотреть файл

@ -102,6 +102,24 @@ function test() {
testHeaders("type", "ascending");
return testContents([0, 1, 2, 3, 4]);
})
.then(() => {
info("Testing transferred sort, ascending.");
EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-transferred-button"));
testHeaders("transferred", "ascending");
return testContents([0, 1, 2, 3, 4]);
})
.then(() => {
info("Testing transferred sort, descending.");
EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-transferred-button"));
testHeaders("transferred", "descending");
return testContents([4, 3, 2, 1, 0]);
})
.then(() => {
info("Testing transferred sort, ascending. Checking sort loops correctly.");
EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-transferred-button"));
testHeaders("transferred", "ascending");
return testContents([0, 1, 2, 3, 4]);
})
.then(() => {
info("Testing size sort, ascending.");
EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-size-button"));
@ -199,6 +217,7 @@ function test() {
statusText: "Meh",
type: "1",
fullMimeType: "text/1",
transferred: L10N.getStr("networkMenu.sizeUnavailable"),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0),
time: true
});
@ -209,6 +228,7 @@ function test() {
statusText: "Meh",
type: "2",
fullMimeType: "text/2",
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01),
time: true
});
@ -219,6 +239,7 @@ function test() {
statusText: "Meh",
type: "3",
fullMimeType: "text/3",
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
time: true
});
@ -229,6 +250,7 @@ function test() {
statusText: "Meh",
type: "4",
fullMimeType: "text/4",
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
time: true
});
@ -239,6 +261,7 @@ function test() {
statusText: "Meh",
type: "5",
fullMimeType: "text/5",
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
time: true
});

Просмотреть файл

@ -130,6 +130,7 @@ function test() {
statusText: "Meh",
type: "1",
fullMimeType: "text/1",
transferred: L10N.getStr("networkMenu.sizeUnavailable"),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0),
time: true
});
@ -142,6 +143,7 @@ function test() {
statusText: "Meh",
type: "2",
fullMimeType: "text/2",
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01),
time: true
});
@ -154,6 +156,7 @@ function test() {
statusText: "Meh",
type: "3",
fullMimeType: "text/3",
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
time: true
});
@ -166,6 +169,7 @@ function test() {
statusText: "Meh",
type: "4",
fullMimeType: "text/4",
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
time: true
});
@ -178,6 +182,7 @@ function test() {
statusText: "Meh",
type: "5",
fullMimeType: "text/5",
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
time: true
});

Просмотреть файл

@ -12,6 +12,12 @@ function test() {
let { document, L10N, NetMonitorView } = aMonitor.panelWin;
let { RequestsMenu } = NetMonitorView;
// Disable transferred size column support for this test.
// Without this, the waterfall only has enough room for one division, which
// would remove most of the value of this test.
document.querySelector("#requests-menu-transferred-header-box").hidden = true;
document.querySelector("#requests-menu-item-template .requests-menu-transferred").hidden = true;
RequestsMenu.lazyUpdate = false;
ok(document.querySelector("#requests-menu-waterfall-label"),

Просмотреть файл

@ -264,7 +264,7 @@ function verifyRequestItemTarget(aRequestItem, aMethod, aUrl, aData = {}) {
info("Widget index of item: " + widgetIndex);
info("Visible index of item: " + visibleIndex);
let { fuzzyUrl, status, statusText, type, fullMimeType, size, time } = aData;
let { fuzzyUrl, status, statusText, type, fullMimeType, transferred, size, time } = aData;
let { attachment, target } = aRequestItem
let uri = Services.io.newURI(aUrl, null, null).QueryInterface(Ci.nsIURL);
@ -319,6 +319,14 @@ function verifyRequestItemTarget(aRequestItem, aMethod, aUrl, aData = {}) {
is(value, type, "The displayed type is incorrect.");
is(tooltip, fullMimeType, "The tooltip type is incorrect.");
}
if (transferred !== undefined) {
let value = target.querySelector(".requests-menu-transferred").getAttribute("value");
let tooltip = target.querySelector(".requests-menu-transferred").getAttribute("tooltiptext");
info("Displayed transferred size: " + value);
info("Tooltip transferred size: " + tooltip);
is(value, transferred, "The displayed transferred size is incorrect.");
is(tooltip, transferred, "The tooltip transferred size is incorrect.");
}
if (size !== undefined) {
let value = target.querySelector(".requests-menu-size").getAttribute("value");
let tooltip = target.querySelector(".requests-menu-size").getAttribute("tooltiptext");

Просмотреть файл

@ -6,7 +6,7 @@
* You can also use this initialization format as a template for other tests.
*/
let test = Task.async(function*() {
add_task(function*() {
let { target, panel } = yield initTimelinePanel(SIMPLE_URL);
ok(target, "Should have a target available.");
@ -15,7 +15,4 @@ let test = Task.async(function*() {
ok(panel.panelWin.gToolbox, "Should have a toolbox reference on the panel window.");
ok(panel.panelWin.gTarget, "Should have a target reference on the panel window.");
ok(panel.panelWin.gFront, "Should have a front reference on the panel window.");
yield teardown(panel);
finish();
});

Просмотреть файл

@ -5,7 +5,7 @@
* Tests if the timeline blueprint has a correct structure.
*/
function test() {
add_task(function*() {
let { TIMELINE_BLUEPRINT } = devtools.require("devtools/timeline/global");
ok(TIMELINE_BLUEPRINT,
@ -24,6 +24,4 @@ function test() {
ok("label" in value,
"Each entry in the timeline blueprint contains a `label` key.");
}
finish();
}
});

Просмотреть файл

@ -6,7 +6,7 @@
* and there is data available.
*/
let test = Task.async(function*() {
add_task(function*() {
let { target, panel } = yield initTimelinePanel(SIMPLE_URL);
let { $, EVENTS, TimelineView, TimelineController } = panel.panelWin;
let { OVERVIEW_INITIAL_SELECTION_RATIO: selectionRatio } = panel.panelWin;
@ -41,7 +41,4 @@ let test = Task.async(function*() {
is((selection.end - selection.start) | 0,
(selectionRatio * TimelineView.markersOverview.width) | 0,
"The initial selection end is correct.");
yield teardown(panel);
finish();
});

Просмотреть файл

@ -6,7 +6,7 @@
* and there is no data available.
*/
let test = Task.async(function*() {
add_task(function*() {
let { target, panel } = yield initTimelinePanel(SIMPLE_URL);
let { $, EVENTS, TimelineView, TimelineController } = panel.panelWin;
let { OVERVIEW_INITIAL_SELECTION_RATIO: selectionRatio } = panel.panelWin;
@ -32,7 +32,4 @@ let test = Task.async(function*() {
"The initial selection start is correct.");
is(selection.end, null,
"The initial selection end is correct.");
yield teardown(panel);
finish();
});

Просмотреть файл

@ -5,7 +5,7 @@
* Tests if the markers and memory overviews are continuously updated.
*/
let test = Task.async(function*() {
add_task(function*() {
let { target, panel } = yield initTimelinePanel("about:blank");
let { $, EVENTS, TimelineView, TimelineController } = panel.panelWin;
@ -68,7 +68,4 @@ let test = Task.async(function*() {
"The selection should now be enabled for the memory overview.");
is(TimelineView.memoryOverview.hasSelection(), false,
"The memory overview should not have a selection after recording.");
yield teardown(panel);
finish();
});

Просмотреть файл

@ -6,7 +6,7 @@
* recording starts and stops.
*/
let test = Task.async(function*() {
add_task(function*() {
let { target, panel } = yield initTimelinePanel(SIMPLE_URL);
let { $, EVENTS } = panel.panelWin;
@ -36,7 +36,4 @@ let test = Task.async(function*() {
"The record button should be unchecked again.");
is($("#timeline-pane").selectedPanel, $("#timeline-waterfall-container"),
"A waterfall view is now displayed.");
yield teardown(panel);
finish();
});

Просмотреть файл

@ -5,7 +5,7 @@
* Tests if the timeline actor isn't unnecessarily asked to record memory.
*/
let test = Task.async(function*() {
add_task(function*() {
let { target, panel } = yield initTimelinePanel(SIMPLE_URL);
let { $, EVENTS, TimelineView, TimelineController } = panel.panelWin;
@ -30,7 +30,4 @@ let test = Task.async(function*() {
"There are some markers available.");
is(memory.length, 0,
"There are no memory measurements available.");
yield teardown(panel);
finish();
});

Просмотреть файл

@ -5,7 +5,7 @@
* Tests if the timeline can properly start and stop a recording.
*/
let test = Task.async(function*() {
add_task(function*() {
let { target, panel } = yield initTimelinePanel(SIMPLE_URL);
let { $, gFront, TimelineController } = panel.panelWin;
@ -35,6 +35,5 @@ let test = Task.async(function*() {
TimelineController.getInterval().startTime,
"Some time has passed since the recording started.");
yield teardown(panel);
finish();
yield TimelineController.toggleRecording();
});

Просмотреть файл

@ -6,7 +6,7 @@
* the container bounds.
*/
let test = Task.async(function*() {
add_task(function*() {
let { target, panel } = yield initTimelinePanel(SIMPLE_URL);
let { $, EVENTS, TimelineView, TimelineController } = panel.panelWin;
@ -41,7 +41,4 @@ let test = Task.async(function*() {
"The canvas width is correct.");
is(TimelineView.waterfall._canvas.height, 1,
"The canvas height is correct.");
yield teardown(panel);
finish();
});

Просмотреть файл

@ -5,7 +5,7 @@
* Tests if the waterfall is properly built after finishing a recording.
*/
let test = Task.async(function*() {
add_task(function*() {
let { target, panel } = yield initTimelinePanel(SIMPLE_URL);
let { $, $$, EVENTS, TimelineController } = panel.panelWin;
@ -62,7 +62,4 @@ let test = Task.async(function*() {
"Some marker waterfall nodes should have been created.");
ok($$(".waterfall-marker-item:not(spacer) > .waterfall-marker-bar").length,
"Some marker color bars should have been created inside the waterfall.");
yield teardown(panel);
finish();
});

Просмотреть файл

@ -5,7 +5,7 @@
* Tests if the sidebar is properly updated when a marker is selected.
*/
let test = Task.async(function*() {
add_task(function*() {
let { target, panel } = yield initTimelinePanel(SIMPLE_URL);
let { $, $$, EVENTS, TimelineController, TimelineView } = panel.panelWin;
let { L10N } = devtools.require("devtools/timeline/global");
@ -53,7 +53,4 @@ let test = Task.async(function*() {
is(toMs(m.end), printedEndTime, "sidebar end time is valid");
is(toMs(m.end - m.start), printedDuration, "sidebar duration is valid");
}
yield teardown(panel);
finish();
});

Просмотреть файл

@ -17,7 +17,7 @@ var gRGB_TO_HSL = {
"rgb(153, 153, 153)": "hsl(0,0%,60%)",
};
let test = Task.async(function*() {
add_task(function*() {
let { target, panel } = yield initTimelinePanel(SIMPLE_URL);
let { TIMELINE_BLUEPRINT } = devtools.require("devtools/timeline/global");
let { $, $$, EVENTS, TimelineController } = panel.panelWin;
@ -85,7 +85,4 @@ let test = Task.async(function*() {
ok(bar.style.transform.match(/^translateX\(.*px\)$/),
"The bar appears to have proper translations.");
}
yield teardown(panel);
finish();
});

Просмотреть файл

@ -36,6 +36,16 @@ registerCleanupFunction(() => {
Services.prefs.setBoolPref("devtools.timeline.enabled", gToolEnabled);
});
// Close the toolbox and all opened tabs automatically.
registerCleanupFunction(function*() {
let target = TargetFactory.forTab(gBrowser.selectedTab);
yield gDevTools.closeToolbox(target);
while (gBrowser.tabs.length > 1) {
gBrowser.removeCurrentTab();
}
});
function addTab(url) {
info("Adding tab: " + url);
@ -52,22 +62,6 @@ function addTab(url) {
return deferred.promise;
}
function removeTab(tab) {
info("Removing tab.");
let deferred = promise.defer();
let tabContainer = gBrowser.tabContainer;
tabContainer.addEventListener("TabClose", function onClose(aEvent) {
tabContainer.removeEventListener("TabClose", onClose, false);
info("Tab removed and finished closing.");
deferred.resolve();
}, false);
gBrowser.removeTab(tab);
return deferred.promise;
}
/**
* Spawns a new tab and starts up a toolbox with the timeline panel
* automatically selected.
@ -93,25 +87,6 @@ function* initTimelinePanel(url) {
return { target, panel };
}
/**
* Closes a tab and destroys the toolbox holding a timeline panel.
*
* Must be used within a task.
*
* @param object panel
* The timeline panel, created by the toolbox.
* @return object
* A promise resolved once the timeline, toolbox and debuggee tab
* are destroyed.
*/
function* teardown(panel) {
info("Destroying the specified timeline.");
let tab = panel.target.tab;
yield panel._toolbox.destroy();
yield removeTab(tab);
}
/**
* Waits until a predicate returns true.
*

Просмотреть файл

@ -5,7 +5,7 @@
* Test AudioNode#bypass(), AudioNode#isBypassed()
*/
function spawnTest () {
add_task(function*() {
let { target, front } = yield initBackend(SIMPLE_CONTEXT_URL);
let [_, [destNode, oscNode, gainNode]] = yield Promise.all([
front.setup({ reload: true }),
@ -25,5 +25,4 @@ function spawnTest () {
is((yield gainNode.isBypassed()), false, "Node back to being unbypassed.");
yield removeTab(target.tab);
finish();
}
});

Просмотреть файл

@ -6,7 +6,7 @@
* Uses the editor front as the actors do not retain connect state.
*/
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(SIMPLE_CONTEXT_URL);
let { panelWin } = panel;
let { gFront, $, $$, EVENTS, gAudioNodes } = panelWin;
@ -28,7 +28,6 @@ function spawnTest() {
]);
ok(true, "Oscillator disconnected, event emitted.");
info("Reconnecting oscillator...");
osc.connectNode(gain);
yield Promise.all([
@ -37,8 +36,5 @@ function spawnTest() {
]);
ok(true, "Oscillator reconnected.");
yield teardown(panel);
finish();
}
yield teardown(target);
});

Просмотреть файл

@ -6,7 +6,7 @@
* Uses the editor front as the actors do not retain connect state.
*/
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(SIMPLE_CONTEXT_URL);
let { panelWin } = panel;
let { gFront, $, $$, EVENTS, gAudioNodes } = panelWin;
@ -29,7 +29,5 @@ function spawnTest() {
]);
ok(true, "Oscillator connect to Gain's Gain AudioParam, event emitted.");
yield teardown(panel);
finish();
}
yield teardown(target);
});

Просмотреть файл

@ -5,7 +5,7 @@
* Test AudioNode#getParamFlags()
*/
function spawnTest () {
add_task(function*() {
let { target, front } = yield initBackend(SIMPLE_NODES_URL);
let [_, nodes] = yield Promise.all([
front.setup({ reload: true }),
@ -45,5 +45,4 @@ function spawnTest () {
}
yield removeTab(target.tab);
finish();
}
});

Просмотреть файл

@ -5,7 +5,7 @@
* Test AudioNode#getParams()
*/
function spawnTest () {
add_task(function*() {
let { target, front } = yield initBackend(SIMPLE_NODES_URL);
let [_, nodes] = yield Promise.all([
front.setup({ reload: true }),
@ -42,5 +42,4 @@ function spawnTest () {
});
yield removeTab(target.tab);
finish();
}
});

Просмотреть файл

@ -6,7 +6,7 @@
* from the AudioNode actors.
*/
function spawnTest() {
add_task(function*() {
let { target, front } = yield initBackend(SIMPLE_NODES_URL);
let [_, nodes] = yield Promise.all([
front.setup({ reload: true }),
@ -26,8 +26,7 @@ function spawnTest() {
});
yield removeTab(target.tab);
finish();
}
});
function compare (actual, expected, type) {
actual.forEach(({ value, param }) => {

Просмотреть файл

@ -5,7 +5,7 @@
* Test AudioNode#getParam() / AudioNode#setParam()
*/
function spawnTest () {
add_task(function*() {
let { target, front } = yield initBackend(SIMPLE_CONTEXT_URL);
let [_, [destNode, oscNode, gainNode]] = yield Promise.all([
front.setup({ reload: true }),
@ -44,5 +44,4 @@ function spawnTest () {
}
yield removeTab(target.tab);
finish();
}
});

Просмотреть файл

@ -5,7 +5,7 @@
* Test AudioNode#getType()
*/
function spawnTest () {
add_task(function*() {
let { target, front } = yield initBackend(SIMPLE_NODES_URL);
let [_, nodes] = yield Promise.all([
front.setup({ reload: true }),
@ -25,5 +25,4 @@ function spawnTest () {
});
yield removeTab(target.tab);
finish();
}
});

Просмотреть файл

@ -5,7 +5,7 @@
* Test AudioNode#isSource()
*/
function spawnTest () {
add_task(function*() {
let { target, front } = yield initBackend(SIMPLE_NODES_URL);
let [_, nodes] = yield Promise.all([
front.setup({ reload: true }),
@ -24,5 +24,4 @@ function spawnTest () {
});
yield removeTab(target.tab);
finish();
}
});

Просмотреть файл

@ -9,7 +9,7 @@
* All done in one test since this test takes a few seconds to clear GC.
*/
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(DESTROY_NODES_URL);
let { panelWin } = panel;
let { gFront, $, $$, gAudioNodes } = panelWin;
@ -56,7 +56,5 @@ function spawnTest() {
ok(isVisible($("#web-audio-editor-details-pane-empty")),
"InspectorView empty message should show if the currently selected node gets collected.");
yield teardown(panel);
finish();
}
yield teardown(target);
});

Просмотреть файл

@ -12,7 +12,7 @@ thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Error: Connection closed");
* Tests that the reloading/onContentLoaded hooks work.
*/
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(SIMPLE_CONTEXT_URL);
let { gFront, $ } = panel.panelWin;
@ -46,6 +46,5 @@ function spawnTest() {
is($("#content").hidden, false,
"The tool's content should not be hidden anymore.");
yield teardown(panel);
finish();
}
yield teardown(target);
});

Просмотреть файл

@ -6,7 +6,7 @@
* the correct node in the InspectorView
*/
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(COMPLEX_CONTEXT_URL);
let panelWin = panel.panelWin;
let { gFront, $, $$, InspectorView } = panelWin;
@ -46,6 +46,5 @@ function spawnTest() {
ok(InspectorView.isVisible(),
"InspectorView still visible after several nodes have been clicked.");
yield teardown(panel);
finish();
}
yield teardown(target);
});

Просмотреть файл

@ -5,7 +5,7 @@
* Tests that the SVG marker styling is updated when devtools theme changes.
*/
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(SIMPLE_CONTEXT_URL);
let { panelWin } = panel;
let { gFront, $, $$, MARKER_STYLING } = panelWin;
@ -47,9 +47,8 @@ function spawnTest() {
is(getFill($("#arrowhead")), MARKER_STYLING.light,
"marker styling switches back to light once again.");
yield teardown(panel);
finish();
}
yield teardown(target);
});
/**
* Returns a hex value found in styling for an element. So parses

Просмотреть файл

@ -7,7 +7,7 @@
let connectCount = 0;
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(SIMPLE_CONTEXT_URL);
let { panelWin } = panel;
let { gFront, $, $$, EVENTS, gAudioNodes } = panelWin;
@ -37,9 +37,8 @@ function spawnTest() {
gAudioNodes.off("connect", onConnectNode);
yield teardown(panel);
finish();
}
yield teardown(target);
});
function onConnectNode () {
++connectCount;

Просмотреть файл

@ -5,7 +5,7 @@
* Tests more edge rendering for complex graphs.
*/
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(COMPLEX_CONTEXT_URL);
let { panelWin } = panel;
let { gFront, $, $$ } = panelWin;
@ -45,7 +45,5 @@ function spawnTest() {
"found edge for " + msg);
});
yield teardown(panel);
finish();
}
yield teardown(target);
});

Просмотреть файл

@ -5,7 +5,7 @@
* Tests to ensure that selected nodes stay selected on graph redraw.
*/
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(SIMPLE_CONTEXT_URL);
let { panelWin } = panel;
let { gFront, $, $$, EVENTS } = panelWin;
@ -31,7 +31,5 @@ function spawnTest() {
ok(findGraphNode(panelWin, gain.actorID).classList.contains("selected"),
"Node still selected after rerender.");
yield teardown(panel);
finish();
}
yield teardown(target);
});

Просмотреть файл

@ -5,7 +5,7 @@
* Tests audio param connection rendering.
*/
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(CONNECT_MULTI_PARAM_URL);
let { panelWin } = panel;
let { gFront, $, $$, EVENTS } = panelWin;
@ -34,7 +34,5 @@ function spawnTest() {
ok(edge.classList.contains("param-connection"), "edge is classified as a param-connection");
});
yield teardown(panel);
finish();
}
yield teardown(target);
});

Просмотреть файл

@ -5,7 +5,7 @@
* Tests to ensure that param connections trigger graph redraws
*/
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(SIMPLE_CONTEXT_URL);
let { panelWin } = panel;
let { gFront, $, $$, EVENTS } = panelWin;
@ -25,7 +25,5 @@ function spawnTest() {
yield waitForGraphRendered(panelWin, 3, 1, 1);
ok(true, "Graph re-rendered upon param connection");
yield teardown(panel);
finish();
}
yield teardown(target);
});

Просмотреть файл

@ -5,7 +5,7 @@
* Tests that SVG nodes and edges were created for the Graph View.
*/
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(SIMPLE_CONTEXT_URL);
let { panelWin } = panel;
let { gFront, $, $$, EVENTS } = panelWin;
@ -46,7 +46,5 @@ function spawnTest() {
ok(findGraphNode(panelWin, gainId).classList.contains("selected"),
"Newly selected node now has class 'selected'.");
yield teardown(panel);
finish();
}
yield teardown(target);
});

Просмотреть файл

@ -5,7 +5,7 @@
* Tests that the graph's scale and position is reset on a page reload.
*/
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(SIMPLE_CONTEXT_URL);
let { panelWin } = panel;
let { gFront, $, $$, EVENTS, ContextView } = panelWin;
@ -39,7 +39,5 @@ function spawnTest() {
is(ContextView.getCurrentTranslation()[0], 20, "After refresh, x-translation is 20.");
is(ContextView.getCurrentTranslation()[1], 20, "After refresh, y-translation is 20.");
yield teardown(panel);
finish();
}
yield teardown(target);
});

Просмотреть файл

@ -6,7 +6,7 @@
* the inspector panel as intended.
*/
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(SIMPLE_CONTEXT_URL);
let { panelWin } = panel;
let { gFront, $, $$, EVENTS, InspectorView } = panelWin;
@ -61,6 +61,5 @@ function spawnTest() {
is($("#web-audio-inspector-title").value, "Oscillator",
"Inspector title updates when loading node while open.");
yield teardown(panel);
finish();
}
yield teardown(target);
});

Просмотреть файл

@ -6,7 +6,7 @@
* loads the correct node inside the inspector.
*/
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(SIMPLE_CONTEXT_URL);
let { panelWin } = panel;
let { gFront, $, $$, EVENTS, InspectorView } = panelWin;
@ -55,6 +55,5 @@ function spawnTest() {
is($("#web-audio-inspector-title").value, "Gain",
"Inspector title updates when a new node is selected.");
yield teardown(panel);
finish();
}
yield teardown(target);
});

Просмотреть файл

@ -6,7 +6,7 @@
* the audio graph if both pages have an AudioContext.
*/
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(SIMPLE_CONTEXT_URL);
let { panelWin } = panel;
let { gFront, $ } = panelWin;
@ -40,6 +40,5 @@ function spawnTest() {
ise(nodes, 14, "after navigation, should have 14 nodes");
ise(edges, 0, "after navigation, should have 0 edges.");
yield teardown(panel);
finish();
}
yield teardown(target);
});

Просмотреть файл

@ -5,7 +5,7 @@
* Tests that properties are updated when modifying the VariablesView.
*/
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(SIMPLE_CONTEXT_URL);
let { panelWin } = panel;
let { gFront, $, $$, EVENTS, InspectorView } = panelWin;
@ -52,9 +52,8 @@ function spawnTest() {
yield setAndCheck(0, "gain", "0.1", 0.1, "sets float as float");
yield setAndCheck(0, "gain", ".2", 0.2, "sets float without leading zero as float");
yield teardown(panel);
finish();
}
yield teardown(target);
});
function setAndCheckVariable (panelWin, gVars) {
return Task.async(function (varNum, prop, value, expected, desc) {
@ -64,4 +63,3 @@ function setAndCheckVariable (panelWin, gVars) {
checkVariableView(gVars, varNum, props, desc);
});
}

Просмотреть файл

@ -5,7 +5,7 @@
* Tests that properties are not updated when modifying the VariablesView.
*/
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(COMPLEX_CONTEXT_URL);
let { panelWin } = panel;
let { gFront, $, $$, EVENTS, InspectorView } = panelWin;
@ -40,6 +40,5 @@ function spawnTest() {
checkVariableView(gVars, 0, {bufferSize: 4096}, "check that unwritable variable is not updated");
yield teardown(panel);
finish();
}
yield teardown(target);
});

Просмотреть файл

@ -34,7 +34,7 @@ function waitForDeviceClosed() {
return deferred.promise;
}
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(MEDIA_NODES_URL);
let { panelWin } = panel;
let { gFront, $, $$, EVENTS, InspectorView } = panelWin;
@ -66,9 +66,7 @@ function spawnTest() {
// Reset permissions on getUserMedia
Services.prefs.setBoolPref(MEDIA_PERMISSION, mediaPermissionPref);
yield teardown(panel);
yield teardown(target);
yield waitForDeviceClosed();
finish();
}
});

Просмотреть файл

@ -6,7 +6,7 @@
* like AudioBuffer and Float32Array in properties of AudioNodes.
*/
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(BUFFER_AND_ARRAY_URL);
let { panelWin } = panel;
let { gFront, $, $$, EVENTS, InspectorView } = panelWin;
@ -42,6 +42,5 @@ function spawnTest() {
state = aVar.target.querySelector(".theme-twisty").hasAttribute("invisible");
ok(state, "AudioBuffer property should not have a dropdown.");
yield teardown(panel);
finish();
}
yield teardown(target);
});

Просмотреть файл

@ -6,7 +6,7 @@
* correctly, with default values and correct types.
*/
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(SIMPLE_NODES_URL);
let { panelWin } = panel;
let { gFront, $, $$, EVENTS, InspectorView } = panelWin;
@ -34,6 +34,5 @@ function spawnTest() {
checkVariableView(gVars, 0, NODE_DEFAULT_VALUES[types[i]], types[i]);
}
yield teardown(panel);
finish();
}
yield teardown(target);
});

Просмотреть файл

@ -5,7 +5,7 @@
* Tests that params view shows params when they exist, and are hidden otherwise.
*/
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(SIMPLE_CONTEXT_URL);
let { panelWin } = panel;
let { gFront, $, $$, EVENTS, InspectorView } = panelWin;
@ -38,6 +38,5 @@ function spawnTest() {
ok(isVisible($("#properties-tabpanel-content-empty")),
"Empty message shown when no AudioParams exist.");
yield teardown(panel);
finish();
}
yield teardown(target);
});

Просмотреть файл

@ -13,7 +13,7 @@ thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Error: Connection closed");
* event and reshow the tools after reloading.
*/
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(SIMPLE_CONTEXT_URL);
let { gFront, $ } = panel.panelWin;
@ -61,6 +61,5 @@ function spawnTest() {
is($("#content").hidden, false,
"The tool's content should reappear without closing and reopening the toolbox.");
yield teardown(panel);
finish();
}
yield teardown(target);
});

Просмотреть файл

@ -6,7 +6,7 @@
* the graph.
*/
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(SIMPLE_CONTEXT_URL);
let { panelWin } = panel;
let { gFront, $ } = panelWin;
@ -33,6 +33,5 @@ function spawnTest() {
ise(nodes, 3, "after reload, should only be 3 nodes.");
ise(edges, 2, "after reload, should only be 2 edges.");
yield teardown(panel);
finish();
}
yield teardown(target);
});

Просмотреть файл

@ -6,7 +6,7 @@
* the inspector and selected node.
*/
function spawnTest() {
add_task(function*() {
let { target, panel } = yield initWebAudioEditor(SIMPLE_CONTEXT_URL);
let { panelWin } = panel;
let { gFront, $, InspectorView } = panelWin;
@ -44,6 +44,5 @@ function spawnTest() {
"InspectorView visible after selecting a node after a reset.");
is(InspectorView.getCurrentAudioNode().id, nodeIds[2], "InspectorView has correct node set upon clicking graph node after a reset.");
yield teardown(panel);
finish();
}
yield teardown(target);
});

Просмотреть файл

@ -12,7 +12,7 @@ thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Error: Connection closed");
* Tests that switching to an iframe works fine.
*/
function spawnTest() {
add_task(function*() {
Services.prefs.setBoolPref("devtools.command-button-frames.enabled", true);
let { target, panel, toolbox } = yield initWebAudioEditor(IFRAME_CONTEXT_URL);
@ -58,6 +58,5 @@ function spawnTest() {
is($("#content").hidden, false,
"The tool's content should appear after reload.");
yield teardown(panel);
finish();
}
yield teardown(target);
});

Просмотреть файл

@ -5,7 +5,7 @@
* Test the `connect-param` event on the web audio actor.
*/
function spawnTest () {
add_task(function*() {
let { target, front } = yield initBackend(CONNECT_PARAM_URL);
let [, , [destNode, carrierNode, modNode, gainNode], , connectParam] = yield Promise.all([
front.setup({ reload: true }),
@ -22,5 +22,4 @@ function spawnTest () {
is(connectParam.param, "gain", "`connect-param` has correct parameter name for `param`");
yield removeTab(target.tab);
finish();
}
});

Просмотреть файл

@ -5,7 +5,7 @@
* Test `destroy-node` event on WebAudioActor.
*/
function spawnTest () {
add_task(function*() {
let { target, front } = yield initBackend(DESTROY_NODES_URL);
let waitUntilDestroyed = getN(front, "destroy-node", 10);
@ -29,8 +29,7 @@ function spawnTest () {
});
yield removeTab(target.tab);
finish();
}
});
function actorIsInList (list, actor) {
for (let i = 0; i < list.length; i++) {

Просмотреть файл

@ -5,7 +5,7 @@
* Test basic communication of Web Audio actor
*/
function spawnTest () {
add_task(function*() {
let { target, front } = yield initBackend(SIMPLE_CONTEXT_URL);
let [_, __, [destNode, oscNode, gainNode], [connect1, connect2]] = yield Promise.all([
front.setup({ reload: true }),
@ -31,5 +31,4 @@ function spawnTest () {
is(dest.actorID, destNode.actorID, "WebAudioActor:connect-node returns correct actor with ID on dest (gain->dest)");
yield removeTab(target.tab);
finish();
}
});

Просмотреть файл

@ -84,11 +84,6 @@ function removeTab(aTab, aWindow) {
return deferred.promise;
}
function handleError(aError) {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
finish();
}
function once(aTarget, aEventName, aUseCapture = false) {
info("Waiting for event: '" + aEventName + "' on " + aTarget + ".");
@ -121,10 +116,10 @@ function navigate(aTarget, aUrl, aWaitForTargetEvent = "navigate") {
return once(aTarget, aWaitForTargetEvent);
}
function test () {
Task.spawn(spawnTest).then(finish, handleError);
}
/**
* Adds a new tab, and instantiate a WebAudiFront object.
* This requires calling removeTab before the test ends.
*/
function initBackend(aUrl) {
info("Initializing a web audio editor front.");
@ -144,6 +139,11 @@ function initBackend(aUrl) {
});
}
/**
* Adds a new tab, and open the toolbox for that tab, selecting the audio editor
* panel.
* This requires calling teardown before the test ends.
*/
function initWebAudioEditor(aUrl) {
info("Initializing a web audio editor pane.");
@ -160,18 +160,16 @@ function initWebAudioEditor(aUrl) {
});
}
function teardown(aPanel) {
/**
* Close the toolbox, destroying all panels, and remove the added test tabs.
*/
function teardown(aTarget) {
info("Destroying the web audio editor.");
return Promise.all([
once(aPanel, "destroyed"),
removeTab(aPanel.target.tab)
]).then(() => {
let gBrowser = window.gBrowser;
return gDevTools.closeToolbox(aTarget).then(() => {
while (gBrowser.tabs.length > 1) {
gBrowser.removeCurrentTab();
}
gBrowser = null;
});
}

Просмотреть файл

@ -10,62 +10,54 @@ let { isTargetSupported } = Tools.scratchpad;
Tools.scratchpad.isTargetSupported = () => true;
function test()
{
add_task(function*() {
waitForExplicitFinish();
yield loadTab(TEST_URI);
loadTab(TEST_URI).then(() => {
info("Opening toolbox with Scratchpad panel");
info("Opening toolbox with Scratchpad panel");
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "scratchpad", "window").then(runTests);
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = yield gDevTools.showToolbox(target, "scratchpad", "window");
let scratchpadPanel = toolbox.getPanel("scratchpad");
let { scratchpad } = scratchpadPanel;
is(toolbox.getCurrentPanel(), scratchpadPanel,
"Scratchpad is currently selected panel");
info("Switching to webconsole panel");
let webconsolePanel = yield toolbox.selectTool("webconsole");
let { hud } = webconsolePanel;
is(toolbox.getCurrentPanel(), webconsolePanel,
"Webconsole is currently selected panel");
info("console.log()ing from Scratchpad");
scratchpad.setText("console.log('foobar-from-scratchpad')");
scratchpad.run();
let messages = yield waitForMessages({
webconsole: hud,
messages: [{ text: "foobar-from-scratchpad" }]
});
}
function runTests(aToolbox)
{
Task.spawn(function*() {
let scratchpadPanel = aToolbox.getPanel("scratchpad");
let { scratchpad } = scratchpadPanel;
is(aToolbox.getCurrentPanel(), scratchpadPanel,
"Scratchpad is currently selected panel");
info("Clicking link to switch to and focus Scratchpad");
info("Switching to webconsole panel");
let [matched] = [...messages[0].matched];
ok(matched, "Found logged message from Scratchpad");
let anchor = matched.querySelector("a.message-location");
let webconsolePanel = yield aToolbox.selectTool("webconsole");
let { hud } = webconsolePanel;
is(aToolbox.getCurrentPanel(), webconsolePanel,
"Webconsole is currently selected panel");
toolbox.on("scratchpad-selected", function selected() {
toolbox.off("scratchpad-selected", selected);
info("console.log()ing from Scratchpad");
is(toolbox.getCurrentPanel(), scratchpadPanel,
"Clicking link switches to Scratchpad panel");
scratchpad.setText("console.log('foobar-from-scratchpad')");
scratchpad.run();
let messages = yield waitForMessages({
webconsole: hud,
messages: [{ text: "foobar-from-scratchpad" }]
});
is(Services.ww.activeWindow, toolbox.frame.ownerGlobal,
"Scratchpad's toolbox is focused");
info("Clicking link to switch to and focus Scratchpad");
let [matched] = [...messages[0].matched];
ok(matched, "Found logged message from Scratchpad");
let anchor = matched.querySelector("a.message-location");
aToolbox.on("scratchpad-selected", function selected() {
aToolbox.off("scratchpad-selected", selected);
is(aToolbox.getCurrentPanel(), scratchpadPanel,
"Clicking link switches to Scratchpad panel");
is(Services.ww.activeWindow, aToolbox.frame.ownerGlobal,
"Scratchpad's toolbox is focused");
Tools.scratchpad.isTargetSupported = isTargetSupported;
finish();
});
EventUtils.synthesizeMouse(anchor, 2, 2, {}, hud.iframeWindow);
Tools.scratchpad.isTargetSupported = isTargetSupported;
finish();
});
}
EventUtils.synthesizeMouse(anchor, 2, 2, {}, hud.iframeWindow);
});

Просмотреть файл

@ -319,8 +319,7 @@ let finishTest = Task.async(function* () {
finish();
});
function tearDown()
{
registerCleanupFunction(function*() {
gDevTools.testing = false;
dumpConsoles();
@ -330,14 +329,12 @@ function tearDown()
}
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.closeToolbox(target);
yield gDevTools.closeToolbox(target);
while (gBrowser.tabs.length > 1) {
gBrowser.removeCurrentTab();
}
}
registerCleanupFunction(tearDown);
});
waitForExplicitFinish();

Просмотреть файл

@ -6,11 +6,7 @@
pref("devtools.webide.showProjectEditor", true);
pref("devtools.webide.templatesURL", "https://code.cdn.mozilla.net/templates/list.json");
pref("devtools.webide.autoinstallADBHelper", true);
#ifdef MOZ_DEV_EDITION
pref("devtools.webide.autoinstallFxdtAdapters", true);
#else
pref("devtools.webide.autoinstallFxdtAdapters", false);
#endif
pref("devtools.webide.autoConnectRuntime", true);
pref("devtools.webide.restoreLastProject", true);
pref("devtools.webide.enableLocalRuntime", false);

Просмотреть файл

@ -42,8 +42,14 @@
- in the network table toolbar, above the "type" column. -->
<!ENTITY netmonitorUI.toolbar.type "Type">
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.transferred): This is the label displayed
- in the network table toolbar, above the "transferred" column, which is the
- compressed / encoded size. -->
<!ENTITY netmonitorUI.toolbar.transferred "Transferred">
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.size): This is the label displayed
- in the network table toolbar, above the "size" column. -->
- in the network table toolbar, above the "size" column, which is the
- uncompressed / decoded size. -->
<!ENTITY netmonitorUI.toolbar.size "Size">
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.waterfall): This is the label displayed

Просмотреть файл

@ -129,6 +129,11 @@ networkMenu.summary=One request, #2 KB, #3 s;#1 requests, #2 KB, #3 s
# in the network menu specifying the size of a request (in kilobytes).
networkMenu.sizeKB=%S KB
# LOCALIZATION NOTE (networkMenu.sizeUnavailable): This is the label displayed
# in the network menu specifying the transferred size of a request is
# unavailable.
networkMenu.sizeUnavailable=
# LOCALIZATION NOTE (networkMenu.totalMS): This is the label displayed
# in the network menu specifying the time for a request to finish (in milliseconds).
networkMenu.totalMS=→ %S ms

Просмотреть файл

@ -143,13 +143,21 @@ this.UITour = {
},
}],
["loop-selectedRoomButtons", {
infoPanelPosition: "leftcenter bottomright",
infoPanelOffsetY: -20,
infoPanelPosition: "start_after",
query: (aDocument) => {
let chatbox = aDocument.querySelector("chatbox[src^='about\:loopconversation'][selected]");
if (!chatbox || !chatbox.contentDocument) {
// Check that the real target actually exists
if (!chatbox || !chatbox.contentDocument ||
!chatbox.contentDocument.querySelector(".call-action-group")) {
return null;
}
return chatbox.contentDocument.querySelector(".call-action-group");
// But anchor on the <browser> in the chatbox so the panel doesn't jump to undefined
// positions when the copy/email buttons disappear e.g. when the feedback form opens or
// somebody else joins the room.
return chatbox.content;
},
}],
["loop-signInUpLink", {
@ -164,6 +172,7 @@ this.UITour = {
["privateWindow", {query: "#privatebrowsing-button"}],
["quit", {query: "#PanelUI-quit"}],
["search", {
infoPanelOffsetX: 18,
infoPanelPosition: "after_start",
query: "#searchbar",
widgetName: "search-container",
@ -902,6 +911,8 @@ this.UITour = {
deferred.resolve({
addTargetListener: targetObject.addTargetListener,
infoPanelOffsetX: targetObject.infoPanelOffsetX,
infoPanelOffsetY: targetObject.infoPanelOffsetY,
infoPanelPosition: targetObject.infoPanelPosition,
node: node,
removeTargetListener: targetObject.removeTargetListener,
@ -1241,12 +1252,10 @@ this.UITour = {
alignment = aAnchor.infoPanelPosition;
}
let xOffset = 0, yOffset = 0;
if (aAnchor.targetName == "search") {
xOffset = 18;
}
let { infoPanelOffsetX: xOffset, infoPanelOffsetY: yOffset } = aAnchor;
this._addAnnotationPanelMutationObserver(tooltip);
tooltip.openPopup(aAnchorEl, alignment, xOffset, yOffset);
tooltip.openPopup(aAnchorEl, alignment, xOffset || 0, yOffset || 0);
if (tooltip.state == "closed") {
document.defaultView.addEventListener("endmodalstate", function endModalStateHandler() {
document.defaultView.removeEventListener("endmodalstate", endModalStateHandler);

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше