Merge mozilla-central to inbound. a=merge CLOSED TREE
|
@ -112,7 +112,7 @@ tasks:
|
|||
ACTION_PARAMETERS: {$json: {$eval: 'parameters'}}
|
||||
|
||||
cache:
|
||||
level-${repository.level}-checkouts-sparse-v1: /builds/worker/checkouts
|
||||
level-${repository.level}-checkouts-sparse-v2: /builds/worker/checkouts
|
||||
|
||||
features:
|
||||
taskclusterProxy: true
|
||||
|
@ -122,7 +122,7 @@ tasks:
|
|||
# exist in tree so we must hard code the hash
|
||||
# XXX Changing this will break Chain of Trust without an associated puppet and
|
||||
# scriptworker patch!
|
||||
image: 'taskcluster/decision:2.0.0@sha256:4039fd878e5700b326d4a636e28c595c053fbcb53909c1db84ad1f513cf644ef'
|
||||
image: 'taskcluster/decision:2.1.0@sha256:6db3b697d7a3c7aba440d72f04199331b872111cefff57206b8b8b1d53230360'
|
||||
|
||||
maxRunTime: 1800
|
||||
|
||||
|
|
|
@ -1428,6 +1428,9 @@ pref("identity.fxaccounts.migrateToDevEdition", true);
|
|||
pref("identity.fxaccounts.migrateToDevEdition", false);
|
||||
#endif
|
||||
|
||||
// If activated, send tab will use the new FxA messages backend.
|
||||
pref("identity.fxaccounts.messages.enabled", false);
|
||||
|
||||
// On GTK, we now default to showing the menubar only when alt is pressed:
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
pref("ui.key.menuAccessKeyFocuses", true);
|
||||
|
|
|
@ -189,6 +189,11 @@ var SidebarUI = {
|
|||
}
|
||||
|
||||
this.hideSwitcherPanel();
|
||||
|
||||
let content = SidebarUI.browser.contentWindow;
|
||||
if (content && content.updatePosition) {
|
||||
content.updatePosition();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -319,10 +319,34 @@ var gSync = {
|
|||
switchToTabHavingURI(url, true, { replaceQueryString: true });
|
||||
},
|
||||
|
||||
sendTabToDevice(url, clientId, title) {
|
||||
Weave.Service.clientsEngine.sendURIToClientForDisplay(url, clientId, title).catch(e => {
|
||||
console.error("Could not send tab to device", e);
|
||||
});
|
||||
async sendTabToDevice(url, clients, title) {
|
||||
let devices;
|
||||
try {
|
||||
devices = await fxAccounts.getDeviceList();
|
||||
} catch (e) {
|
||||
console.error("Could not get the FxA device list", e);
|
||||
devices = []; // We can still run in degraded mode.
|
||||
}
|
||||
const toSendMessages = [];
|
||||
for (const client of clients) {
|
||||
const device = devices.find(d => d.id == client.fxaDeviceId);
|
||||
if (device && fxAccounts.messages.canReceiveSendTabMessages(device)) {
|
||||
toSendMessages.push(device);
|
||||
} else {
|
||||
try {
|
||||
await Weave.Service.clientsEngine.sendURIToClientForDisplay(url, client.id, title);
|
||||
} catch (e) {
|
||||
console.error("Could not send tab to device", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (toSendMessages.length) {
|
||||
try {
|
||||
await fxAccounts.messages.sendTab(toSendMessages, {url, title});
|
||||
} catch (e) {
|
||||
console.error("Could not send tab to device", e);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
populateSendTabToDevicesMenu(devicesPopup, url, title, createDeviceNodeFn) {
|
||||
|
@ -363,18 +387,23 @@ var gSync = {
|
|||
devicesPopup.appendChild(fragment);
|
||||
},
|
||||
|
||||
// TODO: once our transition from the old-send tab world is complete,
|
||||
// this list should be built using the FxA device list instead of the client
|
||||
// collection.
|
||||
_appendSendTabDeviceList(fragment, createDeviceNodeFn, url, title) {
|
||||
const onSendAllCommand = (event) => {
|
||||
this.sendTabToDevice(url, this.remoteClients, title);
|
||||
};
|
||||
const onTargetDeviceCommand = (event) => {
|
||||
let clients = event.target.getAttribute("clientId") ?
|
||||
[event.target.getAttribute("clientId")] :
|
||||
this.remoteClients.map(client => client.id);
|
||||
|
||||
clients.forEach(clientId => this.sendTabToDevice(url, clientId, title));
|
||||
const clientId = event.target.getAttribute("clientId");
|
||||
const client = this.remoteClients.find(c => c.id == clientId);
|
||||
this.sendTabToDevice(url, [client], title);
|
||||
};
|
||||
|
||||
function addTargetDevice(clientId, name, clientType, lastModified) {
|
||||
const targetDevice = createDeviceNodeFn(clientId, name, clientType, lastModified);
|
||||
targetDevice.addEventListener("command", onTargetDeviceCommand, true);
|
||||
targetDevice.addEventListener("command", clientId ? onTargetDeviceCommand :
|
||||
onSendAllCommand, true);
|
||||
targetDevice.classList.add("sync-menuitem", "sendtab-target");
|
||||
targetDevice.setAttribute("clientId", clientId);
|
||||
targetDevice.setAttribute("clientType", clientType);
|
||||
|
|
|
@ -93,6 +93,17 @@ var gBrowser = {
|
|||
},
|
||||
};
|
||||
|
||||
function updatePosition() {
|
||||
// We need both of these to make sure we update the position
|
||||
// after any lower level updates have finished.
|
||||
requestAnimationFrame(() => setTimeout(() => {
|
||||
let browser = document.getElementById("webext-panels-browser");
|
||||
if (browser && browser.isRemoteBrowser) {
|
||||
browser.frameLoader.requestUpdatePosition();
|
||||
}
|
||||
}, 0));
|
||||
}
|
||||
|
||||
function loadPanel(extensionId, extensionUrl, browserStyle) {
|
||||
let browserEl = document.getElementById("webext-panels-browser");
|
||||
if (browserEl) {
|
||||
|
|
|
@ -444,6 +444,7 @@ BrowserGlue.prototype = {
|
|||
this._onDeviceDisconnected();
|
||||
}
|
||||
break;
|
||||
case "fxaccounts:messages:display-tabs":
|
||||
case "weave:engine:clients:display-uris":
|
||||
this._onDisplaySyncURIs(subject);
|
||||
break;
|
||||
|
@ -598,6 +599,7 @@ BrowserGlue.prototype = {
|
|||
os.addObserver(this, "fxaccounts:device_connected");
|
||||
os.addObserver(this, "fxaccounts:verify_login");
|
||||
os.addObserver(this, "fxaccounts:device_disconnected");
|
||||
os.addObserver(this, "fxaccounts:messages:display-tabs");
|
||||
os.addObserver(this, "weave:engine:clients:display-uris");
|
||||
os.addObserver(this, "session-save");
|
||||
os.addObserver(this, "places-init-complete");
|
||||
|
@ -640,6 +642,7 @@ BrowserGlue.prototype = {
|
|||
os.removeObserver(this, "fxaccounts:device_connected");
|
||||
os.removeObserver(this, "fxaccounts:verify_login");
|
||||
os.removeObserver(this, "fxaccounts:device_disconnected");
|
||||
os.removeObserver(this, "fxaccounts:messages:display-tabs");
|
||||
os.removeObserver(this, "weave:engine:clients:display-uris");
|
||||
os.removeObserver(this, "session-save");
|
||||
if (this._bookmarksBackupIdleTime) {
|
||||
|
@ -2543,7 +2546,7 @@ BrowserGlue.prototype = {
|
|||
await Promise.all(URIs.slice(1).map(URI => openTab(URI)));
|
||||
|
||||
let title, body;
|
||||
const deviceName = Weave.Service.clientsEngine.getClientName(URIs[0].clientId);
|
||||
const deviceName = URIs[0].sender.name;
|
||||
const bundle = Services.strings.createBundle("chrome://browser/locale/accounts.properties");
|
||||
if (URIs.length == 1) {
|
||||
// Due to bug 1305895, tabs from iOS may not have device information, so
|
||||
|
@ -2567,7 +2570,7 @@ BrowserGlue.prototype = {
|
|||
}
|
||||
} else {
|
||||
title = bundle.GetStringFromName("multipleTabsArrivingNotification.title");
|
||||
const allSameDevice = URIs.every(URI => URI.clientId == URIs[0].clientId);
|
||||
const allSameDevice = URIs.every(URI => URI.sender.id == URIs[0].sender.id);
|
||||
const unknownDevice = allSameDevice && !deviceName;
|
||||
let tabArrivingBody;
|
||||
if (unknownDevice) {
|
||||
|
|
|
@ -109,7 +109,7 @@ const LibraryButton = {
|
|||
const {nextSibling} = libraryViewInsertionPoint;
|
||||
const item = win.document.createElement("toolbarbutton");
|
||||
item.className = "subviewbutton subviewbutton-iconic";
|
||||
item.addEventListener("command", () => win.openTrustedLinkIn(this.PAGE_TO_OPEN, "tab"));
|
||||
item.addEventListener("command", () => win.openWebLinkIn(this.PAGE_TO_OPEN, "tab"));
|
||||
item.id = this.ITEM_ID;
|
||||
const iconURL = this.ICON_URL;
|
||||
item.setAttribute("image", iconURL);
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
</Description>
|
||||
</em:targetApplication>
|
||||
<em:type>2</em:type>
|
||||
<em:version>30.1.0</em:version>
|
||||
<em:version>32.1.0</em:version>
|
||||
<em:bootstrap>true</em:bootstrap>
|
||||
<em:homepageURL>https://screenshots.firefox.com/</em:homepageURL>
|
||||
<em:multiprocessCompatible>true</em:multiprocessCompatible>
|
||||
|
|
|
@ -157,6 +157,18 @@ FINAL_TARGET_FILES.features['screenshots@mozilla.org']["webextension"]["_locales
|
|||
'webextension/_locales/ga_IE/messages.json'
|
||||
]
|
||||
|
||||
FINAL_TARGET_FILES.features['screenshots@mozilla.org']["webextension"]["_locales"]["gd"] += [
|
||||
'webextension/_locales/gd/messages.json'
|
||||
]
|
||||
|
||||
FINAL_TARGET_FILES.features['screenshots@mozilla.org']["webextension"]["_locales"]["gl"] += [
|
||||
'webextension/_locales/gl/messages.json'
|
||||
]
|
||||
|
||||
FINAL_TARGET_FILES.features['screenshots@mozilla.org']["webextension"]["_locales"]["gn"] += [
|
||||
'webextension/_locales/gn/messages.json'
|
||||
]
|
||||
|
||||
FINAL_TARGET_FILES.features['screenshots@mozilla.org']["webextension"]["_locales"]["gu_IN"] += [
|
||||
'webextension/_locales/gu_IN/messages.json'
|
||||
]
|
||||
|
@ -245,6 +257,10 @@ FINAL_TARGET_FILES.features['screenshots@mozilla.org']["webextension"]["_locales
|
|||
'webextension/_locales/ml/messages.json'
|
||||
]
|
||||
|
||||
FINAL_TARGET_FILES.features['screenshots@mozilla.org']["webextension"]["_locales"]["mn"] += [
|
||||
'webextension/_locales/mn/messages.json'
|
||||
]
|
||||
|
||||
FINAL_TARGET_FILES.features['screenshots@mozilla.org']["webextension"]["_locales"]["mr"] += [
|
||||
'webextension/_locales/mr/messages.json'
|
||||
]
|
||||
|
@ -261,6 +277,10 @@ FINAL_TARGET_FILES.features['screenshots@mozilla.org']["webextension"]["_locales
|
|||
'webextension/_locales/nb_NO/messages.json'
|
||||
]
|
||||
|
||||
FINAL_TARGET_FILES.features['screenshots@mozilla.org']["webextension"]["_locales"]["ne_NP"] += [
|
||||
'webextension/_locales/ne_NP/messages.json'
|
||||
]
|
||||
|
||||
FINAL_TARGET_FILES.features['screenshots@mozilla.org']["webextension"]["_locales"]["nl"] += [
|
||||
'webextension/_locales/nl/messages.json'
|
||||
]
|
||||
|
|
|
@ -15,22 +15,22 @@ async function togglePageActionPanel() {
|
|||
}
|
||||
|
||||
function promiseOpenPageActionPanel() {
|
||||
let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
const dwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
return BrowserTestUtils.waitForCondition(() => {
|
||||
// Wait for the main page action button to become visible. It's hidden for
|
||||
// some URIs, so depending on when this is called, it may not yet be quite
|
||||
// visible. It's up to the caller to make sure it will be visible.
|
||||
info("Waiting for main page action button to have non-0 size");
|
||||
let bounds = dwu.getBoundsWithoutFlushing(BrowserPageActions.mainButtonNode);
|
||||
const bounds = dwu.getBoundsWithoutFlushing(BrowserPageActions.mainButtonNode);
|
||||
return bounds.width > 0 && bounds.height > 0;
|
||||
}).then(() => {
|
||||
// Wait for the panel to become open, by clicking the button if necessary.
|
||||
info("Waiting for main page action panel to be open");
|
||||
if (BrowserPageActions.panelNode.state == "open") {
|
||||
if (BrowserPageActions.panelNode.state === "open") {
|
||||
return Promise.resolve();
|
||||
}
|
||||
let shownPromise = promisePageActionPanelEvent("popupshown");
|
||||
const shownPromise = promisePageActionPanelEvent("popupshown");
|
||||
EventUtils.synthesizeMouseAtCenter(BrowserPageActions.mainButtonNode, {});
|
||||
return shownPromise;
|
||||
}).then(() => {
|
||||
|
@ -41,9 +41,9 @@ function promiseOpenPageActionPanel() {
|
|||
|
||||
function promisePageActionPanelEvent(eventType) {
|
||||
return new Promise(resolve => {
|
||||
let panel = BrowserPageActions.panelNode;
|
||||
if ((eventType == "popupshown" && panel.state == "open") ||
|
||||
(eventType == "popuphidden" && panel.state == "closed")) {
|
||||
const panel = BrowserPageActions.panelNode;
|
||||
if ((eventType === "popupshown" && panel.state === "open") ||
|
||||
(eventType === "popuphidden" && panel.state === "closed")) {
|
||||
executeSoon(resolve);
|
||||
return;
|
||||
}
|
||||
|
@ -55,12 +55,12 @@ function promisePageActionPanelEvent(eventType) {
|
|||
|
||||
function promisePageActionViewChildrenVisible(panelViewNode) {
|
||||
info("promisePageActionViewChildrenVisible waiting for a child node to be visible");
|
||||
let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
const dwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
return BrowserTestUtils.waitForCondition(() => {
|
||||
let bodyNode = panelViewNode.firstChild;
|
||||
for (let childNode of bodyNode.childNodes) {
|
||||
let bounds = dwu.getBoundsWithoutFlushing(childNode);
|
||||
const bodyNode = panelViewNode.firstChild;
|
||||
for (const childNode of bodyNode.childNodes) {
|
||||
const bounds = dwu.getBoundsWithoutFlushing(childNode);
|
||||
if (bounds.width > 0 && bounds.height > 0) {
|
||||
return true;
|
||||
}
|
||||
|
@ -78,8 +78,8 @@ add_task(async function() {
|
|||
|
||||
// Toggle the page action panel to get it to rebuild itself. An actionable
|
||||
// page must be opened first.
|
||||
let url = "http://example.com/browser_screenshots_ui_check";
|
||||
await BrowserTestUtils.withNewTab(url, async () => {
|
||||
const url = "http://example.com/browser_screenshots_ui_check";
|
||||
await BrowserTestUtils.withNewTab(url, async () => { // eslint-disable-line space-before-function-paren
|
||||
await togglePageActionPanel();
|
||||
|
||||
await BrowserTestUtils.waitForCondition(
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
"downloadScreenshot": {
|
||||
"message": "Gam"
|
||||
},
|
||||
"downloadOnlyDetailsESR": {
|
||||
"message": "Itye ka tic ki Firefox pi ESR."
|
||||
},
|
||||
"notificationLinkCopiedTitle": {
|
||||
"message": "Ki loko kakube"
|
||||
},
|
||||
|
@ -40,6 +43,17 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"copyScreenshot": {
|
||||
"message": "Loki"
|
||||
},
|
||||
"imageCroppedWarning": {
|
||||
"message": "Ki ngolo cal ma odoko $PIXELS$px.",
|
||||
"placeholders": {
|
||||
"pixels": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requestErrorTitle": {
|
||||
"message": "Pe tye katic."
|
||||
},
|
||||
|
|
|
@ -129,7 +129,7 @@
|
|||
"message": "Novi način da sačuvate"
|
||||
},
|
||||
"tourBodyPageAction": {
|
||||
"message": "Proširite meni radnji stranice u adresnoj traci svaki put kada želite snimiti ekran."
|
||||
"message": "Proširite meni s radnjama stranice u adresnoj traci svaki put kada želite snimiti ekran."
|
||||
},
|
||||
"tourHeaderClickAndDrag": {
|
||||
"message": "Uslikajte baš ono što želite"
|
||||
|
|
|
@ -44,6 +44,12 @@
|
|||
"downloadOnlyDetailsNeverRemember": {
|
||||
"message": "S'ha activat l'opció «No recordarà mai l'historial»."
|
||||
},
|
||||
"downloadOnlyDetailsESR": {
|
||||
"message": "Feu servir el Firefox ESR."
|
||||
},
|
||||
"downloadOnlyDetailsNoUploadPref": {
|
||||
"message": "Les pujades estan inhabilitades."
|
||||
},
|
||||
"notificationLinkCopiedTitle": {
|
||||
"message": "S'ha copiat l'enllaç"
|
||||
},
|
||||
|
|
|
@ -44,6 +44,12 @@
|
|||
"downloadOnlyDetailsNeverRemember": {
|
||||
"message": "„Chronik niemals anlegen“ ist aktiviert."
|
||||
},
|
||||
"downloadOnlyDetailsESR": {
|
||||
"message": "Sie verwenden Firefox ESR."
|
||||
},
|
||||
"downloadOnlyDetailsNoUploadPref": {
|
||||
"message": "Uploads wurden deaktiviert."
|
||||
},
|
||||
"notificationLinkCopiedTitle": {
|
||||
"message": "Link kopiert"
|
||||
},
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
"downloadScreenshot": {
|
||||
"message": "Λήψη"
|
||||
},
|
||||
"downloadOnlyDetailsPrivate": {
|
||||
"message": "Σε ένα παράθυρο ιδιωτικής περιήγησης."
|
||||
},
|
||||
"downloadOnlyDetailsThirdParty": {
|
||||
"message": "Τα cookies τρίτων είναι απενεργοποιημένα."
|
||||
},
|
||||
|
|
|
@ -44,6 +44,12 @@
|
|||
"downloadOnlyDetailsNeverRemember": {
|
||||
"message": "“ei säilita ajalugu” on lubatud"
|
||||
},
|
||||
"downloadOnlyDetailsESR": {
|
||||
"message": "Sa kasutad Firefox ESRi."
|
||||
},
|
||||
"downloadOnlyDetailsNoUploadPref": {
|
||||
"message": "Üleslaadimised on keelatud."
|
||||
},
|
||||
"notificationLinkCopiedTitle": {
|
||||
"message": "Link kopeeriti"
|
||||
},
|
||||
|
@ -58,6 +64,17 @@
|
|||
"copyScreenshot": {
|
||||
"message": "Kopeeri"
|
||||
},
|
||||
"notificationImageCopiedTitle": {
|
||||
"message": "Pilt kopeeriti"
|
||||
},
|
||||
"notificationImageCopiedDetails": {
|
||||
"message": "Sinu pilt kopeeriti vahemällu. Asetamiseks vajuta $META_KEY$-V.",
|
||||
"placeholders": {
|
||||
"meta_key": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"imageCroppedWarning": {
|
||||
"message": "See pilt on vähendatud $PIXELS$-le pikslile.",
|
||||
"placeholders": {
|
||||
|
|
|
@ -0,0 +1,184 @@
|
|||
{
|
||||
"addonDescription": {
|
||||
"message": "Tog cliopaichean is glacaidhean-sgrìn on lìon is sàbhail iad rè seal no gu buan."
|
||||
},
|
||||
"addonAuthorsList": {
|
||||
"message": "Mozilla <screenshots-feedback@mozilla.com>"
|
||||
},
|
||||
"contextMenuLabel": {
|
||||
"message": "Tog glacadh-sgrìn"
|
||||
},
|
||||
"myShotsLink": {
|
||||
"message": "Na glacaidhean agam"
|
||||
},
|
||||
"screenshotInstructions": {
|
||||
"message": "Dèan briogadh no slaodadh air an duilleag airson raon a thaghadh. Brùth ESC airson sgur dheth."
|
||||
},
|
||||
"saveScreenshotSelectedArea": {
|
||||
"message": "Sàbhail"
|
||||
},
|
||||
"saveScreenshotVisibleArea": {
|
||||
"message": "Sàbhail na tha ri fhaicinn"
|
||||
},
|
||||
"saveScreenshotFullPage": {
|
||||
"message": "Sàbhail an duilleag shlàn"
|
||||
},
|
||||
"cancelScreenshot": {
|
||||
"message": "Sguir dheth"
|
||||
},
|
||||
"downloadScreenshot": {
|
||||
"message": "Luchdaich a-nuas"
|
||||
},
|
||||
"downloadOnlyNotice": {
|
||||
"message": "Tha thu sa mhodh luchdaidh a-nuas a-mhàin."
|
||||
},
|
||||
"downloadOnlyDetails": {
|
||||
"message": "Bidh gleus glacaidhean-sgrìn Firefox sa mhodh luchdaidh a-nuas gu fèin-obrachail sna suidheachaidhean a leanas:"
|
||||
},
|
||||
"downloadOnlyDetailsPrivate": {
|
||||
"message": "Ann an uinneag brabhsaidh phrìobhaidich."
|
||||
},
|
||||
"downloadOnlyDetailsThirdParty": {
|
||||
"message": "Tha briosgaidean threas-phàrtaidhean à comas."
|
||||
},
|
||||
"downloadOnlyDetailsNeverRemember": {
|
||||
"message": "Tha “Na cuimhnich an eachdraidh idir” an comas."
|
||||
},
|
||||
"downloadOnlyDetailsESR": {
|
||||
"message": "Tha thu a’ cleachdadh Firefox ESR."
|
||||
},
|
||||
"downloadOnlyDetailsNoUploadPref": {
|
||||
"message": "Chaidh an luchdadh suas a chur à comas."
|
||||
},
|
||||
"notificationLinkCopiedTitle": {
|
||||
"message": "Chaidh lethbhreac a dhèanamh dhen cheangal"
|
||||
},
|
||||
"notificationLinkCopiedDetails": {
|
||||
"message": "Chaidh lethbhreac de cheangal a’ ghlacaidh agad a chur air an stòr-bhòrd. Brùth $META_KEY$-V airson a chur ann.",
|
||||
"placeholders": {
|
||||
"meta_key": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"copyScreenshot": {
|
||||
"message": "Dèan lethbhreac"
|
||||
},
|
||||
"notificationImageCopiedTitle": {
|
||||
"message": "Chaidh lethbhreac a dhèanamh dhen ghlacadh"
|
||||
},
|
||||
"notificationImageCopiedDetails": {
|
||||
"message": "Chaidh lethbhreac dhen ghlacadh agad a chur air an stòr-bhòrd. Brùth $META_KEY$-V airson a chur ann.",
|
||||
"placeholders": {
|
||||
"meta_key": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"imageCroppedWarning": {
|
||||
"message": "Chaidh an dealbh a bhearradh is tha e $PIXELS$px a-nis.",
|
||||
"placeholders": {
|
||||
"pixels": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requestErrorTitle": {
|
||||
"message": "Tuibriste."
|
||||
},
|
||||
"requestErrorDetails": {
|
||||
"message": "Tha sinn duilich! Cha b’ urrainn dhuinn an glacadh agad a shàbhaladh. Feuch ris a-rithist an ceann greis."
|
||||
},
|
||||
"connectionErrorTitle": {
|
||||
"message": "Cha b’ urrainn dhuinn na glacaidhean-sgrìn agad a shàbhaladh."
|
||||
},
|
||||
"connectionErrorDetails": {
|
||||
"message": "Thoir sùil air a’ cheangal agad ris an eadar-lìon. Ma tha ceangal agad ris, dh’fhaoidte gu bheil duilgheadas sealach aig seirbheis glacaidhean-sgrìn Firefox."
|
||||
},
|
||||
"loginErrorDetails": {
|
||||
"message": "Cha b’ urrainn dhuinn an glacadh agad a shàbhaladh air sgàth duilgheadas le seirbheis glacaidhean-sgrìn Firefox. Feuch ris a-rithist an ceann greis."
|
||||
},
|
||||
"unshootablePageErrorTitle": {
|
||||
"message": "Chan urrainn dhuinn glacadh-sgrìn a dhèanamh dhen duilleag seo."
|
||||
},
|
||||
"unshootablePageErrorDetails": {
|
||||
"message": "Chan eil duilleag-lìn àbhaisteach a tha seo ’s chan urrainn dhut glacadh-sgrìn a dhèanamh dheth."
|
||||
},
|
||||
"selfScreenshotErrorTitle": {
|
||||
"message": "Chan urrainn dhut glacadh a thogail de dhuilleag ghlacaidhean-sgrìn Firefox!"
|
||||
},
|
||||
"emptySelectionErrorTitle": {
|
||||
"message": "Tha na thagh thu ro bheag"
|
||||
},
|
||||
"privateWindowErrorTitle": {
|
||||
"message": "Tha gleus nan glacaidhean-sgrìn à comas ann am modh a’ bhrabhsaidh phrìobhaidich"
|
||||
},
|
||||
"privateWindowErrorDetails": {
|
||||
"message": "Tha sinn duilich mu dhèidhinn. Tha sinn ag obair air agus an dòchas gum bi e ri làimh a dh’aithghearr."
|
||||
},
|
||||
"genericErrorTitle": {
|
||||
"message": "Ìoc! Sin glacaidhean-sgrìn Firefox air feadh na fìdhle."
|
||||
},
|
||||
"genericErrorDetails": {
|
||||
"message": "Chan eil sinn cinnteach dè thachair. A bheil thu airson feuchainn ris a-rithist no glacadh a thogail de dhuilleag eile?"
|
||||
},
|
||||
"tourBodyIntro": {
|
||||
"message": "Tog, sàbhail is co-roinn glacadh-sgrìn gun Firefix fhàgail."
|
||||
},
|
||||
"tourHeaderPageAction": {
|
||||
"message": "Dòigh ùr airson sàbhaladh"
|
||||
},
|
||||
"tourBodyPageAction": {
|
||||
"message": "Leudaich clàr-taice gnìomhan na duilleige ann am bàr an t-seòlaidh uair sam bith a tha thu airson glacadh-sgrìn a thogail."
|
||||
},
|
||||
"tourHeaderClickAndDrag": {
|
||||
"message": "Na glac ach dìreach na tha a dhìth ort"
|
||||
},
|
||||
"tourBodyClickAndDrag": {
|
||||
"message": "Dèan briogadh is slaodadh airson earrann de dhuilleag a ghlacadh. ’S urrainn dhut fantainn os cionn rud cuideachd airson na thagh thu a shoillseachadh."
|
||||
},
|
||||
"tourHeaderFullPage": {
|
||||
"message": "Glac uinneagan no duilleagan slàna"
|
||||
},
|
||||
"tourBodyFullPage": {
|
||||
"message": "Tagh na putanan air an taobh deas gu h-àrd airson na tha ri fhaicinn san uinneag a ghlacadh no airson duilleag shlàn a ghlacadh."
|
||||
},
|
||||
"tourHeaderDownloadUpload": {
|
||||
"message": "Do thoil fhèin"
|
||||
},
|
||||
"tourBodyDownloadUpload": {
|
||||
"message": "Sàbhail na glacaidhean bearrte air an lìon ach am bi e furasta an co-roinneadh no luchdaich a-nuas iad dhan choimpiutair agad. ’S urrainn dhut briogadh air a’ phutan “Na glacaidhean agam” cuideachd is chì thu gach glacadh a thog thu."
|
||||
},
|
||||
"tourSkip": {
|
||||
"message": "LEUM SEACHAD"
|
||||
},
|
||||
"tourNext": {
|
||||
"message": "An ath-shleamhnag"
|
||||
},
|
||||
"tourPrevious": {
|
||||
"message": "An t-sleamhnag roimhe"
|
||||
},
|
||||
"tourDone": {
|
||||
"message": "Dèanta"
|
||||
},
|
||||
"termsAndPrivacyNotice2": {
|
||||
"message": "Ma chleachdas tu gleus nan glacaidhean-sgrìn aig Firefox, bidh thu ag aontachadh ris na $TERMSANDPRIVACYNOTICETERMSLINK$ agus $TERMSANDPRIVACYNOTICEPRIVACYLINK$ againn.",
|
||||
"placeholders": {
|
||||
"termsandprivacynoticetermslink": {
|
||||
"content": "$1"
|
||||
},
|
||||
"termsandprivacynoticeprivacylink": {
|
||||
"content": "$2"
|
||||
}
|
||||
}
|
||||
},
|
||||
"termsAndPrivacyNoticeTermsLink": {
|
||||
"message": "na teirmichean"
|
||||
},
|
||||
"termsAndPrivacyNoticyPrivacyLink": {
|
||||
"message": "an aithris prìobhaideachd"
|
||||
},
|
||||
"libraryLabel": {
|
||||
"message": "Glacaidhean-sgrìn"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
{
|
||||
"myShotsLink": {
|
||||
"message": "As miñas capturas"
|
||||
},
|
||||
"saveScreenshotSelectedArea": {
|
||||
"message": "Gardar"
|
||||
},
|
||||
"saveScreenshotVisibleArea": {
|
||||
"message": "Gardar a parte visible"
|
||||
},
|
||||
"saveScreenshotFullPage": {
|
||||
"message": "Gardar a páxina completa"
|
||||
},
|
||||
"cancelScreenshot": {
|
||||
"message": "Cancelar"
|
||||
},
|
||||
"downloadScreenshot": {
|
||||
"message": "Descargar"
|
||||
},
|
||||
"downloadOnlyDetailsPrivate": {
|
||||
"message": "Nunha xanela de navegación privada."
|
||||
},
|
||||
"downloadOnlyDetailsThirdParty": {
|
||||
"message": "Cando as cookies de terceiros están desactivadas."
|
||||
},
|
||||
"downloadOnlyDetailsNeverRemember": {
|
||||
"message": "Cando está activa a opción \"Nunca gardará o historial\"."
|
||||
},
|
||||
"downloadOnlyDetailsESR": {
|
||||
"message": "Está usando Firefox ESR."
|
||||
},
|
||||
"notificationLinkCopiedTitle": {
|
||||
"message": "Copiouse a ligazón"
|
||||
},
|
||||
"copyScreenshot": {
|
||||
"message": "Copiar"
|
||||
},
|
||||
"notificationImageCopiedTitle": {
|
||||
"message": "Copiouse a captura"
|
||||
},
|
||||
"tourDone": {
|
||||
"message": "Feito"
|
||||
},
|
||||
"termsAndPrivacyNotice2": {
|
||||
"message": "Ao usar Firefox Screenshots, vostede acepta os nosos $TERMSANDPRIVACYNOTICETERMSLINK$ e a $TERMSANDPRIVACYNOTICEPRIVACYLINK$.",
|
||||
"placeholders": {
|
||||
"termsandprivacynoticetermslink": {
|
||||
"content": "$1"
|
||||
},
|
||||
"termsandprivacynoticeprivacylink": {
|
||||
"content": "$2"
|
||||
}
|
||||
}
|
||||
},
|
||||
"termsAndPrivacyNoticeTermsLink": {
|
||||
"message": "Termos"
|
||||
},
|
||||
"termsAndPrivacyNoticyPrivacyLink": {
|
||||
"message": "Política de privacidade"
|
||||
},
|
||||
"libraryLabel": {
|
||||
"message": "Capturas de pantalla"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"saveScreenshotSelectedArea": {
|
||||
"message": "Ñongatu"
|
||||
},
|
||||
"saveScreenshotVisibleArea": {
|
||||
"message": "Ñongatu hechapy"
|
||||
},
|
||||
"saveScreenshotFullPage": {
|
||||
"message": "Kuatiarogue tuichavéva ñongatu"
|
||||
},
|
||||
"cancelScreenshot": {
|
||||
"message": "Heja"
|
||||
}
|
||||
}
|
|
@ -29,6 +29,27 @@
|
|||
"downloadScreenshot": {
|
||||
"message": "הורדה"
|
||||
},
|
||||
"downloadOnlyNotice": {
|
||||
"message": "הינך כרגע במצב הורדה בלבד."
|
||||
},
|
||||
"downloadOnlyDetails": {
|
||||
"message": "Firefox Screenshots משתנה אוטומטית למצב הורדה בלבד במקרים הבאים:"
|
||||
},
|
||||
"downloadOnlyDetailsPrivate": {
|
||||
"message": "בחלון גלישה פרטית."
|
||||
},
|
||||
"downloadOnlyDetailsThirdParty": {
|
||||
"message": "כשעוגיות צד שלישי מנוטרלות."
|
||||
},
|
||||
"downloadOnlyDetailsNeverRemember": {
|
||||
"message": "„לא לזכור היסטוריה” פעיל."
|
||||
},
|
||||
"downloadOnlyDetailsESR": {
|
||||
"message": "הגרסה שלך היא Firefox ESR."
|
||||
},
|
||||
"downloadOnlyDetailsNoUploadPref": {
|
||||
"message": "ההעלאות הושבתו."
|
||||
},
|
||||
"notificationLinkCopiedTitle": {
|
||||
"message": "הקישור הועתק"
|
||||
},
|
||||
|
@ -40,6 +61,28 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"copyScreenshot": {
|
||||
"message": "העתקה"
|
||||
},
|
||||
"notificationImageCopiedTitle": {
|
||||
"message": "צילום המסך הועתק"
|
||||
},
|
||||
"notificationImageCopiedDetails": {
|
||||
"message": "צילום המסך שלך הועתק ללוח העריכה. יש ללחוץ על $META_KEY$-V כדי להדביק.",
|
||||
"placeholders": {
|
||||
"meta_key": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"imageCroppedWarning": {
|
||||
"message": "תמונה זו נחתכה לגודל של $PIXELS$ פיקסלים.",
|
||||
"placeholders": {
|
||||
"pixels": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requestErrorTitle": {
|
||||
"message": "לא תקין."
|
||||
},
|
||||
|
@ -85,6 +128,9 @@
|
|||
"tourHeaderPageAction": {
|
||||
"message": "דרך חדשה לשמירה"
|
||||
},
|
||||
"tourBodyPageAction": {
|
||||
"message": "יש לפתוח את תפריט פעולות הדף בסרגל הכתובת בכל פעם שברצונך לצלם את המסך."
|
||||
},
|
||||
"tourHeaderClickAndDrag": {
|
||||
"message": "לצלם רק את מה שנחוץ לך"
|
||||
},
|
||||
|
|
|
@ -58,6 +58,20 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"copyScreenshot": {
|
||||
"message": "प्रतिलिपि बनाएँ"
|
||||
},
|
||||
"notificationImageCopiedTitle": {
|
||||
"message": "शॉट प्रतिलिपि बनाई गई"
|
||||
},
|
||||
"notificationImageCopiedDetails": {
|
||||
"message": "आपके शॉट के लिंक क्लिपबोर्ड पर कॉपी किए गए हैं. पेस्ट करने के लिए $META_KEY$-V दबाएँ.",
|
||||
"placeholders": {
|
||||
"meta_key": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"imageCroppedWarning": {
|
||||
"message": "इस छवि को $PIXELS$px में छोटा किया गया है.",
|
||||
"placeholders": {
|
||||
|
|
|
@ -44,6 +44,9 @@
|
|||
"downloadOnlyDetailsNeverRemember": {
|
||||
"message": "“히스토리 기억 안함”이 활성화되어 있을 때"
|
||||
},
|
||||
"downloadOnlyDetailsESR": {
|
||||
"message": "Firefox ESR을 사용중입니다."
|
||||
},
|
||||
"notificationLinkCopiedTitle": {
|
||||
"message": "링크 복사됨"
|
||||
},
|
||||
|
|
|
@ -40,6 +40,9 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"copyScreenshot": {
|
||||
"message": "Còpia"
|
||||
},
|
||||
"requestErrorTitle": {
|
||||
"message": "Feua serviçio."
|
||||
},
|
||||
|
@ -73,6 +76,9 @@
|
|||
"tourBodyIntro": {
|
||||
"message": "Fanni, sarva e condividdi föto do schermo sensa sciortî da Firefox."
|
||||
},
|
||||
"tourHeaderPageAction": {
|
||||
"message": "Un neuvo mòddo de sarvâ"
|
||||
},
|
||||
"tourHeaderClickAndDrag": {
|
||||
"message": "Catua solo quello che t'eu"
|
||||
},
|
||||
|
@ -103,13 +109,13 @@
|
|||
"tourDone": {
|
||||
"message": "Fæto"
|
||||
},
|
||||
"termsAndPrivacyNoticeCloudServices": {
|
||||
"message": "Se ti deuvi Firefox Screenshots, ti e d'acordio con {termsAndPrivacyNoticeTermsLink} e {termsAndPrivacyNoticePrivacyLink} de Firefox Cloud Services."
|
||||
},
|
||||
"termsAndPrivacyNoticeTermsLink": {
|
||||
"message": "Termini"
|
||||
},
|
||||
"termsAndPrivacyNoticyPrivacyLink": {
|
||||
"message": "Informativa in sciâ privacy"
|
||||
},
|
||||
"libraryLabel": {
|
||||
"message": "Föto do schermo"
|
||||
}
|
||||
}
|
|
@ -29,6 +29,27 @@
|
|||
"downloadScreenshot": {
|
||||
"message": "Преземи"
|
||||
},
|
||||
"downloadOnlyNotice": {
|
||||
"message": "Во моментов сте во режим Само Преземање."
|
||||
},
|
||||
"downloadOnlyDetails": {
|
||||
"message": "Firefox Screenshots се префрла во режим Само Преземање во овие случаи:"
|
||||
},
|
||||
"downloadOnlyDetailsPrivate": {
|
||||
"message": "Во приватен прозорец."
|
||||
},
|
||||
"downloadOnlyDetailsThirdParty": {
|
||||
"message": "Колачињата од трети страни се оневозможени."
|
||||
},
|
||||
"downloadOnlyDetailsNeverRemember": {
|
||||
"message": "“Никогаш нема да ја памти историјата” е вклучена."
|
||||
},
|
||||
"downloadOnlyDetailsESR": {
|
||||
"message": "Користите Firefox ESR."
|
||||
},
|
||||
"downloadOnlyDetailsNoUploadPref": {
|
||||
"message": "Качувањето на датотеки е оневозможено."
|
||||
},
|
||||
"notificationLinkCopiedTitle": {
|
||||
"message": "Врската е ископирана"
|
||||
},
|
||||
|
@ -40,6 +61,20 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"copyScreenshot": {
|
||||
"message": "Копирај"
|
||||
},
|
||||
"notificationImageCopiedTitle": {
|
||||
"message": "Слика е ископирана"
|
||||
},
|
||||
"notificationImageCopiedDetails": {
|
||||
"message": "Вашата слика беше ископирана во меморија. Притиснете $META_KEY$-V за да ја вметнете.",
|
||||
"placeholders": {
|
||||
"meta_key": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"imageCroppedWarning": {
|
||||
"message": "Оваа слика е скратена до $PIXELS$px.",
|
||||
"placeholders": {
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"addonDescription": {
|
||||
"message": "Вэбээс авсан клип болон дэлгэцийн зургийг аваад тэдгээрийг түр эсвэл бүрмөсөн хадгал."
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"addonDescription": {
|
||||
"message": "वेबबाट फोटो र सिक्रिनसट या क्लिपहरू लिएर क्षणिक वा सदाको लागि सङ्ग्रह गर्न ।"
|
||||
},
|
||||
"contextMenuLabel": {
|
||||
"message": "स्क्रिनसट लिनुहोस्"
|
||||
},
|
||||
"myShotsLink": {
|
||||
"message": "मेरा सटहरू"
|
||||
},
|
||||
"saveScreenshotSelectedArea": {
|
||||
"message": "सङ्ग्रह गर्नुहोस्"
|
||||
},
|
||||
"saveScreenshotVisibleArea": {
|
||||
"message": "दृश्यात्मक सङ्ग्रह गर्नुहोस्"
|
||||
},
|
||||
"cancelScreenshot": {
|
||||
"message": "रद्द गर्नुहोस"
|
||||
}
|
||||
}
|
|
@ -26,15 +26,65 @@
|
|||
"downloadScreenshot": {
|
||||
"message": "ਡਾਊਨਲੋਡ ਕਰੋ"
|
||||
},
|
||||
"downloadOnlyDetailsPrivate": {
|
||||
"message": "ਇੱਕ ਨਿੱਜੀ ਬਰਾਊਜਿੰਗ ਵਿੰਡੋ ਵਿੱਚ"
|
||||
},
|
||||
"downloadOnlyDetailsThirdParty": {
|
||||
"message": "ਤੀਜੀ ਧਿਰ ਦੀਆਂ ਕੂਕੀਜ ਆਯੋਗ ਹਨ।"
|
||||
},
|
||||
"downloadOnlyDetailsNeverRemember": {
|
||||
"message": "\"ਅਤੀਤ ਕਦੇ ਵੀ ਯਾਦ ਨਾ ਰੱਖੋ\" ਆਯੋਗ ਕੀਤਾ ਗਿਆ ਹੈ।"
|
||||
},
|
||||
"downloadOnlyDetailsESR": {
|
||||
"message": "ਤੁਸੀਂ ESR ਫਾਇਰਫਾਕਸ ਵਰਤ ਰਹੇ ਹੋ।"
|
||||
},
|
||||
"downloadOnlyDetailsNoUploadPref": {
|
||||
"message": "ਅੱਪਲ੍ਹੋਡ ਆਯੋਗ ਕੀਤੇ ਗਏ ਹਨ।"
|
||||
},
|
||||
"notificationLinkCopiedTitle": {
|
||||
"message": "ਲਿੰਕ ਕਾਪੀ ਕੀਤਾ ਗਿਆ"
|
||||
},
|
||||
"copyScreenshot": {
|
||||
"message": "ਕਾਪੀ"
|
||||
},
|
||||
"notificationImageCopiedTitle": {
|
||||
"message": "ਸ਼ਾਟ ਕਾਪੀ ਕੀਤਾ ਗਿਆ"
|
||||
},
|
||||
"notificationImageCopiedDetails": {
|
||||
"message": "ਤੁਹਾਡਾ ਸ਼ਾਟ ਕਲਿੱਪਬੋਰਡ ਤੋਂ ਕਾਪੀ ਕੀਤਾ ਗਿਆ ਹੈ। ਪੇਸਟ ਕਰਨ ਲਈ $META_KEY$-V ਨੂੰ ਦਬਾਓ।",
|
||||
"placeholders": {
|
||||
"meta_key": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requestErrorTitle": {
|
||||
"message": "ਖ਼ਰਾਬ ਹੈ।"
|
||||
},
|
||||
"connectionErrorTitle": {
|
||||
"message": "ਅਸੀਂ ਤੁਹਾਡੇ ਸਕਰੀਨਸ਼ਾਟ ਨਾਲ ਕੁਨੈੱਕਟ ਨਹੀਂ ਕਰ ਸਕਦੇ।"
|
||||
},
|
||||
"unshootablePageErrorTitle": {
|
||||
"message": "ਅਸੀਂ ਇਸ ਸਫੇ ਦਾ ਸਕਰੀਨਸ਼ਾਟ ਨਹੀਂ ਲੈ ਸਕਦੇ।"
|
||||
},
|
||||
"emptySelectionErrorTitle": {
|
||||
"message": "ਤੁਹਾਡੀ ਚੋਣ ਬਹੁਤ ਛੋਟੀ ਹੈ"
|
||||
},
|
||||
"privateWindowErrorTitle": {
|
||||
"message": "ਨਿੱਜੀ ਬਰਾਊਜਿੰਗ ਮੋਡ ਵਿੱਚ ਸਕਰੀਨਸ਼ਾਟ ਆਯੋਗ ਹੋਇਆ"
|
||||
},
|
||||
"genericErrorTitle": {
|
||||
"message": "ਠਹਿਰੋ! ਫਾਇਰਫਾਕਸ ਸਕਰੀਨਸ਼ਾਟ ਲੈਣ 'ਚ ਸਮੱਸਿਆ ਆਈ"
|
||||
},
|
||||
"tourBodyIntro": {
|
||||
"message": "ਬਿਨਾਂ ਫਾਇਰਫਾਕਸ ਨੂੰ ਛੱਡੇ ਸਕਰੀਨਸ਼ਾਟ ਲਓ, ਸੰਭਾਲੋ, ਅਤੇ ਸਾਂਝਾ ਕਰੋ।"
|
||||
},
|
||||
"tourHeaderPageAction": {
|
||||
"message": "ਸੰਭਾਲਣ ਦਾ ਨਵਾਂ ਢੰਗ"
|
||||
},
|
||||
"tourHeaderClickAndDrag": {
|
||||
"message": "ਕੈਪਚਰ ਕਰੋ ਤੁਸੀਂ ਕੀ ਚਾਹੁੰਦੇ ਹੋ"
|
||||
},
|
||||
"tourSkip": {
|
||||
"message": "ਛੱਡੋ"
|
||||
},
|
||||
|
@ -46,5 +96,8 @@
|
|||
},
|
||||
"tourDone": {
|
||||
"message": "ਮੁਕੰਮਲ"
|
||||
},
|
||||
"termsAndPrivacyNoticyPrivacyLink": {
|
||||
"message": "ਨਿੱਜੀ ਨੋਟਿਸ"
|
||||
}
|
||||
}
|
|
@ -30,7 +30,7 @@
|
|||
"message": "Descarcă"
|
||||
},
|
||||
"downloadOnlyNotice": {
|
||||
"message": "Momentan sunteți în modul descărcare."
|
||||
"message": "În prezent ești în modul numai de descărcare."
|
||||
},
|
||||
"downloadOnlyDetails": {
|
||||
"message": "Firefox Screenshots se mută automat în modul descărcare în aceste situații:"
|
||||
|
|
|
@ -26,6 +26,15 @@
|
|||
"downloadOnlyNotice": {
|
||||
"message": "మీరు ప్రస్తుతం దింపుకోలు-మాత్రమే రీతిలో ఉన్నారు."
|
||||
},
|
||||
"downloadOnlyDetailsPrivate": {
|
||||
"message": "అంతరంగిక విహారణ కిటికీలో."
|
||||
},
|
||||
"downloadOnlyDetailsThirdParty": {
|
||||
"message": "మూడవ-పక్ష కుకీలు అచేతనమయ్యాయి."
|
||||
},
|
||||
"downloadOnlyDetailsESR": {
|
||||
"message": "మీరు Firefox ESR ఉపయోగిస్తున్నారు."
|
||||
},
|
||||
"downloadOnlyDetailsNoUploadPref": {
|
||||
"message": "ఎక్కింపులు అచేతమై ఉన్నాయి."
|
||||
},
|
||||
|
@ -35,6 +44,9 @@
|
|||
"copyScreenshot": {
|
||||
"message": "కాపీచెయ్యి"
|
||||
},
|
||||
"notificationImageCopiedTitle": {
|
||||
"message": "పట్టు కాపీఅయ్యింది"
|
||||
},
|
||||
"requestErrorTitle": {
|
||||
"message": "పని చెయుట లేదు."
|
||||
},
|
||||
|
|
|
@ -38,6 +38,9 @@
|
|||
"downloadOnlyDetailsThirdParty": {
|
||||
"message": "คุกกี้บุคคลที่สามถูกปิดการใช้งาน"
|
||||
},
|
||||
"downloadOnlyDetailsESR": {
|
||||
"message": "คุณกำลังใช้ Firefox ESR"
|
||||
},
|
||||
"notificationLinkCopiedTitle": {
|
||||
"message": "คัดลอกลิงก์แล้ว"
|
||||
},
|
||||
|
@ -49,6 +52,12 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"copyScreenshot": {
|
||||
"message": "คัดลอก"
|
||||
},
|
||||
"notificationImageCopiedTitle": {
|
||||
"message": "คัดลอกภาพแล้ว"
|
||||
},
|
||||
"imageCroppedWarning": {
|
||||
"message": "ภาพนี้ถูกตัดเป็น $PIXELS$ พิกเซล",
|
||||
"placeholders": {
|
||||
|
|
|
@ -129,13 +129,13 @@
|
|||
"message": "Kaydetmenin yeni yolu"
|
||||
},
|
||||
"tourBodyPageAction": {
|
||||
"message": "Ekran görüntüsü almak istediğiniz zaman adres çubuğundaki sayfa eylemleri menüsünü açabilirsiniz."
|
||||
"message": "Ekran görüntüsü almak istediğiniz zaman adres çubuğundaki sayfa eylemleri menüsünü açın."
|
||||
},
|
||||
"tourHeaderClickAndDrag": {
|
||||
"message": "İstediğini yakala"
|
||||
},
|
||||
"tourBodyClickAndDrag": {
|
||||
"message": "Sayfanın belli bir kısmını yakalamak için işaretçiyi tıklayıp sürükleyin. Seçiminizi vurgulamak için fareyle üzerine gelebilirsiniz."
|
||||
"message": "Sayfanın belli bir kısmını yakalamak için tıklayıp sürükleyin. Seçiminizi işaretlemek için fareyle üzerine de gidebilirsiniz."
|
||||
},
|
||||
"tourHeaderFullPage": {
|
||||
"message": "Pencereleri veya sayfaların tamamını yakala"
|
||||
|
@ -147,7 +147,7 @@
|
|||
"message": "İstediğin gibi yakala"
|
||||
},
|
||||
"tourBodyDownloadUpload": {
|
||||
"message": "Ekran görüntülerinizi daha kolay paylaşmak veya bilgisayarınıza indirmek için web’e kaydedin. Kaydettiğiniz tüm görüntüleri bulmak için \"Ekran görüntülerim\" düğmesine tıklayabilirsiniz."
|
||||
"message": "Ekran görüntülerinizi daha kolay paylaşmak web’e kaydedebilir veya bilgisayarınıza indirebilirsiniz. Kaydettiğiniz tüm görüntüleri bulmak için “Ekran görüntülerim” düğmesine tıklayabilirsiniz."
|
||||
},
|
||||
"tourSkip": {
|
||||
"message": "GEÇ"
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
"downloadScreenshot": {
|
||||
"message": "ڈاؤن لوڈ"
|
||||
},
|
||||
"downloadOnlyDetailsESR": {
|
||||
"message": "آپ Firefox ESR استعمال کر رہے ہیں۔"
|
||||
},
|
||||
"notificationLinkCopiedTitle": {
|
||||
"message": "تبط نقل کر دیا گیا"
|
||||
},
|
||||
|
@ -40,6 +43,9 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"copyScreenshot": {
|
||||
"message": "نقل کریں"
|
||||
},
|
||||
"requestErrorTitle": {
|
||||
"message": "خراب ہے۔"
|
||||
},
|
||||
|
|
|
@ -11,11 +11,9 @@ this.main = (function() {
|
|||
const manifest = browser.runtime.getManifest();
|
||||
let backend;
|
||||
|
||||
let hasSeenOnboarding;
|
||||
|
||||
browser.storage.local.get(["hasSeenOnboarding"]).then((result) => {
|
||||
hasSeenOnboarding = !!result.hasSeenOnboarding;
|
||||
if (!hasSeenOnboarding) {
|
||||
let hasSeenOnboarding = browser.storage.local.get(["hasSeenOnboarding"]).then((result) => {
|
||||
const onboarded = !!result.hasSeenOnboarding;
|
||||
if (!onboarded) {
|
||||
setIconActive(false, null);
|
||||
// Note that the branded name 'Firefox Screenshots' is not localized:
|
||||
startBackground.photonPageActionPort.postMessage({
|
||||
|
@ -23,6 +21,8 @@ this.main = (function() {
|
|||
title: "Firefox Screenshots"
|
||||
});
|
||||
}
|
||||
hasSeenOnboarding = Promise.resolve(onboarded);
|
||||
return hasSeenOnboarding;
|
||||
}).catch((error) => {
|
||||
log.error("Error getting hasSeenOnboarding:", error);
|
||||
});
|
||||
|
@ -93,34 +93,36 @@ this.main = (function() {
|
|||
|
||||
// This is called by startBackground.js, directly in response to clicks on the Photon page action
|
||||
exports.onClicked = catcher.watchFunction((tab) => {
|
||||
if (shouldOpenMyShots(tab.url)) {
|
||||
if (!hasSeenOnboarding) {
|
||||
catcher.watchPromise(analytics.refreshTelemetryPref().then(() => {
|
||||
sendEvent("goto-onboarding", "selection-button", {incognito: tab.incognito});
|
||||
return forceOnboarding();
|
||||
}));
|
||||
return;
|
||||
}
|
||||
catcher.watchPromise(analytics.refreshTelemetryPref().then(() => {
|
||||
sendEvent("goto-myshots", "about-newtab", {incognito: tab.incognito});
|
||||
}));
|
||||
catcher.watchPromise(
|
||||
auth.authHeaders()
|
||||
.then(() => browser.tabs.update({url: backend + "/shots"})));
|
||||
} else {
|
||||
catcher.watchPromise(
|
||||
toggleSelector(tab)
|
||||
.then(active => {
|
||||
const event = active ? "start-shot" : "cancel-shot";
|
||||
sendEvent(event, "toolbar-button", {incognito: tab.incognito});
|
||||
}, (error) => {
|
||||
if ((!hasSeenOnboarding) && error.popupMessage === "UNSHOOTABLE_PAGE") {
|
||||
sendEvent("goto-onboarding", "selection-button", {incognito: tab.incognito});
|
||||
return forceOnboarding();
|
||||
}
|
||||
throw error;
|
||||
catcher.watchPromise(hasSeenOnboarding.then(onboarded => {
|
||||
if (shouldOpenMyShots(tab.url)) {
|
||||
if (!onboarded) {
|
||||
catcher.watchPromise(analytics.refreshTelemetryPref().then(() => {
|
||||
sendEvent("goto-onboarding", "selection-button", {incognito: tab.incognito});
|
||||
return forceOnboarding();
|
||||
}));
|
||||
}
|
||||
return;
|
||||
}
|
||||
catcher.watchPromise(analytics.refreshTelemetryPref().then(() => {
|
||||
sendEvent("goto-myshots", "about-newtab", {incognito: tab.incognito});
|
||||
}));
|
||||
catcher.watchPromise(
|
||||
auth.authHeaders()
|
||||
.then(() => browser.tabs.update({url: backend + "/shots"})));
|
||||
} else {
|
||||
catcher.watchPromise(
|
||||
toggleSelector(tab)
|
||||
.then(active => {
|
||||
const event = active ? "start-shot" : "cancel-shot";
|
||||
sendEvent(event, "toolbar-button", {incognito: tab.incognito});
|
||||
}, (error) => {
|
||||
if ((!onboarded) && error.popupMessage === "UNSHOOTABLE_PAGE") {
|
||||
sendEvent("goto-onboarding", "selection-button", {incognito: tab.incognito});
|
||||
return forceOnboarding();
|
||||
}
|
||||
throw error;
|
||||
}));
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
function forceOnboarding() {
|
||||
|
@ -273,8 +275,8 @@ this.main = (function() {
|
|||
});
|
||||
|
||||
communication.register("hasSeenOnboarding", () => {
|
||||
hasSeenOnboarding = true;
|
||||
catcher.watchPromise(browser.storage.local.set({hasSeenOnboarding}));
|
||||
hasSeenOnboarding = Promise.resolve(true);
|
||||
catcher.watchPromise(browser.storage.local.set({hasSeenOnboarding: true}));
|
||||
setIconActive(false, null);
|
||||
startBackground.photonPageActionPort.postMessage({
|
||||
type: "setProperties",
|
||||
|
|
|
@ -66,24 +66,26 @@ this.selectorLoader = (function() {
|
|||
const loadingTabs = new Set();
|
||||
|
||||
exports.loadModules = function(tabId, hasSeenOnboarding) {
|
||||
loadingTabs.add(tabId);
|
||||
let promise = downloadOnlyCheck(tabId);
|
||||
if (hasSeenOnboarding) {
|
||||
promise = promise.then(() => {
|
||||
return executeModules(tabId, standardScripts.concat(selectorScripts));
|
||||
catcher.watchPromise(hasSeenOnboarding.then(onboarded => {
|
||||
loadingTabs.add(tabId);
|
||||
let promise = downloadOnlyCheck(tabId);
|
||||
if (onboarded) {
|
||||
promise = promise.then(() => {
|
||||
return executeModules(tabId, standardScripts.concat(selectorScripts));
|
||||
});
|
||||
} else {
|
||||
promise = promise.then(() => {
|
||||
return executeModules(tabId, standardScripts.concat(onboardingScripts).concat(selectorScripts));
|
||||
});
|
||||
}
|
||||
return promise.then((result) => {
|
||||
loadingTabs.delete(tabId);
|
||||
return result;
|
||||
}, (error) => {
|
||||
loadingTabs.delete(tabId);
|
||||
throw error;
|
||||
});
|
||||
} else {
|
||||
promise = promise.then(() => {
|
||||
return executeModules(tabId, standardScripts.concat(onboardingScripts).concat(selectorScripts));
|
||||
});
|
||||
}
|
||||
return promise.then((result) => {
|
||||
loadingTabs.delete(tabId);
|
||||
return result;
|
||||
}, (error) => {
|
||||
loadingTabs.delete(tabId);
|
||||
throw error;
|
||||
});
|
||||
}));
|
||||
};
|
||||
|
||||
// TODO: since bootstrap communication is now required, would this function
|
||||
|
|
|
@ -191,13 +191,14 @@ this.takeshot = (function() {
|
|||
files.push({fieldName: "thumbnail", filename: "thumbnail.png", blob: thumbnail});
|
||||
}
|
||||
return createMultipart(
|
||||
{shot: JSON.stringify(shot.asJson())},
|
||||
{shot: JSON.stringify(shot)},
|
||||
|
||||
files
|
||||
);
|
||||
}
|
||||
return {
|
||||
"content-type": "application/json",
|
||||
body: JSON.stringify(shot.asJson())
|
||||
body: JSON.stringify(shot)
|
||||
};
|
||||
|
||||
}).then((submission) => {
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
this.shot = (function () {let exports={}; // Note: in this library we can't use any "system" dependencies because this can be used from multiple
|
||||
// environments
|
||||
|
||||
const isNode = typeof process !== "undefined" && Object.prototype.toString.call(process) === "[object process]";
|
||||
const URL = (isNode && require("url").URL) || window.URL;
|
||||
|
||||
/** Throws an error if the condition isn't true. Any extra arguments after the condition
|
||||
are used as console.error() arguments. */
|
||||
function assert(condition, ...args) {
|
||||
|
@ -13,23 +16,17 @@ function assert(condition, ...args) {
|
|||
|
||||
/** True if `url` is a valid URL */
|
||||
function isUrl(url) {
|
||||
// FIXME: this is rather naive, obviously
|
||||
if ((/^about:.{1,8000}$/i).test(url)) {
|
||||
try {
|
||||
const parsed = new URL(url);
|
||||
|
||||
if (parsed.protocol === "view-source:") {
|
||||
return isUrl(url.substr("view-source:".length));
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
if ((/^file:\/.{0,8000}$/i).test(url)) {
|
||||
return true;
|
||||
}
|
||||
if ((/^data:.*$/i).test(url)) {
|
||||
return true;
|
||||
}
|
||||
if ((/^chrome:.{0,8000}/i).test(url)) {
|
||||
return true;
|
||||
}
|
||||
if ((/^view-source:/i).test(url)) {
|
||||
return isUrl(url.substr("view-source:".length));
|
||||
}
|
||||
return (/^https?:\/\/[a-z0-9._-]{1,8000}[a-z0-9](:[0-9]{1,8000})?\/?/i).test(url);
|
||||
}
|
||||
|
||||
function isValidClipImageUrl(url) {
|
||||
|
@ -48,7 +45,7 @@ function assertUrl(url) {
|
|||
}
|
||||
|
||||
function isSecureWebUri(url) {
|
||||
return (/^https?:\/\/[a-z0-9._-]{1,8000}[a-z0-9](:[0-9]{1,8000})?\/?/i).test(url);
|
||||
return isUrl(url) && url.toLowerCase().startsWith("https");
|
||||
}
|
||||
|
||||
function assertOrigin(url) {
|
||||
|
@ -115,39 +112,6 @@ function jsonify(obj, required, optional) {
|
|||
return result;
|
||||
}
|
||||
|
||||
/** Resolve url relative to base */
|
||||
function resolveUrl(base, url) {
|
||||
// FIXME: totally ad hoc and probably incorrect, but we can't
|
||||
// use any libraries in this file
|
||||
if (url.search(/^https?:/) !== -1) {
|
||||
// Absolute url
|
||||
return url;
|
||||
}
|
||||
if (url.indexOf("//") === 0) {
|
||||
// Protocol-relative URL
|
||||
return (/^https?:/i).exec(base)[0] + url;
|
||||
}
|
||||
if (url.indexOf("/") === 0) {
|
||||
// Domain-relative URL
|
||||
return (/^https?:\/\/[a-z0-9._-]{1,4000}/i).exec(base)[0] + url;
|
||||
}
|
||||
// Otherwise, a full relative URL
|
||||
while (url.indexOf("./") === 0) {
|
||||
url = url.substr(2);
|
||||
}
|
||||
if (!base) {
|
||||
// It's not an absolute URL, and we don't have a base URL, so we have
|
||||
// to throw away the URL
|
||||
return null;
|
||||
}
|
||||
let match = (/.*\//).exec(base)[0];
|
||||
if (match.search(/^https?:\/$/i) === 0) {
|
||||
// Domain without path
|
||||
match = match + "/";
|
||||
}
|
||||
return match + url;
|
||||
}
|
||||
|
||||
/** True if the two objects look alike. Null, undefined, and absent properties
|
||||
are all treated as equivalent. Traverses objects and arrays */
|
||||
function deepEqual(a, b) {
|
||||
|
@ -275,8 +239,8 @@ class AbstractShot {
|
|||
}
|
||||
if (typeof json[attr] === "object" && typeof this[attr] === "object" && this[attr] !== null) {
|
||||
let val = this[attr];
|
||||
if (val.asJson) {
|
||||
val = val.asJson();
|
||||
if (val.toJSON) {
|
||||
val = val.toJSON();
|
||||
}
|
||||
if (!deepEqual(json[attr], val)) {
|
||||
this[attr] = json[attr];
|
||||
|
@ -292,7 +256,7 @@ class AbstractShot {
|
|||
this.delClip(clipId);
|
||||
} else if (!this.getClip(clipId)) {
|
||||
this.setClip(clipId, json.clips[clipId]);
|
||||
} else if (!deepEqual(this.getClip(clipId).asJson(), json.clips[clipId])) {
|
||||
} else if (!deepEqual(this.getClip(clipId).toJSON(), json.clips[clipId])) {
|
||||
this.setClip(clipId, json.clips[clipId]);
|
||||
}
|
||||
}
|
||||
|
@ -301,18 +265,18 @@ class AbstractShot {
|
|||
}
|
||||
|
||||
/** Returns a JSON version of this shot */
|
||||
asJson() {
|
||||
toJSON() {
|
||||
const result = {};
|
||||
for (const attr of this.REGULAR_ATTRS) {
|
||||
let val = this[attr];
|
||||
if (val && val.asJson) {
|
||||
val = val.asJson();
|
||||
if (val && val.toJSON) {
|
||||
val = val.toJSON();
|
||||
}
|
||||
result[attr] = val;
|
||||
}
|
||||
result.clips = {};
|
||||
for (const attr in this._clips) {
|
||||
result.clips[attr] = this._clips[attr].asJson();
|
||||
result.clips[attr] = this._clips[attr].toJSON();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -322,13 +286,13 @@ class AbstractShot {
|
|||
const result = {clips: {}};
|
||||
for (const attr of this.RECALL_ATTRS) {
|
||||
let val = this[attr];
|
||||
if (val && val.asJson) {
|
||||
val = val.asJson();
|
||||
if (val && val.toJSON) {
|
||||
val = val.toJSON();
|
||||
}
|
||||
result[attr] = val;
|
||||
}
|
||||
for (const name of this.clipNames()) {
|
||||
result.clips[name] = this.getClip(name).asJson();
|
||||
result.clips[name] = this.getClip(name).toJSON();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -374,7 +338,8 @@ class AbstractShot {
|
|||
// eslint-disable-next-line no-control-regex
|
||||
filenameTitle = filenameTitle.replace(/[:\\<>/!@&?"*.|\x00-\x1F]/g, " ");
|
||||
filenameTitle = filenameTitle.replace(/\s{1,4000}/g, " ");
|
||||
let clipFilename = `Screenshot-${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()} ${filenameTitle}`;
|
||||
const filenameDate = new Date(date.getTime() - date.getTimezoneOffset() * 60 * 1000).toISOString().substring(0, 10);
|
||||
let clipFilename = `Screenshot_${filenameDate} ${filenameTitle}`;
|
||||
const clipFilenameBytesSize = clipFilename.length * 2; // JS STrings are UTF-16
|
||||
if (clipFilenameBytesSize > 251) { // 255 bytes (Usual filesystems max) - 4 for the ".png" file extension string
|
||||
const excedingchars = (clipFilenameBytesSize - 246) / 2; // 251 - 5 for ellipsis "[...]"
|
||||
|
@ -497,14 +462,8 @@ class AbstractShot {
|
|||
return this._favicon;
|
||||
}
|
||||
set favicon(val) {
|
||||
// We allow but ignore bad favicon URLs, as they seem somewhat common
|
||||
// We set the favicon with tabs.Tab.faviConUrl, which is a full URL.
|
||||
val = val || null;
|
||||
if (!isUrl(val)) {
|
||||
val = null;
|
||||
}
|
||||
if (val) {
|
||||
val = resolveUrl(this.url, val);
|
||||
}
|
||||
this._favicon = val;
|
||||
}
|
||||
|
||||
|
@ -658,7 +617,7 @@ class _Image {
|
|||
this.alt = json.alt;
|
||||
}
|
||||
|
||||
asJson() {
|
||||
toJSON() {
|
||||
return jsonify(this, ["url"], ["dimensions"]);
|
||||
}
|
||||
}
|
||||
|
@ -689,7 +648,7 @@ class _Clip {
|
|||
return `[Shot Clip id=${this.id} sortOrder=${this.sortOrder} image ${this.image.dimensions.x}x${this.image.dimensions.y}]`;
|
||||
}
|
||||
|
||||
asJson() {
|
||||
toJSON() {
|
||||
return jsonify(this, ["createdDate"], ["sortOrder", "image"]);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ this.clipboard = (function() {
|
|||
element.style.opacity = "0";
|
||||
element.style.width = "1px";
|
||||
element.style.height = "1px";
|
||||
element.style.display = "block";
|
||||
element.addEventListener("load", catcher.watchFunction(() => {
|
||||
try {
|
||||
const doc = element.contentDocument;
|
||||
|
|
|
@ -1 +1 @@
|
|||
<svg width="32" height="32" xmlns="http://www.w3.org/2000/svg" fill="context-fill" fill-opacity="context-fill-opacity"><path d="M8 2a4 4 0 0 0-4 4h4V2zm12 0h-4v4h4V2zm8 0v4h4a4 4 0 0 0-4-4zM14 2h-4v4h4V2zm12 0h-4v4h4V2zm2 10h4V8h-4v4zm0 12a4 4 0 0 0 4-4h-4v4zm0-6h4v-4h-4v4zm-.882-4.334a4 4 0 0 0-5.57-.984l-7.67 5.662-3.936-2.76c.031-.193.05-.388.058-.584a4.976 4.976 0 0 0-2-3.978V8H4v2.1a5 5 0 1 0 3.916 8.948l2.484 1.738-2.8 1.964a4.988 4.988 0 1 0 2.3 3.266l17.218-12.35zM5 17.5a2.5 2.5 0 1 1 0-5 2.5 2.5 0 0 1 0 5zm0 12a2.5 2.5 0 1 1 0-5 2.5 2.5 0 0 1 0 5zm10.8-4.858l6.034 4.6a4 4 0 0 0 5.57-.984L19.28 22.2l-3.48 2.442z"/></svg>
|
||||
<svg viewBox="0 0 32 32" width="32" height="32" xmlns="http://www.w3.org/2000/svg" fill="context-fill" fill-opacity="context-fill-opacity"><path d="M8 2a4 4 0 0 0-4 4h4V2zm12 0h-4v4h4V2zm8 0v4h4a4 4 0 0 0-4-4zM14 2h-4v4h4V2zm12 0h-4v4h4V2zm2 10h4V8h-4v4zm0 12a4 4 0 0 0 4-4h-4v4zm0-6h4v-4h-4v4zm-.882-4.334a4 4 0 0 0-5.57-.984l-7.67 5.662-3.936-2.76c.031-.193.05-.388.058-.584a4.976 4.976 0 0 0-2-3.978V8H4v2.1a5 5 0 1 0 3.916 8.948l2.484 1.738-2.8 1.964a4.988 4.988 0 1 0 2.3 3.266l17.218-12.35zM5 17.5a2.5 2.5 0 1 1 0-5 2.5 2.5 0 0 1 0 5zm0 12a2.5 2.5 0 1 1 0-5 2.5 2.5 0 0 1 0 5zm10.8-4.858l6.034 4.6a4 4 0 0 0 5.57-.984L19.28 22.2l-3.48 2.442z"/></svg>
|
||||
|
|
До Ширина: | Высота: | Размер: 636 B После Ширина: | Высота: | Размер: 657 B |
До Ширина: | Высота: | Размер: 27 KiB После Ширина: | Высота: | Размер: 27 KiB |
До Ширина: | Высота: | Размер: 67 KiB После Ширина: | Высота: | Размер: 40 KiB |
До Ширина: | Высота: | Размер: 57 KiB После Ширина: | Высота: | Размер: 34 KiB |
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Firefox Screenshots",
|
||||
"version": "30.1.0",
|
||||
"version": "32.1.0",
|
||||
"description": "__MSG_addonDescription__",
|
||||
"author": "__MSG_addonAuthorsList__",
|
||||
"homepage_url": "https://github.com/mozilla-services/screenshots",
|
||||
|
@ -30,6 +30,9 @@
|
|||
]
|
||||
}
|
||||
],
|
||||
"icons": {
|
||||
"32": "icons/icon-v2.svg"
|
||||
},
|
||||
"web_accessible_resources": [
|
||||
"blank.html",
|
||||
"icons/cancel.svg",
|
||||
|
|
|
@ -24,6 +24,7 @@ this.slides = (function() {
|
|||
iframe.src = browser.extension.getURL("blank.html");
|
||||
iframe.id = "firefox-screenshots-onboarding-iframe";
|
||||
iframe.style.zIndex = "99999999999";
|
||||
iframe.style.display = "block";
|
||||
iframe.style.border = "none";
|
||||
iframe.style.position = "fixed";
|
||||
iframe.style.top = "0";
|
||||
|
|
|
@ -115,7 +115,7 @@ this.shooter = (function() { // eslint-disable-line no-unused-vars
|
|||
}
|
||||
isSaving = null;
|
||||
}, 1000);
|
||||
selectedPos = selectedPos.asJson();
|
||||
selectedPos = selectedPos.toJSON();
|
||||
let captureText = "";
|
||||
if (buildSettings.captureText) {
|
||||
captureText = util.captureEnclosedText(selectedPos);
|
||||
|
@ -152,7 +152,7 @@ this.shooter = (function() { // eslint-disable-line no-unused-vars
|
|||
},
|
||||
selectedPos,
|
||||
shotId: shotObject.id,
|
||||
shot: shotObject.asJson(),
|
||||
shot: shotObject.toJSON(),
|
||||
imageBlob
|
||||
}).then((url) => {
|
||||
return clipboard.copy(url).then((copied) => {
|
||||
|
@ -185,7 +185,7 @@ this.shooter = (function() { // eslint-disable-line no-unused-vars
|
|||
if (!dataUrl) {
|
||||
promise = callBackground(
|
||||
"screenshotPage",
|
||||
selectedPos.asJson(),
|
||||
selectedPos.toJSON(),
|
||||
{
|
||||
scrollX: window.scrollX,
|
||||
scrollY: window.scrollY,
|
||||
|
|
|
@ -173,7 +173,7 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
|
|||
|
||||
unhide() {
|
||||
this.updateElementSize();
|
||||
this.element.style.display = "";
|
||||
this.element.style.display = "block";
|
||||
catcher.watchPromise(callBackground("sendEvent", "internal", "unhide-selection-frame"));
|
||||
if (highContrastCheck(this.element.contentWindow)) {
|
||||
this.element.contentDocument.body.classList.add("hcm");
|
||||
|
@ -222,7 +222,7 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
|
|||
}
|
||||
}
|
||||
if (force && visible) {
|
||||
this.element.style.display = "";
|
||||
this.element.style.display = "block";
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -344,7 +344,7 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
|
|||
unhide() {
|
||||
window.addEventListener("scroll", watchFunction(assertIsTrusted(this.onScroll)));
|
||||
window.addEventListener("resize", this.onResize, true);
|
||||
this.element.style.display = "";
|
||||
this.element.style.display = "block";
|
||||
catcher.watchPromise(callBackground("sendEvent", "internal", "unhide-preselection-frame"));
|
||||
if (highContrastCheck(this.element.contentWindow)) {
|
||||
this.element.contentDocument.body.classList.add("hcm");
|
||||
|
@ -458,7 +458,7 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
|
|||
},
|
||||
|
||||
unhide() {
|
||||
this.element.style.display = "";
|
||||
this.element.style.display = "block";
|
||||
catcher.watchPromise(callBackground("sendEvent", "internal", "unhide-preview-frame"));
|
||||
this.element.focus();
|
||||
},
|
||||
|
@ -635,7 +635,7 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
|
|||
this.bgRight.style.top = `${pos.top}px`;
|
||||
this.bgRight.style.height = `${pos.bottom - pos.top}px`;
|
||||
this.bgRight.style.left = `${pos.right}px`;
|
||||
this.bgRight.style.width = "100%";
|
||||
this.bgRight.style.width = `${document.body.scrollWidth - pos.right}px`;
|
||||
// the download notice is injected into an iframe that matches the document size
|
||||
// in order to reposition it on scroll we need to bind an updated positioning
|
||||
// function to some window events.
|
||||
|
|
|
@ -351,7 +351,7 @@ this.uicontrol = (function() {
|
|||
return new Selection(this.x1, this.y1, this.x2, this.y2);
|
||||
}
|
||||
|
||||
asJson() {
|
||||
toJSON() {
|
||||
return {
|
||||
left: this.left,
|
||||
right: this.right,
|
||||
|
|
|
@ -26,6 +26,7 @@ class ToolboxController extends Component {
|
|||
highlightedTools: new Set(),
|
||||
panelDefinitions: [],
|
||||
hostTypes: [],
|
||||
currentHostType: undefined,
|
||||
areDockOptionsEnabled: true,
|
||||
canCloseToolbox: true,
|
||||
isSplitConsoleActive: false,
|
||||
|
@ -43,6 +44,7 @@ class ToolboxController extends Component {
|
|||
this.highlightTool = this.highlightTool.bind(this);
|
||||
this.unhighlightTool = this.unhighlightTool.bind(this);
|
||||
this.setHostTypes = this.setHostTypes.bind(this);
|
||||
this.setCurrentHostType = this.setCurrentHostType.bind(this);
|
||||
this.setDockOptionsEnabled = this.setDockOptionsEnabled.bind(this);
|
||||
this.setCanCloseToolbox = this.setCanCloseToolbox.bind(this);
|
||||
this.setIsSplitConsoleActive = this.setIsSplitConsoleActive.bind(this);
|
||||
|
@ -137,6 +139,10 @@ class ToolboxController extends Component {
|
|||
this.setState({ hostTypes });
|
||||
}
|
||||
|
||||
setCurrentHostType(currentHostType) {
|
||||
this.setState({ currentHostType });
|
||||
}
|
||||
|
||||
setCanCloseToolbox(canCloseToolbox) {
|
||||
this.setState({ canCloseToolbox }, this.updateButtonIds);
|
||||
}
|
||||
|
|
|
@ -39,6 +39,9 @@ class ToolboxToolbar extends Component {
|
|||
position: PropTypes.string.isRequired,
|
||||
switchHost: PropTypes.func.isRequired,
|
||||
})),
|
||||
// Current docking type. Typically one of the position values in
|
||||
// |hostTypes| but this is not always the case (e.g. when it is "custom").
|
||||
currentHostType: PropTypes.string,
|
||||
// Should the docking options be enabled? They are disabled in some
|
||||
// contexts such as WebIDE.
|
||||
areDockButtonsEnabled: PropTypes.bool,
|
||||
|
@ -212,6 +215,8 @@ function renderSeparator() {
|
|||
* Position name.
|
||||
* @param {Function} hostTypes[].switchHost
|
||||
* Function to switch the host.
|
||||
* @param {string} currentHostType
|
||||
* The current docking configuration.
|
||||
* @param {boolean} areDockOptionsEnabled
|
||||
* They are not enabled in certain situations like when they are in the
|
||||
* WebIDE.
|
||||
|
@ -298,12 +303,14 @@ function renderToolboxControls(props) {
|
|||
* The id of the currently selected tool.
|
||||
* @param {Object[]} props.hostTypes
|
||||
* Array of host type objects.
|
||||
* This array will be empty if we shouldn't shouldn't show any dock
|
||||
* options.
|
||||
* @param {string} props.hostTypes[].position
|
||||
* Position name.
|
||||
* @param {Function} props.hostTypes[].switchHost
|
||||
* Function to switch the host.
|
||||
* This array will be empty if we shouldn't shouldn't show any dock
|
||||
* options.
|
||||
* @param {string} props.currentHostType
|
||||
* The current docking configuration.
|
||||
* @param {boolean} isSplitConsoleActive
|
||||
* Is the split console currently visible?
|
||||
* @param {boolean|undefined} disableAutohide
|
||||
|
@ -327,6 +334,7 @@ function showMeatballMenu(
|
|||
{
|
||||
currentToolId,
|
||||
hostTypes,
|
||||
currentHostType,
|
||||
isSplitConsoleActive,
|
||||
disableAutohide,
|
||||
selectTool,
|
||||
|
@ -340,13 +348,23 @@ function showMeatballMenu(
|
|||
|
||||
// Dock options
|
||||
for (const hostType of hostTypes) {
|
||||
menu.append(new MenuItem({
|
||||
id: `toolbox-meatball-menu-dock-${hostType.position}`,
|
||||
label: L10N.getStr(
|
||||
`toolbox.meatballMenu.dock.${hostType.position}.label`
|
||||
),
|
||||
click: () => hostType.switchHost(),
|
||||
}));
|
||||
const l10nkey =
|
||||
hostType.position === "window"
|
||||
? "separateWindow"
|
||||
: hostType.position;
|
||||
menu.append(
|
||||
new MenuItem({
|
||||
id: `toolbox-meatball-menu-dock-${hostType.position}`,
|
||||
label: L10N.getStr(`toolbox.meatballMenu.dock.${l10nkey}.label`),
|
||||
click: () => hostType.switchHost(),
|
||||
type: "checkbox",
|
||||
checked: hostType.position === currentHostType,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (menu.items.length) {
|
||||
menu.append(new MenuItem({ type: "separator" }));
|
||||
}
|
||||
|
||||
// Split console
|
||||
|
@ -377,10 +395,6 @@ function showMeatballMenu(
|
|||
}));
|
||||
}
|
||||
|
||||
if (menu.items.length) {
|
||||
menu.append(new MenuItem({ type: "separator" }));
|
||||
}
|
||||
|
||||
// Settings
|
||||
menu.append(new MenuItem({
|
||||
id: "toolbox-meatball-menu-settings",
|
||||
|
|
|
@ -1094,8 +1094,7 @@ Toolbox.prototype = {
|
|||
let hostTypes = [];
|
||||
for (let type in Toolbox.HostType) {
|
||||
let position = Toolbox.HostType[type];
|
||||
if (position == this.hostType ||
|
||||
position == Toolbox.HostType.CUSTOM ||
|
||||
if (position == Toolbox.HostType.CUSTOM ||
|
||||
(!sideEnabled && position == Toolbox.HostType.SIDE)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -1106,6 +1105,7 @@ Toolbox.prototype = {
|
|||
});
|
||||
}
|
||||
|
||||
this.component.setCurrentHostType(this.hostType);
|
||||
this.component.setHostTypes(hostTypes);
|
||||
},
|
||||
|
||||
|
@ -2445,6 +2445,8 @@ Toolbox.prototype = {
|
|||
|
||||
this.emit("host-changed");
|
||||
this._telemetry.log(HOST_HISTOGRAM, this._getTelemetryHostId());
|
||||
|
||||
this.component.setCurrentHostType(hostType);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -151,7 +151,7 @@ toolbox.meatballMenu.button.tooltip=Customize Developer Tools and get help
|
|||
# docking (or undocking) the developer tools toolbox.
|
||||
toolbox.meatballMenu.dock.bottom.label=Dock to bottom
|
||||
toolbox.meatballMenu.dock.side.label=Dock to side
|
||||
toolbox.meatballMenu.dock.window.label=Undock
|
||||
toolbox.meatballMenu.dock.separateWindow.label=Separate window
|
||||
|
||||
# LOCALIZATION NOTE (toolbox.meatballMenu.{splitconsole,hideconsole}.label):
|
||||
# These are the labels in the "..." menu in the toolbox for toggling the split
|
||||
|
|
|
@ -767,7 +767,6 @@ VariablesView.prototype = {
|
|||
let currFocusedItem = null;
|
||||
|
||||
do {
|
||||
commandDispatcher.suppressFocusScroll = true;
|
||||
commandDispatcher[aDirection]();
|
||||
|
||||
// Make sure the newly focused item is a part of this view.
|
||||
|
|
|
@ -1133,7 +1133,6 @@ const WidgetMethods = exports.WidgetMethods = {
|
|||
let currFocusedElement;
|
||||
|
||||
do {
|
||||
commandDispatcher.suppressFocusScroll = true;
|
||||
commandDispatcher[direction]();
|
||||
currFocusedElement = commandDispatcher.focusedElement;
|
||||
|
||||
|
|
|
@ -160,6 +160,10 @@
|
|||
background-position: center;
|
||||
}
|
||||
|
||||
.tools-chevron-menu:-moz-locale-dir(rtl) {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
#toolbox-controls {
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,14 @@ add_task(async function() {
|
|||
checkHostType(Toolbox.HostType.SIDE);
|
||||
checkToolboxUI();
|
||||
await toolbox.switchHost(Toolbox.HostType.WINDOW);
|
||||
|
||||
// checkHostType, below, will open the meatball menu to read the "Split
|
||||
// console" menu item label. However, if we've just opened a new window then
|
||||
// on some platforms when we switch focus to the new window we might end up
|
||||
// triggering the auto-close behavior on the menu popup. To avoid that, wait
|
||||
// a moment before querying the menu.
|
||||
await new Promise(resolve => requestIdleCallback(resolve));
|
||||
|
||||
checkHostType(Toolbox.HostType.WINDOW);
|
||||
checkToolboxUI();
|
||||
await toolbox.switchHost(Toolbox.HostType.BOTTOM);
|
||||
|
|
|
@ -284,11 +284,15 @@ GetComputedTimingDictionary(const ComputedTiming& aComputedTiming,
|
|||
aRetVal.mDelay = aTiming.Delay().ToMilliseconds();
|
||||
aRetVal.mEndDelay = aTiming.EndDelay().ToMilliseconds();
|
||||
aRetVal.mFill = aComputedTiming.mFill;
|
||||
aRetVal.mIterations = aComputedTiming.mIterations;
|
||||
aRetVal.mIterationStart = aComputedTiming.mIterationStart;
|
||||
aRetVal.mIterations = aComputedTiming.mIterations;
|
||||
aRetVal.mDuration.SetAsUnrestrictedDouble() =
|
||||
aComputedTiming.mDuration.ToMilliseconds();
|
||||
aRetVal.mDirection = aTiming.Direction();
|
||||
if (aTiming.TimingFunction()) {
|
||||
aRetVal.mEasing.Truncate();
|
||||
aTiming.TimingFunction()->AppendToString(aRetVal.mEasing);
|
||||
}
|
||||
|
||||
// ComputedTimingProperties
|
||||
aRetVal.mActiveDuration = aComputedTiming.mActiveDuration.ToMilliseconds();
|
||||
|
|
|
@ -24,11 +24,6 @@ div {
|
|||
<script>
|
||||
'use strict';
|
||||
|
||||
// Stylo matches the spec more closely wrt serialization of specified calc().
|
||||
//
|
||||
// See https://github.com/w3c/csswg-drafts/issues/1731
|
||||
const isStylo = SpecialPowers.DOMWindowUtils.isStyledByServo;
|
||||
|
||||
var gTests = [
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
@ -571,7 +566,7 @@ var gTests = [
|
|||
frames: { left: ['calc(10em + 10px)', 'calc(10em + 10%)'] },
|
||||
expected: [ { property: 'left',
|
||||
values: [ valueFormat(0, 'calc(110px)', 'replace', 'linear'),
|
||||
valueFormat(1, isStylo ? 'calc(10% + 100px)' : 'calc(100px + 10%)', 'replace') ] } ]
|
||||
valueFormat(1, 'calc(10% + 100px)', 'replace') ] } ]
|
||||
},
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
@ -590,7 +585,7 @@ var gTests = [
|
|||
frames: { left: ['10px', 'calc(var(--var-100px) / 2 - 10%)'] },
|
||||
expected: [ { property: 'left',
|
||||
values: [ valueFormat(0, '10px', 'replace', 'linear'),
|
||||
valueFormat(1, isStylo ? 'calc(-10% + 50px)' : 'calc(50px + -10%)', 'replace') ] } ]
|
||||
valueFormat(1, 'calc(-10% + 50px)', 'replace') ] } ]
|
||||
},
|
||||
{ desc: 'CSS variables in shorthands are resolved to their corresponding'
|
||||
+ ' values',
|
||||
|
|
|
@ -56,7 +56,7 @@ support-files =
|
|||
[mozilla/test_cascade.html]
|
||||
[mozilla/test_cubic_bezier_limits.html]
|
||||
[mozilla/test_deferred_start.html]
|
||||
skip-if = (toolkit == 'android' && debug) || (os == 'win' && bits == 64) || webrender # Bug 1363957; bug 1424752 for webrender
|
||||
skip-if = (toolkit == 'android' && debug) || (os == 'win' && bits == 64) # Bug 1363957
|
||||
[mozilla/test_disable_animations_api_core.html]
|
||||
[mozilla/test_disabled_properties.html]
|
||||
[mozilla/test_discrete_animations.html]
|
||||
|
@ -67,21 +67,18 @@ skip-if = (toolkit == 'android' && debug) || (os == 'win' && bits == 64) || webr
|
|||
[mozilla/test_hide_and_show.html]
|
||||
[mozilla/test_moz_prefixed_properties.html]
|
||||
[mozilla/test_restyles.html]
|
||||
skip-if = webrender # bug 1424752
|
||||
[mozilla/test_restyling_xhr_doc.html]
|
||||
[mozilla/test_set_easing.html]
|
||||
[mozilla/test_transform_limits.html]
|
||||
[mozilla/test_transition_finish_on_compositor.html]
|
||||
skip-if = toolkit == 'android' || webrender # bug 1424752 for webrender
|
||||
skip-if = toolkit == 'android'
|
||||
[mozilla/test_underlying_discrete_value.html]
|
||||
[mozilla/test_event_listener_leaks.html]
|
||||
[style/test_animation-seeking-with-current-time.html]
|
||||
[style/test_animation-seeking-with-start-time.html]
|
||||
[style/test_animation-setting-effect.html]
|
||||
[style/test_composite.html]
|
||||
skip-if = webrender # bug 1424752
|
||||
[style/test_interpolation-from-interpolatematrix-to-none.html]
|
||||
[style/test_missing-keyframe.html]
|
||||
[style/test_missing-keyframe-on-compositor.html]
|
||||
skip-if = webrender # bug 1424752
|
||||
[style/test_transform-non-normalizable-rotate3d.html]
|
||||
|
|
|
@ -164,8 +164,9 @@ function tweakExpectedRestyleCount(aAnimation, aExpectedRestyleCount) {
|
|||
var omtaEnabled = isOMTAEnabled();
|
||||
|
||||
var isAndroid = !!navigator.userAgent.includes("Android");
|
||||
var isServo = isStyledByServo();
|
||||
var hasConformantPromiseHandling;
|
||||
const isWebRender =
|
||||
SpecialPowers.DOMWindowUtils.layerManagerType == 'WebRender';
|
||||
|
||||
function add_task_if_omta_enabled(test) {
|
||||
if (!omtaEnabled) {
|
||||
|
@ -713,7 +714,15 @@ waitForAllPaints(() => {
|
|||
var animation = div.getAnimations()[0];
|
||||
|
||||
await animation.ready;
|
||||
ok(!SpecialPowers.wrap(animation).isRunningOnCompositor);
|
||||
if (!isWebRender) {
|
||||
ok(!SpecialPowers.wrap(animation).isRunningOnCompositor);
|
||||
} else {
|
||||
// FIXME: Bug 1456389: The animation should be throttled on the
|
||||
// main-thread (i.e. not to be sent to the compositor)
|
||||
todo(!SpecialPowers.wrap(animation).isRunningOnCompositor,
|
||||
'Animation in visibility:hidden element should NOT be running ' +
|
||||
'on the compositor');
|
||||
}
|
||||
|
||||
var markers = await observeStyling(5);
|
||||
|
||||
|
@ -1270,24 +1279,12 @@ waitForAllPaints(() => {
|
|||
// Apply another animation style
|
||||
div.style.animation = 'background-color 110s';
|
||||
var markers = await observeStyling(1);
|
||||
if (isServo) {
|
||||
// There should be two restyles.
|
||||
// 1) Animation-only restyle for before applying the new animation style
|
||||
// 2) Animation-only restyle for after applying the new animation style
|
||||
is(markers.length, 2,
|
||||
'Applying animation style with different duration ' +
|
||||
'should restyle twice');
|
||||
} else {
|
||||
// There should be three restyles.
|
||||
// 1) Animation-only restyle for before applying the new animation style
|
||||
// 2) Restyle for applying the new animation style
|
||||
// Note: In gecko styling for animations is not separated.
|
||||
// 3) Restyle triggered by updating an existing animation (specifically
|
||||
// the animation-duration)
|
||||
is(markers.length, 3,
|
||||
'Applying animation style with different duration ' +
|
||||
'should restyles three times');
|
||||
}
|
||||
// There should be two restyles.
|
||||
// 1) Animation-only restyle for before applying the new animation style
|
||||
// 2) Animation-only restyle for after applying the new animation style
|
||||
is(markers.length, 2,
|
||||
'Applying animation style with different duration ' +
|
||||
'should restyle twice');
|
||||
await ensureElementRemoval(div);
|
||||
});
|
||||
|
||||
|
@ -1728,15 +1725,9 @@ waitForAllPaints(() => {
|
|||
|
||||
div.style.setProperty('color', 'blue', '');
|
||||
var markers = await observeStyling(5);
|
||||
if (isServo) {
|
||||
is(markers.length, 0,
|
||||
'The opacity animation keeps running on the compositor when ' +
|
||||
'color style is changed');
|
||||
} else {
|
||||
todo_is(markers.length, 0,
|
||||
'Bug 1307341 The opacity animation keeps running on the ' +
|
||||
'compositor when color style is changed');
|
||||
}
|
||||
is(markers.length, 0,
|
||||
'The opacity animation keeps running on the compositor when ' +
|
||||
'color style is changed');
|
||||
await ensureElementRemoval(div);
|
||||
}
|
||||
);
|
||||
|
@ -1794,16 +1785,9 @@ waitForAllPaints(() => {
|
|||
is(div.getAnimations().length, 0, 'There should be no animation');
|
||||
});
|
||||
|
||||
if (isServo) {
|
||||
is(markers.length, 1, // For discarding the throttled animation.
|
||||
'Element.getAnimations() should flush throttled animation style so ' +
|
||||
'that the throttled animation is discarded');
|
||||
} else {
|
||||
is(markers.length, 2, // One is done through UpdateOnlyAnimationStyles(),
|
||||
// the other is for discarding the animation.
|
||||
'Element.getAnimations() should flush throttled animation style that ' +
|
||||
'the throttled animation is discarded');
|
||||
}
|
||||
is(markers.length, 1, // For discarding the throttled animation.
|
||||
'Element.getAnimations() should flush throttled animation style so ' +
|
||||
'that the throttled animation is discarded');
|
||||
|
||||
await ensureElementRemoval(div);
|
||||
});
|
||||
|
|
|
@ -84,10 +84,6 @@ promise_test(t => {
|
|||
}, 'Forcing an animation targetting an element in a document without a'
|
||||
+ ' browsing context to play does not cause style to update');
|
||||
|
||||
// Following is an additional Gecko-specific test to confirm the behavior
|
||||
// when we have an element with an animation restyle and then move it to
|
||||
// a document without a pres shell.
|
||||
|
||||
promise_test(t => {
|
||||
let anim;
|
||||
return getXHRDoc(t).then(xhrdoc => {
|
||||
|
@ -101,15 +97,8 @@ promise_test(t => {
|
|||
xhrdoc.body.appendChild(div);
|
||||
// We should skip applying animation styles to elements in documents
|
||||
// without a pres shell.
|
||||
//
|
||||
// The Gecko style backend, however, does not do this. Since we expect the
|
||||
// Gecko style backend to be obsolete in the near future, we only perform
|
||||
// this check when the Servo backend is in use.
|
||||
let isServo = SpecialPowers.DOMWindowUtils.isStyledByServo;
|
||||
if (isServo) {
|
||||
assert_equals(getComputedStyle(div).opacity, '1',
|
||||
'Style should NOT be updated');
|
||||
}
|
||||
assert_equals(getComputedStyle(div).opacity, '1',
|
||||
'Style should NOT be updated');
|
||||
});
|
||||
}, 'Moving an element with a pending animation restyle to a document without'
|
||||
+ ' a browsing context resets animation style');
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
<script>
|
||||
"use strict";
|
||||
|
||||
const isGecko = !isStyledByServo();
|
||||
|
||||
// Tests that we correctly extract the underlying value when the animation
|
||||
// type is 'discrete'.
|
||||
const discreteTests = [
|
||||
|
@ -33,11 +31,6 @@ const discreteTests = [
|
|||
{ computedOffset: 1, alignContent: "normal" }
|
||||
],
|
||||
explanation: "Test for 0% keyframe only",
|
||||
// The value of 100% should be 'normal',
|
||||
// but we are not supporting underlying value for Gecko.
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1295401
|
||||
// So, we skip this test case.
|
||||
skip: isGecko
|
||||
},
|
||||
{
|
||||
stylesheet: {
|
||||
|
@ -48,11 +41,6 @@ const discreteTests = [
|
|||
{ computedOffset: 1, alignContent: "flex-end" }
|
||||
],
|
||||
explanation: "Test for 100% keyframe only",
|
||||
// The value of 0% should be 'normal',
|
||||
// but we are not supporting underlying value for Gecko.
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1295401
|
||||
// So, we skip this test case.
|
||||
skip: isGecko
|
||||
},
|
||||
{
|
||||
stylesheet: {
|
||||
|
@ -94,11 +82,6 @@ const discreteTests = [
|
|||
],
|
||||
explanation: "Test for no 0%/100% keyframes " +
|
||||
"and 'inherit' specified on target element",
|
||||
// The value of 0%/100% should be 'normal',
|
||||
// but we are not supporting underlying value for Gecko.
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1295401
|
||||
// So, we skip this test case.
|
||||
skip: isGecko
|
||||
},
|
||||
{
|
||||
stylesheet: {
|
||||
|
|
|
@ -363,13 +363,6 @@ function isOMTAEnabled() {
|
|||
SpecialPowers.getBoolPref(OMTAPrefKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the document is styled by servo.
|
||||
*/
|
||||
function isStyledByServo() {
|
||||
return SpecialPowers.DOMWindowUtils.isStyledByServo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append an SVG element to the target element.
|
||||
*
|
||||
|
|
|
@ -12,9 +12,7 @@
|
|||
#include "mozilla/Base64.h"
|
||||
#include "mozilla/BasePrincipal.h"
|
||||
#include "mozilla/CycleCollectedJSRuntime.h"
|
||||
#ifndef RELEASE_OR_BETA
|
||||
#include "mozilla/PerformanceUtils.h"
|
||||
#endif
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/IdleDeadline.h"
|
||||
|
@ -657,7 +655,6 @@ ChromeUtils::ClearRecentJSDevError(GlobalObject&)
|
|||
}
|
||||
#endif // NIGHTLY_BUILD
|
||||
|
||||
#ifndef RELEASE_OR_BETA
|
||||
/* static */ void
|
||||
ChromeUtils::RequestPerformanceMetrics(GlobalObject&)
|
||||
{
|
||||
|
@ -682,7 +679,6 @@ ChromeUtils::RequestPerformanceMetrics(GlobalObject&)
|
|||
);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
constexpr auto kSkipSelfHosted = JS::SavedFrameSelfHosted::Exclude;
|
||||
|
||||
|
|
|
@ -155,9 +155,7 @@ public:
|
|||
|
||||
static void ClearRecentJSDevError(GlobalObject& aGlobal);
|
||||
|
||||
#ifndef RELEASE_OR_BETA
|
||||
static void RequestPerformanceMetrics(GlobalObject& aGlobal);
|
||||
#endif
|
||||
|
||||
static void Import(const GlobalObject& aGlobal,
|
||||
const nsAString& aResourceURI,
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/DocGroup.h"
|
||||
#include "mozilla/dom/DOMPrefs.h"
|
||||
#include "mozilla/dom/DOMTypes.h"
|
||||
#include "mozilla/dom/TabGroup.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
@ -51,9 +52,9 @@ DocGroup::DocGroup(TabGroup* aTabGroup, const nsACString& aKey)
|
|||
: mKey(aKey), mTabGroup(aTabGroup)
|
||||
{
|
||||
// This method does not add itself to mTabGroup->mDocGroups as the caller does it for us.
|
||||
#ifndef RELEASE_OR_BETA
|
||||
mPerformanceCounter = new mozilla::PerformanceCounter(aKey);
|
||||
#endif
|
||||
if (mozilla::dom::DOMPrefs::SchedulerLoggingEnabled()) {
|
||||
mPerformanceCounter = new mozilla::PerformanceCounter(aKey);
|
||||
}
|
||||
}
|
||||
|
||||
DocGroup::~DocGroup()
|
||||
|
@ -67,11 +68,11 @@ DocGroup::~DocGroup()
|
|||
mTabGroup->mDocGroups.RemoveEntry(mKey);
|
||||
}
|
||||
|
||||
#ifndef RELEASE_OR_BETA
|
||||
PerformanceInfo
|
||||
DocGroup::ReportPerformanceInfo()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(mPerformanceCounter);
|
||||
#if defined(XP_WIN)
|
||||
uint32_t pid = GetCurrentProcessId();
|
||||
#else
|
||||
|
@ -127,15 +128,14 @@ DocGroup::ReportPerformanceInfo()
|
|||
mPerformanceCounter->ResetPerformanceCounters();
|
||||
return PerformanceInfo(host, pid, wid, pwid, duration, false, items);
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
DocGroup::Dispatch(TaskCategory aCategory,
|
||||
already_AddRefed<nsIRunnable>&& aRunnable)
|
||||
{
|
||||
#ifndef RELEASE_OR_BETA
|
||||
mPerformanceCounter->IncrementDispatchCounter(DispatchCategory(aCategory));
|
||||
#endif
|
||||
if (mPerformanceCounter) {
|
||||
mPerformanceCounter->IncrementDispatchCounter(DispatchCategory(aCategory));
|
||||
}
|
||||
return mTabGroup->DispatchWithDocGroup(aCategory, Move(aRunnable), this);
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ public:
|
|||
{
|
||||
return aKey == mKey;
|
||||
}
|
||||
#ifndef RELEASE_OR_BETA
|
||||
|
||||
PerformanceCounter* GetPerformanceCounter()
|
||||
{
|
||||
return mPerformanceCounter;
|
||||
|
@ -66,7 +66,7 @@ public:
|
|||
|
||||
PerformanceInfo
|
||||
ReportPerformanceInfo();
|
||||
#endif
|
||||
|
||||
TabGroup* GetTabGroup()
|
||||
{
|
||||
return mTabGroup;
|
||||
|
@ -139,9 +139,9 @@ private:
|
|||
nsTArray<nsIDocument*> mDocuments;
|
||||
RefPtr<mozilla::dom::CustomElementReactionsStack> mReactionsStack;
|
||||
nsTArray<RefPtr<HTMLSlotElement>> mSignalSlotList;
|
||||
#ifndef RELEASE_OR_BETA
|
||||
// This pointer will be null if dom.performance.enable_scheduler_timing is
|
||||
// false (default value)
|
||||
RefPtr<mozilla::PerformanceCounter> mPerformanceCounter;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -291,7 +291,10 @@ const kEventConstructors = {
|
|||
RTCDataChannelEvent: { create: function (aName, aProps) {
|
||||
let pc = new RTCPeerConnection();
|
||||
aProps.channel = pc.createDataChannel("foo");
|
||||
return new RTCDataChannelEvent(aName, aProps);
|
||||
let e = new RTCDataChannelEvent(aName, aProps);
|
||||
aProps.channel.close();
|
||||
pc.close();
|
||||
return e;
|
||||
},
|
||||
},
|
||||
RTCDTMFToneChangeEvent: { create: function (aName, aProps) {
|
||||
|
|
|
@ -30,7 +30,6 @@ interface nsIDOMXULCommandDispatcher : nsISupports
|
|||
void advanceFocus();
|
||||
void rewindFocus();
|
||||
void advanceFocusIntoSubtree(in nsIDOMElement elt);
|
||||
attribute boolean suppressFocusScroll;
|
||||
|
||||
// When locked, command updating is batched until unlocked. Always ensure that
|
||||
// lock and unlock is called in a pair.
|
||||
|
|
|
@ -69,9 +69,7 @@
|
|||
#include "mozilla/net/NeckoChild.h"
|
||||
#include "mozilla/net/CookieServiceChild.h"
|
||||
#include "mozilla/net/CaptivePortalService.h"
|
||||
#ifndef RELEASE_OR_BETA
|
||||
#include "mozilla/PerformanceUtils.h"
|
||||
#endif
|
||||
#include "mozilla/plugins/PluginInstanceParent.h"
|
||||
#include "mozilla/plugins/PluginModuleParent.h"
|
||||
#include "mozilla/widget/ScreenManager.h"
|
||||
|
@ -1382,15 +1380,11 @@ ContentChild::GetResultForRenderingInitFailure(base::ProcessId aOtherPid)
|
|||
mozilla::ipc::IPCResult
|
||||
ContentChild::RecvRequestPerformanceMetrics()
|
||||
{
|
||||
#ifndef RELEASE_OR_BETA
|
||||
MOZ_ASSERT(mozilla::dom::DOMPrefs::SchedulerLoggingEnabled());
|
||||
nsTArray<PerformanceInfo> info;
|
||||
CollectPerformanceInfo(info);
|
||||
SendAddPerformanceMetrics(info);
|
||||
return IPC_OK();
|
||||
#endif
|
||||
#ifdef RELEASE_OR_BETA
|
||||
return IPC_OK();
|
||||
#endif
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
|
|
|
@ -184,9 +184,7 @@
|
|||
#include "private/pprio.h"
|
||||
#include "ContentProcessManager.h"
|
||||
#include "mozilla/dom/ipc/StructuredCloneData.h"
|
||||
#ifndef RELEASE_OR_BETA
|
||||
#include "mozilla/PerformanceUtils.h"
|
||||
#endif
|
||||
#include "mozilla/psm/PSMContentListener.h"
|
||||
#include "nsPluginHost.h"
|
||||
#include "nsPluginTags.h"
|
||||
|
@ -3278,9 +3276,12 @@ ContentParent::RecvFinishMemoryReport(const uint32_t& aGeneration)
|
|||
mozilla::ipc::IPCResult
|
||||
ContentParent::RecvAddPerformanceMetrics(nsTArray<PerformanceInfo>&& aMetrics)
|
||||
{
|
||||
#ifndef RELEASE_OR_BETA
|
||||
if (!mozilla::dom::DOMPrefs::SchedulerLoggingEnabled()) {
|
||||
// The pref is off, we should not get a performance metrics from the content
|
||||
// child
|
||||
return IPC_OK();
|
||||
}
|
||||
Unused << NS_WARN_IF(NS_FAILED(mozilla::NotifyPerformanceInfo(aMetrics)));
|
||||
#endif
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
|
|
@ -76,9 +76,17 @@ SpecialPowers.pushPrefEnv({'set':[
|
|||
});
|
||||
});
|
||||
|
||||
let i = content.document.createElement("iframe");
|
||||
i.setAttribute("src", "data:text/html,foo");
|
||||
content.document.documentElement.appendChild(i);
|
||||
function go() {
|
||||
let i = content.document.createElement("iframe");
|
||||
i.setAttribute("src", "data:text/html,foo");
|
||||
content.document.documentElement.appendChild(i);
|
||||
}
|
||||
|
||||
if (content.document.readyState == "complete") {
|
||||
go();
|
||||
} else {
|
||||
addEventListener("load", go, { once: true, capture: true });
|
||||
}
|
||||
}, false);
|
||||
});
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
[DEFAULT]
|
||||
prefs = dom.performance.enable_scheduler_timing=true
|
||||
support-files =
|
||||
browser_frame_elements.html
|
||||
page_privatestorageevent.html
|
||||
|
@ -74,4 +75,3 @@ support-files =
|
|||
test_noopener_target.html
|
||||
[browser_noopener_null_uri.js]
|
||||
[browser_test_performance_metrics.js]
|
||||
run-if = nightly_build
|
|
@ -474,7 +474,6 @@ WorkerDebugger::ReportErrorToDebuggerOnMainThread(const nsAString& aFilename,
|
|||
WorkerErrorReport::LogErrorToConsole(report, 0);
|
||||
}
|
||||
|
||||
#ifndef RELEASE_OR_BETA
|
||||
PerformanceInfo
|
||||
WorkerDebugger::ReportPerformanceInfo()
|
||||
{
|
||||
|
@ -515,7 +514,6 @@ WorkerDebugger::ReportPerformanceInfo()
|
|||
return PerformanceInfo(uri->GetSpecOrDefault(), pid, wid, pwid, duration,
|
||||
true, items);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
|
|
|
@ -44,14 +44,12 @@ public:
|
|||
ReportErrorToDebugger(const nsAString& aFilename, uint32_t aLineno,
|
||||
const nsAString& aMessage);
|
||||
|
||||
#ifndef RELEASE_OR_BETA
|
||||
/*
|
||||
* Sends back a PerformanceInfo struct from the counters
|
||||
* in mWorkerPrivate. Counters are reset to zero after this call.
|
||||
*/
|
||||
PerformanceInfo
|
||||
ReportPerformanceInfo();
|
||||
#endif
|
||||
|
||||
private:
|
||||
virtual
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "mozilla/dom/ClientSource.h"
|
||||
#include "mozilla/dom/ClientState.h"
|
||||
#include "mozilla/dom/Console.h"
|
||||
#include "mozilla/dom/DOMPrefs.h"
|
||||
#include "mozilla/dom/DOMTypes.h"
|
||||
#include "mozilla/dom/ErrorEvent.h"
|
||||
#include "mozilla/dom/ErrorEventBinding.h"
|
||||
|
@ -429,9 +430,9 @@ private:
|
|||
// Let's be sure that it is created before any
|
||||
// content loading.
|
||||
aWorkerPrivate->EnsurePerformanceStorage();
|
||||
#ifndef RELEASE_OR_BETA
|
||||
aWorkerPrivate->EnsurePerformanceCounter();
|
||||
#endif
|
||||
if (mozilla::dom::DOMPrefs::SchedulerLoggingEnabled()) {
|
||||
aWorkerPrivate->EnsurePerformanceCounter();
|
||||
}
|
||||
|
||||
ErrorResult rv;
|
||||
workerinternals::LoadMainScript(aWorkerPrivate, mScriptURL, WorkerScript, rv);
|
||||
|
@ -2681,9 +2682,7 @@ WorkerPrivate::WorkerPrivate(WorkerPrivate* aParent,
|
|||
, mIsSecureContext(false)
|
||||
, mDebuggerRegistered(false)
|
||||
, mIsInAutomation(false)
|
||||
#ifndef RELEASE_OR_BETA
|
||||
, mPerformanceCounter(nullptr)
|
||||
#endif
|
||||
{
|
||||
MOZ_ASSERT_IF(!IsDedicatedWorker(), NS_IsMainThread());
|
||||
mLoadInfo.StealFrom(aLoadInfo);
|
||||
|
@ -5368,11 +5367,11 @@ WorkerPrivate::DumpCrashInformation(nsACString& aString)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef RELEASE_OR_BETA
|
||||
void
|
||||
WorkerPrivate::EnsurePerformanceCounter()
|
||||
{
|
||||
AssertIsOnWorkerThread();
|
||||
MOZ_ASSERT(mozilla::dom::DOMPrefs::SchedulerLoggingEnabled());
|
||||
if (!mPerformanceCounter) {
|
||||
mPerformanceCounter = new PerformanceCounter(NS_ConvertUTF16toUTF8(mWorkerName));
|
||||
}
|
||||
|
@ -5384,7 +5383,6 @@ WorkerPrivate::GetPerformanceCounter()
|
|||
MOZ_ASSERT(mPerformanceCounter);
|
||||
return mPerformanceCounter;
|
||||
}
|
||||
#endif
|
||||
|
||||
PerformanceStorage*
|
||||
WorkerPrivate::GetPerformanceStorage()
|
||||
|
|
|
@ -550,10 +550,8 @@ public:
|
|||
void
|
||||
EnsurePerformanceStorage();
|
||||
|
||||
#ifndef RELEASE_OR_BETA
|
||||
void
|
||||
EnsurePerformanceCounter();
|
||||
#endif
|
||||
|
||||
const ClientInfo&
|
||||
GetClientInfo() const;
|
||||
|
@ -573,10 +571,8 @@ public:
|
|||
PerformanceStorage*
|
||||
GetPerformanceStorage();
|
||||
|
||||
#ifndef RELEASE_OR_BETA
|
||||
PerformanceCounter*
|
||||
GetPerformanceCounter();
|
||||
#endif
|
||||
|
||||
bool
|
||||
IsAcceptingEvents()
|
||||
|
@ -1473,9 +1469,9 @@ private:
|
|||
// We expose some extra testing functions in that case.
|
||||
bool mIsInAutomation;
|
||||
|
||||
#ifndef RELEASE_OR_BETA
|
||||
// This pointer will be null if dom.performance.enable_scheduler_timing is
|
||||
// false (default value)
|
||||
RefPtr<mozilla::PerformanceCounter> mPerformanceCounter;
|
||||
#endif
|
||||
};
|
||||
|
||||
class AutoSyncLoopHolder
|
||||
|
|
|
@ -228,14 +228,12 @@ WorkerThread::Dispatch(already_AddRefed<nsIRunnable> aRunnable, uint32_t aFlags)
|
|||
|
||||
const bool onWorkerThread = PR_GetCurrentThread() == mThread;
|
||||
|
||||
#ifndef RELEASE_OR_BETA
|
||||
if (GetSchedulerLoggingEnabled() && onWorkerThread && mWorkerPrivate) {
|
||||
PerformanceCounter* performanceCounter = mWorkerPrivate->GetPerformanceCounter();
|
||||
if (performanceCounter) {
|
||||
performanceCounter->IncrementDispatchCounter(DispatchCategory::Worker);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
if (runnable && !onWorkerThread) {
|
||||
|
@ -324,7 +322,6 @@ WorkerThread::RecursionDepth(const WorkerThreadFriendKey& /* aKey */) const
|
|||
return mNestedEventLoopDepth;
|
||||
}
|
||||
|
||||
#ifndef RELEASE_OR_BETA
|
||||
PerformanceCounter*
|
||||
WorkerThread::GetPerformanceCounter(nsIRunnable* aEvent)
|
||||
{
|
||||
|
@ -333,7 +330,6 @@ WorkerThread::GetPerformanceCounter(nsIRunnable* aEvent)
|
|||
}
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMPL_ISUPPORTS(WorkerThread::Observer, nsIThreadObserver)
|
||||
|
||||
|
|
|
@ -81,10 +81,8 @@ public:
|
|||
uint32_t
|
||||
RecursionDepth(const WorkerThreadFriendKey& aKey) const;
|
||||
|
||||
#ifndef RELEASE_OR_BETA
|
||||
PerformanceCounter*
|
||||
GetPerformanceCounter(nsIRunnable* aEvent) override;
|
||||
#endif
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING_INHERITED(WorkerThread, nsThread)
|
||||
|
||||
|
|
|
@ -452,19 +452,6 @@ nsXULCommandDispatcher::GetControllerForCommand(const char *aCommand, nsIControl
|
|||
_retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULCommandDispatcher::GetSuppressFocusScroll(bool* aSuppressFocusScroll)
|
||||
{
|
||||
*aSuppressFocusScroll = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULCommandDispatcher::SetSuppressFocusScroll(bool aSuppressFocusScroll)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULCommandDispatcher::Lock()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
// # don't remove this comment! (the first line is ignored by Mozilla)
|
||||
|
||||
// Verify this one has a user value
|
||||
pref("_autoconfig_.test.userpref", "userpref");
|
||||
|
||||
// Verify this one has a default pref
|
||||
defaultPref("_autoconfig_.test.defaultpref", "defaultpref");
|
||||
|
||||
// Verify this one is locked
|
||||
lockPref("_autoconfig_.test.lockpref", "lockpref");
|
||||
|
||||
lockPref("_autoconfig_.test.unlockpref", "unlockpref");
|
||||
// Verify this one is unlocked
|
||||
unlockPref("_autoconfig_.test.unlockpref");
|
||||
|
||||
pref("_autoconfig_.test.clearpref", "clearpref");
|
||||
// Verify this one has no value
|
||||
clearPref("_autoconfig_.test.clearpref");
|
||||
|
||||
// Verify this one is set to the correct value
|
||||
pref("_autoconfig_.test.getpref.query", "getpref");
|
||||
pref("_autoconfig_.test.getpref", getPref("_autoconfig_.test.getpref.query"));
|
||||
|
||||
// Verify this one is set to the correct value
|
||||
pref("_autoconfig_.test.getenv", getenv("AUTOCONFIG_TEST_GETENV"));
|
||||
|
||||
// Since we can't test displayError directly, verify that it
|
||||
// exists and is a function
|
||||
pref("_autoconfig_.test.displayerror", typeof(displayError));
|
||||
|
||||
// We are not getPrefBranch because it is being removed
|
|
@ -0,0 +1,82 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* eslint no-unsafe-finally: "off"*/
|
||||
/* Turning off this rule to allow control flow operations in finally block
|
||||
* http://eslint.org/docs/rules/no-unsafe-finally */
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function run_test() {
|
||||
let env = Cc["@mozilla.org/process/environment;1"]
|
||||
.getService(Ci.nsIEnvironment);
|
||||
let prefs = Services.prefs.getBranch(null);
|
||||
let defPrefs = Services.prefs.getDefaultBranch(null);
|
||||
|
||||
let greD = Services.dirsvc.get("GreD", Ci.nsIFile);
|
||||
let defaultPrefD = Services.dirsvc.get("PrfDef", Ci.nsIFile);
|
||||
let testDir = do_get_cwd();
|
||||
|
||||
try {
|
||||
let autoConfigJS = testDir.clone();
|
||||
autoConfigJS.append("autoconfig.js");
|
||||
autoConfigJS.copyTo(defaultPrefD, "autoconfig.js");
|
||||
|
||||
// Make sure nsReadConfig is initialized.
|
||||
Cc["@mozilla.org/readconfig;1"].getService(Ci.nsISupports);
|
||||
Services.prefs.resetPrefs();
|
||||
|
||||
let autoConfigCfg = testDir.clone();
|
||||
autoConfigCfg.append("autoconfig-all.cfg");
|
||||
autoConfigCfg.copyTo(greD, "autoconfig.cfg");
|
||||
|
||||
env.set("AUTOCONFIG_TEST_GETENV", "getenv");
|
||||
|
||||
Services.obs.notifyObservers(Services.prefs, "prefservice:before-read-userprefs");
|
||||
|
||||
ok(prefs.prefHasUserValue("_autoconfig_.test.userpref"));
|
||||
equal("userpref", prefs.getStringPref("_autoconfig_.test.userpref"));
|
||||
|
||||
equal("defaultpref", defPrefs.getStringPref("_autoconfig_.test.defaultpref"));
|
||||
equal("defaultpref", prefs.getStringPref("_autoconfig_.test.defaultpref"));
|
||||
|
||||
ok(prefs.prefIsLocked("_autoconfig_.test.lockpref"));
|
||||
equal("lockpref", prefs.getStringPref("_autoconfig_.test.lockpref"));
|
||||
|
||||
ok(!prefs.prefIsLocked("_autoconfig_.test.unlockpref"));
|
||||
equal("unlockpref", prefs.getStringPref("_autoconfig_.test.unlockpref"));
|
||||
|
||||
ok(!prefs.prefHasUserValue("_autoconfig_.test.clearpref"));
|
||||
|
||||
equal("getpref", prefs.getStringPref("_autoconfig_.test.getpref"));
|
||||
|
||||
equal("getenv", prefs.getStringPref("_autoconfig_.test.getenv"));
|
||||
|
||||
equal("function", prefs.getStringPref("_autoconfig_.test.displayerror"));
|
||||
|
||||
Services.prefs.resetPrefs();
|
||||
|
||||
} finally {
|
||||
try {
|
||||
let autoConfigJS = defaultPrefD.clone();
|
||||
autoConfigJS.append("autoconfig.js");
|
||||
autoConfigJS.remove(false);
|
||||
} catch (e) {
|
||||
if (e.result != Cr.NS_ERROR_FILE_NOT_FOUND) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
let autoConfigCfg = greD.clone();
|
||||
autoConfigCfg.append("autoconfig.cfg");
|
||||
autoConfigCfg.remove(false);
|
||||
} catch (e) {
|
||||
if (e.result != Cr.NS_ERROR_FILE_NOT_FOUND) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
Services.prefs.resetPrefs();
|
||||
}
|
||||
}
|
|
@ -2,8 +2,10 @@
|
|||
head =
|
||||
skip-if = toolkit == 'android'
|
||||
support-files =
|
||||
autoconfig-all.cfg
|
||||
autoconfig-latin1.cfg
|
||||
autoconfig-utf8.cfg
|
||||
autoconfig.js
|
||||
|
||||
[test_autoconfig.js]
|
||||
[test_autoconfig_nonascii.js]
|
||||
|
|
|
@ -92,10 +92,17 @@ CompositorAnimationStorage::SetAnimatedValue(uint64_t aId,
|
|||
const TransformData& aData)
|
||||
{
|
||||
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
||||
AnimatedValue* value = new AnimatedValue(Move(aTransformInDevSpace),
|
||||
Move(aFrameTransform),
|
||||
aData);
|
||||
mAnimatedValues.Put(aId, value);
|
||||
auto count = mAnimatedValues.Count();
|
||||
AnimatedValue* value = mAnimatedValues.LookupOrAdd(aId,
|
||||
Move(aTransformInDevSpace),
|
||||
Move(aFrameTransform),
|
||||
aData);
|
||||
if (count == mAnimatedValues.Count()) {
|
||||
MOZ_ASSERT(value->mType == AnimatedValue::TRANSFORM);
|
||||
value->mTransform.mTransformInDevSpace = Move(aTransformInDevSpace);
|
||||
value->mTransform.mFrameTransform = Move(aFrameTransform);
|
||||
value->mTransform.mData = aData;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -104,10 +111,10 @@ CompositorAnimationStorage::SetAnimatedValue(uint64_t aId,
|
|||
{
|
||||
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
||||
const TransformData dontCare = {};
|
||||
AnimatedValue* value = new AnimatedValue(Move(aTransformInDevSpace),
|
||||
gfx::Matrix4x4(),
|
||||
dontCare);
|
||||
mAnimatedValues.Put(aId, value);
|
||||
SetAnimatedValue(aId,
|
||||
Move(aTransformInDevSpace),
|
||||
Move(gfx::Matrix4x4()),
|
||||
dontCare);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -115,8 +122,12 @@ CompositorAnimationStorage::SetAnimatedValue(uint64_t aId,
|
|||
const float& aOpacity)
|
||||
{
|
||||
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
||||
AnimatedValue* value = new AnimatedValue(aOpacity);
|
||||
mAnimatedValues.Put(aId, value);
|
||||
auto count = mAnimatedValues.Count();
|
||||
AnimatedValue* value = mAnimatedValues.LookupOrAdd(aId, aOpacity);
|
||||
if (count == mAnimatedValues.Count()) {
|
||||
MOZ_ASSERT(value->mType == AnimatedValue::OPACITY);
|
||||
value->mOpacity = aOpacity;
|
||||
}
|
||||
}
|
||||
|
||||
AnimationArray*
|
||||
|
|
|
@ -362,20 +362,35 @@ APZUpdater::RunOnUpdaterThread(LayersId aLayersId, already_AddRefed<Runnable> aT
|
|||
// during the callback from the updater thread, which we trigger by the
|
||||
// call to WakeSceneBuilder.
|
||||
|
||||
bool sendWakeMessage = true;
|
||||
{ // scope lock
|
||||
MutexAutoLock lock(mQueueLock);
|
||||
for (const auto& queuedTask : mUpdaterQueue) {
|
||||
if (queuedTask.mLayersId == aLayersId) {
|
||||
// If there's already a task in the queue with this layers id, then
|
||||
// we must have previously sent a WakeSceneBuilder message (when
|
||||
// adding the first task with this layers id to the queue). Either
|
||||
// that hasn't been fully processed yet, or the layers id is blocked
|
||||
// waiting for an epoch - in either case there's no point in sending
|
||||
// another WakeSceneBuilder message.
|
||||
sendWakeMessage = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mUpdaterQueue.push_back(QueuedTask { aLayersId, task });
|
||||
}
|
||||
RefPtr<wr::WebRenderAPI> api = mApz->GetWebRenderAPI();
|
||||
if (api) {
|
||||
api->WakeSceneBuilder();
|
||||
} else {
|
||||
// Not sure if this can happen, but it might be possible. If it does,
|
||||
// the task is in the queue, but if we didn't get a WebRenderAPI it
|
||||
// might never run, or it might run later if we manage to get a
|
||||
// WebRenderAPI later. For now let's just emit a warning, this can
|
||||
// probably be upgraded to an assert later.
|
||||
NS_WARNING("Possibly dropping task posted to updater thread");
|
||||
if (sendWakeMessage) {
|
||||
RefPtr<wr::WebRenderAPI> api = mApz->GetWebRenderAPI();
|
||||
if (api) {
|
||||
api->WakeSceneBuilder();
|
||||
} else {
|
||||
// Not sure if this can happen, but it might be possible. If it does,
|
||||
// the task is in the queue, but if we didn't get a WebRenderAPI it
|
||||
// might never run, or it might run later if we manage to get a
|
||||
// WebRenderAPI later. For now let's just emit a warning, this can
|
||||
// probably be upgraded to an assert later.
|
||||
NS_WARNING("Possibly dropping task posted to updater thread");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -327,13 +327,7 @@ bool
|
|||
CompositorBridgeChild::DeallocPLayerTransactionChild(PLayerTransactionChild* actor)
|
||||
{
|
||||
LayersId childId = static_cast<LayerTransactionChild*>(actor)->GetId();
|
||||
|
||||
for (auto iter = mFrameMetricsTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsAutoPtr<SharedFrameMetricsData>& data = iter.Data();
|
||||
if (data->GetLayersId() == childId) {
|
||||
iter.Remove();
|
||||
}
|
||||
}
|
||||
ClearSharedFrameMetricsData(childId);
|
||||
static_cast<LayerTransactionChild*>(actor)->ReleaseIPDLReference();
|
||||
return true;
|
||||
}
|
||||
|
@ -1111,10 +1105,22 @@ bool
|
|||
CompositorBridgeChild::DeallocPWebRenderBridgeChild(PWebRenderBridgeChild* aActor)
|
||||
{
|
||||
WebRenderBridgeChild* child = static_cast<WebRenderBridgeChild*>(aActor);
|
||||
ClearSharedFrameMetricsData(wr::AsLayersId(child->GetPipeline()));
|
||||
child->ReleaseIPDLReference();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CompositorBridgeChild::ClearSharedFrameMetricsData(LayersId aLayersId)
|
||||
{
|
||||
for (auto iter = mFrameMetricsTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsAutoPtr<SharedFrameMetricsData>& data = iter.Data();
|
||||
if (data->GetLayersId() == aLayersId) {
|
||||
iter.Remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t
|
||||
CompositorBridgeChild::GetNextResourceId()
|
||||
{
|
||||
|
|
|
@ -324,6 +324,8 @@ private:
|
|||
|
||||
uint64_t GetNextResourceId();
|
||||
|
||||
void ClearSharedFrameMetricsData(LayersId aLayersId);
|
||||
|
||||
// Class used to store the shared FrameMetrics, mutex, and APZCId in a hash table
|
||||
class SharedFrameMetricsData {
|
||||
public:
|
||||
|
|
|
@ -178,6 +178,12 @@ CompositorBridgeParentBase::DeallocShmem(ipc::Shmem& aShmem)
|
|||
PCompositorBridgeParent::DeallocShmem(aShmem);
|
||||
}
|
||||
|
||||
static inline MessageLoop*
|
||||
CompositorLoop()
|
||||
{
|
||||
return CompositorThreadHolder::Loop();
|
||||
}
|
||||
|
||||
base::ProcessId
|
||||
CompositorBridgeParentBase::RemotePid()
|
||||
{
|
||||
|
@ -190,6 +196,21 @@ CompositorBridgeParentBase::StartSharingMetrics(ipc::SharedMemoryBasic::Handle a
|
|||
LayersId aLayersId,
|
||||
uint32_t aApzcId)
|
||||
{
|
||||
if (!CompositorThreadHolder::IsInCompositorThread()) {
|
||||
MOZ_ASSERT(CompositorLoop());
|
||||
CompositorLoop()->PostTask(
|
||||
NewRunnableMethod<ipc::SharedMemoryBasic::Handle,
|
||||
CrossProcessMutexHandle,
|
||||
LayersId,
|
||||
uint32_t>(
|
||||
"layers::CompositorBridgeParent::StartSharingMetrics",
|
||||
this,
|
||||
&CompositorBridgeParentBase::StartSharingMetrics,
|
||||
aHandle, aMutexHandle, aLayersId, aApzcId));
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
||||
if (!mCanSend) {
|
||||
return false;
|
||||
}
|
||||
|
@ -201,6 +222,18 @@ bool
|
|||
CompositorBridgeParentBase::StopSharingMetrics(FrameMetrics::ViewID aScrollId,
|
||||
uint32_t aApzcId)
|
||||
{
|
||||
if (!CompositorThreadHolder::IsInCompositorThread()) {
|
||||
MOZ_ASSERT(CompositorLoop());
|
||||
CompositorLoop()->PostTask(
|
||||
NewRunnableMethod<FrameMetrics::ViewID, uint32_t>(
|
||||
"layers::CompositorBridgeParent::StopSharingMetrics",
|
||||
this,
|
||||
&CompositorBridgeParentBase::StopSharingMetrics,
|
||||
aScrollId, aApzcId));
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
||||
if (!mCanSend) {
|
||||
return false;
|
||||
}
|
||||
|
@ -313,12 +346,6 @@ CalculateCompositionFrameRate()
|
|||
}
|
||||
#endif
|
||||
|
||||
static inline MessageLoop*
|
||||
CompositorLoop()
|
||||
{
|
||||
return CompositorThreadHolder::Loop();
|
||||
}
|
||||
|
||||
CompositorBridgeParent::CompositorBridgeParent(CompositorManagerParent* aManager,
|
||||
CSSToLayoutDeviceScale aScale,
|
||||
const TimeDuration& aVsyncRate,
|
||||
|
@ -517,6 +544,9 @@ mozilla::ipc::IPCResult
|
|||
CompositorBridgeParent::RecvWillClose()
|
||||
{
|
||||
StopAndClearResources();
|
||||
// Once we get the WillClose message, the client side is going to go away
|
||||
// soon and we can't be guaranteed that sending messages will work.
|
||||
mCanSend = false;
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
|
|
@ -117,6 +117,10 @@ bool Pickle::IteratorHasRoomFor(const PickleIterator& iter, uint32_t len) const
|
|||
return iter.iter_.HasRoomFor(AlignInt(len));
|
||||
}
|
||||
|
||||
bool Pickle::HasBytesAvailable(const PickleIterator* iter, uint32_t len) const {
|
||||
return iter->iter_.HasBytesAvailable(buffers_, len);
|
||||
}
|
||||
|
||||
void Pickle::UpdateIter(PickleIterator* iter, uint32_t bytes) const {
|
||||
// Make sure we don't get into trouble where AlignInt(bytes) == 0.
|
||||
MOZ_RELEASE_ASSERT(bytes < 64);
|
||||
|
|
|
@ -139,6 +139,14 @@ class Pickle {
|
|||
// telemetry probe.
|
||||
void EndRead(PickleIterator& iter, uint32_t ipcMessageType = 0) const;
|
||||
|
||||
// Returns true if the given iterator has at least |len| bytes remaining it,
|
||||
// across all segments. If there is not that much data available, returns
|
||||
// false. Generally used when reading a (len, data) pair from the message,
|
||||
// before allocating |len| bytes of space, to ensure that reading |len| bytes
|
||||
// will succeed.
|
||||
bool HasBytesAvailable(const PickleIterator* iter, uint32_t len) const;
|
||||
|
||||
|
||||
// Methods for adding to the payload of the Pickle. These values are
|
||||
// appended to the end of the Pickle's payload. When reading values from a
|
||||
// Pickle, it is important to read them in the order in which they were added
|
||||
|
|
|
@ -394,6 +394,9 @@ struct ParamTraits<nsACString>
|
|||
if (!ReadParam(aMsg, aIter, &length)) {
|
||||
return false;
|
||||
}
|
||||
if (!aMsg->HasBytesAvailable(aIter, length)) {
|
||||
return false;
|
||||
}
|
||||
aResult->SetLength(length);
|
||||
|
||||
return aMsg->ReadBytesInto(aIter, aResult->BeginWriting(), length);
|
||||
|
@ -443,13 +446,13 @@ struct ParamTraits<nsAString>
|
|||
return false;
|
||||
}
|
||||
|
||||
aResult->SetLength(length);
|
||||
|
||||
mozilla::CheckedInt<uint32_t> byteLength = mozilla::CheckedInt<uint32_t>(length) * sizeof(char16_t);
|
||||
if (!byteLength.isValid()) {
|
||||
if (!byteLength.isValid() || !aMsg->HasBytesAvailable(aIter, byteLength.value())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aResult->SetLength(length);
|
||||
|
||||
return aMsg->ReadBytesInto(aIter, aResult->BeginWriting(), byteLength.value());
|
||||
}
|
||||
|
||||
|
@ -583,6 +586,14 @@ struct ParamTraits<nsTArray<E>>
|
|||
E* elements = aResult->AppendElements(length);
|
||||
return aMsg->ReadBytesInto(aIter, elements, pickledLength);
|
||||
} else {
|
||||
|
||||
// Each ReadParam<E> may read more than 1 byte each; this is an attempt
|
||||
// to minimally validate that the length isn't much larger than what's
|
||||
// actually available in aMsg.
|
||||
if (!aMsg->HasBytesAvailable(aIter, length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aResult->SetCapacity(length);
|
||||
|
||||
for (uint32_t index = 0; index < length; index++) {
|
||||
|
|
|
@ -107,7 +107,7 @@ struct IPDLParamTraits<nsTArray<T>>
|
|||
|
||||
if (sUseWriteBytes) {
|
||||
auto pickledLength = CheckedInt<int>(length) * sizeof(T);
|
||||
if (!pickledLength.isValid()) {
|
||||
if (!pickledLength.isValid() || !aMsg->HasBytesAvailable(aIter, pickledLength.value())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -115,6 +115,15 @@ struct IPDLParamTraits<nsTArray<T>>
|
|||
return aMsg->ReadBytesInto(aIter, elements, pickledLength.value());
|
||||
}
|
||||
|
||||
// Each ReadIPDLParam<E> may read more than 1 byte each; this is an attempt
|
||||
// to minimally validate that the length isn't much larger than what's
|
||||
// actually available in aMsg. We cannot use |pickledLength|, like in the
|
||||
// codepath above, because ReadIPDLParam can read variable amounts of data
|
||||
// from aMsg.
|
||||
if (!aMsg->HasBytesAvailable(aIter, length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aResult->SetCapacity(length);
|
||||
|
||||
for (uint32_t index = 0; index < length; index++) {
|
||||
|
|
|
@ -461,11 +461,23 @@ nsButtonFrameRenderer::GetButtonInnerFocusRect(const nsRect& aRect, nsRect& aRes
|
|||
aResult = aRect;
|
||||
aResult.Deflate(mFrame->GetUsedBorderAndPadding());
|
||||
|
||||
nsMargin innerFocusPadding(0,0,0,0);
|
||||
if (mInnerFocusStyle) {
|
||||
nsMargin innerFocusPadding(0,0,0,0);
|
||||
mInnerFocusStyle->StylePadding()->GetPadding(innerFocusPadding);
|
||||
|
||||
nsMargin framePadding = mFrame->GetUsedPadding();
|
||||
|
||||
innerFocusPadding.top = std::min(innerFocusPadding.top,
|
||||
framePadding.top);
|
||||
innerFocusPadding.right = std::min(innerFocusPadding.right,
|
||||
framePadding.right);
|
||||
innerFocusPadding.bottom = std::min(innerFocusPadding.bottom,
|
||||
framePadding.bottom);
|
||||
innerFocusPadding.left = std::min(innerFocusPadding.left,
|
||||
framePadding.left);
|
||||
|
||||
aResult.Inflate(innerFocusPadding);
|
||||
}
|
||||
aResult.Inflate(innerFocusPadding);
|
||||
}
|
||||
|
||||
ImgDrawResult
|
||||
|
@ -560,7 +572,7 @@ nsButtonFrameRenderer::ReResolveStyles(nsPresContext* aPresContext)
|
|||
ComputedStyle* context = mFrame->Style();
|
||||
ServoStyleSet* styleSet = aPresContext->StyleSet();
|
||||
|
||||
// get styles assigned to -moz-inner-focus (ie dotted border on Windows)
|
||||
// get styles assigned to -moz-focus-inner (ie dotted border on Windows)
|
||||
mInnerFocusStyle =
|
||||
styleSet->ProbePseudoElementStyle(mFrame->GetContent()->AsElement(),
|
||||
CSSPseudoElementType::mozFocusInner,
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<style>
|
||||
button {
|
||||
padding: 0px;
|
||||
border:none;
|
||||
font-size: 64px;
|
||||
background-color: green;
|
||||
}
|
||||
button::-moz-focus-inner {
|
||||
padding-inline-start: 0px;
|
||||
padding-inline-end: 0px;
|
||||
}
|
||||
button:-moz-focusring::-moz-focus-inner {
|
||||
border: 4px solid;
|
||||
}
|
||||
</style>
|
||||
<div>
|
||||
<button id="button1"><span>Menu1</span></button>
|
||||
</div>
|
||||
<script>
|
||||
window.onload = () => {
|
||||
button1.focus();
|
||||
document.documentElement.classList.remove('reftest-wait');
|
||||
}
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<style>
|
||||
button {
|
||||
padding: 0px;
|
||||
border:none;
|
||||
font-size: 64px;
|
||||
background-color: green;
|
||||
}
|
||||
button::-moz-focus-inner {
|
||||
padding-inline-start: 20px;
|
||||
padding-inline-end: 20px;
|
||||
}
|
||||
button:-moz-focusring::-moz-focus-inner {
|
||||
border: 4px solid;
|
||||
}
|
||||
</style>
|
||||
<div>
|
||||
<button id="button1"><span>Menu1</span></button>
|
||||
</div>
|
||||
<script>
|
||||
window.onload = () => {
|
||||
button1.focus();
|
||||
document.documentElement.classList.remove('reftest-wait');
|
||||
}
|
||||
</script>
|
||||
</html>
|
|
@ -41,3 +41,5 @@ fails-if(Android) == disabled-1.html disabled-1-ref.html
|
|||
== 1317351.html 1317351-ref.html
|
||||
|
||||
== dynamic-text-indent.html dynamic-text-indent-ref.html
|
||||
|
||||
== 1349646.html 1349646-ref.html
|
||||
|
|
|
@ -52,7 +52,6 @@ skip-if = (toolkit == 'android')
|
|||
support-files = Ahem.ttf file_animations_async_tests.html
|
||||
[test_animations_dynamic_changes.html]
|
||||
[test_animations_effect_timing_duration.html]
|
||||
skip-if = webrender # bug 1424752
|
||||
[test_animations_effect_timing_enddelay.html]
|
||||
skip-if = webrender # bug 1424752
|
||||
[test_animations_effect_timing_iterations.html]
|
||||
|
@ -64,13 +63,11 @@ skip-if = webrender # bug 1424752
|
|||
[test_animations_omta.html]
|
||||
skip-if = webrender # bug 1424752
|
||||
[test_animations_omta_start.html]
|
||||
skip-if = webrender # bug 1424752
|
||||
[test_animations_pausing.html]
|
||||
skip-if = webrender # bug 1424752
|
||||
[test_animations_playbackrate.html]
|
||||
skip-if = webrender # bug 1424752
|
||||
[test_animations_reverse.html]
|
||||
skip-if = webrender # bug 1424752
|
||||
[test_animations_styles_on_event.html]
|
||||
[test_animations_variable_changes.html]
|
||||
[test_animations_with_disabled_properties.html]
|
||||
|
@ -328,7 +325,7 @@ skip-if = (android_version == '18' && debug) # bug 1159532
|
|||
[test_transitions_bug537151.html]
|
||||
[test_transitions_dynamic_changes.html]
|
||||
[test_transitions_per_property.html]
|
||||
skip-if = (toolkit == 'android') || webrender # bug 775227 for android, bug 1424752 for webrender
|
||||
skip-if = (toolkit == 'android') # bug 775227 for android
|
||||
[test_transitions_replacement_on_busy_frame.html]
|
||||
[test_transitions_step_functions.html]
|
||||
[test_transitions_with_disabled_properties.html]
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "nsScrollbarFrame.h"
|
||||
#include "nsSliderFrame.h"
|
||||
#include "nsScrollbarButtonFrame.h"
|
||||
#include "nsContentCreatorFunctions.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsIScrollbarMediator.h"
|
||||
|
@ -39,6 +40,7 @@ NS_IMPL_FRAMEARENA_HELPERS(nsScrollbarFrame)
|
|||
|
||||
NS_QUERYFRAME_HEAD(nsScrollbarFrame)
|
||||
NS_QUERYFRAME_ENTRY(nsScrollbarFrame)
|
||||
NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
|
||||
NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
|
||||
|
||||
void
|
||||
|
@ -55,6 +57,16 @@ nsScrollbarFrame::Init(nsIContent* aContent,
|
|||
AddStateBits(NS_FRAME_REFLOW_ROOT);
|
||||
}
|
||||
|
||||
void nsScrollbarFrame::DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData)
|
||||
{
|
||||
aPostDestroyData.AddAnonymousContent(mUpTopButton.forget());
|
||||
aPostDestroyData.AddAnonymousContent(mDownTopButton.forget());
|
||||
aPostDestroyData.AddAnonymousContent(mSlider.forget());
|
||||
aPostDestroyData.AddAnonymousContent(mUpBottomButton.forget());
|
||||
aPostDestroyData.AddAnonymousContent(mDownBottomButton.forget());
|
||||
nsBoxFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
|
||||
}
|
||||
|
||||
void
|
||||
nsScrollbarFrame::Reflow(nsPresContext* aPresContext,
|
||||
ReflowOutput& aDesiredSize,
|
||||
|
@ -83,6 +95,9 @@ nsScrollbarFrame::AttributeChanged(int32_t aNameSpaceID,
|
|||
nsresult rv = nsBoxFrame::AttributeChanged(aNameSpaceID, aAttribute,
|
||||
aModType);
|
||||
|
||||
// Update value in our children
|
||||
UpdateChildrenAttributeValue(aAttribute, true);
|
||||
|
||||
// if the current position changes, notify any nsGfxScrollFrame
|
||||
// parent we may have
|
||||
if (aAttribute != nsGkAtoms::curpos)
|
||||
|
@ -291,3 +306,222 @@ nsScrollbarFrame::MoveToNewPosition()
|
|||
content->UnsetAttr(kNameSpaceID_None, nsGkAtoms::smooth, false);
|
||||
return curpos;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsScrollbarFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
|
||||
{
|
||||
// <xul:scrollbarbutton sbattr="scrollbar-up-top" type="decrement" xbl:inherits="curpos,maxpos,disabled"/>
|
||||
// <xul:scrollbarbutton sbattr="scrollbar-down-top" type="increment" xbl:inherits="curpos,maxpos,disabled"/>
|
||||
// <xul:slider flex="1" xbl:inherits="disabled,curpos,maxpos,pageincrement,increment,orient">
|
||||
// <xul:thumb sbattr="scrollbar-thumb" xbl:inherits="orient,collapsed=disabled"
|
||||
// align="center" pack="center"/>
|
||||
// </xul:slider>
|
||||
// <xul:scrollbarbutton sbattr="scrollbar-up-bottom" type="decrement" xbl:inherits="curpos,maxpos,disabled"/>
|
||||
// <xul:scrollbarbutton sbattr="scrollbar-down-bottom" type="increment" xbl:inherits="curpos,maxpos,disabled"/>
|
||||
|
||||
nsNodeInfoManager* nodeInfoManager = mContent->NodeInfo()->NodeInfoManager();
|
||||
|
||||
Element* el(GetContent()->AsElement());
|
||||
|
||||
// If there are children already in the node, don't create any anonymous content
|
||||
// (this only apply to crashtests/369038-1.xhtml)
|
||||
if (el->HasChildren()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoString orient;
|
||||
el->GetAttr(kNameSpaceID_None, nsGkAtoms::orient, orient);
|
||||
|
||||
NS_TrustedNewXULElement(getter_AddRefs(mUpTopButton),
|
||||
nodeInfoManager->GetNodeInfo(nsGkAtoms::scrollbarbutton, nullptr,
|
||||
kNameSpaceID_XUL,
|
||||
nsINode::ELEMENT_NODE)
|
||||
);
|
||||
mUpTopButton->SetAttr(kNameSpaceID_None, nsGkAtoms::sbattr,
|
||||
NS_LITERAL_STRING("scrollbar-up-top"), false);
|
||||
mUpTopButton->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
|
||||
NS_LITERAL_STRING("decrement"), false);
|
||||
|
||||
if (!aElements.AppendElement(mUpTopButton)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_TrustedNewXULElement(getter_AddRefs(mDownTopButton),
|
||||
nodeInfoManager->GetNodeInfo(nsGkAtoms::scrollbarbutton, nullptr,
|
||||
kNameSpaceID_XUL,
|
||||
nsINode::ELEMENT_NODE)
|
||||
);
|
||||
mDownTopButton->SetAttr(kNameSpaceID_None, nsGkAtoms::sbattr,
|
||||
NS_LITERAL_STRING("scrollbar-down-top"), false);
|
||||
mDownTopButton->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
|
||||
NS_LITERAL_STRING("increment"), false);
|
||||
|
||||
if (!aElements.AppendElement(mDownTopButton)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_TrustedNewXULElement(getter_AddRefs(mSlider),
|
||||
nodeInfoManager->GetNodeInfo(nsGkAtoms::slider, nullptr,
|
||||
kNameSpaceID_XUL,
|
||||
nsINode::ELEMENT_NODE)
|
||||
);
|
||||
mSlider->SetAttr(kNameSpaceID_None, nsGkAtoms::orient, orient, false);
|
||||
mSlider->SetAttr(kNameSpaceID_None, nsGkAtoms::flex,
|
||||
NS_LITERAL_STRING("1"), false);
|
||||
|
||||
if (!aElements.AppendElement(mSlider)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_TrustedNewXULElement(getter_AddRefs(mThumb),
|
||||
nodeInfoManager->GetNodeInfo(nsGkAtoms::thumb, nullptr,
|
||||
kNameSpaceID_XUL,
|
||||
nsINode::ELEMENT_NODE)
|
||||
);
|
||||
mThumb->SetAttr(kNameSpaceID_None, nsGkAtoms::sbattr,
|
||||
NS_LITERAL_STRING("scrollbar-thumb"), false);
|
||||
mThumb->SetAttr(kNameSpaceID_None, nsGkAtoms::orient, orient, false);
|
||||
mThumb->SetAttr(kNameSpaceID_None, nsGkAtoms::align,
|
||||
NS_LITERAL_STRING("center"), false);
|
||||
mThumb->SetAttr(kNameSpaceID_None, nsGkAtoms::pack,
|
||||
NS_LITERAL_STRING("center"), false);
|
||||
mSlider->AppendChildTo(mThumb, false);
|
||||
|
||||
NS_TrustedNewXULElement(getter_AddRefs(mUpBottomButton),
|
||||
nodeInfoManager->GetNodeInfo(nsGkAtoms::scrollbarbutton, nullptr,
|
||||
kNameSpaceID_XUL,
|
||||
nsINode::ELEMENT_NODE)
|
||||
);
|
||||
mUpBottomButton->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
|
||||
NS_LITERAL_STRING("decrement"), false);
|
||||
mUpBottomButton->SetAttr(kNameSpaceID_None, nsGkAtoms::sbattr,
|
||||
NS_LITERAL_STRING("scrollbar-up-bottom"), false);
|
||||
|
||||
if (!aElements.AppendElement(mUpBottomButton)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_TrustedNewXULElement(getter_AddRefs(mDownBottomButton),
|
||||
nodeInfoManager->GetNodeInfo(nsGkAtoms::scrollbarbutton, nullptr,
|
||||
kNameSpaceID_XUL,
|
||||
nsINode::ELEMENT_NODE)
|
||||
);
|
||||
mDownBottomButton->SetAttr(kNameSpaceID_None, nsGkAtoms::sbattr,
|
||||
NS_LITERAL_STRING("scrollbar-down-bottom"), false);
|
||||
mDownBottomButton->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
|
||||
NS_LITERAL_STRING("increment"), false);
|
||||
|
||||
if (!aElements.AppendElement(mDownBottomButton)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
UpdateChildrenAttributeValue(nsGkAtoms::curpos, false);
|
||||
UpdateChildrenAttributeValue(nsGkAtoms::maxpos, false);
|
||||
UpdateChildrenAttributeValue(nsGkAtoms::disabled, false);
|
||||
UpdateChildrenAttributeValue(nsGkAtoms::pageincrement, false);
|
||||
UpdateChildrenAttributeValue(nsGkAtoms::increment, false);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsScrollbarFrame::UpdateChildrenAttributeValue(nsAtom* aAttribute, bool aNotify)
|
||||
{
|
||||
Element* el(GetContent()->AsElement());
|
||||
|
||||
nsAutoString value;
|
||||
el->GetAttr(kNameSpaceID_None, aAttribute, value);
|
||||
|
||||
if (!el->HasAttr(kNameSpaceID_None, aAttribute)) {
|
||||
if (mUpTopButton) {
|
||||
mUpTopButton->UnsetAttr(kNameSpaceID_None, aAttribute, aNotify);
|
||||
}
|
||||
if (mDownTopButton) {
|
||||
mDownTopButton->UnsetAttr(kNameSpaceID_None, aAttribute, aNotify);
|
||||
}
|
||||
if (mSlider) {
|
||||
mSlider->UnsetAttr(kNameSpaceID_None, aAttribute, aNotify);
|
||||
}
|
||||
if (mThumb && aAttribute == nsGkAtoms::disabled) {
|
||||
mThumb->UnsetAttr(kNameSpaceID_None, nsGkAtoms::collapsed, aNotify);
|
||||
}
|
||||
if (mUpBottomButton) {
|
||||
mUpBottomButton->UnsetAttr(kNameSpaceID_None, aAttribute, aNotify);
|
||||
}
|
||||
if (mDownBottomButton) {
|
||||
mDownBottomButton->UnsetAttr(kNameSpaceID_None, aAttribute, aNotify);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (aAttribute == nsGkAtoms::curpos ||
|
||||
aAttribute == nsGkAtoms::maxpos) {
|
||||
if (mUpTopButton) {
|
||||
mUpTopButton->SetAttr(kNameSpaceID_None, aAttribute, value, aNotify);
|
||||
}
|
||||
if (mDownTopButton) {
|
||||
mDownTopButton->SetAttr(kNameSpaceID_None, aAttribute, value, aNotify);
|
||||
}
|
||||
if (mSlider) {
|
||||
mSlider->SetAttr(kNameSpaceID_None, aAttribute, value, aNotify);
|
||||
}
|
||||
if (mUpBottomButton) {
|
||||
mUpBottomButton->SetAttr(kNameSpaceID_None, aAttribute, value, aNotify);
|
||||
}
|
||||
if (mDownBottomButton) {
|
||||
mDownBottomButton->SetAttr(kNameSpaceID_None, aAttribute, value, aNotify);
|
||||
}
|
||||
}
|
||||
else if (aAttribute == nsGkAtoms::disabled) {
|
||||
if (mUpTopButton) {
|
||||
mUpTopButton->SetAttr(kNameSpaceID_None, aAttribute, value, aNotify);
|
||||
}
|
||||
if (mDownTopButton) {
|
||||
mDownTopButton->SetAttr(kNameSpaceID_None, aAttribute, value, aNotify);
|
||||
}
|
||||
if (mSlider) {
|
||||
mSlider->SetAttr(kNameSpaceID_None, aAttribute, value, aNotify);
|
||||
}
|
||||
// Set the value on "collapsed" attribute.
|
||||
if (mThumb) {
|
||||
mThumb->SetAttr(kNameSpaceID_None, nsGkAtoms::collapsed, value, aNotify);
|
||||
}
|
||||
if (mUpBottomButton) {
|
||||
mUpBottomButton->SetAttr(kNameSpaceID_None, aAttribute, value, aNotify);
|
||||
}
|
||||
if (mDownBottomButton) {
|
||||
mDownBottomButton->SetAttr(kNameSpaceID_None, aAttribute, value, aNotify);
|
||||
}
|
||||
}
|
||||
else if (aAttribute == nsGkAtoms::pageincrement ||
|
||||
aAttribute == nsGkAtoms::increment) {
|
||||
if (mSlider) {
|
||||
mSlider->SetAttr(kNameSpaceID_None, aAttribute, value, aNotify);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsScrollbarFrame::AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
|
||||
uint32_t aFilter)
|
||||
{
|
||||
if (mUpTopButton) {
|
||||
aElements.AppendElement(mUpTopButton);
|
||||
}
|
||||
|
||||
if (mDownTopButton) {
|
||||
aElements.AppendElement(mDownTopButton);
|
||||
}
|
||||
|
||||
if (mSlider) {
|
||||
aElements.AppendElement(mSlider);
|
||||
}
|
||||
|
||||
if (mUpBottomButton) {
|
||||
aElements.AppendElement(mUpBottomButton);
|
||||
}
|
||||
|
||||
if (mDownBottomButton) {
|
||||
aElements.AppendElement(mDownBottomButton);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#define nsScrollbarFrame_h__
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsIAnonymousContentCreator.h"
|
||||
#include "nsBoxFrame.h"
|
||||
|
||||
class nsIScrollbarMediator;
|
||||
|
@ -19,7 +20,8 @@ class nsIScrollbarMediator;
|
|||
nsIFrame* NS_NewScrollbarFrame(nsIPresShell* aPresShell,
|
||||
mozilla::ComputedStyle* aStyle);
|
||||
|
||||
class nsScrollbarFrame final : public nsBoxFrame
|
||||
class nsScrollbarFrame final : public nsBoxFrame,
|
||||
public nsIAnonymousContentCreator
|
||||
{
|
||||
public:
|
||||
explicit nsScrollbarFrame(ComputedStyle* aStyle)
|
||||
|
@ -27,6 +29,12 @@ public:
|
|||
, mIncrement(0)
|
||||
, mSmoothScroll(false)
|
||||
, mScrollbarMediator(nullptr)
|
||||
, mUpTopButton(nullptr)
|
||||
, mDownTopButton(nullptr)
|
||||
, mSlider(nullptr)
|
||||
, mThumb(nullptr)
|
||||
, mUpBottomButton(nullptr)
|
||||
, mDownBottomButton(nullptr)
|
||||
{}
|
||||
|
||||
NS_DECL_QUERYFRAME
|
||||
|
@ -60,6 +68,8 @@ public:
|
|||
mozilla::WidgetGUIEvent* aEvent,
|
||||
nsEventStatus* aEventStatus) override;
|
||||
|
||||
virtual void DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData) override;
|
||||
|
||||
virtual void Init(nsIContent* aContent,
|
||||
nsContainerFrame* aParent,
|
||||
nsIFrame* aPrevInFlow) override;
|
||||
|
@ -101,12 +111,26 @@ public:
|
|||
int32_t MoveToNewPosition();
|
||||
int32_t GetIncrement() { return mIncrement; }
|
||||
|
||||
// nsIAnonymousContentCreator
|
||||
virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
|
||||
virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
|
||||
uint32_t aFilter) override;
|
||||
|
||||
void UpdateChildrenAttributeValue(nsAtom* aAttribute, bool aNotify);
|
||||
|
||||
protected:
|
||||
int32_t mIncrement; // Amount to scroll, in CSSPixels
|
||||
bool mSmoothScroll;
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIContent> mScrollbarMediator;
|
||||
|
||||
nsCOMPtr<Element> mUpTopButton;
|
||||
nsCOMPtr<Element> mDownTopButton;
|
||||
nsCOMPtr<Element> mSlider;
|
||||
nsCOMPtr<Element> mThumb;
|
||||
nsCOMPtr<Element> mUpBottomButton;
|
||||
nsCOMPtr<Element> mDownBottomButton;
|
||||
}; // class nsScrollbarFrame
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,13 +17,15 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=159346
|
|||
<![CDATA[
|
||||
|
||||
var scrollbar = document.getElementById("scrollbar");
|
||||
var downButton =
|
||||
document.getAnonymousElementByAttribute(scrollbar, "sbattr",
|
||||
"scrollbar-down-bottom");
|
||||
var downButton;
|
||||
|
||||
var domWinUtils = SpecialPowers.DOMWindowUtils;
|
||||
domWinUtils.loadSheetUsingURIString('data:text/css,@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); scrollbarbutton[type="increment"][sbattr="scrollbar-down-bottom"] { display: -moz-box; }', domWinUtils.AGENT_SHEET);
|
||||
|
||||
function init()
|
||||
{
|
||||
downButton.style.display = "-moz-box";
|
||||
downButton = SpecialPowers.unwrap(
|
||||
SpecialPowers.InspectorUtils.getChildrenForNode(scrollbar, true)[4]);
|
||||
SimpleTest.executeSoon(doTest1);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,12 +17,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=703150
|
|||
<![CDATA[
|
||||
|
||||
var scrollbar = document.getElementById("scrollbar");
|
||||
var scrollbarThumb =
|
||||
document.getAnonymousElementByAttribute(scrollbar, "sbattr",
|
||||
"scrollbar-thumb");
|
||||
var scrollbarThumb;
|
||||
|
||||
function doTest()
|
||||
{
|
||||
scrollbarThumb = SpecialPowers.unwrap(
|
||||
SpecialPowers.InspectorUtils.getChildrenForNode(scrollbar, true)[2]).childNodes[0];
|
||||
|
||||
function mousedownHandler(aEvent)
|
||||
{
|
||||
aEvent.stopPropagation();
|
||||
|
|