From 30d117a964c954abc8245c2c23ee003b3b5ed470 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Thu, 23 May 2019 10:47:16 +0200 Subject: [PATCH 1/3] Cross-browser extension interface --- packages/extension/package.json | 1 + packages/extension/src/background/ChromeStore.ts | 16 +++++++++------- .../src/background/handlers/Extension.ts | 2 +- .../src/background/handlers/SigningRequests.ts | 6 ++++-- .../extension/src/background/handlers/Tabs.ts | 2 +- .../extension/src/background/handlers/index.ts | 2 +- packages/extension/src/background/index.ts | 8 +++++--- packages/extension/src/background/types.ts | 2 +- packages/extension/src/events.ts | 2 +- packages/extension/src/extensionizer.d.ts | 9 +++++++++ packages/extension/src/inject/Accounts.ts | 2 +- packages/extension/src/inject/Injected.ts | 2 +- packages/extension/src/inject/Signer.ts | 2 +- packages/extension/src/inject/types.ts | 2 +- packages/extension/src/loader.ts | 6 ++++-- yarn.lock | 5 +++++ 16 files changed, 46 insertions(+), 23 deletions(-) create mode 100644 packages/extension/src/extensionizer.d.ts diff --git a/packages/extension/package.json b/packages/extension/package.json index d50c057e0cf..b9ff2a2422f 100644 --- a/packages/extension/package.json +++ b/packages/extension/package.json @@ -11,6 +11,7 @@ }, "devDependencies": { "@types/chrome": "^0.0.86", + "extensionizer": "^1.0.1", "extract-loader": "^3.1.0", "file-loader": "^3.0.1", "html-loader": "^0.5.5" diff --git a/packages/extension/src/background/ChromeStore.ts b/packages/extension/src/background/ChromeStore.ts index 4e344297fdb..72a38e4a0c1 100644 --- a/packages/extension/src/background/ChromeStore.ts +++ b/packages/extension/src/background/ChromeStore.ts @@ -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(); diff --git a/packages/extension/src/background/handlers/Extension.ts b/packages/extension/src/background/handlers/Extension.ts index f348dd04e13..833e7e01679 100644 --- a/packages/extension/src/background/handlers/Extension.ts +++ b/packages/extension/src/background/handlers/Extension.ts @@ -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. diff --git a/packages/extension/src/background/handlers/SigningRequests.ts b/packages/extension/src/background/handlers/SigningRequests.ts index 8d3827548c8..a9fd484f9cb 100644 --- a/packages/extension/src/background/handlers/SigningRequests.ts +++ b/packages/extension/src/background/handlers/SigningRequests.ts @@ -1,9 +1,11 @@ -// 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 { MessageExtrinsicSign, MessageExtrinsicSign$Response } from '../types'; +import extension from 'extensionizer'; + type Request = { id: number, request: MessageExtrinsicSign, @@ -41,7 +43,7 @@ export default class SigningRequests { private updateIcon (): void { const count = this.numRequests; - chrome.browserAction.setBadgeText({ text: count ? `${this.numRequests}` : '' }); + extension.browserAction.setBadgeText({ text: count ? `${this.numRequests}` : '' }); } get (id: number): Request { diff --git a/packages/extension/src/background/handlers/Tabs.ts b/packages/extension/src/background/handlers/Tabs.ts index 8f140369843..86bc4cbfbe5 100644 --- a/packages/extension/src/background/handlers/Tabs.ts +++ b/packages/extension/src/background/handlers/Tabs.ts @@ -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. diff --git a/packages/extension/src/background/handlers/index.ts b/packages/extension/src/background/handlers/index.ts index eef41aeb2af..82f2b5ae2f0 100644 --- a/packages/extension/src/background/handlers/index.ts +++ b/packages/extension/src/background/handlers/index.ts @@ -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. diff --git a/packages/extension/src/background/index.ts b/packages/extension/src/background/index.ts index b2953dcb0f6..d6bbfbfc4c2 100644 --- a/packages/extension/src/background/index.ts +++ b/packages/extension/src/background/index.ts @@ -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(() => { diff --git a/packages/extension/src/background/types.ts b/packages/extension/src/background/types.ts index 181789d2966..9306bdc1506 100644 --- a/packages/extension/src/background/types.ts +++ b/packages/extension/src/background/types.ts @@ -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. diff --git a/packages/extension/src/events.ts b/packages/extension/src/events.ts index 48b923775ab..9b2200e36b6 100644 --- a/packages/extension/src/events.ts +++ b/packages/extension/src/events.ts @@ -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. diff --git a/packages/extension/src/extensionizer.d.ts b/packages/extension/src/extensionizer.d.ts new file mode 100644 index 00000000000..486f528841f --- /dev/null +++ b/packages/extension/src/extensionizer.d.ts @@ -0,0 +1,9 @@ +// 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 module 'extensionizer' { + const extensionizer: typeof chrome; + + export default extensionizer; +} diff --git a/packages/extension/src/inject/Accounts.ts b/packages/extension/src/inject/Accounts.ts index d68b61608e4..c4c4e1bb182 100644 --- a/packages/extension/src/inject/Accounts.ts +++ b/packages/extension/src/inject/Accounts.ts @@ -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. diff --git a/packages/extension/src/inject/Injected.ts b/packages/extension/src/inject/Injected.ts index 4ae70ffa5d7..092e0e7753d 100644 --- a/packages/extension/src/inject/Injected.ts +++ b/packages/extension/src/inject/Injected.ts @@ -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. diff --git a/packages/extension/src/inject/Signer.ts b/packages/extension/src/inject/Signer.ts index 792483f1173..77a416bbaae 100644 --- a/packages/extension/src/inject/Signer.ts +++ b/packages/extension/src/inject/Signer.ts @@ -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. diff --git a/packages/extension/src/inject/types.ts b/packages/extension/src/inject/types.ts index 0e6cdbab436..e0d0a405f1b 100644 --- a/packages/extension/src/inject/types.ts +++ b/packages/extension/src/inject/types.ts @@ -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. diff --git a/packages/extension/src/loader.ts b/packages/extension/src/loader.ts index 33f136f2753..b62d4952665 100644 --- a/packages/extension/src/loader.ts +++ b/packages/extension/src/loader.ts @@ -2,6 +2,8 @@ // 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'; + import events from './events'; function sendResponse (detail: any): void { @@ -14,7 +16,7 @@ document.addEventListener(events.request, (event) => { 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 +30,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) { diff --git a/yarn.lock b/yarn.lock index ff1174abc93..37f3ae48488 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5666,6 +5666,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" From 7ae68d3272a936f8d02cc38bd9897c20133025c3 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Thu, 23 May 2019 12:35:27 +0200 Subject: [PATCH 2/3] Allow eventTarget --- packages/extension/package.json | 1 + packages/extension/src/events.ts | 9 +++++++++ packages/extension/src/extensionizer.d.ts | 6 ++++++ packages/extension/src/inject/index.ts | 14 +++++++++----- packages/extension/src/loader.ts | 7 ++++--- yarn.lock | 5 +++++ 6 files changed, 34 insertions(+), 8 deletions(-) diff --git a/packages/extension/package.json b/packages/extension/package.json index b9ff2a2422f..84708736ec3 100644 --- a/packages/extension/package.json +++ b/packages/extension/package.json @@ -11,6 +11,7 @@ }, "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", diff --git a/packages/extension/src/events.ts b/packages/extension/src/events.ts index 9b2200e36b6..8c54d07847d 100644 --- a/packages/extension/src/events.ts +++ b/packages/extension/src/events.ts @@ -2,9 +2,18 @@ // 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; diff --git a/packages/extension/src/extensionizer.d.ts b/packages/extension/src/extensionizer.d.ts index 486f528841f..df4244b2d0a 100644 --- a/packages/extension/src/extensionizer.d.ts +++ b/packages/extension/src/extensionizer.d.ts @@ -2,6 +2,12 @@ // 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; diff --git a/packages/extension/src/inject/index.ts b/packages/extension/src/inject/index.ts index 581355b79b7..46b5d947322 100644 --- a/packages/extension/src/inject/index.ts +++ b/packages/extension/src/inject/index.ts @@ -4,14 +4,14 @@ import { WindowInjected } from './types'; -import events from '../events'; +import events, { eventTarget } from '../events'; import Injected from './Injected'; const callbacks: { [index: number]: { resolve: (data: any) => void, reject: (error: Error) => void } } = {}; let idCounter = 0; // 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]; @@ -29,15 +29,19 @@ document.addEventListener(events.response, (event) => { } }); -(window as WindowInjected).injectedWeb3 = (window as WindowInjected).injectedWeb3 || {}; -(window as WindowInjected).injectedWeb3['polkadot-js'] = new Injected( +// small helper with the typescript types, just cast window +const windowInject = window as WindowInjected; + +// attach the injectedWeb3 object +windowInject.injectedWeb3 = windowInject.injectedWeb3 || {}; +windowInject.injectedWeb3['polkadot-js'] = new Injected( (message: string, request: any = null): Promise => { return new Promise((resolve, reject) => { const id = ++idCounter; callbacks[id] = { resolve, reject }; - document.dispatchEvent( + eventTarget.dispatchEvent( new CustomEvent(events.request, { detail: { id, message, request } }) ); }); diff --git a/packages/extension/src/loader.ts b/packages/extension/src/loader.ts index b62d4952665..2dcdf61970c 100644 --- a/packages/extension/src/loader.ts +++ b/packages/extension/src/loader.ts @@ -4,14 +4,15 @@ import extension from 'extensionizer'; -import events from './events'; +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; diff --git a/yarn.lock b/yarn.lock index 37f3ae48488..e2822edf705 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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" From dc32082665c77553425c025d3c63236bf8fb30c2 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Thu, 23 May 2019 13:14:40 +0200 Subject: [PATCH 3/3] Use extension.* in State --- packages/extension/src/background/handlers/State.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/extension/src/background/handlers/State.ts b/packages/extension/src/background/handlers/State.ts index 7206efbef32..934cc56e76e 100644 --- a/packages/extension/src/background/handlers/State.ts +++ b/packages/extension/src/background/handlers/State.ts @@ -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 {