--- a/b2g/chrome/content/touchcontrols.css
+++ b/b2g/chrome/content/touchcontrols.css
@@ -46,27 +46,31 @@
.fullscreenButton {
background: url("chrome://b2g/content/images/fullscreen-hdpi.png") no-repeat center;
}
.fullscreenButton[fullscreened="true"] {
background: url("chrome://b2g/content/images/exitfullscreen-hdpi.png") no-repeat center;
}
+.controlBar[fullscreen-unavailable] .fullscreenButton {
+ display: none;
+}
+
.playButton {
background: url("chrome://b2g/content/images/pause-hdpi.png") no-repeat center;
}
/*
* Normally the button bar has fullscreen spacer play spacer mute, but if
* this is an audio control rather than a video control, the fullscreen button
* is hidden by videocontrols.xml, and that alters the position of the
* play button. This workaround moves it back to center.
*/
-.controlBar.audio-only .playButton {
+.controlBar[fullscreen-unavailable] .playButton {
transform: translateX(28px);
}
.playButton[paused="true"] {
background: url("chrome://b2g/content/images/play-hdpi.png") no-repeat center;
}
.castingButton {
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -436,17 +436,16 @@ panel[noactions] > richlistbox > richlis
}
#PopupAutoComplete {
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#browser-autocomplete-result-popup");
}
#PopupSearchAutoComplete {
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#browser-search-autocomplete-result-popup");
- margin-left: -23px;
}
/* Overlay a badge on top of the icon of additional open search providers
in the search panel. */
.addengine-item > .button-box > .button-icon {
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#addengine-icon");
display: -moz-stack;
}
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -1127,31 +1127,36 @@
let engines = Services.search.getVisibleEngines()
.filter(e => e.name != currentEngineName &&
hiddenList.indexOf(e.name) == -1);
let header = document.getAnonymousElementByAttribute(this, "anonid",
"search-panel-one-offs-header")
header.collapsed = list.collapsed = !engines.length;
- if (!engines.length)
- return;
-
// 49px is the min-width of each search engine button,
// adapt this const when changing the css.
// It's actually 48px + 1px of right border.
const ENGINE_WIDTH = 49;
+ let panel = document.getElementById("PopupSearchAutoComplete");
+ // The panel width only spans to the textbox size, but we also want it
+ // to include the magnifier icon's width.
+ let ltr = getComputedStyle(this).direction == "ltr";
+ let magnifierWidth = parseInt(getComputedStyle(panel)[
+ ltr ? "marginLeft" : "marginRight"
+ ]) * -1;
+ let minWidth = parseInt(panel.width) + magnifierWidth;
+ if (engines.length) {
+ // Ensure the panel is wide enough to fit at least 3 engines.
+ minWidth = Math.max(minWidth, ENGINE_WIDTH * 3);
+ }
+ panel.setAttribute("style", "min-width: " + minWidth + "px");
- let panel = document.getElementById("PopupSearchAutoComplete");
- // The + 23 is because the panel width only spans to the textbox
- // size, but we also want it to include the magnifier icon's width.
- let minWidth = parseInt(panel.width) + 23;
- // Ensure the panel is wide enough to fit at least 3 engines.
- minWidth = Math.max(minWidth, ENGINE_WIDTH * 3);
- panel.setAttribute("style", "min-width: " + minWidth + "px");
+ if (!engines.length)
+ return;
let panelWidth = parseInt(panel.clientWidth);
// The + 1 is because the last button doesn't have a right border.
let enginesPerRow = Math.floor((panelWidth + 1) / ENGINE_WIDTH);
let buttonWidth = Math.floor(panelWidth / enginesPerRow);
// There will be an emtpy area of:
// panelWidth - enginesPerRow * buttonWidth px
// at the end of each row.
--- a/browser/components/loop/content/js/conversationViews.js
+++ b/browser/components/loop/content/js/conversationViews.js
@@ -15,16 +15,21 @@ loop.conversationViews = (function(mozL1
var sharedUtils = loop.shared.utils;
var sharedViews = loop.shared.views;
var sharedMixins = loop.shared.mixins;
var sharedModels = loop.shared.models;
// This duplicates a similar function in contacts.jsx that isn't used in the
// conversation window. If we get too many of these, we might want to consider
// finding a logical place for them to be shared.
+
+ // XXXdmose this code is already out of sync with the code in contacts.jsx
+ // which, unlike this code, now has unit tests. We should totally do the
+ // above.
+
function _getPreferredEmail(contact) {
// A contact may not contain email addresses, but only a phone number.
if (!contact.email || contact.email.length === 0) {
return { value: "" };
}
return contact.email.find(e => e.pref) || contact.email[0];
}
@@ -756,16 +761,35 @@ loop.conversationViews = (function(mozL1
_renderError: function() {
if (!this.state.emailLinkError) {
return;
}
return React.createElement("p", {className: "error"}, mozL10n.get("unable_retrieve_url"));
},
+ _getTitleMessage: function() {
+ var callStateReason =
+ this.props.store.getStoreState("callStateReason");
+
+ if (callStateReason === "reject" || callStateReason === "busy" ||
+ callStateReason === "setup") {
+ var contactDisplayName = _getContactDisplayName(this.props.contact);
+ if (contactDisplayName.length) {
+ return mozL10n.get(
+ "contact_unavailable_title",
+ {"contactName": contactDisplayName});
+ }
+
+ return mozL10n.get("generic_contact_unavailable_title");
+ } else {
+ return mozL10n.get("generic_failure_title");
+ }
+ },
+
retryCall: function() {
this.props.dispatcher.dispatch(new sharedActions.RetryCall());
},
cancelCall: function() {
this.props.dispatcher.dispatch(new sharedActions.CancelCall());
},
@@ -779,17 +803,17 @@ loop.conversationViews = (function(mozL1
roomOwner: navigator.mozLoop.userProfile.email,
roomName: _getContactDisplayName(this.props.contact)
}));
},
render: function() {
return (
React.createElement("div", {className: "call-window"},
- React.createElement("h2", null, mozL10n.get("generic_failure_title")),
+ React.createElement("h2", null, this._getTitleMessage() ),
React.createElement("p", {className: "btn-label"}, mozL10n.get("generic_failure_with_reason2")),
this._renderError(),
React.createElement("div", {className: "btn-group call-action-group"},
React.createElement("button", {className: "btn btn-cancel",
onClick: this.cancelCall},
@@ -1043,16 +1067,17 @@ loop.conversationViews = (function(mozL1
},
});
return {
PendingConversationView: PendingConversationView,
CallIdentifierView: CallIdentifierView,
ConversationDetailView: ConversationDetailView,
CallFailedView: CallFailedView,
+ _getContactDisplayName: _getContactDisplayName,
GenericFailureView: GenericFailureView,
IncomingCallView: IncomingCallView,
IncomingConversationView: IncomingConversationView,
OngoingConversationView: OngoingConversationView,
OutgoingConversationView: OutgoingConversationView
};
})(document.mozL10n || navigator.mozL10n);
--- a/browser/components/loop/content/js/conversationViews.jsx
+++ b/browser/components/loop/content/js/conversationViews.jsx
@@ -15,16 +15,21 @@ loop.conversationViews = (function(mozL1
var sharedUtils = loop.shared.utils;
var sharedViews = loop.shared.views;
var sharedMixins = loop.shared.mixins;
var sharedModels = loop.shared.models;
// This duplicates a similar function in contacts.jsx that isn't used in the
// conversation window. If we get too many of these, we might want to consider
// finding a logical place for them to be shared.
+
+ // XXXdmose this code is already out of sync with the code in contacts.jsx
+ // which, unlike this code, now has unit tests. We should totally do the
+ // above.
+
function _getPreferredEmail(contact) {
// A contact may not contain email addresses, but only a phone number.
if (!contact.email || contact.email.length === 0) {
return { value: "" };
}
return contact.email.find(e => e.pref) || contact.email[0];
}
@@ -756,16 +761,35 @@ loop.conversationViews = (function(mozL1
_renderError: function() {
if (!this.state.emailLinkError) {
return;
}
return <p className="error">{mozL10n.get("unable_retrieve_url")}</p>;
},
+ _getTitleMessage: function() {
+ var callStateReason =
+ this.props.store.getStoreState("callStateReason");
+
+ if (callStateReason === "reject" || callStateReason === "busy" ||
+ callStateReason === "setup") {
+ var contactDisplayName = _getContactDisplayName(this.props.contact);
+ if (contactDisplayName.length) {
+ return mozL10n.get(
+ "contact_unavailable_title",
+ {"contactName": contactDisplayName});
+ }
+
+ return mozL10n.get("generic_contact_unavailable_title");
+ } else {
+ return mozL10n.get("generic_failure_title");
+ }
+ },
+
retryCall: function() {
this.props.dispatcher.dispatch(new sharedActions.RetryCall());
},
cancelCall: function() {
this.props.dispatcher.dispatch(new sharedActions.CancelCall());
},
@@ -779,17 +803,17 @@ loop.conversationViews = (function(mozL1
roomOwner: navigator.mozLoop.userProfile.email,
roomName: _getContactDisplayName(this.props.contact)
}));
},
render: function() {
return (
<div className="call-window">
- <h2>{mozL10n.get("generic_failure_title")}</h2>
+ <h2>{ this._getTitleMessage() }</h2>
<p className="btn-label">{mozL10n.get("generic_failure_with_reason2")}</p>
{this._renderError()}
<div className="btn-group call-action-group">
<button className="btn btn-cancel"
onClick={this.cancelCall}>
@@ -1043,16 +1067,17 @@ loop.conversationViews = (function(mozL1
},
});
return {
PendingConversationView: PendingConversationView,
CallIdentifierView: CallIdentifierView,
ConversationDetailView: ConversationDetailView,
CallFailedView: CallFailedView,
+ _getContactDisplayName: _getContactDisplayName,
GenericFailureView: GenericFailureView,
IncomingCallView: IncomingCallView,
IncomingConversationView: IncomingConversationView,
OngoingConversationView: OngoingConversationView,
OutgoingConversationView: OutgoingConversationView
};
})(document.mozL10n || navigator.mozL10n);
--- a/browser/components/loop/content/shared/css/conversation.css
+++ b/browser/components/loop/content/shared/css/conversation.css
@@ -274,17 +274,17 @@
}
/* XXX Once we get the incoming call avatar, bug 1047435, the H2 should
* disappear from our markup, and we should remove this rule entirely.
*/
.call-window h2 {
font-size: 1.5em;
font-weight: normal;
-
+ text-align: center;
/* compensate for reset.css overriding this; values borrowed from
Firefox Mac html.css */
margin: 0.83em 0;
}
.fx-embedded-call-button-spacer {
display: flex;
flex: 1;
--- a/browser/components/loop/test/desktop-local/conversationViews_test.js
+++ b/browser/components/loop/test/desktop-local/conversationViews_test.js
@@ -407,16 +407,71 @@ describe("loop.conversationViews", funct
view = mountTestComponent({contact: contact});
sinon.assert.calledOnce(navigator.mozLoop.getAudioBlob);
sinon.assert.calledWithExactly(navigator.mozLoop.getAudioBlob,
"failure", sinon.match.func);
sinon.assert.calledOnce(fakeAudio.play);
expect(fakeAudio.loop).to.equal(false);
});
+
+ it("should show 'something went wrong' when the reason is 'media-fail'",
+ function () {
+ store.setStoreState({callStateReason: "media-fail"});
+
+ view = mountTestComponent({contact: contact});
+
+ sinon.assert.calledWith(document.mozL10n.get, "generic_failure_title");
+ });
+
+ it("should show 'contact unavailable' when the reason is 'reject'",
+ function () {
+ store.setStoreState({callStateReason: "reject"});
+
+ view = mountTestComponent({contact: contact});
+
+ sinon.assert.calledWithExactly(document.mozL10n.get,
+ "contact_unavailable_title",
+ {contactName: loop.conversationViews._getContactDisplayName(contact)});
+ });
+
+ it("should show 'contact unavailable' when the reason is 'busy'",
+ function () {
+ store.setStoreState({callStateReason: "busy"});
+
+ view = mountTestComponent({contact: contact});
+
+ sinon.assert.calledWithExactly(document.mozL10n.get,
+ "contact_unavailable_title",
+ {contactName: loop.conversationViews._getContactDisplayName(contact)});
+ });
+
+ it("should show 'contact unavailable' when the reason is 'setup'",
+ function () {
+ store.setStoreState({callStateReason: "setup"});
+
+ view = mountTestComponent({contact: contact});
+
+ sinon.assert.calledWithExactly(document.mozL10n.get,
+ "contact_unavailable_title",
+ {contactName: loop.conversationViews._getContactDisplayName(contact)});
+ });
+
+ it("should display a generic contact unavailable msg when the reason is" +
+ " 'busy' and no display name is available", function() {
+ store.setStoreState({callStateReason: "busy"});
+ var phoneOnlyContact = {
+ tel: [{"pref": true, type: "work", value: ""}]
+ };
+
+ view = mountTestComponent({contact: phoneOnlyContact});
+
+ sinon.assert.calledWith(document.mozL10n.get,
+ "generic_contact_unavailable_title");
+ });
});
describe("OngoingConversationView", function() {
function mountTestComponent(props) {
return TestUtils.renderIntoDocument(
React.createElement(loop.conversationViews.OngoingConversationView, props));
}
@@ -526,17 +581,20 @@ describe("loop.conversationViews", funct
});
feedbackStore = new loop.store.FeedbackStore(dispatcher, {
feedbackClient: {}
});
});
it("should render the CallFailedView when the call state is 'terminated'",
function() {
- store.setStoreState({callState: CALL_STATES.TERMINATED});
+ store.setStoreState({
+ callState: CALL_STATES.TERMINATED,
+ contact: contact
+ });
view = mountTestComponent();
TestUtils.findRenderedComponentWithType(view,
loop.conversationViews.CallFailedView);
});
it("should render the PendingConversationView when the call state is 'gather'",
--- a/browser/components/loop/ui/ui-showcase.js
+++ b/browser/components/loop/ui/ui-showcase.js
@@ -69,16 +69,21 @@
sdkDriver: {}
});
var roomStore = new loop.store.RoomStore(dispatcher, {
mozLoop: navigator.mozLoop
});
var feedbackStore = new loop.store.FeedbackStore(dispatcher, {
feedbackClient: stageFeedbackApiClient
});
+ var conversationStore = new loop.store.ConversationStore(dispatcher, {
+ client: {},
+ mozLoop: navigator.mozLoop,
+ sdkDriver: {}
+ });
// Local mocks
var mockMozLoopRooms = _.extend({}, navigator.mozLoop);
mockMozLoopRooms.roomsEnabled = true;
var mockContact = {
name: ["Mr Smith"],
@@ -371,23 +376,24 @@
)
)
),
React.createElement(Section, {name: "CallFailedView"},
React.createElement(Example, {summary: "Call Failed", dashed: "true",
style: {width: "260px", height: "265px"}},
React.createElement("div", {className: "fx-embedded"},
- React.createElement(CallFailedView, {dispatcher: dispatcher})
+ React.createElement(CallFailedView, {dispatcher: dispatcher, store: conversationStore})
)
),
React.createElement(Example, {summary: "Call Failed — with call URL error", dashed: "true",
style: {width: "260px", height: "265px"}},
React.createElement("div", {className: "fx-embedded"},
- React.createElement(CallFailedView, {dispatcher: dispatcher, emailLinkError: true})
+ React.createElement(CallFailedView, {dispatcher: dispatcher, emailLinkError: true,
+ store: conversationStore})
)
)
),
React.createElement(Section, {name: "StartConversationView"},
React.createElement(Example, {summary: "Start conversation view", dashed: "true"},
React.createElement("div", {className: "standalone"},
React.createElement(StartConversationView, {conversation: mockConversationModel,
--- a/browser/components/loop/ui/ui-showcase.jsx
+++ b/browser/components/loop/ui/ui-showcase.jsx
@@ -69,16 +69,21 @@
sdkDriver: {}
});
var roomStore = new loop.store.RoomStore(dispatcher, {
mozLoop: navigator.mozLoop
});
var feedbackStore = new loop.store.FeedbackStore(dispatcher, {
feedbackClient: stageFeedbackApiClient
});
+ var conversationStore = new loop.store.ConversationStore(dispatcher, {
+ client: {},
+ mozLoop: navigator.mozLoop,
+ sdkDriver: {}
+ });
// Local mocks
var mockMozLoopRooms = _.extend({}, navigator.mozLoop);
mockMozLoopRooms.roomsEnabled = true;
var mockContact = {
name: ["Mr Smith"],
@@ -371,23 +376,24 @@
</div>
</Example>
</Section>
<Section name="CallFailedView">
<Example summary="Call Failed" dashed="true"
style={{width: "260px", height: "265px"}}>
<div className="fx-embedded">
- <CallFailedView dispatcher={dispatcher} />
+ <CallFailedView dispatcher={dispatcher} store={conversationStore} />
</div>
</Example>
<Example summary="Call Failed — with call URL error" dashed="true"
style={{width: "260px", height: "265px"}}>
<div className="fx-embedded">
- <CallFailedView dispatcher={dispatcher} emailLinkError={true} />
+ <CallFailedView dispatcher={dispatcher} emailLinkError={true}
+ store={conversationStore} />
</div>
</Example>
</Section>
<Section name="StartConversationView">
<Example summary="Start conversation view" dashed="true">
<div className="standalone">
<StartConversationView conversation={mockConversationModel}
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -2403,38 +2403,38 @@ let DefaultBrowserCheck = {
if (event.target.id == "defaultBrowserNever") {
ShellService.shouldCheckDefaultBrowser = false;
}
this.closePrompt();
}
},
prompt: function(win) {
+ let useNotificationBar = Services.prefs.getBoolPref("browser.defaultbrowser.notificationbar");
+
let brandBundle = win.document.getElementById("bundle_brand");
- let shellBundle = win.document.getElementById("bundle_shell");
-
let brandShortName = brandBundle.getString("brandShortName");
- let promptMessage = shellBundle.getFormattedString("setDefaultBrowserMessage2",
- [brandShortName]);
- let yesButton = shellBundle.getFormattedString("setDefaultBrowserConfirm.label",
+ let shellBundle = win.document.getElementById("bundle_shell");
+ let buttonPrefix = "setDefaultBrowser" + (useNotificationBar ? "" : "Alert");
+ let yesButton = shellBundle.getFormattedString(buttonPrefix + "Confirm.label",
[brandShortName]);
-
- let notNowButton = shellBundle.getString("setDefaultBrowserNotNow.label");
- let notNowButtonKey = shellBundle.getString("setDefaultBrowserNotNow.accesskey");
+ let notNowButton = shellBundle.getString(buttonPrefix + "NotNow.label");
- let neverLabel = shellBundle.getString("setDefaultBrowserNever.label");
- let neverKey = shellBundle.getString("setDefaultBrowserNever.accesskey");
-
- let useNotificationBar = Services.prefs.getBoolPref("browser.defaultbrowser.notificationbar");
if (useNotificationBar) {
+ let promptMessage = shellBundle.getFormattedString("setDefaultBrowserMessage2",
+ [brandShortName]);
let optionsMessage = shellBundle.getString("setDefaultBrowserOptions.label");
let optionsKey = shellBundle.getString("setDefaultBrowserOptions.accesskey");
+ let neverLabel = shellBundle.getString("setDefaultBrowserNever.label");
+ let neverKey = shellBundle.getString("setDefaultBrowserNever.accesskey");
+
let yesButtonKey = shellBundle.getString("setDefaultBrowserConfirm.accesskey");
+ let notNowButtonKey = shellBundle.getString("setDefaultBrowserNotNow.accesskey");
let notificationBox = win.document.getElementById("high-priority-global-notificationbox");
this._createPopup(win, {
label: notNowButton,
accesskey: notNowButtonKey
}, {
label: neverLabel,
@@ -2462,24 +2462,28 @@ let DefaultBrowserCheck = {
const priority = notificationBox.PRIORITY_WARNING_HIGH;
let callback = this._onNotificationEvent.bind(this);
this._notification = notificationBox.appendNotification(promptMessage, "default-browser",
iconURL, priority, buttons,
callback);
} else {
// Modal prompt
let promptTitle = shellBundle.getString("setDefaultBrowserTitle");
+ let promptMessage = shellBundle.getFormattedString("setDefaultBrowserMessage",
+ [brandShortName]);
+ let dontAskLabel = shellBundle.getFormattedString("setDefaultBrowserDontAsk",
+ [brandShortName]);
let ps = Services.prompt;
let dontAsk = { value: false };
let buttonFlags = (ps.BUTTON_TITLE_IS_STRING * ps.BUTTON_POS_0) +
(ps.BUTTON_TITLE_IS_STRING * ps.BUTTON_POS_1) +
ps.BUTTON_POS_0_DEFAULT;
let rv = ps.confirmEx(win, promptTitle, promptMessage, buttonFlags,
- yesButton, notNowButton, null, neverLabel, dontAsk);
+ yesButton, notNowButton, null, dontAskLabel, dontAsk);
if (rv == 0) {
this.setAsDefault();
} else if (dontAsk.value) {
ShellService.shouldCheckDefaultBrowser = false;
}
}
},
--- a/browser/components/preferences/colors.xul
+++ b/browser/components/preferences/colors.xul
@@ -75,21 +75,28 @@
</hbox>
<separator class="thin"/>
<hbox align="center">
<checkbox id="browserUnderlineAnchors" label="&underlineLinks.label;" accesskey="&underlineLinks.accesskey;"
preference="browser.underline_anchors"/>
</hbox>
</groupbox>
</hbox>
+#ifdef XP_WIN
<vbox align="start">
- <label accesskey="&allowPagesToUseColors.accesskey;"
- control="useDocumentColors">&allowPagesToUseColors.label;</label>
+#else
+ <vbox>
+#endif
+ <label accesskey="&overridePageColors.accesskey;"
+ control="useDocumentColors">&overridePageColors.label;</label>
<menulist id="useDocumentColors" preference="browser.display.document_color_use">
<menupopup>
- <menuitem label="&allowPagesToUseColors.automatic.label;" value="0" id="documentColorAutomatic"/>
- <menuitem label="&allowPagesToUseColors.always.label;" value="1" id="documentColorAlways"/>
- <menuitem label="&allowPagesToUseColors.never.label;" value="2" id="documentColorNever"/>
+ <menuitem label="&overridePageColors.always.label;"
+ value="2" id="documentColorAlways"/>
+ <menuitem label="&overridePageColors.auto.label;"
+ value="0" id="documentColorAutomatic"/>
+ <menuitem label="&overridePageColors.never.label;"
+ value="1" id="documentColorNever"/>
</menupopup>
</menulist>
</vbox>
</prefpane>
</prefwindow>
--- a/browser/components/search/content/search.xml
+++ b/browser/components/search/content/search.xml
@@ -746,16 +746,21 @@
if (Services.focus.getLastFocusMethod(window) == Services.focus.FLAG_BYMOUSE)
return;
this.openSuggestionsPanel();
]]></handler>
<handler event="click" button="0">
<![CDATA[
+ // Ignore clicks on the search go button.
+ if (event.originalTarget.getAttribute("anonid") == "search-go-button") {
+ return;
+ }
+
// 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>
--- a/browser/components/search/test/browser_searchbar_openpopup.js
+++ b/browser/components/search/test/browser_searchbar_openpopup.js
@@ -1,13 +1,14 @@
// 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 goButton = document.getAnonymousElementByAttribute(searchbar, "anonid", "search-go-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() {
@@ -313,8 +314,24 @@ add_task(function* refocus_window_doesnt
// 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 = "";
});
+
+// Clicking the search go button shouldn't open the popup
+add_no_popup_task(function* search_go_doesnt_open_popup() {
+ gBrowser.selectedTab = gBrowser.addTab();
+
+ gURLBar.focus();
+ textbox.value = "foo";
+ searchbar.inputChanged();
+
+ let promise = promiseOnLoad();
+ EventUtils.synthesizeMouseAtCenter(goButton, {});
+ yield promise;
+
+ textbox.value = "";
+ gBrowser.removeCurrentTab();
+});
--- a/browser/devtools/netmonitor/netmonitor-controller.js
+++ b/browser/devtools/netmonitor/netmonitor-controller.js
@@ -387,26 +387,16 @@ let NetMonitorController = {
*/
get supportsCustomRequest() {
return this.webConsoleClient &&
(this.webConsoleClient.traits.customNetworkRequest ||
!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
*/
get supportsPerfStats() {
return this.tabClient &&
(this.tabClient.traits.reconfigure || !this._target.isApp);
},
@@ -595,17 +585,16 @@ NetworkEventsHandler.prototype = {
statusText: aPacket.response.statusText,
headersSize: aPacket.response.headersSize
});
window.emit(EVENTS.STARTED_RECEIVING_RESPONSE, actor);
break;
case "responseContent":
NetMonitorView.RequestsMenu.updateRequest(aPacket.from, {
contentSize: aPacket.contentSize,
- transferredSize: aPacket.transferredSize,
mimeType: aPacket.mimeType
});
this.webConsoleClient.getResponseContent(actor, this._onResponseContent);
window.emit(EVENTS.UPDATING_RESPONSE_CONTENT, actor);
break;
case "eventTimings":
NetMonitorView.RequestsMenu.updateRequest(aPacket.from, {
totalTime: aPacket.totalTime
--- a/browser/devtools/netmonitor/netmonitor-view.js
+++ b/browser/devtools/netmonitor/netmonitor-view.js
@@ -411,21 +411,16 @@ RequestsMenuView.prototype = Heritage.ex
$("#requests-menu-network-summary-label").addEventListener("click", this._onContextPerfCommand, false);
$("#network-statistics-back-button").addEventListener("command", this._onContextPerfCommand, false);
} else {
$("#notice-perf-message").hidden = true;
$("#request-menu-context-perf").hidden = true;
$("#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;
- }
},
/**
* Destruction function, called when the network monitor is closed.
*/
destroy: function() {
dumpn("Destroying the SourcesView");
@@ -799,18 +794,18 @@ RequestsMenuView.prototype = Heritage.ex
flash: this.isFlash,
other: this.isOther
}),
/**
* Sorts all network requests in this container by a specified detail.
*
* @param string aType
- * Either "status", "method", "file", "domain", "type", "transferred",
- * "size" or "waterfall".
+ * Either "status", "method", "file", "domain", "type", "size" or
+ * "waterfall".
*/
sortBy: function(aType = "waterfall") {
let target = $("#requests-menu-" + aType + "-button");
let headers = document.querySelectorAll(".requests-menu-header-button");
for (let header of headers) {
if (header != target) {
header.removeAttribute("sorted");
@@ -861,23 +856,16 @@ RequestsMenuView.prototype = Heritage.ex
break;
case "type":
if (direction == "ascending") {
this.sortContents(this._byType);
} else {
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);
} else {
this.sortContents((a, b) => !this._bySize(a, b));
}
break;
case "waterfall":
@@ -1000,23 +988,18 @@ RequestsMenuView.prototype = Heritage.ex
_byType: function({ attachment: first }, { attachment: second }) {
let firstType = this._getAbbreviatedMimeType(first.mimeType).toLowerCase();
let secondType = this._getAbbreviatedMimeType(second.mimeType).toLowerCase();
return firstType == secondType
? first.startedMillis > second.startedMillis
: firstType > secondType;
},
- _byTransferred: function({ attachment: first }, { attachment: second }) {
- return first.transferredSize > second.transferredSize;
- },
-
- _bySize: function({ attachment: first }, { attachment: second }) {
- return first.contentSize > second.contentSize;
- },
+ _bySize: function({ attachment: first }, { attachment: second })
+ first.contentSize > second.contentSize,
/**
* Refreshes the status displayed in this container's footer, providing
* concise information about all requests.
*/
refreshSummary: function() {
let visibleItems = this.visibleItems;
let visibleRequestsCount = visibleItems.length;
@@ -1171,20 +1154,16 @@ RequestsMenuView.prototype = Heritage.ex
break;
case "headersSize":
requestItem.attachment.headersSize = value;
break;
case "contentSize":
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);
break;
case "responseContent":
// If there's no mime type available when the response content
// is received, assume text/plain as a fallback.
if (!requestItem.attachment.mimeType) {
@@ -1323,30 +1302,16 @@ RequestsMenuView.prototype = Heritage.ex
let kb = aValue / 1024;
let size = L10N.numberWithDecimals(kb, CONTENT_SIZE_DECIMALS);
let node = $(".requests-menu-size", target);
let text = L10N.getFormatStr("networkMenu.sizeKB", size);
node.setAttribute("value", text);
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);
let text = CONTENT_MIME_TYPE_ABBREVIATIONS[type] || type;
node.setAttribute("value", text);
node.setAttribute("tooltiptext", aValue);
break;
}
--- a/browser/devtools/netmonitor/netmonitor.xul
+++ b/browser/devtools/netmonitor/netmonitor.xul
@@ -96,26 +96,16 @@
align="center">
<button id="requests-menu-type-button"
class="requests-menu-header-button requests-menu-type"
data-key="type"
label="&netmonitorUI.toolbar.type;"
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">
<button id="requests-menu-size-button"
class="requests-menu-header-button requests-menu-size"
data-key="size"
label="&netmonitorUI.toolbar.size;"
flex="1">
@@ -179,18 +169,16 @@
<label class="plain requests-menu-file"
crop="end"
flex="1"/>
</hbox>
<label class="plain requests-menu-subitem requests-menu-domain"
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"
align="center"
flex="1">
<hbox class="requests-menu-timings"
align="center">
<label class="plain requests-menu-timings-total"/>
--- a/browser/devtools/netmonitor/test/browser_net_simple-request-data.js
+++ b/browser/devtools/netmonitor/test/browser_net_simple-request-data.js
@@ -60,18 +60,16 @@ function test() {
"The httpVersion should not yet be set.");
is(requestItem.attachment.status, undefined,
"The status should not yet be set.");
is(requestItem.attachment.statusText, undefined,
"The statusText should not yet be set.");
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.");
is(requestItem.attachment.mimeType, undefined,
"The mimeType should not yet be set.");
is(requestItem.attachment.responseContent, undefined,
"The responseContent should not yet be set.");
@@ -153,27 +151,24 @@ function test() {
status: "200",
statusText: "Och Aye"
});
});
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",
"The mimeType attachment has an incorrect value.");
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),
});
});
aMonitor.panelWin.once(aMonitor.panelWin.EVENTS.RECEIVED_RESPONSE_CONTENT, () => {
let requestItem = RequestsMenu.getItemAtIndex(0);
ok(requestItem.attachment.responseContent,
@@ -183,17 +178,16 @@ function test() {
is(requestItem.attachment.responseContent.content.text, "Hello world!",
"The responseContent attachment has an incorrect |content.text| property.");
is(requestItem.attachment.responseContent.content.size, 12,
"The responseContent attachment has an incorrect |content.size| property.");
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),
});
});
aMonitor.panelWin.once(aMonitor.panelWin.EVENTS.UPDATING_EVENT_TIMINGS, () => {
let requestItem = RequestsMenu.getItemAtIndex(0);
is(typeof requestItem.attachment.totalTime, "number",
--- a/browser/devtools/netmonitor/test/browser_net_sort-01.js
+++ b/browser/devtools/netmonitor/test/browser_net_sort-01.js
@@ -197,57 +197,52 @@ function test() {
"The requests menu items aren't ordered correctly. Fifth item is misplaced.");
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(a),
"GET", STATUS_CODES_SJS + "?sts=100", {
status: 101,
statusText: "Switching Protocols",
type: "plain",
fullMimeType: "text/plain; charset=utf-8",
- transferred: L10N.getStr("networkMenu.sizeUnavailable"),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0),
time: true
});
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(b),
"GET", STATUS_CODES_SJS + "?sts=200", {
status: 202,
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
});
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(c),
"GET", STATUS_CODES_SJS + "?sts=300", {
status: 303,
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
});
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(d),
"GET", STATUS_CODES_SJS + "?sts=400", {
status: 404,
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
});
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(e),
"GET", STATUS_CODES_SJS + "?sts=500", {
status: 501,
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
});
return promise.resolve(null);
}
aDebuggee.performRequests();
--- a/browser/devtools/netmonitor/test/browser_net_sort-02.js
+++ b/browser/devtools/netmonitor/test/browser_net_sort-02.js
@@ -98,34 +98,16 @@ function test() {
})
.then(() => {
info("Testing type sort, ascending. Checking sort loops correctly.");
EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-type-button"));
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"));
testHeaders("size", "ascending");
return testContents([0, 1, 2, 3, 4]);
})
.then(() => {
info("Testing size sort, descending.");
EventUtils.sendMouseEvent({ type: "click" }, $("#requests-menu-size-button"));
@@ -212,61 +194,56 @@ function test() {
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(a),
"GET1", SORTING_SJS + "?index=1", {
fuzzyUrl: true,
status: 101,
statusText: "Meh",
type: "1",
fullMimeType: "text/1",
- transferred: L10N.getStr("networkMenu.sizeUnavailable"),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0),
time: true
});
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(b),
"GET2", SORTING_SJS + "?index=2", {
fuzzyUrl: true,
status: 200,
statusText: "Meh",
type: "2",
fullMimeType: "text/2",
- transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01),
time: true
});
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(c),
"GET3", SORTING_SJS + "?index=3", {
fuzzyUrl: true,
status: 300,
statusText: "Meh",
type: "3",
fullMimeType: "text/3",
- transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
time: true
});
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(d),
"GET4", SORTING_SJS + "?index=4", {
fuzzyUrl: true,
status: 400,
statusText: "Meh",
type: "4",
fullMimeType: "text/4",
- transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
time: true
});
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(e),
"GET5", SORTING_SJS + "?index=5", {
fuzzyUrl: true,
status: 500,
statusText: "Meh",
type: "5",
fullMimeType: "text/5",
- transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
time: true
});
return promise.resolve(null);
}
aDebuggee.performRequests();
--- a/browser/devtools/netmonitor/test/browser_net_sort-03.js
+++ b/browser/devtools/netmonitor/test/browser_net_sort-03.js
@@ -125,69 +125,64 @@ function test() {
for (let i = 0, len = aOrder.length / 5; i < len; i++) {
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(aOrder[i]),
"GET1", SORTING_SJS + "?index=1", {
fuzzyUrl: true,
status: 101,
statusText: "Meh",
type: "1",
fullMimeType: "text/1",
- transferred: L10N.getStr("networkMenu.sizeUnavailable"),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0),
time: true
});
}
for (let i = 0, len = aOrder.length / 5; i < len; i++) {
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(aOrder[i + len]),
"GET2", SORTING_SJS + "?index=2", {
fuzzyUrl: true,
status: 200,
statusText: "Meh",
type: "2",
fullMimeType: "text/2",
- transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01),
time: true
});
}
for (let i = 0, len = aOrder.length / 5; i < len; i++) {
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(aOrder[i + len * 2]),
"GET3", SORTING_SJS + "?index=3", {
fuzzyUrl: true,
status: 300,
statusText: "Meh",
type: "3",
fullMimeType: "text/3",
- transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
time: true
});
}
for (let i = 0, len = aOrder.length / 5; i < len; i++) {
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(aOrder[i + len * 3]),
"GET4", SORTING_SJS + "?index=4", {
fuzzyUrl: true,
status: 400,
statusText: "Meh",
type: "4",
fullMimeType: "text/4",
- transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
time: true
});
}
for (let i = 0, len = aOrder.length / 5; i < len; i++) {
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(aOrder[i + len * 4]),
"GET5", SORTING_SJS + "?index=5", {
fuzzyUrl: true,
status: 500,
statusText: "Meh",
type: "5",
fullMimeType: "text/5",
- transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
time: true
});
}
return promise.resolve(null);
}
--- a/browser/devtools/netmonitor/test/browser_net_timeline_ticks.js
+++ b/browser/devtools/netmonitor/test/browser_net_timeline_ticks.js
@@ -7,22 +7,16 @@
function test() {
initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => {
info("Starting 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"),
"An timeline label should be displayed when the frontend is opened.");
ok(document.querySelectorAll(".requests-menu-timings-division").length == 0,
"No tick labels should be displayed when the frontend is opened.");
ok(!RequestsMenu._canvas,
--- a/browser/devtools/netmonitor/test/head.js
+++ b/browser/devtools/netmonitor/test/head.js
@@ -259,17 +259,17 @@ function verifyRequestItemTarget(aReques
let requestsMenu = aRequestItem.ownerView;
let widgetIndex = requestsMenu.indexOfItem(aRequestItem);
let visibleIndex = requestsMenu.visibleItems.indexOf(aRequestItem);
info("Widget index of item: " + widgetIndex);
info("Visible index of item: " + visibleIndex);
- let { fuzzyUrl, status, statusText, type, fullMimeType, transferred, size, time } = aData;
+ let { fuzzyUrl, status, statusText, type, fullMimeType, size, time } = aData;
let { attachment, target } = aRequestItem
let uri = Services.io.newURI(aUrl, null, null).QueryInterface(Ci.nsIURL);
let name = uri.fileName || "/";
let query = uri.query;
let hostPort = uri.hostPort;
if (fuzzyUrl) {
@@ -314,24 +314,16 @@ function verifyRequestItemTarget(aReques
if (type !== undefined) {
let value = target.querySelector(".requests-menu-type").getAttribute("value");
let tooltip = target.querySelector(".requests-menu-type").getAttribute("tooltiptext");
info("Displayed type: " + value);
info("Tooltip type: " + tooltip);
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");
info("Displayed size: " + value);
info("Tooltip size: " + tooltip);
is(value, size, "The displayed size is incorrect.");
is(tooltip, size, "The tooltip size is incorrect.");
}
--- a/browser/locales/en-US/chrome/browser/devtools/netmonitor.dtd
+++ b/browser/locales/en-US/chrome/browser/devtools/netmonitor.dtd
@@ -37,24 +37,18 @@
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.domain): This is the label displayed
- in the network table toolbar, above the "domain" column. -->
<!ENTITY netmonitorUI.toolbar.domain "Domain">
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.type): This is the label displayed
- 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, which is the
- - uncompressed / decoded size. -->
+ - in the network table toolbar, above the "size" column. -->
<!ENTITY netmonitorUI.toolbar.size "Size">
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.waterfall): This is the label displayed
- in the network table toolbar, above the "waterfall" column. -->
<!ENTITY netmonitorUI.toolbar.waterfall "Timeline">
<!-- LOCALIZATION NOTE (debuggerUI.tab.headers): This is the label displayed
- in the network details pane identifying the headers tab. -->
--- a/browser/locales/en-US/chrome/browser/devtools/netmonitor.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/netmonitor.properties
@@ -124,21 +124,16 @@ networkMenu.empty=No requests
# information about all requests. Parameters: #1 is the number of requests,
# #2 is the size, #3 is the number of seconds.
networkMenu.summary=One request, #2 KB, #3 s;#1 requests, #2 KB, #3 s
# LOCALIZATION NOTE (networkMenu.sizeKB): This is the label displayed
# 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
# LOCALIZATION NOTE (networkMenu.millisecond): This is the label displayed
# in the network menu specifying timing interval divisions (in milliseconds).
networkMenu.millisecond=%S ms
--- a/browser/locales/en-US/chrome/browser/loop/loop.properties
+++ b/browser/locales/en-US/chrome/browser/loop/loop.properties
@@ -220,16 +220,22 @@ call_progress_connecting_description=Connecting…
## when the other client is actually ringing.
## https://people.mozilla.org/~dhenein/labs/loop-mvp-spec/#call-outgoing
call_progress_ringing_description=Ringing…
peer_ended_conversation2=The person you were calling has ended the conversation.
conversation_has_ended=Your conversation has ended.
restart_call=Rejoin
+## LOCALIZATION NOTE (contact_unavailable_title): The title displayed
+## when a contact is unavailable. Don't translate the part between {{..}}
+## because this will be replaced by the contact's name.
+contact_unavailable_title={{contactName}} is unavailable.
+generic_contact_unavailable_title=This person is unavailable.
+
generic_failure_title=Something went wrong.
generic_failure_with_reason2=You can try again or email a link to be reached at later.
generic_failure_no_reason2=Would you like to try again?
## LOCALIZATION NOTE (contact_offline_title): Title for
## https://people.mozilla.org/~dhenein/labs/loop-mvp-spec/#link-prompt
## displayed when the contact is offline.
contact_offline_title=This person is not online
--- a/browser/locales/en-US/chrome/browser/preferences/colors.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/colors.dtd
@@ -1,22 +1,22 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!ENTITY colorsDialog.title "Colors">
<!ENTITY window.width "38em">
<!ENTITY window.macWidth "41em">
-<!ENTITY allowPagesToUseColors.label "Allow pages to choose their own colors, instead of my selections above:">
-<!ENTITY allowPagesToUseColors.accesskey "A">
+<!ENTITY overridePageColors.label "Override the colors specified by the page with my selections above:">
+<!ENTITY overridePageColors.accesskey "O">
-<!ENTITY allowPagesToUseColors.automatic.label "Automatic">
-<!ENTITY allowPagesToUseColors.always.label "Always">
-<!ENTITY allowPagesToUseColors.never.label "Never">
+<!ENTITY overridePageColors.always.label "Always">
+<!ENTITY overridePageColors.auto.label "Only with High Contrast themes">
+<!ENTITY overridePageColors.never.label "Never">
<!ENTITY color "Text and Background">
<!ENTITY textColor.label "Text:">
<!ENTITY textColor.accesskey "T">
<!ENTITY backgroundColor.label "Background:">
<!ENTITY backgroundColor.accesskey "B">
<!ENTITY useSystemColors.label "Use system colors">
<!ENTITY useSystemColors.accesskey "s">
--- a/browser/locales/en-US/chrome/browser/shellservice.properties
+++ b/browser/locales/en-US/chrome/browser/shellservice.properties
@@ -12,18 +12,20 @@ setDefaultBrowserConfirm.label = Use
setDefaultBrowserConfirm.accesskey = U
setDefaultBrowserOptions.label = Options
setDefaultBrowserOptions.accesskey = O
setDefaultBrowserNotNow.label = Not now
setDefaultBrowserNotNow.accesskey = N
setDefaultBrowserNever.label = Don't ask me again
setDefaultBrowserNever.accesskey = D
-# LOCALIZATION NOTE (setDefaultBrowserTitle, setDefaultBrowserMessage, setDefaultBrowserDontAsk):
+# LOCALIZATION NOTE (setDefaultBrowserTitle, setDefaultBrowserMessage, setDefaultBrowserDontAsk, setDefaultBrowserAlertConfirm.label, setDefaultBrowserAlertNotNow.label):
# These strings are used as an alternative to the ones above, in a modal dialog.
# %S will be replaced by brandShortName
setDefaultBrowserTitle=Default Browser
setDefaultBrowserMessage=%S is not currently set as your default browser. Would you like to make it your default browser?
setDefaultBrowserDontAsk=Always perform this check when starting %S.
+setDefaultBrowserAlertConfirm.label=Use %S as my default browser
+setDefaultBrowserAlertNotNow.label=Not now
desktopBackgroundLeafNameWin=Desktop Background.bmp
DesktopBackgroundDownloading=Saving Picture…
DesktopBackgroundSet=Set Desktop Background
--- a/browser/metro/theme/touchcontrols.css
+++ b/browser/metro/theme/touchcontrols.css
@@ -40,27 +40,31 @@
.fullscreenButton {
background: url("chrome://browser/skin/images/fullscreen-hdpi.png") no-repeat center;
}
.fullscreenButton[fullscreened="true"] {
background: url("chrome://browser/skin/images/exitfullscreen-hdpi.png") no-repeat center;
}
+.controlBar[fullscreen-unavailable] .fullscreenButton {
+ display: none;
+}
+
.playButton {
background: url("chrome://browser/skin/images/pause-hdpi.png") no-repeat center;
}
/*
* Normally the button bar has fullscreen spacer play spacer mute, but if
* this is an audio control rather than a video control, the fullscreen button
* is hidden by videocontrols.xml, and that alters the position of the
* play button. This workaround moves it back to center.
*/
-.controlBar.audio-only .playButton {
+.controlBar[fullscreen-unavailable] .playButton {
transform: translateX(28px);
}
.playButton[paused="true"] {
background: url("chrome://browser/skin/images/play-hdpi.png") no-repeat center;
}
.castingButton {
--- a/browser/themes/linux/searchbar.css
+++ b/browser/themes/linux/searchbar.css
@@ -1,12 +1,16 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#PopupSearchAutoComplete {
+ -moz-margin-start: -24px;
+}
+
.searchbar-textbox {
min-height: 22px;
background-color: -moz-field;
}
.autocomplete-textbox-container {
-moz-box-align: stretch;
}
@@ -19,17 +23,16 @@
font-weight: bold;
}
/* Engine button */
.searchbar-engine-image {
height: 16px;
width: 16px;
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
- -moz-margin-start: 2px;
}
.searchbar-engine-button {
-moz-appearance: none;
min-width: 0;
margin: 0;
border: 0;
-moz-box-align: center;
@@ -67,24 +70,22 @@ menuitem[cmd="cmd_clearhistory"][disable
list-style-image: url("moz-icon://stock/gtk-clear?size=menu&state=disabled");
}
.searchbar-search-button-container {
-moz-box-align: center;
- padding: 2px 3px;
- -moz-padding-end: 2px;
}
.searchbar-search-button {
list-style-image: url("chrome://browser/skin/search-indicator.png");
-moz-image-region: rect(0, 20px, 20px, 0);
- margin: -2px -2px;
+ -moz-margin-start: 2px;
}
.searchbar-search-button[addengines="true"] {
list-style-image: url("chrome://browser/skin/search-indicator-badge-add.png");
}
.searchbar-search-button:hover {
-moz-image-region: rect(0, 40px, 20px, 20px);
@@ -235,17 +236,17 @@ searchbar[oneoffui] .searchbar-engine-bu
border-top: none !important;
}
.search-panel-tree > .autocomplete-treebody::-moz-tree-cell-text {
-moz-padding-start: 4px;
}
.search-panel-tree > .autocomplete-treebody::-moz-tree-image {
- -moz-padding-start: 6px;
+ -moz-padding-start: 5px;
width: 14px;
height: 14px;
}
.search-panel-tree > .autocomplete-treebody::-moz-tree-image(fromhistory) {
list-style-image: url("chrome://browser/skin/search-history-icon.svg#search-history-icon");
}
--- a/browser/themes/osx/searchbar.css
+++ b/browser/themes/osx/searchbar.css
@@ -1,12 +1,16 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#PopupSearchAutoComplete {
+ -moz-margin-start: -23px;
+}
+
.searchbar-dropmarker-image {
--searchbar-dropmarker-url: url("chrome://browser/skin/searchbar-dropmarker.png");
--searchbar-dropmarker-2x-url: url("chrome://browser/skin/searchbar-dropmarker@2x.png");
}
.searchbar-textbox {
border-radius: 10000px;
}
@@ -44,28 +48,27 @@
.search-go-container {
-moz-box-align: center;
-moz-padding-end: 6px;
}
.searchbar-search-button-container {
-moz-box-align: center;
- -moz-padding-start: 6px;
- -moz-padding-end: 4px;
}
.search-go-button {
list-style-image: url("chrome://browser/skin/Search.png");
}
.searchbar-search-button {
list-style-image: url("chrome://browser/skin/search-indicator.png");
-moz-image-region: rect(0, 20px, 20px, 0);
- margin: 0 -3px;
+ -moz-margin-start: 3px;
+ -moz-margin-end: 1px;
}
.searchbar-search-button[addengines="true"] {
list-style-image: url("chrome://browser/skin/search-indicator-badge-add.png");
}
.searchbar-search-button:hover {
-moz-image-region: rect(0, 40px, 20px, 20px);
--- a/browser/themes/shared/devtools/netmonitor.inc.css
+++ b/browser/themes/shared/devtools/netmonitor.inc.css
@@ -161,21 +161,16 @@
width: 4em;
}
.requests-menu-size {
text-align: center;
width: 8em;
}
-.requests-menu-transferred {
- text-align: center;
- width: 8em;
-}
-
/* Network requests table: status codes */
box.requests-menu-status {
background: #fff;
width: 10px;
-moz-margin-start: 5px;
-moz-margin-end: 5px;
border-radius: 10px;
--- a/browser/themes/windows/searchbar.css
+++ b/browser/themes/windows/searchbar.css
@@ -1,12 +1,16 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#PopupSearchAutoComplete {
+ -moz-margin-start: -25px;
+}
+
.searchbar-dropmarker-image {
--searchbar-dropmarker-url: url("chrome://browser/skin/searchbar-dropdown-arrow.png");
}
.autocomplete-textbox-container {
-moz-box-align: stretch;
}
@@ -16,17 +20,16 @@
/* ::::: searchbar-engine-button ::::: */
.searchbar-engine-image {
height: 16px;
width: 16px;
list-style-image: url("chrome://global/skin/icons/folder-item.png");
-moz-image-region: rect(0px, 16px, 16px, 0px);
- -moz-margin-start: 2px;
}
.searchbar-engine-button {
-moz-appearance: none;
min-width: 0;
margin: 0;
padding: 0;
-moz-padding-end: 2px;
@@ -78,24 +81,24 @@
.searchbar-engine-menuitem[selected="true"] > .menu-iconic-text {
font-weight: bold;
}
.searchbar-search-button-container {
-moz-box-align: center;
- padding: 3px 4px;
- -moz-padding-end: 2px;
}
.searchbar-search-button {
list-style-image: url("chrome://browser/skin/search-indicator.png");
-moz-image-region: rect(0, 20px, 20px, 0);
- margin: -2px -2px;
+ margin-top: 1px;
+ margin-bottom: 1px;
+ -moz-margin-start: 4px;
}
.searchbar-search-button[addengines="true"] {
list-style-image: url("chrome://browser/skin/search-indicator-badge-add.png");
}
.searchbar-search-button:hover {
-moz-image-region: rect(0, 40px, 20px, 20px);
--- a/mobile/android/base/tests/BaseTest.java
+++ b/mobile/android/base/tests/BaseTest.java
@@ -854,44 +854,44 @@ abstract class BaseTest extends BaseRobo
pageShowExpecter.blockForEvent();
pageShowExpecter.unregisterListener();
}
public void forward() {
Actions.EventExpecter pageShowExpecter = mActions.expectGeckoEvent("Content:PageShow");
if (devType.equals("tablet")) {
- Element fwdBtn = mDriver.findElement(getActivity(), R.id.forward);
- fwdBtn.click();
+ mSolo.waitForView(R.id.forward);
+ mSolo.clickOnView(mSolo.getView(R.id.forward));
} else {
mActions.sendSpecialKey(Actions.SpecialKey.MENU);
waitForText("^New Tab$");
if (!osVersion.equals("2.x")) {
- Element fwdBtn = mDriver.findElement(getActivity(), R.id.forward);
- fwdBtn.click();
+ mSolo.waitForView(R.id.forward);
+ mSolo.clickOnView(mSolo.getView(R.id.forward));
} else {
mSolo.clickOnText("^Forward$");
}
ensureMenuClosed();
}
pageShowExpecter.blockForEvent();
pageShowExpecter.unregisterListener();
}
public void reload() {
if (devType.equals("tablet")) {
- Element reloadBtn = mDriver.findElement(getActivity(), R.id.reload);
- reloadBtn.click();
+ mSolo.waitForView(R.id.reload);
+ mSolo.clickOnView(mSolo.getView(R.id.reload));
} else {
mActions.sendSpecialKey(Actions.SpecialKey.MENU);
waitForText("^New Tab$");
if (!osVersion.equals("2.x")) {
- Element reloadBtn = mDriver.findElement(getActivity(), R.id.reload);
- reloadBtn.click();
+ mSolo.waitForView(R.id.reload);
+ mSolo.clickOnView(mSolo.getView(R.id.reload));
} else {
mSolo.clickOnText("^Reload$");
}
ensureMenuClosed();
}
}
// DEPRECATED!
--- a/mobile/android/chrome/content/aboutPasswords.js
+++ b/mobile/android/chrome/content/aboutPasswords.js
@@ -27,56 +27,80 @@ function copyStringAndToast(string, noti
gChromeWin.NativeWindow.toast.show(notifyString, "short");
} catch (e) {
debug("Error copying from about:passwords");
gChromeWin.NativeWindow.toast.show(gStringBundle.GetStringFromName("passwordsDetails.copyFailed"), "short");
}
}
let Passwords = {
+ _logins: [],
+
+ _getLogins: function() {
+ let logins;
+ try {
+ logins = Services.logins.getAllLogins();
+ } catch(e) {
+ // Master password was not entered
+ debug("Master password permissions error: " + e);
+ logins = [];
+ }
+
+ logins.sort((a, b) => a.hostname.localeCompare(b.hostname));
+ return this._logins = logins;
+ },
+
init: function () {
window.addEventListener("popstate", this , false);
Services.obs.addObserver(this, "passwordmgr-storage-changed", false);
- this._loadList();
+ this._loadList(this._getLogins());
document.getElementById("copyusername-btn").addEventListener("click", this._copyUsername.bind(this), false);
document.getElementById("copypassword-btn").addEventListener("click", this._copyPassword.bind(this), false);
document.getElementById("details-header").addEventListener("click", this._openLink.bind(this), false);
+ let filterInput = document.getElementById("filter-input");
+ let filterContainer = document.getElementById("filter-input-container");
+
+ filterInput.addEventListener("input", this._filter.bind(this), false);
+ filterInput.addEventListener("blur", (event) => {
+ filterContainer.setAttribute("hidden", true);
+ });
+
+ document.getElementById("filter-button").addEventListener("click", (event) => {
+ filterContainer.removeAttribute("hidden");
+ filterInput.focus();
+ }, false);
+
+ document.getElementById("filter-clear").addEventListener("click", (event) => {
+ filterInput.blur();
+ filterInput.value = "";
+ this._loadList(this._logins);
+ }, false);
+
this._showList();
},
uninit: function () {
Services.obs.removeObserver(this, "passwordmgr-storage-changed");
window.removeEventListener("popstate", this, false);
},
- _loadList: function () {
- let logins;
- try {
- logins = Services.logins.getAllLogins();
- } catch(e) {
- // Master password was not entered
- debug("Master password permissions error: " + e);
- return;
- }
+ _loadList: function (logins) {
+ let list = document.getElementById("logins-list");
+ let newList = list.cloneNode(false);
- logins.forEach(login => login.QueryInterface(Ci.nsILoginMetaInfo));
-
- logins.sort((a, b) => a.hostname.localeCompare(b.hostname));
-
- // Clear all content before filling the logins
- let list = document.getElementById("logins-list");
- list.innerHTML = "";
logins.forEach(login => {
let item = this._createItemForLogin(login);
- list.appendChild(item);
+ newList.appendChild(item);
});
+
+ list.parentNode.replaceChild(newList, list);
},
_showList: function () {
// Hide the detail page and show the list
let details = document.getElementById("login-details");
details.setAttribute("hidden", "true");
let list = document.getElementById("logins-list");
list.removeAttribute("hidden");
@@ -153,17 +177,17 @@ let Passwords = {
}
}
},
observe: function (subject, topic, data) {
switch(topic) {
case "passwordmgr-storage-changed": {
// Reload passwords content.
- this._loadList();
+ this._loadList(this._getLogins());
break;
}
}
},
_showDetails: function (listItem) {
let detailItem = document.querySelector("#login-details > .login-item");
let login = detailItem.login = listItem.login;
@@ -212,13 +236,33 @@ let Passwords = {
let login = detailItem.login;
copyStringAndToast(login.password, gStringBundle.GetStringFromName("passwordsDetails.passwordCopied"));
},
_openLink: function (clickEvent) {
let url = clickEvent.currentTarget.getAttribute("link");
let BrowserApp = gChromeWin.BrowserApp;
BrowserApp.addTab(url, { selected: true, parentId: BrowserApp.selectedTab.id });
+ },
+
+ _filter: function(event) {
+ let value = event.target.value;
+ let logins = this._logins.filter((login) => {
+ if (login.hostname.toLowerCase().indexOf(value) != -1) {
+ return true;
+ }
+ if (login.username &&
+ login.username.toLowerCase().indexOf(value) != -1) {
+ return true;
+ }
+ if (login.httpRealm &&
+ login.httpRealm.toLowerCase().indexOf(value) != -1) {
+ return true;
+ }
+ return false;
+ });
+
+ this._loadList(logins);
}
};
window.addEventListener("load", Passwords.init.bind(Passwords), false);
window.addEventListener("unload", Passwords.uninit.bind(Passwords), false);
--- a/mobile/android/chrome/content/aboutPasswords.xhtml
+++ b/mobile/android/chrome/content/aboutPasswords.xhtml
@@ -18,16 +18,19 @@
<link rel="icon" type="image/png" sizes="64x64" href="chrome://branding/content/favicon64.png" />
<link rel="stylesheet" href="chrome://browser/skin/aboutBase.css" type="text/css"/>
<link rel="stylesheet" href="chrome://browser/skin/aboutPasswords.css" type="text/css"/>
<script type="application/javascript;version=1.8" src="chrome://browser/content/aboutPasswords.js"></script>
</head>
<body dir="&locale.dir;">
<div id="passwords-header" class="header">
<div>&aboutPasswords.title;</div>
+ <ul class="toolbar-buttons">
+ <li id="filter-button"></li>
+ </ul>
</div>
<div id="logins-list" class="list" hidden="true">
</div>
<div id="login-details" class="list" hidden="true">
<div class="login-item list-item">
<img class="icon"/>
<div id="details-header" class="inner">
<div class="details">
@@ -38,10 +41,14 @@
<div id="detail-age"></div>
</div>
<div class="buttons">
<button id="copyusername-btn">&aboutPasswords.copyUsername;</button>
<button id="copypassword-btn">&aboutPasswords.copyPassword;</button>
</div>
</div>
</div>
+ <div id="filter-input-container" hidden="true">
+ <input id="filter-input" type="search"/>
+ <div id="filter-clear"></div>
+ </div>
</body>
</html>
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -11,23 +11,24 @@ let Cu = Components.utils;
let Cr = Components.results;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/AddonManager.jsm");
Cu.import('resource://gre/modules/Payment.jsm');
Cu.import("resource://gre/modules/NotificationDB.jsm");
Cu.import("resource://gre/modules/SpatialNavigation.jsm");
-// TODO: Lazy load this based on a message...?
-Cu.import("resource://gre/modules/DownloadNotifications.jsm");
#ifdef ACCESSIBILITY
Cu.import("resource://gre/modules/accessibility/AccessFu.jsm");
#endif
+XPCOMUtils.defineLazyModuleGetter(this, "DownloadNotifications",
+ "resource://gre/modules/DownloadNotifications.jsm");
+
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
"resource://gre/modules/FileUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "JNI",
"resource://gre/modules/JNI.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "UITelemetry",
"resource://gre/modules/UITelemetry.jsm");
@@ -367,16 +368,17 @@ var BrowserApp = {
Services.obs.notifyObservers(window, "browser-delayed-startup-finished", "");
Messaging.sendRequest({ type: "Gecko:DelayedStartup" });
// Queue up some other performance-impacting initializations
Services.tm.mainThread.dispatch(function() {
Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
CastingApps.init();
+ DownloadNotifications.init();
// Delay this a minute because there's no rush
setTimeout(() => {
BrowserApp.gmpInstallManager = new GMPInstallManager();
BrowserApp.gmpInstallManager.simpleCheckAndInstall().then(null, () => {});
}, 1000 * 60);
}, Ci.nsIThread.DISPATCH_NORMAL);
@@ -461,17 +463,16 @@ var BrowserApp = {
}, false);
// When a restricted key is pressed in DOM full-screen mode, we should display
// the "Press ESC to exit" warning message.
window.addEventListener("MozShowFullScreenWarning", showFullScreenWarning, true);
NativeWindow.init();
LightWeightThemeWebInstaller.init();
- DownloadNotifications.init();
FormAssistant.init();
IndexedDB.init();
HealthReportStatusListener.init();
XPInstallObserver.init();
CharacterEncoding.init();
ActivityObserver.init();
// TODO: replace with Android implementation of WebappOSUtils.isLaunchable.
Cu.import("resource://gre/modules/Webapps.jsm");
--- a/mobile/android/themes/core/aboutPasswords.css
+++ b/mobile/android/themes/core/aboutPasswords.css
@@ -1,11 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+%filter substitution
+%include defines.inc
+
.hidden {
display: none;
}
.details {
width: 100%;
}
@@ -25,8 +29,76 @@
overflow: hidden;
flex: 1;
}
.realm {
/* hostname is not localized, so keep the margin on the left side */
margin-left: .67em;
}
+
+.toolbar-buttons {
+ list-style: none;
+}
+
+.toolbar-buttons > li {
+ background-position: center;
+ background-size: 32px 32px;
+ background-repeat: no-repeat;
+ height: 32px;
+ width: 32px;
+ margin: 0 15px;
+}
+
+#filter-input-container {
+ position: fixed;
+ bottom: 0;
+ width: 100%;
+ padding: 10px 0;
+ display: flex;
+ background: @color_about_background@;
+ border-top: 2px solid @color_about_item_border@;
+}
+
+#filter-input-container[hidden] {
+ display: none;
+}
+
+#filter-input {
+ flex: 1;
+ padding: 5px;
+ -moz-margin-start: 10px;
+ border-radius: 3px;
+}
+
+#filter-button {
+ background-image: url("resource://android/res/drawable-mdpi-v4/ab_search.png");
+}
+
+#filter-clear {
+ background-image: url("resource://android/res/drawable-mdpi-v4/close_edit_mode_light.png");
+ background-position: center;
+ background-size: 12px 12px;
+ background-repeat: no-repeat;
+ height: 32px;
+ width: 32px;
+ margin: 0 5px;
+}
+
+@media screen and (min-resolution: 1.25dppx) {
+ #filter-button {
+ background-image: url("resource://android/res/drawable-hdpi-v4/ab_search.png");
+ }
+
+ #filter-clear {
+ background-image: url("resource://android/res/drawable-hdpi-v4/close_edit_mode_light.png");
+ }
+}
+
+@media screen and (min-resolution: 2dppx) {
+ #filter-button {
+ background-image: url("resource://android/res/drawable-xhdpi-v4/ab_search.png");
+ }
+
+ #filter-clear {
+ background-image: url("resource://android/res/drawable-hdpi-v4/close_edit_mode_light.png");
+ }
+}
--- a/mobile/android/themes/core/jar.mn
+++ b/mobile/android/themes/core/jar.mn
@@ -31,17 +31,17 @@ chrome.jar:
% override chrome://global/skin/about.css chrome://browser/skin/about.css
% override chrome://global/skin/aboutMemory.css chrome://browser/skin/aboutMemory.css
% override chrome://global/skin/aboutReader.css chrome://browser/skin/aboutReader.css
% override chrome://global/skin/aboutSupport.css chrome://browser/skin/aboutSupport.css
% override chrome://global/skin/media/videocontrols.css chrome://browser/skin/touchcontrols.css
% override chrome://global/skin/netError.css chrome://browser/skin/netError.css
#ifdef NIGHTLY_BUILD
- skin/aboutPasswords.css (aboutPasswords.css)
+* skin/aboutPasswords.css (aboutPasswords.css)
#endif
skin/images/search.png (images/search.png)
skin/images/lock.png (images/lock.png)
skin/images/textfield.png (images/textfield.png)
skin/images/5stars.png (images/5stars.png)
skin/images/addons-32.png (images/addons-32.png)
--- a/mobile/android/themes/core/touchcontrols.css
+++ b/mobile/android/themes/core/touchcontrols.css
@@ -75,16 +75,20 @@
background-color: transparent;
background: url("chrome://browser/skin/images/fullscreen-hdpi.png") no-repeat center;
}
.fullscreenButton[fullscreened] {
background: url("chrome://browser/skin/images/exitfullscreen-hdpi.png") no-repeat center;
}
+.controlBar[fullscreen-unavailable] .fullscreenButton {
+ display: none;
+}
+
/* bars */
.scrubberStack {
width: 100%;
min-height: 32px;
max-height: 32px;
padding: 0px 8px;
margin: 0px;
}
--- a/python/mozboot/bin/bootstrap.py
+++ b/python/mozboot/bin/bootstrap.py
@@ -27,17 +27,17 @@ from optparse import OptionParser
# The next two variables define where in the repository the Python files
# reside. This is used to remotely download file content when it isn't
# available locally.
REPOSITORY_PATH_PREFIX = 'python/mozboot'
REPOSITORY_PATHS = [
'mozboot/__init__.py',
- 'mozboot/android-ndk-r8e.rb',
+ 'mozboot/android-ndk.rb',
'mozboot/android.py',
'mozboot/base.py',
'mozboot/bootstrap.py',
'mozboot/centos.py',
'mozboot/debian.py',
'mozboot/fedora.py',
'mozboot/freebsd.py',
'mozboot/gentoo.py',
rename from python/mozboot/mozboot/android-ndk-r8e.rb
rename to python/mozboot/mozboot/android-ndk.rb
--- a/python/mozboot/mozboot/android-ndk-r8e.rb
+++ b/python/mozboot/mozboot/android-ndk.rb
@@ -1,10 +1,14 @@
require "formula"
+# This is an antiquated version pinned to NDK revision r8e. That's
+# the revision Mozilla's automation currently uses. We could push
+# this to https://github.com/Homebrew/homebrew-versions if there's a
+# problem shipping it locally.
class AndroidNdk < Formula
homepage "http://developer.android.com/sdk/ndk/index.html"
if MacOS.prefer_64_bit?
url "http://dl.google.com/android/ndk/android-ndk-r8e-darwin-x86_64.tar.bz2"
sha1 "8c8f0d7df5f160c3ef82f2f4836cbcaf18aabf68"
else
url "http://dl.google.com/android/ndk/android-ndk-r8e-darwin-x86.tar.bz2"
--- a/python/mozboot/mozboot/osx.py
+++ b/python/mozboot/mozboot/osx.py
@@ -319,21 +319,26 @@ class OSXBootstrapper(BaseBootstrapper):
print(PACKAGE_MANAGER_OLD_CLANG % ('Homebrew',))
subprocess.check_call([self.brew, '-v', 'install', 'llvm',
'--with-clang', '--all-targets'])
def ensure_homebrew_mobile_android_packages(self):
import android
+ # If we're run from a downloaded bootstrap.py, then android-ndk.rb is
+ # fetched into a temporary directory. This finds that directory.
+ import inspect
+ path_to_android = os.path.abspath(os.path.dirname(inspect.getfile(android)))
+
# We don't need wget because we install the Android SDK and NDK from
# packages. If we used the android.py module, we'd need wget.
packages = [
('android-sdk', 'android-sdk'),
- ('android-ndk', 'android-ndk-r8e.rb'), # This is a locally provided brew formula!
+ ('android-ndk', os.path.join(path_to_android, 'android-ndk.rb')), # This is a locally provided brew formula!
('ant', 'ant'),
('brew-cask', 'caskroom/cask/brew-cask'), # For installing Java later.
]
self._ensure_homebrew_packages(packages)
casks = [
('java', 'java'),
]
--- a/toolkit/content/tests/widgets/test_videocontrols_audio.html
+++ b/toolkit/content/tests/widgets/test_videocontrols_audio.html
@@ -32,18 +32,18 @@
if (result) {
return result;
}
}
return false;
}
function loadedmetadata(event) {
- var fullscreenButton = findElementByAttribute(video, 'class', 'fullscreenButton');
- is(fullscreenButton.hidden, true, 'Fullscreen button is hidden');
+ var controlBar = findElementByAttribute(video, "class", "controlBar");
+ is(controlBar.getAttribute("fullscreen-unavailable"), "true", "Fullscreen button is hidden");
SimpleTest.finish();
}
var video = document.getElementById("video");
SpecialPowers.pushPrefEnv({"set": [["media.cache_size", 40000]]}, startTest);
function startTest() {
// Kick off test once audio has loaded.
--- a/toolkit/content/widgets/videocontrols.css
+++ b/toolkit/content/widgets/videocontrols.css
@@ -16,16 +16,20 @@
.playButton,
.muteButton,
.scrubber .scale-slider,
.volumeControl .scale-slider {
-moz-user-focus: none;
}
+.controlBar[fullscreen-unavailable] > .fullscreenButton {
+ display: none;
+}
+
.mediaControlsFrame {
direction: ltr;
/* Prevent unwanted style inheritance. See bug 554717. */
text-align: left;
list-style-image: none !important;
font: normal normal normal 100%/normal sans-serif !important;
text-decoration: none !important;
}
--- a/toolkit/content/widgets/videocontrols.xml
+++ b/toolkit/content/widgets/videocontrols.xml
@@ -338,22 +338,17 @@
firstFrameShown : false,
timeUpdateCount : 0,
maxCurrentTimeSeen : 0,
_isAudioOnly : false,
get isAudioOnly() { return this._isAudioOnly; },
set isAudioOnly(val) {
this._isAudioOnly = val;
- if (this._isAudioOnly) {
- this.controlBar.setAttribute("audio-only", true);
- } else {
- this.controlBar.removeAttribute("audio-only");
- }
- this.adjustControlSize();
+ this.setFullscreenButtonState();
if (!this.isTopLevelSyntheticDocument)
return;
if (this._isAudioOnly) {
this.video.style.height = this._controlBarHeight + "px";
this.video.style.width = "66%";
} else {
this.video.style.removeProperty("height");
@@ -1060,19 +1055,22 @@
toggleFullscreen : function () {
this.isVideoInFullScreen() ?
document.mozCancelFullScreen() :
this.video.mozRequestFullScreen();
},
setFullscreenButtonState : function () {
if (this.isAudioOnly || !document.mozFullScreenEnabled) {
- this.fullscreenButton.hidden = true;
+ this.controlBar.setAttribute("fullscreen-unavailable", true);
+ this.adjustControlSize();
return;
}
+ this.controlBar.removeAttribute("fullscreen-unavailable");
+ this.adjustControlSize();
var attrName = this.isVideoInFullScreen() ? "exitfullscreenlabel" : "enterfullscreenlabel";
var value = this.fullscreenButton.getAttribute(attrName);
this.fullscreenButton.setAttribute("aria-label", value);
if (this.isVideoInFullScreen())
this.fullscreenButton.setAttribute("fullscreened", "true");
else
@@ -1387,25 +1385,26 @@
let minScrubberWidth = 25;
let minWidthAllControls = this._playButtonWidth +
minScrubberWidth +
this._durationLabelWidth +
this._muteButtonWidth +
this._volumeControlWidth +
this._fullscreenButtonWidth;
- let isAudioOnly = this.isAudioOnly;
- if (isAudioOnly) {
+ let isFullscreenUnavailable = this.controlBar.hasAttribute("fullscreen-unavailable");
+ if (isFullscreenUnavailable) {
// When the fullscreen button is hidden we add margin-end to the volume stack.
minWidthAllControls -= this._fullscreenButtonWidth - this._volumeStackMarginEnd;
}
let minHeightForControlBar = this._controlBarHeight;
let minWidthOnlyPlayPause = this._playButtonWidth + this._muteButtonWidth;
+ let isAudioOnly = this.isAudioOnly;
let videoHeight = isAudioOnly ? minHeightForControlBar : this.video.clientHeight;
let videoWidth = isAudioOnly ? minWidthAllControls : this.video.clientWidth;
// Adapt the size of the controls to the size of the video
if (this.video.readyState >= this.video.HAVE_METADATA) {
if (!this.isAudioOnly && this.video.videoWidth && this.video.videoHeight) {
var rect = this.video.getBoundingClientRect();
var widthRatio = rect.width / this.video.videoWidth;
--- a/toolkit/devtools/server/actors/webconsole.js
+++ b/toolkit/devtools/server/actors/webconsole.js
@@ -78,17 +78,16 @@ function WebConsoleActor(aConnection, aP
this._onObserverNotification = this._onObserverNotification.bind(this);
if (this.parentActor.isRootActor) {
Services.obs.addObserver(this._onObserverNotification,
"last-pb-context-exited", false);
}
this.traits = {
customNetworkRequest: !this._parentIsContentActor,
- transferredResponseSize: true,
evaluateJSAsync: true
};
}
WebConsoleActor.l10n = new WebConsoleUtils.l10n("chrome://global/locale/console.properties");
WebConsoleActor.prototype =
{
@@ -1971,17 +1970,16 @@ NetworkEventActor.prototype =
}
let packet = {
from: this.actorID,
type: "networkEventUpdate",
updateType: "responseContent",
mimeType: aContent.mimeType,
contentSize: aContent.text.length,
- transferredSize: aContent.transferredSize,
discardResponseBody: aDiscardedResponseBody,
};
this.conn.send(packet);
},
/**
* Add network event timing information.
--- a/toolkit/devtools/webconsole/network-monitor.js
+++ b/toolkit/devtools/webconsole/network-monitor.js
@@ -1,15 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
-const {Cc, Ci, Cu, Cr} = require("chrome");
+const {Cc, Ci, Cu} = require("chrome");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
loader.lazyGetter(this, "NetworkHelper", () => require("devtools/toolkit/webconsole/network-helper"));
loader.lazyImporter(this, "Services", "resource://gre/modules/Services.jsm");
loader.lazyImporter(this, "DevToolsUtils", "resource://gre/modules/devtools/DevToolsUtils.jsm");
loader.lazyImporter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm");
loader.lazyImporter(this, "PrivateBrowsingUtils", "resource://gre/modules/PrivateBrowsingUtils.jsm");
@@ -52,72 +52,32 @@ const RESPONSE_BODY_LIMIT = 1048576; //
* for more information.
*/
function NetworkResponseListener(aOwner, aHttpActivity)
{
this.owner = aOwner;
this.receivedData = "";
this.httpActivity = aHttpActivity;
this.bodySize = 0;
- let channel = this.httpActivity.channel;
- this._wrappedNotificationCallbacks = channel.notificationCallbacks;
- channel.notificationCallbacks = this;
}
exports.NetworkResponseListener = NetworkResponseListener;
NetworkResponseListener.prototype = {
QueryInterface:
XPCOMUtils.generateQI([Ci.nsIStreamListener, Ci.nsIInputStreamCallback,
- Ci.nsIRequestObserver, Ci.nsIInterfaceRequestor,
- Ci.nsISupports]),
-
- // nsIInterfaceRequestor implementation
-
- /**
- * This object implements nsIProgressEventSink, but also needs to forward
- * interface requests to the notification callbacks of other objects.
- */
- getInterface(iid) {
- if (iid.equals(Ci.nsIProgressEventSink)) {
- return this;
- }
- if (this._wrappedNotificationCallbacks) {
- return this._wrappedNotificationCallbacks.getInterface(iid);
- }
- throw Cr.NS_ERROR_NO_INTERFACE;
- },
-
- /**
- * Forward notifications for interfaces this object implements, in case other
- * objects also implemented them.
- */
- _forwardNotification(iid, method, args) {
- if (!this._wrappedNotificationCallbacks) {
- return;
- }
- try {
- let impl = this._wrappedNotificationCallbacks.getInterface(iid);
- impl[method].apply(impl, args);
- } catch(e if e.result == Cr.NS_ERROR_NO_INTERFACE) {}
- },
+ Ci.nsIRequestObserver, Ci.nsISupports]),
/**
* This NetworkResponseListener tracks the NetworkMonitor.openResponses object
* to find the associated uncached headers.
* @private
*/
_foundOpenResponse: false,
/**
- * If the channel already had notificationCallbacks, hold them here internally
- * so that we can forward getInterface requests to that object.
- */
- _wrappedNotificationCallbacks: null,
-
- /**
* The response listener owner.
*/
owner: null,
/**
* The response will be written into the outputStream of this nsIPipe.
* Both ends of the pipe must be blocking.
*/
@@ -129,26 +89,21 @@ NetworkResponseListener.prototype = {
httpActivity: null,
/**
* Stores the received data as a string.
*/
receivedData: null,
/**
- * The uncompressed, decoded response body size.
+ * The network response body size.
*/
bodySize: null,
/**
- * Response body size on the wire, potentially compressed / encoded.
- */
- transferredSize: null,
-
- /**
* The nsIRequest we are started for.
*/
request: null,
/**
* Set the async listener for the given nsIAsyncInputStream. This allows us to
* wait asynchronously for any data coming from the stream.
*
@@ -217,33 +172,16 @@ NetworkResponseListener.prototype = {
* https://developer.mozilla.org/En/NsIRequestObserver
*/
onStopRequest: function NRL_onStopRequest()
{
this._findOpenResponse();
this.sink.outputStream.close();
},
- // nsIProgressEventSink implementation
-
- /**
- * Handle progress event as data is transferred. This is used to record the
- * size on the wire, which may be compressed / encoded.
- */
- onProgress: function(request, context, progress, progressMax) {
- this.transferredSize = progress;
- // Need to forward as well to keep things like Download Manager's progress
- // bar working properly.
- this._forwardNotification(Ci.nsIProgressEventSink, 'onProgress', arguments);
- },
-
- onStatus: function () {
- this._forwardNotification(Ci.nsIProgressEventSink, 'onStatus', arguments);
- },
-
/**
* Find the open response object associated to the current request. The
* NetworkMonitor._httpResponseExaminer() method saves the response headers in
* NetworkMonitor.openResponses. This method takes the data from the open
* response object and puts it into the HTTP activity object, then sends it to
* the remote Web Console instance.
*
* @private
@@ -316,17 +254,16 @@ NetworkResponseListener.prototype = {
_onComplete: function NRL__onComplete(aData)
{
let response = {
mimeType: "",
text: aData || "",
};
response.size = response.text.length;
- response.transferredSize = this.transferredSize;
try {
response.mimeType = this.request.contentType;
}
catch (ex) { }
if (!response.mimeType || !NetworkHelper.isTextMimeType(response.mimeType)) {
response.encoding = "base64";
@@ -337,17 +274,16 @@ NetworkResponseListener.prototype = {
response.mimeType += "; charset=" + this.request.contentCharset;
}
this.receivedData = "";
this.httpActivity.owner.
addResponseContent(response, this.httpActivity.discardResponseBody);
- this._wrappedNotificationCallbacks = null;
this.httpActivity.channel = null;
this.httpActivity.owner = null;
this.httpActivity = null;
this.sink = null;
this.inputStream = null;
this.request = null;
this.owner = null;
},
--- a/toolkit/themes/osx/global/media/videocontrols.css
+++ b/toolkit/themes/osx/global/media/videocontrols.css
@@ -87,17 +87,17 @@
background-image: url(chrome://global/skin/media/volume-empty.png);
}
.volumeForeground {
background-image: url(chrome://global/skin/media/volume-full.png);
background-clip: content-box;
}
-.controlBar[audio-only] > .volumeStack {
+.controlBar[fullscreen-unavailable] > .volumeStack {
/* This value is duplicated in the videocontrols.xml adjustControlSize function. */
-moz-margin-end: 8px;
}
.volumeControl .scale-thumb {
min-width: 0;
opacity: 0;
}
--- a/toolkit/themes/windows/global/media/videocontrols.css
+++ b/toolkit/themes/windows/global/media/videocontrols.css
@@ -87,17 +87,17 @@
background-image: url(chrome://global/skin/media/volume-empty.png);
}
.volumeForeground {
background-image: url(chrome://global/skin/media/volume-full.png);
background-clip: content-box;
}
-.controlBar[audio-only] > .volumeStack {
+.controlBar[fullscreen-unavailable] > .volumeStack {
/* This value is duplicated in the videocontrols.xml adjustControlSize function. */
-moz-margin-end: 8px;
}
.volumeControl .scale-thumb {
min-width: 0;
opacity: 0;
}