2019-08-13 17:40:54 +02:00
|
|
|
import { SafariApp } from './safariApp';
|
|
|
|
|
2019-08-21 16:29:14 +02:00
|
|
|
import { Utils } from 'jslib/misc/utils';
|
|
|
|
|
2018-01-20 20:05:20 +01:00
|
|
|
export class BrowserApi {
|
2018-08-15 03:27:55 +02:00
|
|
|
static isWebExtensionsApi: boolean = (typeof browser !== 'undefined');
|
2021-01-13 23:08:33 +01:00
|
|
|
static isSafariApi: boolean = (window as any).safariAppExtension === true;
|
2018-01-16 03:59:25 +01:00
|
|
|
static isChromeApi: boolean = !BrowserApi.isSafariApi && (typeof chrome !== 'undefined');
|
2018-08-15 03:29:32 +02:00
|
|
|
static isFirefoxOnAndroid: boolean = navigator.userAgent.indexOf('Firefox/') !== -1 &&
|
|
|
|
navigator.userAgent.indexOf('Android') !== -1;
|
2018-01-12 05:04:47 +01:00
|
|
|
|
2017-12-07 21:06:37 +01:00
|
|
|
static async getTabFromCurrentWindowId(): Promise<any> {
|
2021-01-13 23:08:33 +01:00
|
|
|
if (BrowserApi.isChromeApi) {
|
|
|
|
return await BrowserApi.tabsQueryFirst({
|
|
|
|
active: true,
|
|
|
|
windowId: chrome.windows.WINDOW_ID_CURRENT,
|
|
|
|
});
|
|
|
|
} else if (BrowserApi.isSafariApi) {
|
|
|
|
return await BrowserApi.getTabFromCurrentWindow();
|
|
|
|
}
|
2017-12-07 21:06:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static async getTabFromCurrentWindow(): Promise<any> {
|
|
|
|
return await BrowserApi.tabsQueryFirst({
|
|
|
|
active: true,
|
|
|
|
currentWindow: true,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-03-04 04:48:38 +01:00
|
|
|
static async getActiveTabs(): Promise<any[]> {
|
|
|
|
return await BrowserApi.tabsQuery({
|
|
|
|
active: true,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-08-16 16:54:19 +02:00
|
|
|
static async tabsQuery(options: any): Promise<any[]> {
|
2021-01-13 23:08:33 +01:00
|
|
|
if (BrowserApi.isChromeApi) {
|
|
|
|
return new Promise((resolve) => {
|
|
|
|
chrome.tabs.query(options, (tabs: any[]) => {
|
|
|
|
resolve(tabs);
|
|
|
|
});
|
2017-12-07 21:06:37 +01:00
|
|
|
});
|
2021-01-13 23:08:33 +01:00
|
|
|
} else if (BrowserApi.isSafariApi) {
|
|
|
|
const tabs = await SafariApp.sendMessageToApp('tabs_query', JSON.stringify(options));
|
|
|
|
return tabs != null ? JSON.parse(tabs) : null;
|
|
|
|
}
|
2017-12-07 21:06:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static async tabsQueryFirst(options: any): Promise<any> {
|
|
|
|
const tabs = await BrowserApi.tabsQuery(options);
|
|
|
|
if (tabs.length > 0) {
|
|
|
|
return tabs[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
2017-12-07 21:36:24 +01:00
|
|
|
|
2018-01-12 17:32:42 +01:00
|
|
|
static tabSendMessageData(tab: any, command: string, data: any = null): Promise<any[]> {
|
2017-12-07 21:36:24 +01:00
|
|
|
const obj: any = {
|
|
|
|
command: command,
|
|
|
|
};
|
|
|
|
|
|
|
|
if (data != null) {
|
|
|
|
obj.data = data;
|
|
|
|
}
|
|
|
|
|
2018-01-12 17:32:42 +01:00
|
|
|
return BrowserApi.tabSendMessage(tab, obj);
|
|
|
|
}
|
|
|
|
|
2019-08-16 18:51:06 +02:00
|
|
|
static async tabSendMessage(tab: any, obj: any, options: any = null): Promise<any> {
|
2018-01-12 17:32:42 +01:00
|
|
|
if (!tab || !tab.id) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-01-13 23:08:33 +01:00
|
|
|
if (BrowserApi.isChromeApi) {
|
|
|
|
return new Promise((resolve) => {
|
|
|
|
chrome.tabs.sendMessage(tab.id, obj, options, () => {
|
|
|
|
if (chrome.runtime.lastError) {
|
|
|
|
// Some error happened
|
|
|
|
}
|
|
|
|
resolve();
|
|
|
|
});
|
2017-12-07 21:36:24 +01:00
|
|
|
});
|
2021-01-13 23:08:33 +01:00
|
|
|
} else if (BrowserApi.isSafariApi) {
|
|
|
|
if (options != null && options.frameId != null && obj.bitwardenFrameId == null) {
|
|
|
|
obj.bitwardenFrameId = options.frameId;
|
|
|
|
}
|
|
|
|
await SafariApp.sendMessageToApp('tabs_message', JSON.stringify({
|
|
|
|
tab: tab,
|
|
|
|
obj: JSON.stringify(obj),
|
|
|
|
options: options,
|
|
|
|
}), true);
|
|
|
|
}
|
2017-12-07 21:36:24 +01:00
|
|
|
}
|
2018-01-12 05:04:47 +01:00
|
|
|
|
|
|
|
static getBackgroundPage(): any {
|
2021-01-13 23:08:33 +01:00
|
|
|
if (BrowserApi.isChromeApi) {
|
|
|
|
return chrome.extension.getBackgroundPage();
|
|
|
|
} else if (BrowserApi.isSafariApi) {
|
|
|
|
return window;
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
2018-01-12 05:04:47 +01:00
|
|
|
}
|
2018-01-12 16:05:30 +01:00
|
|
|
|
2018-01-12 16:41:01 +01:00
|
|
|
static getApplicationVersion(): string {
|
2021-01-13 23:08:33 +01:00
|
|
|
if (BrowserApi.isChromeApi) {
|
|
|
|
return chrome.runtime.getManifest().version;
|
|
|
|
} else if (BrowserApi.isSafariApi) {
|
|
|
|
return (window as any).bitwardenApplicationVersion;
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
2018-01-12 16:05:30 +01:00
|
|
|
}
|
2018-01-12 17:09:30 +01:00
|
|
|
|
2019-08-20 19:54:10 +02:00
|
|
|
static async isPopupOpen(): Promise<boolean> {
|
2021-01-13 23:08:33 +01:00
|
|
|
if (BrowserApi.isChromeApi) {
|
|
|
|
return Promise.resolve(chrome.extension.getViews({ type: 'popup' }).length > 0);
|
|
|
|
} else if (BrowserApi.isSafariApi) {
|
|
|
|
const open = await SafariApp.sendMessageToApp('isPopoverOpen');
|
|
|
|
return open === 'true';
|
|
|
|
} else {
|
|
|
|
return Promise.resolve(false);
|
|
|
|
}
|
2018-01-12 17:09:30 +01:00
|
|
|
}
|
|
|
|
|
2019-08-22 03:18:00 +02:00
|
|
|
static createNewTab(url: string, extensionPage: boolean = false) {
|
2021-01-13 23:08:33 +01:00
|
|
|
if (BrowserApi.isChromeApi) {
|
|
|
|
chrome.tabs.create({ url: url });
|
|
|
|
} else if (BrowserApi.isSafariApi) {
|
|
|
|
SafariApp.sendMessageToApp('createNewTab', url, true);
|
|
|
|
}
|
2018-01-12 17:09:30 +01:00
|
|
|
}
|
|
|
|
|
2019-08-15 22:36:49 +02:00
|
|
|
static messageListener(name: string, callback: (message: any, sender: any, response: any) => void) {
|
2021-01-13 23:08:33 +01:00
|
|
|
if (BrowserApi.isChromeApi) {
|
|
|
|
chrome.runtime.onMessage.addListener((msg: any, sender: any, response: any) => {
|
|
|
|
callback(msg, sender, response);
|
|
|
|
});
|
|
|
|
} else if (BrowserApi.isSafariApi) {
|
|
|
|
SafariApp.addMessageListener(name, (message: any, sender: any, response: any) => {
|
|
|
|
if (message.bitwardenFrameId != null) {
|
|
|
|
if (sender != null && typeof (sender) === 'object' && sender.frameId == null) {
|
|
|
|
sender.frameId = message.bitwardenFrameId;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
callback(message, sender, response);
|
|
|
|
});
|
|
|
|
}
|
2018-01-12 17:32:42 +01:00
|
|
|
}
|
2018-01-12 21:53:37 +01:00
|
|
|
|
2018-01-12 22:42:47 +01:00
|
|
|
static closePopup(win: Window) {
|
2018-08-15 03:27:55 +02:00
|
|
|
if (BrowserApi.isWebExtensionsApi && BrowserApi.isFirefoxOnAndroid) {
|
2018-08-15 03:32:13 +02:00
|
|
|
// Reactivating the active tab dismisses the popup tab. The promise final
|
|
|
|
// condition is only called if the popup wasn't already dismissed (future proofing).
|
|
|
|
// ref: https://bugzilla.mozilla.org/show_bug.cgi?id=1433604
|
2018-08-15 03:29:32 +02:00
|
|
|
browser.tabs.update({ active: true }).finally(win.close);
|
2021-01-13 23:08:33 +01:00
|
|
|
} else if (BrowserApi.isWebExtensionsApi || BrowserApi.isChromeApi) {
|
2018-01-12 22:42:47 +01:00
|
|
|
win.close();
|
2021-01-13 23:08:33 +01:00
|
|
|
} else if (BrowserApi.isSafariApi) {
|
|
|
|
SafariApp.sendMessageToApp('hidePopover');
|
2018-01-12 22:42:47 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-15 16:01:25 +01:00
|
|
|
static downloadFile(win: Window, blobData: any, blobOptions: any, fileName: string) {
|
2018-01-15 17:04:28 +01:00
|
|
|
if (BrowserApi.isSafariApi) {
|
2019-08-21 16:29:14 +02:00
|
|
|
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);
|
|
|
|
}
|
2019-08-22 02:45:23 +02:00
|
|
|
SafariApp.sendMessageToApp('downloadFile', JSON.stringify({
|
2019-08-23 15:55:59 +02:00
|
|
|
blobData: data,
|
|
|
|
blobOptions: blobOptions,
|
|
|
|
fileName: fileName,
|
2019-08-22 02:45:23 +02:00
|
|
|
}), true);
|
2018-01-15 16:01:25 +01:00
|
|
|
} else {
|
|
|
|
const blob = new Blob([blobData], blobOptions);
|
2018-01-15 17:04:28 +01:00
|
|
|
if (navigator.msSaveOrOpenBlob) {
|
|
|
|
navigator.msSaveBlob(blob, fileName);
|
|
|
|
} else {
|
|
|
|
const a = win.document.createElement('a');
|
2020-08-12 21:45:03 +02:00
|
|
|
a.href = URL.createObjectURL(blob);
|
2018-01-15 17:04:28 +01:00
|
|
|
a.download = fileName;
|
|
|
|
win.document.body.appendChild(a);
|
|
|
|
a.click();
|
|
|
|
win.document.body.removeChild(a);
|
|
|
|
}
|
2018-01-14 05:57:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-26 16:48:32 +01:00
|
|
|
static gaFilter() {
|
2019-08-05 16:03:25 +02:00
|
|
|
return process.env.ENV !== 'production';
|
2018-01-26 16:48:32 +01:00
|
|
|
}
|
2018-04-11 20:52:49 +02:00
|
|
|
|
|
|
|
static getUILanguage(win: Window) {
|
2021-01-13 23:08:33 +01:00
|
|
|
if (BrowserApi.isSafariApi) {
|
|
|
|
return win.navigator.language;
|
|
|
|
} else {
|
|
|
|
return chrome.i18n.getUILanguage();
|
|
|
|
}
|
2018-04-11 20:52:49 +02:00
|
|
|
}
|
2019-03-05 21:05:04 +01:00
|
|
|
|
2019-04-04 17:50:49 +02:00
|
|
|
static reloadExtension(win: Window) {
|
|
|
|
if (win != null) {
|
2019-03-05 21:05:04 +01:00
|
|
|
return win.location.reload(true);
|
2021-01-13 23:08:33 +01:00
|
|
|
} else if (BrowserApi.isSafariApi) {
|
|
|
|
SafariApp.sendMessageToApp('reloadExtension');
|
|
|
|
} else if (!BrowserApi.isSafariApi) {
|
2019-03-05 21:05:04 +01:00
|
|
|
return chrome.runtime.reload();
|
|
|
|
}
|
|
|
|
}
|
2020-08-17 21:49:01 +02:00
|
|
|
|
|
|
|
static reloadOpenWindows() {
|
2021-01-13 23:08:33 +01:00
|
|
|
if (!BrowserApi.isSafariApi) {
|
|
|
|
const views = chrome.extension.getViews() as Window[];
|
|
|
|
views.filter((w) => w.location.href != null).forEach((w) => {
|
|
|
|
w.location.reload();
|
|
|
|
});
|
|
|
|
}
|
2020-08-17 21:49:01 +02:00
|
|
|
}
|
2020-10-09 17:16:15 +02:00
|
|
|
|
|
|
|
static connectNative(application: string): browser.runtime.Port | chrome.runtime.Port {
|
|
|
|
if (BrowserApi.isWebExtensionsApi) {
|
|
|
|
return browser.runtime.connectNative(application);
|
|
|
|
} else if (BrowserApi.isChromeApi) {
|
|
|
|
return chrome.runtime.connectNative(application);
|
|
|
|
}
|
|
|
|
}
|
2017-12-07 21:06:37 +01:00
|
|
|
}
|