commit 41f3117e8e5bd7f0b19a410f8df9a2996494a78d
parent f9a8739e616f3bbbb1deb9c82c11617ac1922875
Author: Daisuke Akatsuka <daisuke@birchill.co.jp>
Date: Wed, 22 Oct 2025 07:58:55 +0000
Bug 1994317: Implement flight progress icon r=desktop-theme-reviewers,adw,dao
Differential Revision: https://phabricator.services.mozilla.com/D268673
Diffstat:
11 files changed, 712 insertions(+), 140 deletions(-)
diff --git a/browser/components/urlbar/UrlbarUtils.sys.mjs b/browser/components/urlbar/UrlbarUtils.sys.mjs
@@ -2937,6 +2937,7 @@ export class UrlbarProvider {
* },
* style: {
* someStyleProperty: someValue,
+ * "another-style-property": someValue,
* },
* l10n: {
* id: someL10nId,
diff --git a/browser/components/urlbar/UrlbarView.sys.mjs b/browser/components/urlbar/UrlbarView.sys.mjs
@@ -2328,7 +2328,14 @@ export class UrlbarView {
this.#updateElementForDynamicType(node, update, item, result);
if (update.style) {
for (let [styleName, value] of Object.entries(update.style)) {
- node.style[styleName] = value;
+ if (styleName.includes("-")) {
+ // Expect hyphen-case. e.g. "background-image", "--a-variable".
+ node.style.setProperty(styleName, value);
+ } else {
+ // Expect camel-case. e.g. "backgroundImage"
+ // NOTE: If want to define the variable, please use hyphen-case.
+ node.style[styleName] = value;
+ }
}
}
if (update.l10n) {
diff --git a/browser/components/urlbar/private/FlightStatusSuggestions.sys.mjs b/browser/components/urlbar/private/FlightStatusSuggestions.sys.mjs
@@ -142,20 +142,44 @@ export class FlightStatusSuggestions extends RealtimeSuggestProvider {
};
}
- return {
- [`item_${i}`]: {
+ let foregroundImage;
+ let backgroundImage;
+ if (status == "inflight") {
+ let backgroundImageId =
+ v.progress_percent == 100 ? 4 : Math.floor(v.progress_percent / 20);
+ backgroundImage = {
+ style: {
+ "--airline-color": v.airline.color,
+ },
attributes: {
- status,
+ backgroundImageId,
+ hasForegroundImage: !!v.airline.icon,
},
- },
- [`image_${i}`]: {
+ };
+ foregroundImage = {
+ attributes: {
+ src: v.airline.icon,
+ },
+ };
+ } else {
+ foregroundImage = {
attributes: {
src:
v.airline.icon ??
"chrome://browser/skin/urlbar/flight-airline.svg",
fallback: !v.airline.icon,
},
+ };
+ }
+
+ return {
+ [`item_${i}`]: {
+ attributes: {
+ status,
+ },
},
+ [`image_container_${i}`]: backgroundImage,
+ [`image_${i}`]: foregroundImage,
[`departure_time_${i}`]: {
textContent: new Intl.DateTimeFormat(undefined, {
hour: "numeric",
diff --git a/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_realtime_flight_status.js b/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_realtime_flight_status.js
@@ -95,7 +95,7 @@ const TEST_MERINO_MULTI = [
scheduled_time: "2025-09-02T18:32:00-02:00",
},
status: "En Route",
- progress_percent: 72,
+ progress_percent: 0,
time_left_minutes: 1,
url: "https://example.com/A2",
},
@@ -148,90 +148,6 @@ const TEST_MERINO_MULTI = [
status: "Cancelled",
url: "https://example.com/A4",
},
- // Delayed flight cases
- {
- flight_number: "D1",
- airline: {
- name: "Delay Air",
- code: "D",
- icon: "chrome://browser/skin/urlbar/market-down.svg",
- },
- origin: {
- city: "Origin D1",
- code: "OD1",
- },
- destination: {
- city: "Destination D1",
- code: "DD1",
- },
- departure: {
- scheduled_time: "2025-09-05T14:05:00+1130",
- estimated_time: "2025-09-05T15:05:00-1130",
- },
- arrival: {
- scheduled_time: "2025-09-05T18:35:00Z",
- estimated_time: "2025-09-05T19:35:00Z",
- },
- status: "Delayed",
- delayed: true,
- url: "https://example.com/D1",
- },
- {
- flight_number: "D2",
- airline: {
- name: null,
- code: null,
- icon: null,
- },
- origin: {
- city: "Origin D2",
- code: "OD2",
- },
- destination: {
- city: "Destination D2",
- code: "DD2",
- },
- departure: {
- scheduled_time: "2025-09-06T14:06:00Z",
- estimated_time: "2025-09-06T15:06:00Z",
- },
- arrival: {
- scheduled_time: "2025-09-06T18:36:00Z",
- estimated_time: "2025-09-06T19:36:00Z",
- },
- status: "En Route",
- time_left_minutes: 10,
- delayed: true,
- url: "https://example.com/D2",
- },
- {
- flight_number: "D3",
- airline: {
- name: null,
- code: null,
- icon: null,
- },
- origin: {
- city: "Origin D3",
- code: "OD3",
- },
- destination: {
- city: "Destination D3",
- code: "DD3",
- },
- departure: {
- scheduled_time: "2025-09-07T14:07:00Z",
- estimated_time: "2025-09-07T15:07:00Z",
- },
- arrival: {
- scheduled_time: "2025-09-07T18:37:00Z",
- estimated_time: "2025-09-07T19:37:00Z",
- },
- status: "Arrived",
- delayed: true,
- time_left_minutes: 0,
- url: "https://example.com/D3",
- },
],
},
},
@@ -254,15 +170,9 @@ add_setup(async function () {
});
});
-add_task(async function ui() {
+add_task(async function ui_basic() {
MerinoTestUtils.server.response.body.suggestions = TEST_MERINO_MULTI;
- await UrlbarTestUtils.promiseAutocompleteResultPopup({
- window,
- value: "only match the Merino suggestion",
- });
- let { element } = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
-
const expectedList = [
{
flight_number: "A1, A Air",
@@ -276,7 +186,7 @@ add_task(async function ui() {
},
{
flight_number: "A2",
- image: "chrome://browser/skin/urlbar/flight-airline.svg",
+ image: "",
departure_time: "2:02 PM",
departure_date: "Tue, September 2",
arrival_time: "6:32 PM",
@@ -306,9 +216,124 @@ add_task(async function ui() {
destination_airport: "Destination 4 (D4)",
status: "Cancelled",
},
+ ];
+
+ await UrlbarTestUtils.promiseAutocompleteResultPopup({
+ window,
+ value: "only match the Merino suggestion",
+ });
+ let { element } = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
+
+ await assertUI({ row: element.row, expectedList });
+
+ await UrlbarTestUtils.promisePopupClose(window);
+ gURLBar.handleRevert();
+});
+
+add_task(async function ui_delayed() {
+ MerinoTestUtils.server.response.body.suggestions = [
+ {
+ provider: "flightaware",
+ is_sponsored: false,
+ score: 0,
+ title: "Flight Suggestion",
+ custom_details: {
+ flightaware: {
+ values: [
+ {
+ flight_number: "D1",
+ airline: {
+ name: "Delay Air",
+ code: "D",
+ icon: "chrome://browser/skin/urlbar/market-unchanged.svg",
+ },
+ origin: {
+ city: "Origin D1",
+ code: "OD1",
+ },
+ destination: {
+ city: "Destination D1",
+ code: "DD1",
+ },
+ departure: {
+ scheduled_time: "2025-09-05T14:05:00+1130",
+ estimated_time: "2025-09-05T15:05:00-1130",
+ },
+ arrival: {
+ scheduled_time: "2025-09-05T18:35:00Z",
+ estimated_time: "2025-09-05T19:35:00Z",
+ },
+ status: "Delayed",
+ delayed: true,
+ url: "https://example.com/D1",
+ },
+ {
+ flight_number: "D2",
+ airline: {
+ name: null,
+ code: null,
+ icon: null,
+ },
+ origin: {
+ city: "Origin D2",
+ code: "OD2",
+ },
+ destination: {
+ city: "Destination D2",
+ code: "DD2",
+ },
+ departure: {
+ scheduled_time: "2025-09-06T14:06:00Z",
+ estimated_time: "2025-09-06T15:06:00Z",
+ },
+ arrival: {
+ scheduled_time: "2025-09-06T18:36:00Z",
+ estimated_time: "2025-09-06T19:36:00Z",
+ },
+ status: "En Route",
+ progress_percent: 18,
+ time_left_minutes: 10,
+ delayed: true,
+ url: "https://example.com/D2",
+ },
+ {
+ flight_number: "D3",
+ airline: {
+ name: null,
+ code: null,
+ icon: null,
+ },
+ origin: {
+ city: "Origin D3",
+ code: "OD3",
+ },
+ destination: {
+ city: "Destination D3",
+ code: "DD3",
+ },
+ departure: {
+ scheduled_time: "2025-09-07T14:07:00Z",
+ estimated_time: "2025-09-07T15:07:00Z",
+ },
+ arrival: {
+ scheduled_time: "2025-09-07T18:37:00Z",
+ estimated_time: "2025-09-07T19:37:00Z",
+ },
+ status: "Arrived",
+ delayed: true,
+ time_left_minutes: 0,
+ url: "https://example.com/D3",
+ },
+ ],
+ },
+ },
+ },
+ ];
+
+ const expectedList = [
{
flight_number: "D1, Delay Air",
- image: "chrome://browser/skin/urlbar/market-down.svg",
+ image: "chrome://browser/skin/urlbar/market-unchanged.svg",
departure_time: "2:05 PM",
departure_date: "Fri, September 5",
arrival_time: "6:35 PM",
@@ -318,7 +343,7 @@ add_task(async function ui() {
},
{
flight_number: "D2",
- image: "chrome://browser/skin/urlbar/flight-airline.svg",
+ image: "",
departure_time: "3:06 PM",
departure_date: "Sat, September 6",
arrival_time: "7:36 PM",
@@ -340,6 +365,413 @@ add_task(async function ui() {
},
];
+ await UrlbarTestUtils.promiseAutocompleteResultPopup({
+ window,
+ value: "only match the Merino suggestion",
+ });
+ let { element } = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
+
+ await assertUI({ row: element.row, expectedList });
+
+ await UrlbarTestUtils.promisePopupClose(window);
+ gURLBar.handleRevert();
+});
+
+add_task(async function ui_inflight() {
+ MerinoTestUtils.server.response.body.suggestions = [
+ {
+ provider: "flightaware",
+ is_sponsored: false,
+ score: 0,
+ title: "Flight Suggestion",
+ custom_details: {
+ flightaware: {
+ values: [
+ {
+ flight_number: "I1",
+ airline: {
+ name: "In flight Air",
+ code: "I",
+ icon: "chrome://browser/skin/urlbar/flight-airline.svg",
+ color: "#f00",
+ },
+ origin: {
+ city: "Origin I1",
+ code: "OI1",
+ },
+ destination: {
+ city: "Destination I1",
+ code: "DI1",
+ },
+ departure: {
+ scheduled_time: "2025-09-05T14:06:00+1130",
+ estimated_time: "2025-09-05T15:06:00-1130",
+ },
+ arrival: {
+ scheduled_time: "2025-09-05T18:36:00Z",
+ estimated_time: "2025-09-05T19:36:00Z",
+ },
+ status: "En Route",
+ progress_percent: 0,
+ url: "https://example.com/I1",
+ },
+ {
+ flight_number: "I2",
+ airline: {
+ name: "In flight Up Air",
+ code: "IUP",
+ icon: "chrome://browser/skin/urlbar/market-up.svg",
+ color: null,
+ },
+ origin: {
+ city: "Origin I2",
+ code: "OI2",
+ },
+ destination: {
+ city: "Destination I2",
+ code: "DI2",
+ },
+ departure: {
+ scheduled_time: "2025-09-05T14:07:00+1130",
+ estimated_time: "2025-09-05T15:07:00-1130",
+ },
+ arrival: {
+ scheduled_time: "2025-09-05T18:37:00Z",
+ estimated_time: "2025-09-05T19:37:00Z",
+ },
+ status: "En Route",
+ progress_percent: 19,
+ url: "https://example.com/I2",
+ },
+ {
+ flight_number: "I3",
+ airline: {
+ name: "In flight Unchanged Air",
+ code: "IUN",
+ icon: "chrome://browser/skin/urlbar/market-unchanged.svg",
+ color: "#0f0",
+ },
+ origin: {
+ city: "Origin I3",
+ code: "OI3",
+ },
+ destination: {
+ city: "Destination I3",
+ code: "DI3",
+ },
+ departure: {
+ scheduled_time: "2025-09-05T14:08:00+1130",
+ estimated_time: "2025-09-05T15:08:00-1130",
+ },
+ arrival: {
+ scheduled_time: "2025-09-05T18:38:00Z",
+ estimated_time: "2025-09-05T19:38:00Z",
+ },
+ status: "En Route",
+ progress_percent: 20,
+ url: "https://example.com/I3",
+ },
+ {
+ flight_number: "I4",
+ airline: {
+ name: "In flight No Color Air",
+ code: "INC",
+ icon: "chrome://browser/skin/urlbar/flight-airline.svg",
+ color: null,
+ },
+ origin: {
+ city: "Origin I4",
+ code: "OI4",
+ },
+ destination: {
+ city: "Destination I4",
+ code: "DI4",
+ },
+ departure: {
+ scheduled_time: "2025-09-05T14:09:00+1130",
+ estimated_time: "2025-09-05T15:09:00-1130",
+ },
+ arrival: {
+ scheduled_time: "2025-09-05T18:39:00Z",
+ estimated_time: "2025-09-05T19:39:00Z",
+ },
+ status: "En Route",
+ progress_percent: 39,
+ url: "https://example.com/I4",
+ },
+ {
+ flight_number: "I5",
+ airline: {
+ name: null,
+ code: null,
+ icon: null,
+ color: "#00f",
+ },
+ origin: {
+ city: "Origin I5",
+ code: "OI5",
+ },
+ destination: {
+ city: "Destination I5",
+ code: "DI5",
+ },
+ departure: {
+ scheduled_time: "2025-09-05T14:10:00+1130",
+ estimated_time: "2025-09-05T15:10:00-1130",
+ },
+ arrival: {
+ scheduled_time: "2025-09-05T18:40:00Z",
+ estimated_time: "2025-09-05T19:40:00Z",
+ },
+ status: "En Route",
+ progress_percent: 40,
+ url: "https://example.com/I5",
+ },
+ {
+ flight_number: "I6",
+ airline: {
+ name: null,
+ code: null,
+ icon: null,
+ color: null,
+ },
+ origin: {
+ city: "Origin I6",
+ code: "OI6",
+ },
+ destination: {
+ city: "Destination I6",
+ code: "DI6",
+ },
+ departure: {
+ scheduled_time: "2025-09-05T14:11:00+1130",
+ estimated_time: "2025-09-05T15:11:00-1130",
+ },
+ arrival: {
+ scheduled_time: "2025-09-05T18:41:00Z",
+ estimated_time: "2025-09-05T19:41:00Z",
+ },
+ status: "En Route",
+ progress_percent: 59,
+ url: "https://example.com/I6",
+ },
+ {
+ flight_number: "I7",
+ airline: {
+ name: null,
+ code: null,
+ icon: null,
+ color: "#ff0",
+ },
+ origin: {
+ city: "Origin I7",
+ code: "OI7",
+ },
+ destination: {
+ city: "Destination I7",
+ code: "DI7",
+ },
+ departure: {
+ scheduled_time: "2025-09-05T14:12:00+1130",
+ estimated_time: "2025-09-05T15:12:00-1130",
+ },
+ arrival: {
+ scheduled_time: "2025-09-05T18:42:00Z",
+ estimated_time: "2025-09-05T19:42:00Z",
+ },
+ status: "En Route",
+ progress_percent: 60,
+ url: "https://example.com/I7",
+ },
+ {
+ flight_number: "I8",
+ airline: {
+ name: null,
+ code: null,
+ icon: null,
+ color: null,
+ },
+ origin: {
+ city: "Origin I8",
+ code: "OI8",
+ },
+ destination: {
+ city: "Destination I8",
+ code: "DI8",
+ },
+ departure: {
+ scheduled_time: "2025-09-05T14:13:00+1130",
+ estimated_time: "2025-09-05T15:13:00-1130",
+ },
+ arrival: {
+ scheduled_time: "2025-09-05T18:43:00Z",
+ estimated_time: "2025-09-05T19:43:00Z",
+ },
+ status: "En Route",
+ progress_percent: 79,
+ url: "https://example.com/I8",
+ },
+ {
+ flight_number: "I9",
+ airline: {
+ name: null,
+ code: null,
+ icon: null,
+ color: "#0ff",
+ },
+ origin: {
+ city: "Origin I9",
+ code: "OI9",
+ },
+ destination: {
+ city: "Destination I9",
+ code: "DI9",
+ },
+ departure: {
+ scheduled_time: "2025-09-05T14:14:00+1130",
+ estimated_time: "2025-09-05T15:14:00-1130",
+ },
+ arrival: {
+ scheduled_time: "2025-09-05T18:44:00Z",
+ estimated_time: "2025-09-05T19:44:00Z",
+ },
+ status: "En Route",
+ progress_percent: 80,
+ url: "https://example.com/I9",
+ },
+ {
+ flight_number: "I10",
+ airline: {
+ name: null,
+ code: null,
+ icon: null,
+ color: null,
+ },
+ origin: {
+ city: "Origin I10",
+ code: "OI10",
+ },
+ destination: {
+ city: "Destination I10",
+ code: "DI10",
+ },
+ departure: {
+ scheduled_time: "2025-09-05T14:15:00+1130",
+ estimated_time: "2025-09-05T15:15:00-1130",
+ },
+ arrival: {
+ scheduled_time: "2025-09-05T18:45:00Z",
+ estimated_time: "2025-09-05T19:45:00Z",
+ },
+ status: "En Route",
+ progress_percent: 100,
+ url: "https://example.com/I10",
+ },
+ ],
+ },
+ },
+ },
+ ];
+
+ const expectedList = [
+ {
+ background: {
+ image: "chrome://browser/skin/urlbar/flight-inflight-progress-0.svg",
+ fill: "rgb(255, 0, 0)",
+ stroke: "rgb(255, 0, 0)",
+ },
+ foreground: {
+ image: "chrome://browser/skin/urlbar/flight-airline.svg",
+ },
+ },
+ {
+ background: {
+ image: "chrome://browser/skin/urlbar/flight-inflight-progress-0.svg",
+ },
+ foreground: {
+ image: "chrome://browser/skin/urlbar/market-up.svg",
+ },
+ },
+ {
+ background: {
+ image: "chrome://browser/skin/urlbar/flight-inflight-progress-1.svg",
+ fill: "rgb(0, 255, 0)",
+ stroke: "rgb(0, 255, 0)",
+ },
+ foreground: {
+ image: "chrome://browser/skin/urlbar/market-unchanged.svg",
+ },
+ },
+ {
+ background: {
+ image: "chrome://browser/skin/urlbar/flight-inflight-progress-1.svg",
+ },
+ foreground: {
+ image: "chrome://browser/skin/urlbar/flight-airline.svg",
+ },
+ },
+ {
+ background: {
+ image: "chrome://browser/skin/urlbar/flight-inflight-progress-2.svg",
+ fill: "rgb(0, 0, 255)",
+ stroke: "rgb(0, 0, 255)",
+ },
+ foreground: {
+ image: "",
+ },
+ },
+ {
+ background: {
+ image: "chrome://browser/skin/urlbar/flight-inflight-progress-2.svg",
+ },
+ foreground: {
+ image: "",
+ },
+ },
+ {
+ background: {
+ image: "chrome://browser/skin/urlbar/flight-inflight-progress-3.svg",
+ fill: "rgb(255, 255, 0)",
+ stroke: "rgb(255, 255, 0)",
+ },
+ foreground: {
+ image: "",
+ },
+ },
+ {
+ background: {
+ image: "chrome://browser/skin/urlbar/flight-inflight-progress-3.svg",
+ },
+ foreground: {
+ image: "",
+ },
+ },
+ {
+ background: {
+ image: "chrome://browser/skin/urlbar/flight-inflight-progress-4.svg",
+ fill: "rgb(0, 255, 255)",
+ stroke: "rgb(0, 255, 255)",
+ },
+ foreground: {
+ image: "",
+ },
+ },
+ {
+ background: {
+ image: "chrome://browser/skin/urlbar/flight-inflight-progress-4.svg",
+ },
+ foreground: {
+ image: "",
+ },
+ },
+ ];
+
+ await UrlbarTestUtils.promiseAutocompleteResultPopup({
+ window,
+ value: "only match the Merino suggestion",
+ });
+ let { element } = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
+
let items = element.row.querySelectorAll(".urlbarView-realtime-item");
Assert.equal(items.length, expectedList.length);
@@ -349,47 +781,26 @@ add_task(async function ui() {
let expected = expectedList[i];
await TestUtils.waitForCondition(
- () =>
- item.querySelector(`[name=status_${i}]`).textContent == expected.status,
- "Wait until the status text will be applied by Fluent"
+ () => item.querySelector(`[name=status_${i}]`).textContent == "In flight"
);
- Assert.equal(
- item.querySelector(".urlbarView-realtime-image").src,
- expected.image
- );
- Assert.equal(
- item.querySelector(`[name=departure_time_${i}]`).textContent,
- expected.departure_time
- );
- Assert.equal(
- item.querySelector(`[name=departure_date_${i}]`).textContent,
- expected.departure_date
- );
- Assert.equal(
- item.querySelector(`[name=arrival_time_${i}]`).textContent,
- expected.arrival_time
+ let backgroundStyle = window.getComputedStyle(
+ item.querySelector(".urlbarView-realtime-image-container")
);
Assert.equal(
- item.querySelector(`[name=origin_airport_${i}]`).textContent,
- expected.origin_airport
- );
- Assert.equal(
- item.querySelector(`[name=destination_airport_${i}]`).textContent,
- expected.destination_airport
+ backgroundStyle.backgroundImage,
+ `url("${expected.background.image}")`
);
+
+ // The fill and stroke uses currentColor as the default.
+ let defaultColor = backgroundStyle.color;
+ let expectedFillColor = expected.background.fill ?? defaultColor;
+ let expectedStrokeColor = expected.background.stroke ?? defaultColor;
+ Assert.equal(backgroundStyle.fill, expectedFillColor);
+ Assert.equal(backgroundStyle.stroke, expectedStrokeColor);
Assert.equal(
- item.querySelector(`[name=flight_number_${i}]`).textContent,
- expected.flight_number
+ item.querySelector(".urlbarView-realtime-image").src,
+ expected.foreground.image
);
-
- let timeLeftMinutes = item.querySelector(`[name=time_left_minutes_${i}]`);
- if (typeof expected.time_left_minutes != "undefined") {
- Assert.equal(timeLeftMinutes.textContent, expected.time_left_minutes);
- } else {
- Assert.equal(timeLeftMinutes.textContent, "");
- let previousSeparator = timeLeftMinutes.previousElementSibling;
- Assert.ok(BrowserTestUtils.isHidden(previousSeparator));
- }
}
await UrlbarTestUtils.promisePopupClose(window);
@@ -491,8 +902,56 @@ add_task(async function activate_multi() {
gURLBar.handleRevert();
});
-function toDate(timeString) {
- let time = new Date(timeString);
- time.setMinutes(time.getMinutes() + time.getTimezoneOffset());
- return time;
+async function assertUI({ row, expectedList }) {
+ let items = row.querySelectorAll(".urlbarView-realtime-item");
+ Assert.equal(items.length, expectedList.length);
+
+ for (let i = 0; i < items.length; i++) {
+ info(`Check the item[${i}]`);
+ let item = items[i];
+ let expected = expectedList[i];
+
+ await TestUtils.waitForCondition(
+ () =>
+ item.querySelector(`[name=status_${i}]`).textContent == expected.status,
+ "Wait until the status text will be applied by Fluent"
+ );
+ Assert.equal(
+ item.querySelector(".urlbarView-realtime-image").src,
+ expected.image
+ );
+ Assert.equal(
+ item.querySelector(`[name=departure_time_${i}]`).textContent,
+ expected.departure_time
+ );
+ Assert.equal(
+ item.querySelector(`[name=departure_date_${i}]`).textContent,
+ expected.departure_date
+ );
+ Assert.equal(
+ item.querySelector(`[name=arrival_time_${i}]`).textContent,
+ expected.arrival_time
+ );
+ Assert.equal(
+ item.querySelector(`[name=origin_airport_${i}]`).textContent,
+ expected.origin_airport
+ );
+ Assert.equal(
+ item.querySelector(`[name=destination_airport_${i}]`).textContent,
+ expected.destination_airport
+ );
+ Assert.equal(
+ item.querySelector(`[name=flight_number_${i}]`).textContent,
+ expected.flight_number
+ );
+
+ let timeLeftMinutes = item.querySelector(`[name=time_left_minutes_${i}]`);
+ if (typeof expected.time_left_minutes != "undefined") {
+ Assert.equal(timeLeftMinutes.textContent, expected.time_left_minutes);
+ } else {
+ Assert.equal(timeLeftMinutes.textContent, "");
+ let previousSeparator = timeLeftMinutes.previousElementSibling;
+ Assert.ok(BrowserTestUtils.isHidden(previousSeparator));
+ }
+ }
}
diff --git a/browser/themes/shared/jar.inc.mn b/browser/themes/shared/jar.inc.mn
@@ -29,6 +29,11 @@
skin/classic/browser/toolbarbuttons.css (../shared/toolbarbuttons.css)
skin/classic/browser/toolbarbutton-icons.css (../shared/toolbarbutton-icons.css)
skin/classic/browser/urlbar/flight-airline.svg (../shared/urlbar/flight-airline.svg)
+ skin/classic/browser/urlbar/flight-inflight-progress-0.svg (../shared/urlbar/flight-inflight-progress-0.svg)
+ skin/classic/browser/urlbar/flight-inflight-progress-1.svg (../shared/urlbar/flight-inflight-progress-1.svg)
+ skin/classic/browser/urlbar/flight-inflight-progress-2.svg (../shared/urlbar/flight-inflight-progress-2.svg)
+ skin/classic/browser/urlbar/flight-inflight-progress-3.svg (../shared/urlbar/flight-inflight-progress-3.svg)
+ skin/classic/browser/urlbar/flight-inflight-progress-4.svg (../shared/urlbar/flight-inflight-progress-4.svg)
skin/classic/browser/urlbar/market-down.svg (../shared/urlbar/market-down.svg)
skin/classic/browser/urlbar/market-unchanged.svg (../shared/urlbar/market-unchanged.svg)
skin/classic/browser/urlbar/market-up.svg (../shared/urlbar/market-up.svg)
diff --git a/browser/themes/shared/urlbar/flight-inflight-progress-0.svg b/browser/themes/shared/urlbar/flight-inflight-progress-0.svg
@@ -0,0 +1,8 @@
+<!-- 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 https://mozilla.org/MPL/2.0/. -->
+<svg width="55" height="55" viewBox="0 0 55 55" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M101.558 45.5707C77.6159 16.6368 34.7513 12.5904 5.81738 36.5327" stroke="light-dark(#BAC2CA, #8F8F9D)" stroke-width="2"/>
+<path d="M101.559 45.5703C125.501 74.5042 121.455 117.369 92.521 141.311C63.5871 165.254 20.7225 161.207 -3.21986 132.273C-27.1622 103.339 -23.1157 60.4747 5.81814 36.5324" stroke="context-stroke" stroke-width="2"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M7.21095 33.4537C7.85601 32.8922 8.83425 32.9746 9.39508 33.6377C9.95591 34.3008 9.88759 35.2943 9.24253 35.8559L8.3685 36.6168L8.89272 39.3652C8.96978 39.7688 8.82917 40.1798 8.52551 40.4442L7.36527 41.4542C7.25017 41.5544 7.09043 41.5839 6.94622 41.5315C6.80201 41.4791 6.69524 41.3529 6.66614 41.2003L6.15875 38.5401L4.95716 39.5865L5.01072 40.641C5.0175 40.7744 4.96353 40.9028 4.86439 40.989L3.86092 41.8621C3.74935 41.9591 3.59557 41.99 3.4544 41.9436C3.31324 41.8972 3.20478 41.7801 3.16769 41.6342L2.63179 39.5255L0.658923 38.6678C0.522371 38.6084 0.424834 38.4818 0.401094 38.3332C0.377355 38.1846 0.430793 38.035 0.542351 37.9379L1.54587 37.0643C1.64495 36.978 1.77816 36.9435 1.90706 36.9705L2.92559 37.1844L4.12713 36.1383L1.61308 35.2254C1.46887 35.1731 1.36209 35.0468 1.33297 34.8943C1.30386 34.7417 1.35682 34.586 1.47192 34.4858L2.63216 33.4757C2.93642 33.2109 3.35792 33.1338 3.73818 33.2711L6.33692 34.2146L7.21095 33.4537Z" fill="context-fill"/>
+</svg>
diff --git a/browser/themes/shared/urlbar/flight-inflight-progress-1.svg b/browser/themes/shared/urlbar/flight-inflight-progress-1.svg
@@ -0,0 +1,8 @@
+<!-- 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 https://mozilla.org/MPL/2.0/. -->
+<svg width="54" height="55" viewBox="0 0 54 55" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M107.458 54.7865C88.6178 22.2988 47.0083 11.2351 14.5205 30.0752" stroke="light-dark(#BAC2CA, #8F8F9D)" stroke-width="2"/>
+<path d="M107.458 54.7862C126.298 87.274 115.234 128.883 82.7466 147.724C50.2588 166.564 8.64937 155.5 -10.1907 123.012C-29.0308 90.5244 -17.9672 48.915 14.5206 30.0749" stroke="context-stroke" stroke-width="2"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M16.4023 27.2683C17.1312 26.8208 18.0824 27.0635 18.5262 27.8101C18.9699 28.5567 18.7386 29.5253 18.0097 29.9727L17.0221 30.579L17.0856 33.3762C17.0951 33.7869 16.8885 34.1692 16.5454 34.3798L15.2344 35.1846C15.1044 35.2644 14.942 35.2671 14.8084 35.1916C14.6748 35.1162 14.5903 34.974 14.5868 34.8188L14.5253 32.1113L13.1675 32.9451L13.0463 33.994C13.031 34.1267 12.9566 34.2444 12.8446 34.3131L11.7108 35.0086C11.5848 35.0859 11.428 35.091 11.2964 35.0219C11.1649 34.9529 11.0772 34.8195 11.0647 34.6695L10.8841 32.5013L9.07978 31.3298C8.95489 31.2487 8.87958 31.1078 8.88069 30.9572C8.8818 30.8067 8.95918 30.6681 9.08523 30.5907L10.2191 29.8946C10.3311 29.8259 10.4682 29.8138 10.5909 29.8617L11.5601 30.2407L12.9178 29.4073L10.5888 28.0921C10.4552 28.0166 10.3708 27.8745 10.3672 27.7192C10.3637 27.5639 10.4416 27.4191 10.5717 27.3392L11.8827 26.5345C12.2265 26.3234 12.6549 26.317 13.0073 26.5151L15.4147 27.8745L16.4023 27.2683Z" fill="context-fill"/>
+</svg>
diff --git a/browser/themes/shared/urlbar/flight-inflight-progress-2.svg b/browser/themes/shared/urlbar/flight-inflight-progress-2.svg
@@ -0,0 +1,8 @@
+<!-- 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 https://mozilla.org/MPL/2.0/. -->
+<svg width="55" height="55" viewBox="0 0 55 55" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M112.455 63.8434C98.626 28.9271 59.1097 11.8328 24.1934 25.6622" stroke="light-dark(#BAC2CA, #8F8F9D)" stroke-width="2"/>
+<path d="M112.455 63.8431C126.285 98.7595 109.191 138.276 74.2742 152.105C39.3579 165.935 -0.158425 148.84 -13.9879 113.924C-27.8173 79.0077 -10.723 39.4914 24.1933 25.662" stroke="context-stroke" stroke-width="2"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M26.4699 23.1643C27.2569 22.8296 28.1618 23.2102 28.4902 24.0142C28.8187 24.8182 28.4467 25.742 27.6597 26.0767L26.5933 26.5303L26.2426 29.3062C26.1912 29.7138 25.9304 30.0613 25.5599 30.2188L24.1443 30.8209C24.0039 30.8807 23.8429 30.8593 23.7219 30.7649C23.601 30.6705 23.5384 30.5175 23.5579 30.3634L23.8974 27.6766L22.4312 28.3005L22.1563 29.3199C22.1215 29.4489 22.0306 29.5543 21.9096 29.6057L20.6855 30.1259C20.5494 30.1837 20.3936 30.1655 20.2737 30.0778C20.1538 29.99 20.0868 29.8452 20.0966 29.695L20.2385 27.5239L18.6273 26.0985C18.5158 25.9998 18.4621 25.8493 18.4855 25.7006C18.5088 25.5519 18.6058 25.4262 18.742 25.3683L19.9663 24.8476C20.0872 24.7961 20.2246 24.8044 20.3388 24.87L21.2414 25.3881L22.7074 24.7646L20.5985 23.1195C20.4775 23.0251 20.415 22.8721 20.4344 22.718C20.4539 22.5639 20.5524 22.4321 20.6928 22.3724L22.1084 21.7703C22.4796 21.6124 22.9043 21.6694 23.2235 21.9175L25.4035 23.6179L26.4699 23.1643Z" fill="context-fill"/>
+</svg>
diff --git a/browser/themes/shared/urlbar/flight-inflight-progress-3.svg b/browser/themes/shared/urlbar/flight-inflight-progress-3.svg
@@ -0,0 +1,8 @@
+<!-- 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 https://mozilla.org/MPL/2.0/. -->
+<svg width="54" height="55" viewBox="0 0 54 55" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M115.192 74.6065C107.313 37.8869 71.1591 14.5067 34.4395 22.3854" stroke="light-dark(#BAC2CA, #8F8F9D)" stroke-width="2"/>
+<path d="M115.192 74.6062C123.071 111.326 99.6908 147.48 62.9712 155.359C26.2516 163.237 -9.9025 139.857 -17.7812 103.138C-25.6599 66.4179 -2.27973 30.2638 34.4399 22.3851" stroke="context-stroke" stroke-width="2"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M37.0973 20.2974C37.9288 20.0971 38.7585 20.6218 38.9498 21.469C39.1411 22.3162 38.6217 23.1659 37.7903 23.3662L36.6637 23.6376L35.8597 26.3175C35.7418 26.7111 35.4272 27.0108 35.0358 27.1051L33.5403 27.4653C33.392 27.5011 33.2367 27.4534 33.1329 27.3404C33.0292 27.2273 32.9928 27.0661 33.0374 26.9173L33.8156 24.3234L32.2666 24.6968L31.8272 25.6569C31.7716 25.7783 31.6645 25.8673 31.5367 25.898L30.2435 26.2091C30.0997 26.2437 29.9491 26.2 29.8453 26.0937C29.7415 25.9874 29.6993 25.8335 29.7338 25.6869L30.2321 23.569L28.8781 21.8973C28.7844 21.7816 28.7563 21.6243 28.8038 21.4815C28.8514 21.3387 28.9679 21.2307 29.1117 21.1961L30.4052 20.8845C30.5329 20.8537 30.667 20.8845 30.7688 20.968L31.5736 21.628L33.1224 21.2549L31.3138 19.2844C31.21 19.1713 31.1736 19.0101 31.2182 18.8613C31.2628 18.7125 31.3817 18.5988 31.5301 18.5631L33.0256 18.2028C33.4178 18.1084 33.8272 18.2346 34.1012 18.532L35.9707 20.5687L37.0973 20.2974Z" fill="context-fill"/>
+</svg>
diff --git a/browser/themes/shared/urlbar/flight-inflight-progress-4.svg b/browser/themes/shared/urlbar/flight-inflight-progress-4.svg
@@ -0,0 +1,8 @@
+<!-- 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 https://mozilla.org/MPL/2.0/. -->
+<svg width="55" height="55" viewBox="0 0 55 55" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M117.289 86.9564C116.234 49.4159 84.9458 19.8386 47.4053 20.8938" stroke="light-dark(#BAC2CA, #8F8F9D)" stroke-width="2"/>
+<path d="M117.289 86.9563C118.345 124.497 88.7674 155.785 51.2268 156.84C13.6863 157.895 -17.6017 128.318 -18.6568 90.7773C-19.712 53.2368 9.86523 21.9488 47.4058 20.8937" stroke="context-stroke" stroke-width="2"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M50.3987 19.325C51.2527 19.2796 51.9729 19.9467 52.0066 20.8146C52.0403 21.6824 51.3748 22.4233 50.5208 22.4687L49.3636 22.5302L48.0847 25.0188C47.897 25.3843 47.5332 25.6216 47.1311 25.643L45.595 25.7247C45.4426 25.7328 45.2986 25.6577 45.2172 25.5276C45.1358 25.3976 45.1294 25.2323 45.2004 25.0942L46.4382 22.6855L44.8471 22.7704L44.2401 23.6343C44.1634 23.7436 44.0418 23.8116 43.9106 23.8185L42.5823 23.8887C42.4347 23.8965 42.2945 23.8262 42.2118 23.7027C42.1291 23.5792 42.1157 23.4202 42.1763 23.2824L43.0522 21.2908L42.0255 19.4003C41.9545 19.2694 41.9555 19.1097 42.0283 18.9779C42.1011 18.8462 42.2353 18.7612 42.383 18.7534L43.7116 18.6827C43.8428 18.6757 43.9691 18.7305 44.054 18.8312L44.725 19.6267L46.3158 19.5421L44.8966 17.275C44.8152 17.1449 44.8088 16.9797 44.8798 16.8416C44.9507 16.7034 45.0883 16.6133 45.2407 16.6052L46.7769 16.5235C47.1797 16.5021 47.5593 16.7009 47.7744 17.0431L49.2415 19.3865L50.3987 19.325Z" fill="context-fill"/>
+</svg>
diff --git a/browser/themes/shared/urlbarView.css b/browser/themes/shared/urlbarView.css
@@ -1539,6 +1539,42 @@
border-color: color-mix(in srgb, currentColor 10%, transparent);
background-color: var(--urlbar-box-focus-bgcolor);
+ &[backgroundImageId] {
+ background-position: center;
+ -moz-context-properties: fill, stroke;
+ fill: var(--airline-color, currentColor);
+ stroke: var(--airline-color, currentColor);
+ }
+
+ &[backgroundImageId="0"] {
+ background-image: url(chrome://browser/skin/urlbar/flight-inflight-progress-0.svg);
+ }
+
+ &[backgroundImageId="1"] {
+ background-image: url(chrome://browser/skin/urlbar/flight-inflight-progress-1.svg);
+ }
+
+ &[backgroundImageId="2"] {
+ background-image: url(chrome://browser/skin/urlbar/flight-inflight-progress-2.svg);
+ }
+
+ &[backgroundImageId="3"] {
+ background-image: url(chrome://browser/skin/urlbar/flight-inflight-progress-3.svg);
+ }
+
+ &[backgroundImageId="4"] {
+ background-image: url(chrome://browser/skin/urlbar/flight-inflight-progress-4.svg);
+ }
+
+ &[hasForegroundImage] {
+ /* Move up the progress image if exists */
+ background-position-y: bottom 12px;
+ /* Move the foreground image to the end corner */
+ display: flex;
+ justify-content: end;
+ align-items: end;
+ }
+
> .urlbarView-realtime-image[fallback] {
width: 26px;
height: 26px;