Skip to content
This repository has been archived by the owner on Jan 17, 2023. It is now read-only.

Commit

Permalink
Download only mode (#3655)
Browse files Browse the repository at this point in the history
* Fix #2818, use the private browsing download manager in private browsing mode

Thanks to https://bugzil.la/1362448, webextensions will use the correct
download manager, depending on the `incognito` state of the window.

* Fix #3274, Enable Screenshots in private browsing mode

Leave the l10n string in place, in case this decision is reversed

* Partial fix for #3574, create download only mode for private browsing
  • Loading branch information
jaredhirsch authored Oct 27, 2017
1 parent f7a5027 commit 1223743
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 43 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/Profile
.DS_Store
*.swp
*.swo
screenshots.xpi
*.pyc
dist
Expand Down
27 changes: 10 additions & 17 deletions addon/webextension/background/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,6 @@ 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 (tab.incognito) {
senderror.showError({
popupMessage: "PRIVATE_WINDOW"
});
return;
}
if (shouldOpenMyShots(tab.url)) {
if (!hasSeenOnboarding) {
catcher.watchPromise(analytics.refreshTelemetryPref().then(() => {
Expand Down Expand Up @@ -141,12 +135,6 @@ this.main = (function() {
// Not in a page/tab context, ignore
return;
}
if (tab.incognito) {
senderror.showError({
popupMessage: "PRIVATE_WINDOW"
});
return;
}
if (!urlEnabled(tab.url)) {
senderror.showError({
popupMessage: "UNSHOOTABLE_PAGE"
Expand Down Expand Up @@ -236,11 +224,16 @@ this.main = (function() {
}
});
browser.downloads.onChanged.addListener(onChangedCallback)
return browser.downloads.download({
url,
filename: info.filename
}).then((id) => {
downloadId = id;
return browser.windows.getLastFocused().then(windowInfo => {
return windowInfo.incognito;
}).then((incognito) => {
return browser.downloads.download({
url,
incognito,
filename: info.filename
}).then((id) => {
downloadId = id;
});
});
});

Expand Down
22 changes: 19 additions & 3 deletions addon/webextension/background/selectorLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,16 @@ this.selectorLoader = (function() {
let loadingTabs = new Set();

exports.loadModules = function(tabId, hasSeenOnboarding) {
let promise;
loadingTabs.add(tabId);
let promise = incognitoCheck(tabId);
if (hasSeenOnboarding) {
promise = executeModules(tabId, standardScripts.concat(selectorScripts));
promise = promise.then(() => {
return executeModules(tabId, standardScripts.concat(selectorScripts));
});
} else {
promise = executeModules(tabId, standardScripts.concat(onboardingScripts).concat(selectorScripts));
promise = promise.then(() => {
return executeModules(tabId, standardScripts.concat(onboardingScripts).concat(selectorScripts));
});
}
return promise.then((result) => {
loadingTabs.delete(tabId);
Expand All @@ -81,6 +85,18 @@ this.selectorLoader = (function() {
});
};

function incognitoCheck(tabId) {
return browser.tabs.get(tabId).then(tab => {
return browser.tabs.executeScript(tabId, {
// Note: `window` here refers to a global accessible to content
// scripts, but not the scripts in the underlying page. For more
// details, see https://mdn.io/WebExtensions/Content_scripts#Content_script_environment
code: `window.downloadOnly = ${tab.incognito}`,
runAt: "document_start"
});
});
}

function executeModules(tabId, scripts) {
let lastPromise = Promise.resolve(null);
scripts.forEach((file) => {
Expand Down
104 changes: 81 additions & 23 deletions addon/webextension/selector/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,21 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
return result;
}

function isDownloadOnly() {
return window.downloadOnly;
}

function renderDownloadNotice() {
let notice = makeEl("div", "download-only");
notice.innerHTML = `
<span data-l10n-id="downloadOnlyNotice"></span><span class="circle">?</span>
<div class="download-only-details">
<p data-l10n-id="downloadOnlyDetails">
<ul><li data-l10n-id="downloadOnlyDetailsPrivate">`;
localizeText(notice);
return notice;
}

function initializeIframe() {
let el = document.createElement("iframe");
el.src = browser.extension.getURL("blank.html");
Expand Down Expand Up @@ -264,8 +279,10 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
</div>
<div class="preview-instructions" data-l10n-id="screenshotInstructions"></div>
<div class="myshots-all-buttons-container">
<button class="myshots-button myshots-link" tabindex="1" data-l10n-id="myShotsLink"></button>
<div class="spacer"></div>
${isDownloadOnly() ? '' : `
<button class="myshots-button myshots-link" tabindex="1" data-l10n-id="myShotsLink"></button>
<div class="spacer"></div>
`}
<button class="myshots-button visible" tabindex="2" data-l10n-id="saveScreenshotVisibleArea"></button>
<button class="myshots-button full-page" tabindex="3" data-l10n-id="saveScreenshotFullPage"></button>
</div>
Expand All @@ -280,8 +297,10 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
this.document.documentElement.lang = browser.i18n.getMessage("@@ui_locale");
const overlay = this.document.querySelector(".preview-overlay");
localizeText(this.document);
overlay.querySelector(".myshots-button").addEventListener(
"click", watchFunction(assertIsTrusted(standardOverlayCallbacks.onOpenMyShots)));
if (!(isDownloadOnly())) {
overlay.querySelector(".myshots-button").addEventListener(
"click", watchFunction(assertIsTrusted(standardOverlayCallbacks.onOpenMyShots)));
}
overlay.querySelector(".visible").addEventListener(
"click", watchFunction(assertIsTrusted(standardOverlayCallbacks.onClickVisible)));
overlay.querySelector(".full-page").addEventListener(
Expand Down Expand Up @@ -362,8 +381,13 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
<div class="preview-image">
<div class="preview-buttons">
<button class="highlight-button-cancel"></button>
<button class="highlight-button-download"></button>
<button class="preview-button-save" data-l10n-id="saveScreenshotSelectedArea"></button>
${isDownloadOnly() ?
`<button class="highlight-button-download download-only-button"
data-l10n-id="downloadScreenshot"></button>` :
`<button class="highlight-button-download"></button>
<button class="preview-button-save"
data-l10n-id="saveScreenshotSelectedArea"></button>`
}
</div>
</div>
</div>
Expand All @@ -373,10 +397,14 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
this.document.documentElement.lang = browser.i18n.getMessage("@@ui_locale");
localizeText(this.document);
const overlay = this.document.querySelector(".preview-overlay");
if (isDownloadOnly()) {
overlay.appendChild(renderDownloadNotice());
} else {
overlay.querySelector(".preview-button-save").addEventListener(
"click", watchFunction(assertIsTrusted(standardOverlayCallbacks.onSavePreview)));
}
overlay.querySelector(".highlight-button-download").addEventListener(
"click", watchFunction(assertIsTrusted(standardOverlayCallbacks.onDownloadPreview)));
overlay.querySelector(".preview-button-save").addEventListener(
"click", watchFunction(assertIsTrusted(standardOverlayCallbacks.onSavePreview)));
overlay.querySelector(".highlight-button-cancel").addEventListener(
"click", watchFunction(assertIsTrusted(standardOverlayCallbacks.cancel)));
resolve();
Expand Down Expand Up @@ -479,7 +507,7 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
} else {
this.cancel.style.display = "none";
}
if (callbacks !== undefined && callbacks.save) {
if (callbacks !== undefined && callbacks.save && this.save) {
// We use onclick here because we don't want addEventListener
// to add multiple event handlers to the same button
this.save.removeAttribute("disabled");
Expand All @@ -488,7 +516,7 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
callbacks.save(e);
}));
this.save.style.display = "";
} else {
} else if (this.save) {
this.save.style.display = "none";
}
if (callbacks !== undefined && callbacks.download) {
Expand Down Expand Up @@ -551,21 +579,34 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
this.bgRight.style.left = (pos.right - bodyRect.left) + "px";
this.bgRight.style.width = "100%";

if (this.downloadNotice) {
this.downloadNotice.style.bottom = (docHeight - pageYOffset - winBottom + 10) + "px";
}

if (!(this.isElementInViewport(this.buttons))) {
this.cancel.style.position = this.download.style.position = this.save.style.position = "fixed";
this.cancel.style.position = this.download.style.position = "fixed";
this.cancel.style.left = (pos.left - bodyRect.left - 50) + "px";
this.download.style.left = ((pos.left - bodyRect.left - 100)) + "px";
this.save.style.left = ((pos.left - bodyRect.left) - 190) + "px";
this.cancel.style.top = this.download.style.top = this.save.style.top = (pos.top - bodyRect.top) + "px";
this.cancel.style.top = this.download.style.top = (pos.top - bodyRect.top) + "px";
if (this.save) {
this.save.style.position = "fixed";
this.save.style.left = ((pos.left - bodyRect.left) - 190) + "px";
this.save.style.top = (pos.top - bodyRect.top) + "px";
}
} else {
this.cancel.style.position = this.download.style.position = this.save.style.position = "initial";
this.cancel.style.top = this.download.style.top = this.save.style.top = 0;
this.cancel.style.left = this.download.style.left = this.save.style.left = 0;
this.cancel.style.position = this.download.style.position = "initial";
this.cancel.style.top = this.download.style.top = 0;
this.cancel.style.left = this.download.style.left = 0;
if (this.save) {
this.save.style.position = "initial";
this.save.style.top = 0;
this.save.style.left = 0;
}
}
},

remove() {
for (let name of ["el", "bgTop", "bgLeft", "bgRight", "bgBottom"]) {
for (let name of ["el", "bgTop", "bgLeft", "bgRight", "bgBottom", "downloadNotice"]) {
if (name in this) {
util.removeNode(this[name]);
this[name] = null;
Expand All @@ -583,13 +624,23 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
let cancel = makeEl("button", "highlight-button-cancel");
cancel.title = browser.i18n.getMessage("cancelScreenshot");
buttons.appendChild(cancel);
let download = makeEl("button", "highlight-button-download");
download.title = browser.i18n.getMessage("downloadScreenshot");
let download;
let save;
if (isDownloadOnly()) {
download = makeEl("button", "highlight-button-download download-only-button");
download.title = browser.i18n.getMessage("downloadScreenshot");
download.textContent = browser.i18n.getMessage("downloadScreenshot");
} else {
download = makeEl("button", "highlight-button-download");
download.title = browser.i18n.getMessage("downloadScreenshot");
save = makeEl("button", "highlight-button-save");
save.textContent = browser.i18n.getMessage("saveScreenshotSelectedArea");
save.title = browser.i18n.getMessage("saveScreenshotSelectedArea");
}
buttons.appendChild(download);
let save = makeEl("button", "highlight-button-save");
save.textContent = browser.i18n.getMessage("saveScreenshotSelectedArea");
save.title = browser.i18n.getMessage("saveScreenshotSelectedArea");
buttons.appendChild(save);
if (save) {
buttons.appendChild(save);
}
this.buttons = buttons;
this.cancel = cancel;
this.download = download;
Expand All @@ -610,6 +661,10 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
this.bgBottom = makeEl("div", "bghighlight");
iframe.document().body.appendChild(this.bgBottom);
iframe.document().body.appendChild(boxEl);
if (isDownloadOnly()) {
this.downloadNotice = renderDownloadNotice();
iframe.document().body.appendChild(this.downloadNotice);
}
this.el = boxEl;
},

Expand Down Expand Up @@ -695,6 +750,9 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
if (this.el) {
this.el.style.display = "none";
}
if (this.downloadNotice) {
this.downloadNotice.display = "none";
}
},

remove() {
Expand Down
8 changes: 8 additions & 0 deletions locales/en-US/webextension.properties
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ saveScreenshotVisibleArea = Save visible
saveScreenshotFullPage = Save full page
cancelScreenshot = Cancel
downloadScreenshot = Download
downloadOnlyNotice = You are currently in Download-Only mode.
# The downloadOnlyDetails string introduces a list of items. The keys
# downloadOnlyDetailsPrivate, downloadOnlyDetailsThirdParty, and
# downloadOnlyDetailsNeverRemember are list items in that list.
downloadOnlyDetails = Firefox Screenshots automatically changes to Download-Only mode in these situations:
downloadOnlyDetailsPrivate = In a Private Browsing window.
downloadOnlyDetailsThirdParty = Third-party cookies are disabled.
downloadOnlyDetailsNeverRemember = “Never remember history” is enabled.
notificationLinkCopiedTitle = Link Copied
# The string "{meta_key}-V" should be translated to the region-specific
# shorthand for the Paste keyboard shortcut. {meta_key} is a placeholder for the
Expand Down
74 changes: 74 additions & 0 deletions static/css/inline-selection.scss
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,74 @@ $very-light-grey: #ededed;
}
}

.download-only {
position:absolute;
z-index: $overlay-z-index + 1;
bottom: 10px;

/* horizontal centering */
left: 50%;
transform: translate(-50%, 0);

padding: 10px 15px;
border-radius: 100px;
background: #737373;
font-family: -apple-system, BlinkMacSystemFont, "segoe ui", "helvetica neue", helvetica, ubuntu, roboto, noto, arial, sans-serif;
font-weight: bold;
color: #fff;
font-size: 14px;
line-height: 26px;
white-space: nowrap;
user-select: none;
}

.circle {
display: inline-table;
border: 1px solid #f9f9fa;
border-radius: 50%;
padding: 1px 9px;
margin-left: 10px;
margin-right: -10px;
cursor: default;
}

.download-only-details {
z-index: $overlay-z-index + 1;
display: none;
width: 400px;
position: absolute;
bottom: 72px;
right: -50px;
background: #fff;
border: 1px solid #9d9d9e;
border-radius: 3px;
padding: 0 20px;
font-family: -apple-system, BlinkMacSystemFont, "segoe ui", "helvetica neue", helvetica, ubuntu, roboto, noto, arial, sans-serif;
font-weight: normal;
font-size: 16px;
line-height: 24px;
white-space: normal;
color: #000;
cursor: default;

.download-only:hover & {
display: block;
}

/* down-arrow for the tooltip */
&::after {
content: "";
position: absolute;
height: 0;
width: 0;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid #f9f9fa;
top: 100%;
left: 80%;
}
}

.preview-overlay {
align-items: center;
background-color: $modal-color;
Expand Down Expand Up @@ -291,6 +359,12 @@ $very-light-grey: #ededed;
display: block;
margin: 5px;
width: 40px;

&.download-only-button {
width: auto;
background-position: 7px;
padding-left: 32px;
}
}

.pixel-dimensions {
Expand Down

0 comments on commit 1223743

Please sign in to comment.