Cross-browser extension interface (#21)

* Cross-browser extension interface

* Allow eventTarget

* Use extension.* in State
This commit is contained in:
Jaco Greeff 2019-05-23 13:37:18 +02:00 committed by GitHub
parent f241e7191d
commit ebe20c3e23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 76 additions and 29 deletions

View File

@ -11,6 +11,8 @@
},
"devDependencies": {
"@types/chrome": "^0.0.86",
"@types/firefox-webext-browser": "^67.0.1",
"extensionizer": "^1.0.1",
"extract-loader": "^3.1.0",
"file-loader": "^3.0.1",
"html-loader": "^0.5.5"

View File

@ -1,20 +1,22 @@
// Copyright 2019 @polkadot/extension-bg authors & contributors
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { KeyringStore } from '@polkadot/ui-keyring/types';
import extension from 'extensionizer';
const lastError = (type: string): void => {
const error = chrome.runtime.lastError;
const error = extension.runtime.lastError;
if (error) {
console.error(`ChromeStore.${type}:: chrome.runtime.lastError:`, error);
console.error(`ChromeStore.${type}:: runtime.lastError:`, error);
}
};
export default class ChromeStore implements KeyringStore {
all (cb: (key: string, value: any) => void): void {
chrome.storage.local.get(null, (result: { [index: string]: any }) => {
extension.storage.local.get(null, (result: { [index: string]: any }) => {
lastError('all');
Object.entries(result).forEach(([key, value]) =>
@ -24,7 +26,7 @@ export default class ChromeStore implements KeyringStore {
}
get (key: string, cb: (value: any) => void): void {
chrome.storage.local.get([key], (result: { [index: string]: any }) => {
extension.storage.local.get([key], (result: { [index: string]: any }) => {
lastError('get');
cb(result[key]);
@ -32,7 +34,7 @@ export default class ChromeStore implements KeyringStore {
}
remove (key: string, cb?: () => void): void {
chrome.storage.local.remove(key, () => {
extension.storage.local.remove(key, () => {
lastError('remove');
cb && cb();
@ -47,7 +49,7 @@ export default class ChromeStore implements KeyringStore {
return;
}
chrome.storage.local.set({ [key]: value }, () => {
extension.storage.local.set({ [key]: value }, () => {
lastError('set');
cb && cb();

View File

@ -1,4 +1,4 @@
// Copyright 2019 @polkadot/extension-bg authors & contributors
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

View File

@ -4,6 +4,7 @@
import { AuthorizeRequest, MessageAuthorize, MessageExtrinsicSign, MessageExtrinsicSign$Response, SigningRequest } from '../types';
import extension from 'extensionizer';
import { assert } from '@polkadot/util';
type AuthRequest = {
@ -115,7 +116,7 @@ export default class State {
: (signCount ? `${signCount}` : '')
);
chrome.browserAction.setBadgeText({ text });
extension.browserAction.setBadgeText({ text });
}
async authorizeUrl (url: string, request: MessageAuthorize): Promise<boolean> {

View File

@ -1,4 +1,4 @@
// Copyright 2019 @polkadot/extension-bg authors & contributors
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

View File

@ -1,4 +1,4 @@
// Copyright 2019 @polkadot/extension-bg authors & contributors
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

View File

@ -1,7 +1,9 @@
// Copyright 2019 @polkadot/extension-bg authors & contributors
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import extension from 'extensionizer';
// Runs in the extension background, handling all keyring access
import keyring from '@polkadot/ui-keyring';
@ -10,8 +12,8 @@ import { cryptoWaitReady } from '@polkadot/util-crypto';
import ChromeStore from './ChromeStore';
import handlers from './handlers';
chrome.browserAction.setBadgeBackgroundColor({ color: '#ff0000' });
chrome.runtime.onMessage.addListener(handlers);
extension.browserAction.setBadgeBackgroundColor({ color: '#ff0000' });
extension.runtime.onMessage.addListener(handlers);
cryptoWaitReady()
.then(() => {

View File

@ -1,4 +1,4 @@
// Copyright 2019 @polkadot/extension-bg authors & contributors
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

View File

@ -1,10 +1,19 @@
// Copyright 2019 @polkadot/extension-bg authors & contributors
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
// for FireFox, we need to listent here to allow origin restrictions to not
// be an issue (otherwise we cannot read the properties on the created events)
// const contentDocument = typeof gBrowser !== 'undefined'
// ? gBrowser.selectedBrowser.contentDocument
// : document;
const eventTarget = document;
const events = {
request: 'PolkadotJsWebRequest',
response: 'PolkadotJsWebResponse'
};
export { eventTarget };
export default events;

View File

@ -0,0 +1,15 @@
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
declare var gBrowser: undefined | {
selectedBrowser: {
contentDocument: Document
}
};
declare module 'extensionizer' {
const extensionizer: typeof chrome;
export default extensionizer;
}

View File

@ -1,4 +1,4 @@
// Copyright 2019 @polkadot/extension-inject authors & contributors
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

View File

@ -1,4 +1,4 @@
// Copyright 2019 @polkadot/extension-inject authors & contributors
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

View File

@ -1,4 +1,4 @@
// Copyright 2019 @polkadot/extension-inject authors & contributors
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

View File

@ -5,7 +5,7 @@
import { MessageTypes } from '../background/types';
import { WindowInjected } from './types';
import events from '../events';
import events, { eventTarget } from '../events';
import Injected from './Injected';
// when sending a message from the injector to the expension, we
@ -40,7 +40,7 @@ function sendMessage (message: MessageTypes, request: any = null): Promise<any>
}
// setup a response listener (events created by the loader for extension responses)
document.addEventListener(events.response, (event) => {
eventTarget.addEventListener(events.response, (event) => {
const response = (event as CustomEvent).detail;
const promise = callbacks[response.id];
@ -58,11 +58,14 @@ document.addEventListener(events.response, (event) => {
}
});
// small helper with the typescript types, just cast window
const windowInject = window as WindowInjected;
// don't clobber the existing object, we will add it it (or create as needed)
(window as WindowInjected).injectedWeb3 = (window as WindowInjected).injectedWeb3 || {};
windowInject.injectedWeb3 = windowInject.injectedWeb3 || {};
// add our enable function
(window as WindowInjected).injectedWeb3['polkadot-js'] = {
windowInject.injectedWeb3['polkadot-js'] = {
name: 'polkadot-js', // process.env.PKG_NAME as string,
version: process.env.PKG_VERSION as string,
enable: (origin: string): Promise<Injected> =>

View File

@ -1,4 +1,4 @@
// Copyright 2019 @polkadot/extension-inject authors & contributors
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

View File

@ -2,19 +2,22 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import events from './events';
import extension from 'extensionizer';
import events, { eventTarget } from './events';
function sendResponse (detail: any): void {
document.dispatchEvent(new CustomEvent(events.response, { detail }));
// create the custom event, this will be handled on the injection script
eventTarget.dispatchEvent(new CustomEvent(events.response, { detail }));
}
// Handle all custom events, passing messages to the extension
document.addEventListener(events.request, (event) => {
eventTarget.addEventListener(events.request, (event) => {
// get the request as part of the the event detailt
const request = (event as CustomEvent).detail;
// pass the detail as-is as a message to the extension
chrome.runtime.sendMessage(request, (response) => {
extension.runtime.sendMessage(request, (response) => {
if (!response) {
// no data, send diconnected/unknown error
sendResponse({ id: request.id, error: 'Unknown response' });
@ -28,7 +31,7 @@ document.addEventListener(events.request, (event) => {
// inject our data injector
const script = document.createElement('script');
script.src = chrome.extension.getURL('inject.js');
script.src = extension.extension.getURL('inject.js');
script.onload = (): void => {
// remove the injecting tag when loaded
if (script.parentNode) {

View File

@ -2121,6 +2121,11 @@
resolved "https://registry.yarnpkg.com/@types/filewriter/-/filewriter-0.0.28.tgz#c054e8af4d9dd75db4e63abc76f885168714d4b3"
integrity sha1-wFTor02d11205jq8dviFFocU1LM=
"@types/firefox-webext-browser@^67.0.1":
version "67.0.1"
resolved "https://registry.yarnpkg.com/@types/firefox-webext-browser/-/firefox-webext-browser-67.0.1.tgz#92e3eb4440b56ab43eb93891ea4a3f33516fa7d7"
integrity sha512-+RE7MDu8EQ5EcQe7i0378oCvu1Sf9fEtRdPakYfdcEr79v7wTpO/meQXv9JLqvy7FwM2/9D8cwV7GyclXgRtxA==
"@types/fs-extra@^5.0.3":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-5.1.0.tgz#2a325ef97901504a3828718c390d34b8426a10a1"
@ -5666,6 +5671,11 @@ extend@~3.0.2:
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
extensionizer@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/extensionizer/-/extensionizer-1.0.1.tgz#504544239a7610ba8404b15c1832091a37768d09"
integrity sha512-UES5CSOYqshNsWFrpORcQR47+ph6UvQK25mguD44IyeMemt40CG+LTZrH1PgpGUHX3w7ACtNQnmM0J+qEe8G0Q==
external-editor@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27"