Merge mozilla-central to inbound. a=merge CLOSED TREE

This commit is contained in:
Gurzau Raul 2018-04-25 12:38:44 +03:00
Родитель 7e27ba83c3 faeb9b7ddd
Коммит d4fd165bfc
144 изменённых файлов: 5714 добавлений и 3437 удалений

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

@ -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) {

2
browser/extensions/screenshots/bootstrap.js поставляемый
Просмотреть файл

@ -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, dhfhaoidte 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 dhaithghearr."
},
"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 webe 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 webe 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();

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