bitwarden-estensione-browser/src/browser/browserApi.ts

299 lines
10 KiB
TypeScript
Raw Normal View History

2018-01-20 20:05:20 +01:00
export class BrowserApi {
static isWebExtensionsApi: boolean = (typeof browser !== 'undefined');
2018-01-16 03:59:25 +01:00
static isSafariApi: boolean = (typeof safari !== 'undefined') &&
2018-04-11 20:52:49 +02:00
navigator.userAgent.indexOf(' Safari/') !== -1 && navigator.userAgent.indexOf('Chrome') === -1;
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;
static isEdge18: boolean = navigator.userAgent.indexOf(' Edge/18.') !== -1;
2018-01-12 05:04:47 +01:00
static async getTabFromCurrentWindowId(): Promise<any> {
2018-01-12 19:22:24 +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();
}
}
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,
});
}
static tabsQuery(options: any): Promise<any[]> {
2018-01-12 19:22:24 +01:00
if (BrowserApi.isChromeApi) {
return new Promise((resolve) => {
chrome.tabs.query(options, (tabs: any[]) => {
resolve(tabs);
});
});
2018-01-12 19:22:24 +01:00
} else if (BrowserApi.isSafariApi) {
2018-03-04 04:48:38 +01:00
let wins: any[] = [];
2018-01-12 19:22:24 +01:00
if (options.currentWindow) {
2018-03-04 04:48:38 +01:00
if (safari.application.activeBrowserWindow) {
wins.push(safari.application.activeBrowserWindow);
}
} else {
wins = safari.application.browserWindows;
2018-01-12 19:22:24 +01:00
}
const returnedTabs: any[] = [];
2018-03-04 04:48:38 +01:00
wins.forEach((win: any) => {
if (!win.tabs) {
return;
}
if (options.active && win.activeTab) {
returnedTabs.push(BrowserApi.makeTabObject(win.activeTab));
} else if (!options.active) {
win.tabs.forEach((tab: any) => {
returnedTabs.push(BrowserApi.makeTabObject(tab));
});
}
2018-01-12 19:22:24 +01:00
});
return Promise.resolve(returnedTabs);
}
}
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
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;
}
return BrowserApi.tabSendMessage(tab, obj);
}
static tabSendMessage(tab: any, obj: any, options: any = null): Promise<any> {
if (!tab || !tab.id) {
return;
}
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
});
} else if (BrowserApi.isSafariApi) {
2018-01-13 05:20:26 +01:00
let t = tab.safariTab;
if (!t || !t.page) {
const win = safari.application.activeBrowserWindow;
if (safari.application.browserWindows.indexOf(win) !== tab.windowId) {
return Promise.reject('Window not found.');
}
if (win.tabs.length < tab.index + 1) {
return Promise.reject('Tab not found.');
}
t = win.tabs[tab.index];
}
if (obj.tab && obj.tab.safariTab) {
delete obj.tab.safariTab;
}
if (options != null && options.frameId != null && obj.bitwardenFrameId == null) {
obj.bitwardenFrameId = options.frameId;
}
if (t.page) {
t.page.dispatchMessage('bitwarden', obj);
2018-01-12 22:33:36 +01:00
}
return Promise.resolve();
}
2017-12-07 21:36:24 +01:00
}
2018-01-12 05:04:47 +01:00
static getBackgroundPage(): any {
2018-10-03 14:26:46 +02:00
if (BrowserApi.isChromeApi) {
2018-01-12 05:39:16 +01:00
return chrome.extension.getBackgroundPage();
} else if (BrowserApi.isSafariApi) {
return safari.extension.globalPage.contentWindow;
} 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 {
2018-01-12 16:05:30 +01:00
if (BrowserApi.isChromeApi) {
return chrome.runtime.getManifest().version;
} else if (BrowserApi.isSafariApi) {
2018-01-12 16:07:27 +01:00
return safari.extension.displayVersion;
2018-01-12 16:05:30 +01:00
} else {
return null;
}
}
2018-01-12 17:09:30 +01:00
static isPopupOpen(): boolean {
if (BrowserApi.isChromeApi) {
return chrome.extension.getViews({ type: 'popup' }).length > 0;
} else if (BrowserApi.isSafariApi) {
return safari.extension.popovers && safari.extension.popovers.length &&
safari.extension.popovers[0].visible;
2018-01-12 17:09:30 +01:00
} else {
return null;
}
}
static createNewTab(url: string, extensionPage: boolean = false): any {
2018-01-12 17:09:30 +01:00
if (BrowserApi.isChromeApi) {
chrome.tabs.create({ url: url });
return null;
2018-01-12 17:09:30 +01:00
} else if (BrowserApi.isSafariApi) {
if (extensionPage && url.indexOf('/') === 0) {
url = BrowserApi.getAssetUrl(url);
}
2018-01-13 03:26:49 +01:00
const tab = safari.application.activeBrowserWindow.openTab();
if (tab) {
tab.url = url;
}
return tab;
2018-01-12 17:09:30 +01:00
} else {
return;
}
}
static getAssetUrl(path: string): string {
if (BrowserApi.isChromeApi) {
return chrome.extension.getURL(path);
} else if (BrowserApi.isSafariApi) {
if (path.indexOf('/') === 0) {
path = path.substr(1);
}
return safari.extension.baseURI + path;
2018-01-12 17:09:30 +01:00
} else {
return null;
}
}
static messageListener(callback: (message: any, sender: any, response: any) => void) {
if (BrowserApi.isChromeApi) {
chrome.runtime.onMessage.addListener((msg: any, sender: any, response: any) => {
callback(msg, sender, response);
});
} else if (BrowserApi.isSafariApi) {
2018-01-12 21:29:01 +01:00
safari.application.addEventListener('message', async (msgEvent: any) => {
callback(msgEvent.message, {
2018-01-12 21:53:37 +01:00
tab: BrowserApi.makeTabObject(msgEvent.target),
frameId: msgEvent.message != null && msgEvent.message.bitwardenFrameId != null ?
msgEvent.message.bitwardenFrameId : null,
2018-01-12 21:29:01 +01:00
}, () => { /* No responses in Safari */ });
}, false);
}
}
2018-01-12 21:53:37 +01:00
2018-01-12 22:42:47 +01:00
static closePopup(win: Window) {
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);
} else if (BrowserApi.isWebExtensionsApi || BrowserApi.isChromeApi) {
2018-01-12 22:42:47 +01:00
win.close();
} else if (BrowserApi.isSafariApi && safari.extension.popovers && safari.extension.popovers.length > 0) {
safari.extension.popovers[0].hide();
}
}
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) {
const tab = BrowserApi.createNewTab(BrowserApi.getAssetUrl('downloader/index.html'));
2018-01-15 17:04:28 +01:00
const tabToSend = BrowserApi.makeTabObject(tab);
setTimeout(async () => {
BrowserApi.tabSendMessage(tabToSend, {
command: 'downloaderPageData',
data: {
2018-01-15 16:01:25 +01:00
blobData: blobData,
blobOptions: blobOptions,
fileName: fileName,
},
});
}, 1000);
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');
a.href = win.URL.createObjectURL(blob);
a.download = fileName;
win.document.body.appendChild(a);
a.click();
win.document.body.removeChild(a);
}
}
}
2018-01-18 20:40:23 +01:00
static makeTabObject(tab: any): any {
2018-01-12 21:53:37 +01:00
if (BrowserApi.isChromeApi) {
return tab;
}
if (!tab.browserWindow) {
return {};
}
const winIndex = safari.application.browserWindows.indexOf(tab.browserWindow);
const tabIndex = tab.browserWindow.tabs.indexOf(tab);
return {
id: winIndex + '_' + tabIndex,
index: tabIndex,
windowId: winIndex,
title: tab.title,
active: tab === tab.browserWindow.activeTab,
url: tab.url || 'about:blank',
2018-01-13 05:20:26 +01:00
safariTab: tab,
2018-01-12 21:53:37 +01:00
};
}
2018-01-26 16:48:32 +01:00
static gaFilter() {
2018-04-13 21:14:04 +02:00
return process.env.ENV !== 'production' ||
(BrowserApi.isSafariApi && safari.application.activeBrowserWindow.activeTab.private);
2018-01-26 16:48:32 +01:00
}
2018-04-11 20:52:49 +02:00
static getUILanguage(win: Window) {
if (BrowserApi.isSafariApi) {
return win.navigator.language;
} else {
return chrome.i18n.getUILanguage();
}
}
2019-03-05 21:05:04 +01:00
static reloadExtension(win: Window, popupWindow: boolean) {
if (BrowserApi.isSafariApi) {
return win.location.reload(true);
} else if (!popupWindow) {
return chrome.runtime.reload();
}
}
}