mirror of
https://github.com/bitwarden/browser.git
synced 2025-02-22 02:21:34 +01:00
[fix] Force send attachment to always download and never open (#2908)
* [refactor] Introduce a file download service * [refactor] Point platformUtilsService.saveFile() callers to fileDownloadService.download() instead * [refactor] Remove platformUtilsService.saveFile() * [fix] Force send attachments to always download and never open * [fix] Remove the window property from FileDownloadRequest * [fix] Move FileDownloadRequest to /abstractions/fileDownload * [fix] Simplify FileDownloadRequest to a type * [fix] Move BrowserApi.saveFile logic into BrowserFileDownloadService * [fix] Use proper blob types for file downloads * [fix] forceDownload -> downloadMethod on FileDownloadRequest * [fix] Remove fileType from FileDownloadRequest * [fix] Make fileType private
This commit is contained in:
parent
a89b745f0b
commit
bb7dce031c
@ -1,7 +1,3 @@
|
||||
import { Utils } from "@bitwarden/common/misc/utils";
|
||||
|
||||
import { SafariApp } from "./safariApp";
|
||||
|
||||
export class BrowserApi {
|
||||
static isWebExtensionsApi: boolean = typeof browser !== "undefined";
|
||||
static isSafariApi: boolean =
|
||||
@ -150,39 +146,6 @@ export class BrowserApi {
|
||||
}
|
||||
}
|
||||
|
||||
static downloadFile(win: Window, blobData: any, blobOptions: any, fileName: string) {
|
||||
if (BrowserApi.isSafariApi) {
|
||||
const type = blobOptions != null ? blobOptions.type : null;
|
||||
let data: string = null;
|
||||
if (type === "text/plain" && typeof blobData === "string") {
|
||||
data = blobData;
|
||||
} else {
|
||||
data = Utils.fromBufferToB64(blobData);
|
||||
}
|
||||
SafariApp.sendMessageToApp(
|
||||
"downloadFile",
|
||||
JSON.stringify({
|
||||
blobData: data,
|
||||
blobOptions: blobOptions,
|
||||
fileName: fileName,
|
||||
}),
|
||||
true
|
||||
);
|
||||
} else {
|
||||
const blob = new Blob([blobData], blobOptions);
|
||||
if (navigator.msSaveOrOpenBlob) {
|
||||
navigator.msSaveBlob(blob, fileName);
|
||||
} else {
|
||||
const a = win.document.createElement("a");
|
||||
a.href = URL.createObjectURL(blob);
|
||||
a.download = fileName;
|
||||
win.document.body.appendChild(a);
|
||||
a.click();
|
||||
win.document.body.removeChild(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gaFilter() {
|
||||
return process.env.ENV !== "production";
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import { CryptoFunctionService } from "@bitwarden/common/abstractions/cryptoFunc
|
||||
import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service";
|
||||
import { EventService } from "@bitwarden/common/abstractions/event.service";
|
||||
import { ExportService } from "@bitwarden/common/abstractions/export.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { FileUploadService } from "@bitwarden/common/abstractions/fileUpload.service";
|
||||
import { FolderService } from "@bitwarden/common/abstractions/folder.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
@ -51,6 +52,7 @@ import MainBackground from "../../background/main.background";
|
||||
import { BrowserApi } from "../../browser/browserApi";
|
||||
import { AutofillService } from "../../services/abstractions/autofill.service";
|
||||
import { StateService as StateServiceAbstraction } from "../../services/abstractions/state.service";
|
||||
import { BrowserFileDownloadService } from "../../services/browserFileDownloadService";
|
||||
import BrowserMessagingService from "../../services/browserMessaging.service";
|
||||
import BrowserMessagingPrivateModePopupService from "../../services/browserMessagingPrivateModePopup.service";
|
||||
import { VaultFilterService } from "../../services/vaultFilter.service";
|
||||
@ -272,6 +274,10 @@ function getBgService<T>(service: keyof MainBackground) {
|
||||
useExisting: StateServiceAbstraction,
|
||||
deps: [],
|
||||
},
|
||||
{
|
||||
provide: FileDownloadService,
|
||||
useClass: BrowserFileDownloadService,
|
||||
},
|
||||
],
|
||||
})
|
||||
export class ServicesModule {}
|
||||
|
@ -6,6 +6,7 @@ import { ExportComponent as BaseExportComponent } from "@bitwarden/angular/compo
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { EventService } from "@bitwarden/common/abstractions/event.service";
|
||||
import { ExportService } from "@bitwarden/common/abstractions/export.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
@ -27,7 +28,8 @@ export class ExportComponent extends BaseExportComponent {
|
||||
private router: Router,
|
||||
logService: LogService,
|
||||
userVerificationService: UserVerificationService,
|
||||
formBuilder: FormBuilder
|
||||
formBuilder: FormBuilder,
|
||||
fileDownloadService: FileDownloadService
|
||||
) {
|
||||
super(
|
||||
cryptoService,
|
||||
@ -39,7 +41,8 @@ export class ExportComponent extends BaseExportComponent {
|
||||
window,
|
||||
logService,
|
||||
userVerificationService,
|
||||
formBuilder
|
||||
formBuilder,
|
||||
fileDownloadService
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ import { AttachmentsComponent as BaseAttachmentsComponent } from "@bitwarden/ang
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
@ -28,7 +29,8 @@ export class AttachmentsComponent extends BaseAttachmentsComponent {
|
||||
private location: Location,
|
||||
private route: ActivatedRoute,
|
||||
stateService: StateService,
|
||||
logService: LogService
|
||||
logService: LogService,
|
||||
fileDownloadService: FileDownloadService
|
||||
) {
|
||||
super(
|
||||
cipherService,
|
||||
@ -38,7 +40,8 @@ export class AttachmentsComponent extends BaseAttachmentsComponent {
|
||||
apiService,
|
||||
window,
|
||||
logService,
|
||||
stateService
|
||||
stateService,
|
||||
fileDownloadService
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.s
|
||||
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { EventService } from "@bitwarden/common/abstractions/event.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||
@ -61,7 +62,8 @@ export class ViewComponent extends BaseViewComponent {
|
||||
private popupUtilsService: PopupUtilsService,
|
||||
apiService: ApiService,
|
||||
passwordRepromptService: PasswordRepromptService,
|
||||
logService: LogService
|
||||
logService: LogService,
|
||||
fileDownloadService: FileDownloadService
|
||||
) {
|
||||
super(
|
||||
cipherService,
|
||||
@ -79,7 +81,8 @@ export class ViewComponent extends BaseViewComponent {
|
||||
apiService,
|
||||
passwordRepromptService,
|
||||
logService,
|
||||
stateService
|
||||
stateService,
|
||||
fileDownloadService
|
||||
);
|
||||
}
|
||||
|
||||
|
46
apps/browser/src/services/browserFileDownloadService.ts
Normal file
46
apps/browser/src/services/browserFileDownloadService.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { FileDownloadBuilder } from "@bitwarden/common/abstractions/fileDownload/fileDownloadBuilder";
|
||||
import { FileDownloadRequest } from "@bitwarden/common/abstractions/fileDownload/fileDownloadRequest";
|
||||
import { Utils } from "@bitwarden/common/misc/utils";
|
||||
|
||||
import { BrowserApi } from "../browser/browserApi";
|
||||
import { SafariApp } from "../browser/safariApp";
|
||||
|
||||
@Injectable()
|
||||
export class BrowserFileDownloadService implements FileDownloadService {
|
||||
download(request: FileDownloadRequest): void {
|
||||
const builder = new FileDownloadBuilder(request);
|
||||
if (BrowserApi.isSafariApi) {
|
||||
let data: BlobPart = null;
|
||||
if (builder.blobOptions.type === "text/plain" && typeof request.blobData === "string") {
|
||||
data = request.blobData;
|
||||
} else {
|
||||
builder.blob.arrayBuffer().then((buf) => {
|
||||
data = Utils.fromBufferToB64(buf);
|
||||
});
|
||||
}
|
||||
SafariApp.sendMessageToApp(
|
||||
"downloadFile",
|
||||
JSON.stringify({
|
||||
blobData: data,
|
||||
blobOptions: request.blobOptions,
|
||||
fileName: request.fileName,
|
||||
}),
|
||||
true
|
||||
);
|
||||
} else {
|
||||
if (navigator.msSaveOrOpenBlob) {
|
||||
navigator.msSaveBlob(builder.blob, request.fileName);
|
||||
} else {
|
||||
const a = window.document.createElement("a");
|
||||
a.href = URL.createObjectURL(builder.blob);
|
||||
a.download = request.fileName;
|
||||
window.document.body.appendChild(a);
|
||||
a.click();
|
||||
window.document.body.removeChild(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -122,10 +122,6 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
|
||||
BrowserApi.createNewTab(uri, options && options.extensionPage === true);
|
||||
}
|
||||
|
||||
saveFile(win: Window, blobData: any, blobOptions: any, fileName: string): void {
|
||||
BrowserApi.downloadFile(win, blobData, blobOptions, fileName);
|
||||
}
|
||||
|
||||
getApplicationVersion(): Promise<string> {
|
||||
return Promise.resolve(BrowserApi.getApplicationVersion());
|
||||
}
|
||||
|
18
apps/desktop/src/app/services/desktopFileDownloadService.ts
Normal file
18
apps/desktop/src/app/services/desktopFileDownloadService.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { FileDownloadBuilder } from "@bitwarden/common/abstractions/fileDownload/fileDownloadBuilder";
|
||||
import { FileDownloadRequest } from "@bitwarden/common/abstractions/fileDownload/fileDownloadRequest";
|
||||
|
||||
@Injectable()
|
||||
export class DesktopFileDownloadService implements FileDownloadService {
|
||||
download(request: FileDownloadRequest): void {
|
||||
const a = window.document.createElement("a");
|
||||
a.href = URL.createObjectURL(new FileDownloadBuilder(request).blob);
|
||||
a.download = request.fileName;
|
||||
a.style.position = "fixed";
|
||||
window.document.body.appendChild(a);
|
||||
a.click();
|
||||
window.document.body.removeChild(a);
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ import { AbstractEncryptService } from "@bitwarden/common/abstractions/abstractE
|
||||
import { BroadcasterService as BroadcasterServiceAbstraction } from "@bitwarden/common/abstractions/broadcaster.service";
|
||||
import { CryptoService as CryptoServiceAbstraction } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/abstractions/cryptoFunction.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import {
|
||||
LogService,
|
||||
@ -48,6 +49,7 @@ import { LoginGuard } from "../guards/login.guard";
|
||||
import { SearchBarService } from "../layout/search/search-bar.service";
|
||||
|
||||
import { DesktopThemingService } from "./desktop-theming.service";
|
||||
import { DesktopFileDownloadService } from "./desktopFileDownloadService";
|
||||
import { InitService } from "./init.service";
|
||||
|
||||
const RELOAD_CALLBACK = new InjectionToken<() => any>("RELOAD_CALLBACK");
|
||||
@ -137,6 +139,10 @@ const RELOAD_CALLBACK = new InjectionToken<() => any>("RELOAD_CALLBACK");
|
||||
STATE_SERVICE_USE_CACHE,
|
||||
],
|
||||
},
|
||||
{
|
||||
provide: FileDownloadService,
|
||||
useClass: DesktopFileDownloadService,
|
||||
},
|
||||
{
|
||||
provide: AbstractThemingService,
|
||||
useClass: DesktopThemingService,
|
||||
|
@ -4,6 +4,7 @@ import { AttachmentsComponent as BaseAttachmentsComponent } from "@bitwarden/ang
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
@ -21,7 +22,8 @@ export class AttachmentsComponent extends BaseAttachmentsComponent {
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
apiService: ApiService,
|
||||
logService: LogService,
|
||||
stateService: StateService
|
||||
stateService: StateService,
|
||||
fileDownloadService: FileDownloadService
|
||||
) {
|
||||
super(
|
||||
cipherService,
|
||||
@ -31,7 +33,8 @@ export class AttachmentsComponent extends BaseAttachmentsComponent {
|
||||
apiService,
|
||||
window,
|
||||
logService,
|
||||
stateService
|
||||
stateService,
|
||||
fileDownloadService
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.s
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { EventService } from "@bitwarden/common/abstractions/event.service";
|
||||
import { ExportService } from "@bitwarden/common/abstractions/export.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
@ -31,7 +32,8 @@ export class ExportComponent extends BaseExportComponent implements OnInit {
|
||||
userVerificationService: UserVerificationService,
|
||||
formBuilder: FormBuilder,
|
||||
private broadcasterService: BroadcasterService,
|
||||
logService: LogService
|
||||
logService: LogService,
|
||||
fileDownloadService: FileDownloadService
|
||||
) {
|
||||
super(
|
||||
cryptoService,
|
||||
@ -43,7 +45,8 @@ export class ExportComponent extends BaseExportComponent implements OnInit {
|
||||
window,
|
||||
logService,
|
||||
userVerificationService,
|
||||
formBuilder
|
||||
formBuilder,
|
||||
fileDownloadService
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.s
|
||||
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { EventService } from "@bitwarden/common/abstractions/event.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||
@ -49,7 +50,8 @@ export class ViewComponent extends BaseViewComponent implements OnChanges {
|
||||
private messagingService: MessagingService,
|
||||
passwordRepromptService: PasswordRepromptService,
|
||||
logService: LogService,
|
||||
stateService: StateService
|
||||
stateService: StateService,
|
||||
fileDownloadService: FileDownloadService
|
||||
) {
|
||||
super(
|
||||
cipherService,
|
||||
@ -67,7 +69,8 @@ export class ViewComponent extends BaseViewComponent implements OnChanges {
|
||||
apiService,
|
||||
passwordRepromptService,
|
||||
logService,
|
||||
stateService
|
||||
stateService,
|
||||
fileDownloadService
|
||||
);
|
||||
}
|
||||
ngOnInit() {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Directive } from "@angular/core";
|
||||
|
||||
import { ExportService } from "@bitwarden/common/abstractions/export.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
@ -30,7 +31,8 @@ export abstract class BaseEventsComponent {
|
||||
protected i18nService: I18nService,
|
||||
protected exportService: ExportService,
|
||||
protected platformUtilsService: PlatformUtilsService,
|
||||
protected logService: LogService
|
||||
protected logService: LogService,
|
||||
protected fileDownloadService: FileDownloadService
|
||||
) {
|
||||
const defaultDates = this.eventService.getDefaultDateFilters();
|
||||
this.start = defaultDates[0];
|
||||
@ -173,6 +175,10 @@ export abstract class BaseEventsComponent {
|
||||
|
||||
const data = await this.exportService.getEventExport(events);
|
||||
const fileName = this.exportService.getFileName(this.exportFileName, "csv");
|
||||
this.platformUtilsService.saveFile(window, data, { type: "text/plain" }, fileName);
|
||||
this.fileDownloadService.download({
|
||||
fileName,
|
||||
blobData: data,
|
||||
blobOptions: { type: "text/plain" },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { ExportService } from "@bitwarden/common/abstractions/export.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
||||
@ -37,9 +38,17 @@ export class EventsComponent extends BaseEventsComponent implements OnInit {
|
||||
logService: LogService,
|
||||
private userNamePipe: UserNamePipe,
|
||||
private organizationService: OrganizationService,
|
||||
private providerService: ProviderService
|
||||
private providerService: ProviderService,
|
||||
fileDownloadService: FileDownloadService
|
||||
) {
|
||||
super(eventService, i18nService, exportService, platformUtilsService, logService);
|
||||
super(
|
||||
eventService,
|
||||
i18nService,
|
||||
exportService,
|
||||
platformUtilsService,
|
||||
logService,
|
||||
fileDownloadService
|
||||
);
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
|
||||
@Component({
|
||||
selector: "app-download-license",
|
||||
@ -18,7 +18,7 @@ export class DownloadLicenseComponent {
|
||||
|
||||
constructor(
|
||||
private apiService: ApiService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private fileDownloadService: FileDownloadService,
|
||||
private logService: LogService
|
||||
) {}
|
||||
|
||||
@ -34,12 +34,10 @@ export class DownloadLicenseComponent {
|
||||
);
|
||||
const license = await this.formPromise;
|
||||
const licenseString = JSON.stringify(license, null, 2);
|
||||
this.platformUtilsService.saveFile(
|
||||
window,
|
||||
licenseString,
|
||||
null,
|
||||
"bitwarden_organization_license.json"
|
||||
);
|
||||
this.fileDownloadService.download({
|
||||
fileName: "bitwarden_organization_license.json",
|
||||
blobData: licenseString,
|
||||
});
|
||||
this.onDownloaded.emit();
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
|
@ -5,6 +5,7 @@ import { ActivatedRoute } from "@angular/router";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { EventService } from "@bitwarden/common/abstractions/event.service";
|
||||
import { ExportService } from "@bitwarden/common/abstractions/export.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
@ -28,7 +29,8 @@ export class OrganizationExportComponent extends ExportComponent {
|
||||
policyService: PolicyService,
|
||||
logService: LogService,
|
||||
userVerificationService: UserVerificationService,
|
||||
formBuilder: FormBuilder
|
||||
formBuilder: FormBuilder,
|
||||
fileDownloadService: FileDownloadService
|
||||
) {
|
||||
super(
|
||||
cryptoService,
|
||||
@ -39,7 +41,8 @@ export class OrganizationExportComponent extends ExportComponent {
|
||||
policyService,
|
||||
logService,
|
||||
userVerificationService,
|
||||
formBuilder
|
||||
formBuilder,
|
||||
fileDownloadService
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ import { Component } from "@angular/core";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
@ -29,7 +30,8 @@ export class AttachmentsComponent extends BaseAttachmentsComponent {
|
||||
stateService: StateService,
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
apiService: ApiService,
|
||||
logService: LogService
|
||||
logService: LogService,
|
||||
fileDownloadService: FileDownloadService
|
||||
) {
|
||||
super(
|
||||
cipherService,
|
||||
@ -38,7 +40,8 @@ export class AttachmentsComponent extends BaseAttachmentsComponent {
|
||||
stateService,
|
||||
platformUtilsService,
|
||||
apiService,
|
||||
logService
|
||||
logService,
|
||||
fileDownloadService
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ import { ActivatedRoute } from "@angular/router";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { CryptoFunctionService } from "@bitwarden/common/abstractions/cryptoFunction.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
import { SEND_KDF_ITERATIONS } from "@bitwarden/common/enums/kdfType";
|
||||
@ -44,7 +45,8 @@ export class AccessComponent implements OnInit {
|
||||
private apiService: ApiService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private route: ActivatedRoute,
|
||||
private cryptoService: CryptoService
|
||||
private cryptoService: CryptoService,
|
||||
private fileDownloadService: FileDownloadService
|
||||
) {}
|
||||
|
||||
get sendText() {
|
||||
@ -109,7 +111,11 @@ export class AccessComponent implements OnInit {
|
||||
try {
|
||||
const buf = await response.arrayBuffer();
|
||||
const decBuf = await this.cryptoService.decryptFromBytes(buf, this.decKey);
|
||||
this.platformUtilsService.saveFile(window, decBuf, null, this.send.file.fileName);
|
||||
this.fileDownloadService.download({
|
||||
fileName: this.send.file.fileName,
|
||||
blobData: decBuf,
|
||||
downloadMethod: "save",
|
||||
});
|
||||
} catch (e) {
|
||||
this.platformUtilsService.showToast("error", null, this.i18nService.t("errorOccurred"));
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import {
|
||||
MEMORY_STORAGE,
|
||||
} from "@bitwarden/angular/services/jslib-services.module";
|
||||
import { ModalService as ModalServiceAbstraction } from "@bitwarden/angular/services/modal.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { MessagingService as MessagingServiceAbstraction } from "@bitwarden/common/abstractions/messaging.service";
|
||||
@ -41,6 +42,7 @@ import { InitService } from "./init.service";
|
||||
import { ModalService } from "./modal.service";
|
||||
import { PolicyListService } from "./policy-list.service";
|
||||
import { RouterService } from "./router.service";
|
||||
import { WebFileDownloadService } from "./webFileDownload.service";
|
||||
|
||||
@NgModule({
|
||||
imports: [ToastrModule, JslibServicesModule],
|
||||
@ -114,6 +116,10 @@ import { RouterService } from "./router.service";
|
||||
provide: PasswordRepromptServiceAbstraction,
|
||||
useClass: PasswordRepromptService,
|
||||
},
|
||||
{
|
||||
provide: FileDownloadService,
|
||||
useClass: WebFileDownloadService,
|
||||
},
|
||||
HomeGuard,
|
||||
],
|
||||
})
|
||||
|
26
apps/web/src/app/services/webFileDownload.service.ts
Normal file
26
apps/web/src/app/services/webFileDownload.service.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { FileDownloadBuilder } from "@bitwarden/common/abstractions/fileDownload/fileDownloadBuilder";
|
||||
import { FileDownloadRequest } from "@bitwarden/common/abstractions/fileDownload/fileDownloadRequest";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
|
||||
@Injectable()
|
||||
export class WebFileDownloadService implements FileDownloadService {
|
||||
constructor(private platformUtilsService: PlatformUtilsService) {}
|
||||
|
||||
download(request: FileDownloadRequest): void {
|
||||
const builder = new FileDownloadBuilder(request);
|
||||
const a = window.document.createElement("a");
|
||||
if (builder.downloadMethod === "save") {
|
||||
a.download = request.fileName;
|
||||
} else if (!this.platformUtilsService.isSafari()) {
|
||||
a.target = "_blank";
|
||||
}
|
||||
a.href = URL.createObjectURL(builder.blob);
|
||||
a.style.position = "fixed";
|
||||
window.document.body.appendChild(a);
|
||||
a.click();
|
||||
window.document.body.removeChild(a);
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ import { AttachmentsComponent as BaseAttachmentsComponent } from "@bitwarden/ang
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
@ -25,7 +26,8 @@ export class EmergencyAccessAttachmentsComponent extends BaseAttachmentsComponen
|
||||
stateService: StateService,
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
apiService: ApiService,
|
||||
logService: LogService
|
||||
logService: LogService,
|
||||
fileDownloadService: FileDownloadService
|
||||
) {
|
||||
super(
|
||||
cipherService,
|
||||
@ -35,7 +37,8 @@ export class EmergencyAccessAttachmentsComponent extends BaseAttachmentsComponen
|
||||
apiService,
|
||||
window,
|
||||
logService,
|
||||
stateService
|
||||
stateService,
|
||||
fileDownloadService
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ import { Component, OnInit } from "@angular/core";
|
||||
import { Router } from "@angular/router";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
@ -30,7 +31,8 @@ export class UserSubscriptionComponent implements OnInit {
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService,
|
||||
private router: Router,
|
||||
private logService: LogService
|
||||
private logService: LogService,
|
||||
private fileDownloadService: FileDownloadService
|
||||
) {
|
||||
this.selfHosted = platformUtilsService.isSelfHost();
|
||||
}
|
||||
@ -139,12 +141,10 @@ export class UserSubscriptionComponent implements OnInit {
|
||||
}
|
||||
|
||||
const licenseString = JSON.stringify(this.sub.license, null, 2);
|
||||
this.platformUtilsService.saveFile(
|
||||
window,
|
||||
licenseString,
|
||||
null,
|
||||
"bitwarden_premium_license.json"
|
||||
);
|
||||
this.fileDownloadService.download({
|
||||
fileName: "bitwarden_premium_license.json",
|
||||
blobData: licenseString,
|
||||
});
|
||||
}
|
||||
|
||||
updateLicense() {
|
||||
|
@ -5,6 +5,7 @@ import { ExportComponent as BaseExportComponent } from "@bitwarden/angular/compo
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { EventService } from "@bitwarden/common/abstractions/event.service";
|
||||
import { ExportService } from "@bitwarden/common/abstractions/export.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
@ -27,7 +28,8 @@ export class ExportComponent extends BaseExportComponent {
|
||||
policyService: PolicyService,
|
||||
logService: LogService,
|
||||
userVerificationService: UserVerificationService,
|
||||
formBuilder: FormBuilder
|
||||
formBuilder: FormBuilder,
|
||||
fileDownloadService: FileDownloadService
|
||||
) {
|
||||
super(
|
||||
cryptoService,
|
||||
@ -39,7 +41,8 @@ export class ExportComponent extends BaseExportComponent {
|
||||
window,
|
||||
logService,
|
||||
userVerificationService,
|
||||
formBuilder
|
||||
formBuilder,
|
||||
fileDownloadService
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ import { AttachmentsComponent as BaseAttachmentsComponent } from "@bitwarden/ang
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
@ -24,7 +25,8 @@ export class AttachmentsComponent extends BaseAttachmentsComponent {
|
||||
stateService: StateService,
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
apiService: ApiService,
|
||||
logService: LogService
|
||||
logService: LogService,
|
||||
fileDownloadService: FileDownloadService
|
||||
) {
|
||||
super(
|
||||
cipherService,
|
||||
@ -34,7 +36,8 @@ export class AttachmentsComponent extends BaseAttachmentsComponent {
|
||||
apiService,
|
||||
window,
|
||||
logService,
|
||||
stateService
|
||||
stateService,
|
||||
fileDownloadService
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -104,54 +104,6 @@ export class WebPlatformUtilsService implements PlatformUtilsService {
|
||||
document.body.removeChild(a);
|
||||
}
|
||||
|
||||
saveFile(win: Window, blobData: any, blobOptions: any, fileName: string): void {
|
||||
let blob: Blob = null;
|
||||
let type: string = null;
|
||||
const fileNameLower = fileName.toLowerCase();
|
||||
let doDownload = true;
|
||||
if (fileNameLower.endsWith(".pdf")) {
|
||||
type = "application/pdf";
|
||||
doDownload = false;
|
||||
} else if (fileNameLower.endsWith(".xlsx")) {
|
||||
type = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
||||
} else if (fileNameLower.endsWith(".docx")) {
|
||||
type = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
||||
} else if (fileNameLower.endsWith(".pptx")) {
|
||||
type = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
|
||||
} else if (fileNameLower.endsWith(".csv")) {
|
||||
type = "text/csv";
|
||||
} else if (fileNameLower.endsWith(".png")) {
|
||||
type = "image/png";
|
||||
} else if (fileNameLower.endsWith(".jpg") || fileNameLower.endsWith(".jpeg")) {
|
||||
type = "image/jpeg";
|
||||
} else if (fileNameLower.endsWith(".gif")) {
|
||||
type = "image/gif";
|
||||
}
|
||||
if (type != null) {
|
||||
blobOptions = blobOptions || {};
|
||||
if (blobOptions.type == null) {
|
||||
blobOptions.type = type;
|
||||
}
|
||||
}
|
||||
if (blobOptions != null) {
|
||||
blob = new Blob([blobData], blobOptions);
|
||||
} else {
|
||||
blob = new Blob([blobData]);
|
||||
}
|
||||
|
||||
const a = win.document.createElement("a");
|
||||
if (doDownload) {
|
||||
a.download = fileName;
|
||||
} else if (!this.isSafari()) {
|
||||
a.target = "_blank";
|
||||
}
|
||||
a.href = URL.createObjectURL(blob);
|
||||
a.style.position = "fixed";
|
||||
win.document.body.appendChild(a);
|
||||
a.click();
|
||||
win.document.body.removeChild(a);
|
||||
}
|
||||
|
||||
getApplicationVersion(): Promise<string> {
|
||||
return Promise.resolve(process.env.APPLICATION_VERSION || "-");
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { ExportService } from "@bitwarden/common/abstractions/export.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
@ -34,9 +35,17 @@ export class EventsComponent extends BaseEventsComponent implements OnInit {
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
private router: Router,
|
||||
logService: LogService,
|
||||
private userNamePipe: UserNamePipe
|
||||
private userNamePipe: UserNamePipe,
|
||||
fileDownloadService: FileDownloadService
|
||||
) {
|
||||
super(eventService, i18nService, exportService, platformUtilsService, logService);
|
||||
super(
|
||||
eventService,
|
||||
i18nService,
|
||||
exportService,
|
||||
platformUtilsService,
|
||||
logService,
|
||||
fileDownloadService
|
||||
);
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
|
@ -3,6 +3,7 @@ import { Directive, EventEmitter, Input, OnInit, Output } from "@angular/core";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
@ -36,7 +37,8 @@ export class AttachmentsComponent implements OnInit {
|
||||
protected apiService: ApiService,
|
||||
protected win: Window,
|
||||
protected logService: LogService,
|
||||
protected stateService: StateService
|
||||
protected stateService: StateService,
|
||||
protected fileDownloadService: FileDownloadService
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@ -171,7 +173,10 @@ export class AttachmentsComponent implements OnInit {
|
||||
? attachment.key
|
||||
: await this.cryptoService.getOrgKey(this.cipher.organizationId);
|
||||
const decBuf = await this.cryptoService.decryptFromBytes(buf, key);
|
||||
this.platformUtilsService.saveFile(this.win, decBuf, null, attachment.fileName);
|
||||
this.fileDownloadService.download({
|
||||
fileName: attachment.fileName,
|
||||
blobData: decBuf,
|
||||
});
|
||||
} catch (e) {
|
||||
this.platformUtilsService.showToast("error", null, this.i18nService.t("errorOccurred"));
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import { FormBuilder } from "@angular/forms";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { EventService } from "@bitwarden/common/abstractions/event.service";
|
||||
import { ExportService } from "@bitwarden/common/abstractions/export.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
@ -40,7 +41,8 @@ export class ExportComponent implements OnInit {
|
||||
protected win: Window,
|
||||
private logService: LogService,
|
||||
private userVerificationService: UserVerificationService,
|
||||
private formBuilder: FormBuilder
|
||||
private formBuilder: FormBuilder,
|
||||
protected fileDownloadService: FileDownloadService
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@ -150,6 +152,10 @@ export class ExportComponent implements OnInit {
|
||||
|
||||
private downloadFile(csv: string): void {
|
||||
const fileName = this.getFileName();
|
||||
this.platformUtilsService.saveFile(this.win, csv, { type: "text/plain" }, fileName);
|
||||
this.fileDownloadService.download({
|
||||
fileName: fileName,
|
||||
blobData: csv,
|
||||
blobOptions: { type: "text/plain" },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.s
|
||||
import { CipherService } from "@bitwarden/common/abstractions/cipher.service";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { EventService } from "@bitwarden/common/abstractions/event.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { PasswordRepromptService } from "@bitwarden/common/abstractions/passwordReprompt.service";
|
||||
@ -76,7 +77,8 @@ export class ViewComponent implements OnDestroy, OnInit {
|
||||
protected apiService: ApiService,
|
||||
protected passwordRepromptService: PasswordRepromptService,
|
||||
private logService: LogService,
|
||||
protected stateService: StateService
|
||||
protected stateService: StateService,
|
||||
protected fileDownloadService: FileDownloadService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
@ -373,7 +375,10 @@ export class ViewComponent implements OnDestroy, OnInit {
|
||||
? attachment.key
|
||||
: await this.cryptoService.getOrgKey(this.cipher.organizationId);
|
||||
const decBuf = await this.cryptoService.decryptFromBytes(buf, key);
|
||||
this.platformUtilsService.saveFile(this.win, decBuf, null, attachment.fileName);
|
||||
this.fileDownloadService.download({
|
||||
fileName: attachment.fileName,
|
||||
blobData: decBuf,
|
||||
});
|
||||
} catch (e) {
|
||||
this.platformUtilsService.showToast("error", null, this.i18nService.t("errorOccurred"));
|
||||
}
|
||||
|
@ -0,0 +1,5 @@
|
||||
import { FileDownloadRequest } from "./fileDownloadRequest";
|
||||
|
||||
export abstract class FileDownloadService {
|
||||
download: (request: FileDownloadRequest) => void;
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
import { FileDownloadRequest } from "./fileDownloadRequest";
|
||||
|
||||
export class FileDownloadBuilder {
|
||||
get blobOptions(): any {
|
||||
const options = this._request.blobOptions ?? {};
|
||||
if (options.type == null) {
|
||||
options.type = this.fileType;
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
get blob(): Blob {
|
||||
if (this.blobOptions != null) {
|
||||
return new Blob([this._request.blobData], this.blobOptions);
|
||||
} else {
|
||||
return new Blob([this._request.blobData]);
|
||||
}
|
||||
}
|
||||
|
||||
get downloadMethod(): "save" | "open" {
|
||||
if (this._request.downloadMethod != null) {
|
||||
return this._request.downloadMethod;
|
||||
}
|
||||
return this.fileType != "application/pdf" ? "save" : "open";
|
||||
}
|
||||
|
||||
private get fileType() {
|
||||
const fileNameLower = this._request.fileName.toLowerCase();
|
||||
if (fileNameLower.endsWith(".pdf")) {
|
||||
return "application/pdf";
|
||||
} else if (fileNameLower.endsWith(".xlsx")) {
|
||||
return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
||||
} else if (fileNameLower.endsWith(".docx")) {
|
||||
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
||||
} else if (fileNameLower.endsWith(".pptx")) {
|
||||
return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
|
||||
} else if (fileNameLower.endsWith(".csv")) {
|
||||
return "text/csv";
|
||||
} else if (fileNameLower.endsWith(".png")) {
|
||||
return "image/png";
|
||||
} else if (fileNameLower.endsWith(".jpg") || fileNameLower.endsWith(".jpeg")) {
|
||||
return "image/jpeg";
|
||||
} else if (fileNameLower.endsWith(".gif")) {
|
||||
return "image/gif";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
constructor(private readonly _request: FileDownloadRequest) {}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
export type FileDownloadRequest = {
|
||||
fileName: string;
|
||||
blobData: BlobPart;
|
||||
blobOptions?: BlobPropertyBag;
|
||||
downloadMethod?: "save" | "open";
|
||||
};
|
@ -18,7 +18,6 @@ export abstract class PlatformUtilsService {
|
||||
isMacAppStore: () => boolean;
|
||||
isViewOpen: () => Promise<boolean>;
|
||||
launchUri: (uri: string, options?: any) => void;
|
||||
saveFile: (win: Window, blobData: any, blobOptions: any, fileName: string) => void;
|
||||
getApplicationVersion: () => Promise<string>;
|
||||
supportsWebAuthn: (win: Window) => boolean;
|
||||
supportsDuo: () => boolean;
|
||||
|
@ -83,16 +83,6 @@ export class ElectronPlatformUtilsService implements PlatformUtilsService {
|
||||
shell.openExternal(uri);
|
||||
}
|
||||
|
||||
saveFile(win: Window, blobData: any, blobOptions: any, fileName: string): void {
|
||||
const blob = new Blob([blobData], blobOptions);
|
||||
const a = win.document.createElement("a");
|
||||
a.href = URL.createObjectURL(blob);
|
||||
a.download = fileName;
|
||||
win.document.body.appendChild(a);
|
||||
a.click();
|
||||
win.document.body.removeChild(a);
|
||||
}
|
||||
|
||||
getApplicationVersion(): Promise<string> {
|
||||
return ipcRenderer.invoke("appVersion");
|
||||
}
|
||||
|
@ -84,10 +84,6 @@ export class CliPlatformUtilsService implements PlatformUtilsService {
|
||||
}
|
||||
}
|
||||
|
||||
saveFile(win: Window, blobData: any, blobOptions: any, fileName: string): void {
|
||||
throw new Error("Not implemented.");
|
||||
}
|
||||
|
||||
getApplicationVersion(): Promise<string> {
|
||||
return Promise.resolve(this.packageJson.version);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user